Commit d47e3d69 authored by Louis's avatar Louis
Browse files

[pyromaths] Ajout de commandes et d'options pour filtrer les exercices

- Ajout d'une commande `pyromaths tags` qui liste les tags.
- Ajout d'options --tags et --desc pour n'afficher que les exercices
  correspondant à un certain tag et une certaine description.

Closes #6
parent 4ef49d00
Pipeline #61795 passed with stage
in 43 seconds
......@@ -26,9 +26,11 @@ import argparse
import gettext
import logging
import random
import re
import shutil
import subprocess
import sys
import textwrap
import gettext
......@@ -46,6 +48,9 @@ from pyromaths.version import VERSION
logging.basicConfig(level=logging.INFO)
LOGGER = logging.getLogger()
def _tag_type(string):
return set(tag for tag in string.split("+") if tag)
def argument_parser():
"""Return an argument parser"""
parser = argparse.ArgumentParser(
......@@ -68,12 +73,47 @@ def argument_parser():
"an argument to other commands."
),
formatter_class=argparse.RawDescriptionHelpFormatter,
epilog=textwrap.dedent("""\
# Filtrer les exercices
Les options --tags et --desc permettent de filtrer quels exercices afficher. Par exemple, pour n'afficher que les exercices de seconde dont la description contient le mot « variations », utiliser :
pyromaths ls --desc variation --tag +Seconde
"""),
)
ls.add_argument(
"-v", "--verbose",
help="Affiche davantage de détails.",
action="store_true",
)
ls.add_argument(
"-d", "--desc",
help=textwrap.dedent("""\
Ne liste que les exercice dont la description correspond à l'argument de cette fonction, considéré comme une expression régulière.
Si plusieurs arguments --desc sont donnés, liste les exercices correspondant à l'un des arguments.
"""),
action="append",
default=list(),
type=re.compile,
)
ls.add_argument(
"-t", "--tags",
help=textwrap.dedent("""\
Ne liste que les exercice taggés avec tous des tags fournis en argument (sous la forme "+tag1+tag2+tag3").
Si plusieurs arguments --tags sont donnés, liste les exercices vérifiant l'un des arguments --tags.
La liste des tags peut être affichée avec la commande `pyromaths tags`.
"""),
action="append",
default=list(),
type=_tag_type,
)
# List tags
ls = subparsers.add_parser( # pylint: disable=unused-variable
'tags',
help="List available tags.",
formatter_class=argparse.RawDescriptionHelpFormatter,
)
# Generate
generate_parser = subparsers.add_parser(
......@@ -181,7 +221,7 @@ def do_generate(options):
def do_ls(options): # pylint: disable=unused-argument
"""Perform the `ls` command."""
bag = ExerciseBag()
bag = ExerciseBag().filter_tags(*options.tags).filter_desc(*options.desc)
for name in sorted(bag, key=str.lower):
if options.verbose:
print(u"{}: {} {}".format(
......@@ -192,11 +232,20 @@ def do_ls(options): # pylint: disable=unused-argument
else:
print(name)
def do_tags(options): # pylint: disable=unused-argument
"""Perform the `tags` command."""
bag = ExerciseBag()
tags = set().union(
*(set(exo.tags) for exo in bag.values())
)
print("\n".join(sorted(tags, key=str.lower)))
COMMANDS = {
"generate": do_generate,
"ls": do_ls,
"test": do_test,
"dummy": do_dummy,
"tags": do_tags,
}
def main():
......
......@@ -220,9 +220,13 @@ class ExerciseBag(collections.UserDict):
Des méthodes permettent d'accéder à ces exercices avec d'autres présentations.
"""
def __init__(self):
def __init__(self, *, exercises=None):
super().__init__()
for exo in _iter_exercises():
if exercises is None:
iterable = _iter_exercises()
else:
iterable = exercises
for exo in iterable:
if exo.name() in self:
logging.error(
"Deux exercices portent le même nom '%s': %s et %s.",
......@@ -262,6 +266,26 @@ class ExerciseBag(collections.UserDict):
for niveau in NIVEAUX
]
def filter_tags(self, *clauses):
if not clauses:
return self
exercises = set()
for conjunction in clauses:
for exo in self.values():
if conjunction.issubset(set(exo.tags)):
exercises.add(exo)
return self.__class__(exercises = exercises)
def filter_desc(self, *descriptions):
if not descriptions:
return self
exercises = set()
for desc in descriptions:
for exo in self.values():
if desc.search(exo.description()):
exercises.add(exo)
return self.__class__(exercises = exercises)
################################################################################
# Exercices créés à partir de templates Jinja2
......
......@@ -58,7 +58,7 @@ CANDIDATS = [
class EtatStableSysteme2(Jinja2Exercise):
"""Recherche d'état stable (avec un système)"""
tags = ["Term ES"]
tags = ["Term ES", "matrice", "système", "graphe probabiliste", "spécialité"]
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
......@@ -82,7 +82,7 @@ class InterpolationMatrices(Jinja2Exercise):
"""Interpolation polynomiale en utilisant des matrices"""
# Plus ou moins inspiré du sujet de bac ES Amérique du Nord, juin 2015.
tags = ["Term ES"]
tags = ["Term ES", "matrice", "système", "interpolation", "spécialité"]
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment