API Exercice

Répondre

Smileys
:D :) ;) :( :o :shock: :? 8-) :lol: :x :P :oops: :cry: :evil: :twisted: :roll: :!: :?: :idea: :arrow: :| :mrgreen: :geek: :ugeek:
Voir plus de smileys
Les BBCodes sont activés
[img] est activé
[flash] est désactivé
[url] est activé
Les smileys sont activés
Revue du sujet
   

Etendre la vue Revue du sujet: API Exercice

Re: API Exercice

Message de Yves » Ven 13 Juin 2014, 17:28

J'ai vu ça en regardant le code de l'exercice sur la notion de fonction ;)

Re: API Exercice

Message de Jérôme » Ven 13 Juin 2014, 17:18

C'est même pire que ça. Je n'ai pas utilisé de classe pour créer mes derniers exercices... J'essaierai de corriger plus tard.

Re: API Exercice

Message de Yves » Ven 13 Juin 2014, 15:45

Dans la documentation, j'ai rajouté un avertissement dans l'article Hello world!, en précisant que les infos ne sont plus d'actualité et en rajoutant un lien vers cette discussion.

Comme la plupart des exercices sont encore dans l'ancien format, une fonction retournant un tuple (énoncé, correction) et pas une classe avec les méthodes tex_statement() et tex_answer(), l'article (plus précisément la première partie) a toujours sa place dans la documentation.

Re: API Exercice

Message de Yves » Ven 23 Mai 2014, 19:47

Oui merci ! Sur Mac, la syntaxe est un tout petit peu différente, il faut rajouter des parenthèses:
find dist/Pyromaths.app/Contents/Resources/lib/python2.7/pyromaths/ \( -name '*.pyc' \) -exec rm {} \;
Le code suivant fonctionne aussi:
find dist/Pyromaths.app/Contents/Resources/lib/python2.7/pyromaths/ \( -name '*.pyc' \) -delete
J'ai fait un commit avec cette modification et aussi la suppression de l'option Tous les exercices.

Re: API Exercice

Message de Jérôme » Jeu 22 Mai 2014, 22:26

Juste un remarque pour ta dernière ligne qui souhaite retirer tous les *.pyc. Tu peux utiliser find.
find dist/Pyromaths.app/Contents/Resources/lib/python2.7/pyromaths/ -name "*.pyc" --exec rm {} \;

Re: API Exercice

Message de Yves » Mar 20 Mai 2014, 23:46

  • Résolution de l'erreur pkgutil
    Yves a écrit:la création de l'app avec py2app conduit à l'erreur suivante:
    Code: Tout sélectionner
    ImportError: No module named pkgutil
    En fait, il suffit que pkgutil ne soit pas listé dans site_packages_unused de setup.py.

  • Résolution des dépendances non trouvées
    Yves a écrit:En dézippant Pyromaths.app/Contents/Resources/lib/python2.7/site-packages.zip, il y a bien un dossier pyromaths/ex mais sans les exercices (et encore moins les vignettes), uniquement le fichier __init__.pyc. Le dossier classes est également manquant et le dossier outils est incomplet.
    djinn a écrit:Je pense que c'est modulegraph qui fait des siennes: comme il n'y a plus de dépendance statique à ces packages/modules dans le code, modulegraph les omet. Et comme py2app ne respecte pas non plus Manifest.in, il va falloir le forcer à les intégrer… :(
    Le dossier pyromaths est inclus avec un hack dans setup.py. Il est copié à côté de l'archive Pyromaths.app/Contents/Resources/lib/python2.7/site-packages.zip. Dans le dossier pyromaths, on trouve des fichiers pyc d'où le nettoyage supplémentaire. Tout ça n'est pas très satisfaisant mais ça fonctionne:
    # hack to add dependencies that cannot be found
    os.system("cp -r src/pyromaths dist/Pyromaths.app/Contents/Resources/lib/python2.7")
    os.chdir("dist/Pyromaths.app/Contents/Resources/lib/python2.7/pyromaths/")
    os.system("rm -r *.pyc classes/*.pyc ex/*.pyc ex/sixiemes/*.pyc ex/cinquiemes/*.pyc ex/quatriemes/*.pyc ex/troisiemes/*.pyc ex/lycee/*.pyc ex/examples outils/*.pyc")

Ce dernier problème résolu, ou plutôt contourné, il est possible d'obtenir une application Pyromaths.app fonctionnelle sur OS X 10.6 à 10.9.

Re: API Exercice

Message de Jérôme » Jeu 14 Nov 2013, 23:33

J'ai effectué une légère modification du code. Les niveaux sont nommés 6.sixièmes, 5.cinquièmes, ... Les exercices et leur niveau sont triés par niveau en ordre décroissant dans interface.py puis je supprime les 2 premiers caractères du niveau pour l'affichage dans l'interface.

Re: API Exercice

Message de Jérôme » Mar 12 Nov 2013, 00:09

Bonjour,
j'ai passé du temps sur la classe Fractions de Pyromaths et sa documentation. Je suis arrivé à un résultat qui me satisfait davantage et qui permettra de supprimer outils.Fractions.
J'en ai profité pour regarder la branche exapi. C'est chouette dans l'idée. Par contre, les menus apparaissent dans l'ordre alphabétique, ce qui n'est pas le plus sympa pour les onglets. As-tu des idées pour améliorer cela ?
À bientôt

Re: API Exercice

Message de djinn » Sam 08 Juin 2013, 11:28

fabienm a écrit:- Mis à part tex_statement, moodle_statement(), odt_statement() il y aura sûrement différentes sorties tex... Y'a celle de base, y'a la mienne, et y'en a encore un autre qui fait du beamer :)
…Et j'utilise également la mienne. :)
Mon objectif c'est de rendre pyromaths suffisamment flexible pour qu'on puisse "pluguer" nos modifs personnelles sur un core commun, sans avoir à le hacker en profondeur. Qu'on puisse utiliser le core de pyromaths comme une librairie.
Aujourd'hui, dès qu'on veut personnaliser pyromaths on s'éloigne très vite du code de la branche principale, on s'isole. Il devient rapidement lourd d'intégrer dans un branche des améliorations faites dans l'autre. J'imagine qu'il y a plein de code intéressant qui dort dans des forks isolés, qui ne seront probablement jamais ré-intégrés à pyromaths. Pour éviter ça, il nous faut une base commune qui soit prévue pour permettre ces extensions.

On a vraiment besoin que tous ceux qui bidouillent leur version de pyromaths viennent mettre leur grain de sel dans cette discussion et s'assurer que leurs modifs seront supportées gracieusement par cette API, avant qu'on ne la finalise. :)

fabienm a écrit:- Je trouve un peu dommage que les menus soient créés statiquement dans le code, j'ai toujours ressenti le besoin de réorganiser ça. Quand je regarde les différents forks, officiels ou officieux, j'ai l'impression qu'on a chacun nos préférences à ce sujet, et que une fois tout cela bien clean chacun ira dans son coin modifier la valeur de level dans chaque exo... Est-ce qu'on pourrait pas s'arranger pour que l'orga des menus puisse être géré de manière "exterieure" au code ?
L'objectif pour la couche de présentation à venir c'est bien de pouvoir présenter les exos comme on veut. :)
En l'occurrence, l'objectif c'est même de bien séparer le core et l'UI, de sorte qu'il soit facile d'ajouter d'autres UI. Il en existe déjà deux: Qt et django, moodle en est une troisième, personnellement j'utilise la ligne de commande, etc.
Le core met à disposition de l'UI: la base d'exercices et la génération de pdf. L'UI peut ensuite en faire ce qu'elle veut.

Techniquement, la découverte automatique des exercices n'empêche pas de s'y référer plus ou moins directement (statiquement) dans une UI -- quitte à les importer depuis la base d'exercices découverts au lieu d'utiliser import. Bien entendu, pour pouvoir décider arbitrairement de la présentation d'un exercice, encore faut-il savoir qu'il existe: les exercices créés après la dernière mise à jour d'une telle UI devront donc être traités différemment (ignorés, relégués dans un onglet spécial…). C'est la seule différence notable que je vois avec l'ancienne API.

Re: API Exercice

Message de fabienm » Ven 07 Juin 2013, 22:21

Ca m'intéresse aussi, je peux fondre ma bidouille perso dans cette nouvelle archi qui me parait bien réfléchie :)

Je me permet deux remarques :
- Mis à part tex_statement, moodle_statement(), odt_statement() il y aura sûrement différentes sorties tex... Y'a celle de base, y'a la mienne, et y'en a encore un autre qui fait du beamer :)
- Je trouve un peu dommage que les menus soient créés statiquement dans le code, j'ai toujours ressenti le besoin de réorganiser ça. Quand je regarde les différents forks, officiels ou officieux, j'ai l'impression qu'on a chacun nos préférences à ce sujet, et que une fois tout cela bien clean chacun ira dans son coin modifier la valeur de level dans chaque exo... Est-ce qu'on pourrait pas s'arranger pour que l'orga des menus puisse être géré de manière "exterieure" au code ?

J'avoue que sur le tas j'ai pas d'idées, autant avant c'était faisable, mais ça me parait assez incompatible avec la recherche dynamique d'exo, du moins "proprement".

Re: API Exercice

Message de djinn » Jeu 06 Juin 2013, 10:46

Merci pour vos encouragements. :)
Il y a du progrès, mais ça ne sent pas encore l'API mature, à mon avis. Ça a encore besoin de critique extérieure et de temps pour maturer… Quand vous aurez plus de temps pour vous pencher là-dessus, n'hésitez pas à me faire part de vos remarques et suggestions.

Arnaud a écrit:djinn, je lis en diagonale tes améliorations du code, mais j'avoue ne pas pouvoir tout regarder en détail pour le moment.
D'ici quelques semaines probablement ;)
Je vais moi-même partir en vacances d'ici une à deux semaines. On devrait se croiser. ;)
Ça serait bien que d'ici là on ait une API satisfaisante, que tu puisses t'attaquer en toute sérénité à la réorganisation des outils si tu en as toujours l'intention.
J'ai laissé sciemment cette partie de côté -- quoiqu'elle s'invite parfois d'elle-même dans le débat. Par exemple, en isolant les exercices du reste du code, on réalise qu'il y a deux types d'outils: les outils pour exercices et les outils pour l'application pyromaths elle-même (comme System.py). Ils mériteraient d'être séparés, pour plus de clarté; Voire, de se rapprocher des exercices qu'ils cherchent à servir?
Personnellement, je n'utilise aucun de ces outils dans mes exercices, parce que je ne les connais pas. :?
La documentation que prépare Jérôme aidera certainement. Mais peut-être qu'à un moment il faudra aussi songer à les organiser en une arborescence de domaines (comme je le suggère pour les exercices). Voire, à intégrer chaque outil au package d'exercices traitant de ce domaine?

Grâce à son usage des classes, le nouveau format d'exercice ouvre la possibilité d'une hiérarchie d'exercices: un nouvel exercice peut étendre un exercice existant, héritant de sa logique et remplaçant tex_*() pour produire son propre énoncé/correction.
Ça peut également être un moyen d'hériter d'outils, ou du moins de référence d'outils. Par exemple:
from pyromaths import ex
from pyromaths.outils.decimaux import decimaux

class ExerciceArithmetique(ex.TexExercise):

def decimaux(self, nb, mathenv = 0):
return decimaux(nb, mathsenv)

def tex_statement(self):
# utilise self.decimaux()
return ['\\exercice', u"Énoncé d'arithmétique", ... ]

...

class AutreExerciceArithmetique(ExerciceArithmetique):

def tex_statement(self):
# utilise self.decimaux()
return ['\\exercice', u"Autre énoncé d'arithmétique", ... ]

...

djinn a écrit:Au démarrage de l'application, Values appelle ex.load(), qui scanne les packages d'exercices contenus dans pyromaths.ex et en extrait les TexExercices.
ex.load() peut également être appelée avec un argument: un dossier d'exercices à scanner et référencer (en plus de pyromaths.ex). On peut donc décider que certains dossiers standards (comme /usr/share/.../pyromaths/ex et ~/.config/pyromaths/ex seront scannés au démarrage, de sorte qu'il devient possible de créer et tester un nouvel exercice sans installer les sources complètes de pyromaths. :)
L'idée étant de rendre la création d'exercices (techniquement) accessible à tous les utilisateurs...

Re: API Exercice

Message de Arnaud » Mer 05 Juin 2013, 21:39

djinn, je lis en diagonale tes améliorations du code, mais j'avoue ne pas pouvoir tout regarder en détail pour le moment.
D'ici quelques semaines probablement ;)

Re: API Exercice

Message de Yves » Mer 05 Juin 2013, 21:02

Bravo pour ces avancées ! :)

Re: API Exercice

Message de Jérôme » Mer 05 Juin 2013, 19:52

Premier commentaire : impressionnant ! :o
je crois que ça va me plaire... :)

Re: API Exercice

Message de djinn » Mer 05 Juin 2013, 19:40

Voici une première proposition d'API pour les exercices! :)


API Exercice

Le code est disponible dans la branche exapi. Il contient un exemple: sixieme/arrondi.py a été traduit au nouveau format d'exercice.

Dans ce nouveau format, un exercice n'est plus une fonction retournant un tuple (énoncé, correction), c'est une classe présentant deux méthodes:
  • tex_statement(): renvoit l'énoncé (au format TeX)
  • tex_answer(): renvoit la correction (au format TeX)
Cette classe présente également deux attributs:
  • description: la description de l'exercice (pour affichage dans l'UI, notamment)
  • level: le niveau académique auquel cet exercice est enseigné

Hello World!

Comme un exemple vaut mieux qu'un long discours, voici le sempiternel hello world!:
from pyromaths import ex

class HelloWorld(ex.TexExercise):

description = u'HelloWorld example exercise'
level = u'Example'

def tex_statement(self):
return ['\\exercice', 'Hello, world!']

def tex_answer(self):
return ['\\exercice*', 'Hello again, world!']
Il suffit de mettre ce bout de code dans un package d'exercice quelconque et il apparaîtra au prochain lancement de pyromaths, sous le nouvel onglet 'Example' (level), en tant que 'HelloWorld example exercise' (description). Aucun référencement statique n'est nécessaire.

Modules et packages d'exercices

Il est possible de mettre ce code dans un module d'exercice existant ou dans son propre module python (recommandé).

De même, on peut mettre un module d'exercice dans un package d'exercices existant ou dans un nouveau package: tout package python situé dans pyromaths.ex sera scanné au démarrage pour découvrir d'éventuels exercices.
On peut également créer un nouveau package dans un package existant: le scan est récursif de manière à encourager une organisation arborescente des packages, plus à même de supporter un grand nombre d'exercices à l'avenir.

Interface graphique

Dans l'interface utilisateur, les exercices ayant le même level sont rassemblés dans le même onglet. Créer un onglet revient simplement à définir un nouveau level dans un exercice.
De même, on peut déplacer l'exercice HelloWorld dans l'onglet 'Lycée' en changeant cette ligne dans le code ci-dessus:
level       = u'Lycée'
Désormais orphelin, l'onglet 'Example' disparaît.
Enfin, on peut également afficher cet exercice dans plusieurs onglets:
level       = [u'Lycée', u'Example']
Il est donc possible de déplacer un module d'exercice dans un autre package sans altérer son affichage dans l'interface graphique: il est très facile de réorganiser les exercices.

On peut définir un level par défaut au niveau du module et au niveau du package, qui seront utilisés (dans cet ordre) en cas d'absence du level d'exercice.

Rétro-compatibilité

Enfin il faut noter que les exercices à l'ancien format sont automatiquement encapsulés dans leur propre classe, sous-classe de TexExercise, de façon à être compatibles avec le nouveau format.
La traduction manuelle des anciens exercices au nouveau format peut donc se faire progressivement.

Impact sur le reste du code

Au démarrage de l'application, Values appelle ex.load(), qui scanne les packages d'exercices contenus dans pyromaths.ex et en extrait les TexExercices.
Ce faisant, ex.load() met à jour l'index par niveau ex.levels, un dictionnaire associant chaque niveau à une liste (de classes) d'exercices correspondants. C'est cet index que Values utilise ensuite pour construire LESFICHES.

Ces classes d'exercice sont (ou seront) utilisées aussi directement que possible dans le reste du code.
Par exemple, dans l'interface graphique, on associe directement au widget d'exercice la classe d'exercice correspondante. Pour générer une série d'exercice, il suffit de créer une instance de chaque classe d'exercice sélectionnée, et d'en passer la liste à creation(), qui appellera leurs méthodes tex_statement() et/ou tex_answer(). Plus besoin d'utiliser des indices de LESFICHES pour se référer à un exercice.

Classe et instances

Il est important de comprendre que ce sont des classes qui sont manipulées dans le code, jusqu'à la création de la liste d'exercices désirée par l'utilisateur. Par exemple, ex.levels ne référence que des classes d'exercices.
Une classe d'exercice est utilisée pour créer des instances (objets) de cet exercice. Par exemple, si l'utilisateur commande plusieurs fois le même exercice, la classe correspondante sera utilisée pour créer plusieurs instances de cet exercice -- chaque instance contenant des valeurs (aléatoires) différentes.
Ce sont ces différentes instances qui seront interrogées par creation() pour produire le code TeX final (méthodes tex_*()).

Précisions sur le nouveau format

Les productions de l'énoncé et de la correction étant découplées (respectivement dans tex_statement() et tex_answer()), il faut que ces méthodes partagent quelques variables, comme les valeurs tirées au hasard. On utilise pour cela une
propriété de l'instance (self).
Un TexExercise ne peut pas savoir quelle fonction tex_*() sera appelée en premier ou en second, ou pas du tout (ou plusieurs fois). Pour cette raison notamment, les valeurs partagées doivent être définies une fois pour toutes dans le constructeur (__init__()).

Voici en guise d'exemple un HelloWorld avec partage d'une valeur aléatoire:
import random
from pyromaths import ex

class RandomHelloWorld(ex.TexExercise):

description = u'RandomHelloWorld example exercise'
level = u'Example'

def __init__(self):
self.times = random.randint(2, 10)

def tex_statement(self):
return ['\\exercice', '%u times hello, world!' % self.times]

def tex_answer(self):
return ['\\exercice*', '%u times goodbye, world!' % self.times]
D'un point de vue général, il faut voir les méthodes tex_*() commes de simples "afficheurs TeX" de l'exercice. Demain, l'interface pourrait s'enrichir d'autres "afficheurs": moodle_statement(), odt_statement():)
En conséquence, toute la logique de l'exercice (tirage des paramètres aléatoires, calcul des solutions) doit se trouver dans __init__().

Extensibilité: Actimaths, Moodle, LibreOffice…

On peut enrichir l'interface et étendre les formats produits en définissant une nouvelle sous-classe de la classe mère: Exercise. Par exemple, pour produire un document au format LibreOffice:
class OdtExercise(Exercise):

def odt_statement(self):
return "Énoncé au format ODT"

def odt_answer(self):
return "Correction au format ODT"

Enfin, pour rendre notre HelloWorld ci-dessus compatible avec ce nouveau format:
from pyromaths import ex

class HelloWorld(ex.TexExercise, ex.OdtExercise):

description = u'HelloWorld example exercise'
level = u'Example'

def tex_statement(self):
return ['\\exercice', 'Hello, world!']

def tex_answer(self):
return ['\\exercice*', 'Hello again, world!']

def odt_statement(self):
return "Hello, ODT World!"

def odt_answer(self):
return 'Hello again, ODT World!'



Dans l'attente de vos commentaires… :)

Haut

cron