Metaprogrammation Analyse de code

a marqué ce sujet comme résolu.

Bonjour à tous,

Je travaille depuis plusieurs jours sur un projet lié à cadquery (j’ai créer un billet à ce sujet Billet CadQuery) et je sollicite votre aide.

Cadquery est une librairie python de conception de modèle 3D. Un problème majeur c’est que écrire du code sans visualiser ce qu’on créer ce n’est pas pratique, je développe donc une application ajoutant des fonctionnalités graphique au code que l’on écrit pour générer un modèle.

Dans CadQuery ce que l’on peut appeler une pièce est représenté par la classe Workplane, toutes les méthodes de cette classe sont ce que j’appelle des opérations. Et dans CadQuery on peut chainer les opérations car chaque opération renvoie un objet Workplane donc en gros chaque appel successif à une méthode prolonge l’arbre d’opérations.

On a en gros pour créer un pavé quelque chose comme ça : mon_pavé = cadquery.Workplane().rect(1,1).extrude(10)

Qu’on peut venir modifier plus loin si l’on veut : mon_pavé = mon_pavé.circle(0.5).cutThruAll()

Dans mon application l’utilisateur écris son code dans une console (une qtconsole pour être précis) et le code est exécuté avec exec

Moi j’ai besoin de récupérer plusieurs informations et ma question porte sur comment faire, malgré y avoir pas mal réfléchi je ne suis pas convaincu par mes solutions.

J’ai besoin lors d’une input utilisateur de :

  • Récupérer les noms des méthodes appelées dans l’ordre avec les paramètres passés (stocké dans un dict), c’est ce que j’appelle la liste des opérations
  • Identifier la pièce à laquelle est associée la liste des opérations (en gros si j’ai plusieurs instances de la classe Workplane je dois savoir à laquelle correspond la liste de mes opérations) (Je veux récupérer le nom de la variable)

Pour faire ça j’ai deux pistes, (j’ai surtout creusé la première) :

  1. Parser l’input de l’utilisateur en AST et analyser l’AST pour créer ma liste d’opérations et trouver à qu’elle instance de Workplane elle correspond. Je pense que ça peut fonctionner mais c’est très compliqué et on doit écrire beaucoup de code pour gérer tous les cas "corner cases". C’est particulièrement compliqué dans certains cas typiquement :

part = cq.Workplane().box(1,1,1).union(cq.Workplane().sphere(1.3))

  1. "monkey patcher" les méthodes de la classe Workplane pour qu’elles renvoient les infos voulus lorsqu’elles sont appelées. J’ai deux principaux soucis avec cette méthode
  • Certaines méthodes de Workplane appellent d’autres méthodes en interne et je ne voudrais pas récupérer d’infos sur ces appels internes.
  • Je ne sais pas comment retrouver facilement à quel instance (et donc variable) l’appel de la méthode en question est rattaché étant donné que la méthode n’a connaissance que d’elle même.

Voila !

C’est un assez gros morceau, j’ai essayé de faire assez synthétique, je peux donner plus de précision si besoin. Actuellement j’ai pas mal avancé dans l’implémentation du point 1 mais plus j’essais de prendre en compte de cas de figures plus mon code se complique et moins c’est facile à utiliser.

En revanche j’ai le sentiment qu’il est possible d’arriver à une solution élégante avec la deuxième méthode mais je suis bloqué par les points cités.

Finalement, si vous avez d’autres idées, des pistes ou même de la documentation sur ce genre de truc je suis preneur. Je ne suis pas développeur et il n’y a pas autant d’exemples sur le net de comment parser un AST que d’inverser une liste …

Merci de m’avoir lu !

Salut,

Je ne suis pas sûr de saisir ton problème dans sa globalité, mais par rapport au point 1, c’est du code Python que tu cherches à faire entrer par l’utilisateur ? Est-ce que tu as besoin de quelconques règles de sécurité pour éviter certaines entrées ou est-ce que ça ne dérange pas que ce soit open-bar ? (car la sécurité sur ce point est difficile à réaliser en Python).

Par rapport au point 2, quel est l’intérêt des patchs ? Si les objets n’ont pas certaines méthodes qui seraient utiles, pourquoi ne pas créer tes propres types avec ces méthodes (pour wrapper les Workplace) et les proposer à l’utilisateur ?

Salut entwanne,

  1. Non je n’ai pas vraiment besoin de régles de sécurité. L’idée générale est que l’utilsateur dispose d’une console python et que lorsqu’il utilise certaine méthodes / fonctions l’UI autour de cette console y réagisse et se remplisse de données.

Comme je le disais dans le premier post, j’ai besoin de la liste d’opérations (donc la liste d’appels de méthodes de Workplane sur un même objet) Pour par exemple remplir une TreeView avec le nom de la méthode, les valeurs des arguments passés à la méthode, etc.

  1. L’intérêt des patchs c’est de pouvoir récupérer des infos à l’exécution tout en étant transparent pour l’utilisateur. J’ai mis en pause la méthode via AST et pas mal avancé sur la méthode patch. J’ai réussi à avoir quelque chose de relativement fonctionnel, pas exempt de défaut cela dit.

Je pourrais effectivement wrapper complètement la classe Workplane, ça pourrait me permettre de directement envoyer des signaux Qt plutôt que faire mes bidouilles. Je garde cette idée en tête merci !

Je sais bien que ma demande est assez particulière, de plus CadQuery est aussi une librairie qui est en soit assez particulière à utiliser. Pour mieux comprendre comment ça marche vous pouvez essayer CadQuery dans le navigateur via : https://cadhub.xyz/draft/cadquery

+0 -0
Connectez-vous pour pouvoir poster un message.
Connexion

Pas encore membre ?

Créez un compte en une minute pour profiter pleinement de toutes les fonctionnalités de Zeste de Savoir. Ici, tout est gratuit et sans publicité.
Créer un compte