{"id":4418,"date":"2025-01-14T18:13:11","date_gmt":"2025-01-14T17:13:11","guid":{"rendered":"https:\/\/spgoo.org\/?page_id=4418"},"modified":"2025-01-18T16:26:10","modified_gmt":"2025-01-18T15:26:10","slug":"parsing-python","status":"publish","type":"page","link":"https:\/\/spgoo.org\/?page_id=4418","title":{"rendered":"Parsing Python"},"content":{"rendered":"\n<h2 class=\"wp-block-heading has-text-align-center\">G\u00e9nie logiciel <\/h2>\n\n\n\n<link rel='stylesheet' id='4485-css'  href='https:\/\/spgoo.org\/wp-content\/uploads\/winp-css-js\/4485.css?ver=1747039442' type='text\/css' media='all' \/>\n\n\n\n<p>Dans  le cadre de diff\u00e9rents projets, on est amen\u00e9 \u00e0 r\u00e9cup\u00e9rer diff\u00e9rents codes provenant de diff\u00e9rents concepteurs d\u00e9pos\u00e9s sur github. Dans une certaine mesure, ces codes dispose d&#8217;une documentation limit\u00e9e et peu d\u00e9taill\u00e9e mais qui permet rapidement de prendre en mains ces codes pour une ex\u00e9cution et obtenir le r\u00e9sultat souhait\u00e9. Maintenant dans un contexte qui le permet o\u00f9 l&#8217;on souhaite faire \u00e9voluer le code pour rajouter ou modifier des instructions afin de l&#8217;adapter ou de le mettre \u00e0 jour, il est n\u00e9cessaire de se &#8220;plonger&#8221; de fa\u00e7on plus intense dans la compr\u00e9hension des \u00e9l\u00e9ments et d&#8217;\u00e9viter de le d\u00e9grader. <\/p>\n\n\n\n<p>Dans de dernier cas, plusieurs solutions ont \u00e9t\u00e9 explor\u00e9es comme <span class='tooltipsall tooltipsincontent classtoolTips4'>Sphinx<\/span>, reverse ainsi que <span class='tooltipsall tooltipsincontent classtoolTips0'>Visual Paradigm<\/span> mais rien de concluant et d&#8217;adapter pour nos objectifs. En effet, afin d&#8217;optimiser les d\u00e9veloppements et la r\u00e9utilisation, il nous semble opportun de constituer une biblioth\u00e8que de composants logiciels. Cette biblioth\u00e8que que l&#8217;on se propose de constituer permettra d&#8217;identifier \u00e0 partir de requ\u00eates de haut niveau les blocs instructions int\u00e9ressants et correspondants \u00e0 son besoin. Pour ce faire, il est important \u00e0 partir de fichiers sources d&#8217;un projet d&#8217;\u00eatre capable de reconstituer diff\u00e9rents sch\u00e9mas d&#8217;aide et d&#8217;analyse.<\/p>\n\n\n\n<p>La solution que l&#8217;on souhaite mettre en oeuvre nomm\u00e9e <strong>ParsPy<\/strong> est de d\u00e9velopper un parser pour effectuer ces analyses et ainsi constituer notre base de connaissance. Cette solution va s&#8217;appuyer sur deux \u00e9l\u00e9ments de fondations une base de donn\u00e9es <span class='tooltipsall tooltipsincontent classtoolTips3'>MongoDB<\/span> et une base de donn\u00e9es de type graphe <span class='tooltipsall tooltip_post_id_custom_f5113f3a2be5ab3f866678e00b20144a classtoolTipsCustomShortCode' style='border-bottom:2px dotted #888;'><span class='tooltipsall tooltipsincontent classtoolTips5'>Neo4J<\/span><\/span><script type=\"text\/javascript\">jQuery(\"document\").ready(function(){});<\/script> .<\/p>\n\n\n\n<p class=\"has-pale-cyan-blue-color has-text-color has-link-color has-medium-font-size wp-elements-93866aa87fbe71f3a1f656d3b38d0af0\">Objectifs de ce parser : <\/p>\n\n\n\n<p>En input : un ou plusieurs fichiers python <\/p>\n\n\n\n<p>Constituer une documentation de l&#8217;ensemble de ces fichiers en deux approches compl\u00e9mentaires : <\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Premi\u00e8re approche : recenser dans tous les fichiers d&#8217;un projet les informations de d\u00e9pendances, les structures internes de donn\u00e9es de type classe et les fonctions d\u00e9finies. Cette ensemble d&#8217;informations alimentera la base <span class='tooltipsall tooltipsincontent classtoolTips3'>MongoDB<\/span> et permettra d&#8217;interroger ce contenu avec des crit\u00e8res pouss\u00e9s. Dans cette partie on pourra pousser la v\u00e9rification et le contr\u00f4le de la bonne manipulation des variables. R\u00e9cup\u00e9rer la documentation \u00e0 travers les commentaires.<\/li>\n\n\n\n<li>Deuxi\u00e8me approche : pour l&#8217;ensemble du projet on souhaite reconstituer l&#8217;arbre des d\u00e9pendances et l&#8217;arbre d&#8217;appel des fonctions selon un point d&#8217;entr\u00e9e. Cette arbre doit permettre \u00e0 l&#8217;utilisateur de visualiser et de naviguer sur l\u2019encha\u00eenement pour l&#8217;aider dans sa compr\u00e9hension du fonctionnement de l&#8217;application.<\/li>\n<\/ul>\n\n\n\n<p class=\"has-pale-cyan-blue-color has-text-color has-link-color has-medium-font-size wp-elements-06fb3b34c789c3785295890d57d24d01\">Premi\u00e8re approche : le parsing des sources python <\/p>\n\n\n\n<p>Dans l&#8217;analyse du contenu des sources on va proc\u00e9der par bloc :<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>les d\u00e9pendances<\/li>\n\n\n\n<li>les classes<\/li>\n\n\n\n<li>les variables<\/li>\n\n\n\n<li>les fonctions <\/li>\n<\/ul>\n\n\n\n<p>Pour chaque bloc on va d\u00e9crire le formalisme utilis\u00e9, l&#8217;information que l&#8217;on veut conserver et compl\u00e9ter, l&#8217;analyse que l&#8217;on peut en faire et les repr\u00e9sentations qui en d\u00e9coulent.<\/p>\n\n\n\n<p class=\"has-pale-pink-color has-text-color has-link-color has-medium-font-size wp-elements-84a3a6c9d04e3e0824050dc943b14e26\">Les d\u00e9pendances : <strong>mots cl\u00e9s (import as from<\/strong>)<\/p>\n\n\n\n<p>Dans cette premi\u00e8re partie plusieurs formalismes sont utilis\u00e9s pour importer des librairies dans un contexte d&#8217;ex\u00e9cution python. Les mots cl\u00e9s utilis\u00e9s dans ce contexte sont :<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>import<\/li>\n\n\n\n<li>import &#8230;. as <\/li>\n\n\n\n<li>from <\/li>\n<\/ul>\n\n\n\n<p>La description des librairies \u00e0 importer peut \u00eatre sur une ou plusieurs lignes et avec s\u00e9parateur , pour en indiquer plusieurs. <\/p>\n\n\n\n<p>Exemples :<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>import time\nfrom collections import defaultdict\nfrom typing import TYPE_CHECKING\nfrom tqdm import tqdm\nfrom aizynthfinder.analysis import (\n     RouteCollection,\n     RouteSelectionArguments,\n     TreeAnalysis,\n)\nfrom aizynthfinder.chem import FixedRetroReaction, Molecule, TreeMolecule\nfrom aizynthfinder.context.config import Configuration\n<\/code><\/pre>\n\n\n\n<p>Plusieurs aspects \u00e0 traiter dans cette premi\u00e8re partie, les d\u00e9pendances vers des librairies &#8220;packag\u00e9es&#8221; d&#8217;une version donn\u00e9e que l&#8217;on pourra r\u00e9cup\u00e9rer avec sa version \u00e0 partir de fichier requirements.txt ou autres. Des librairies du projet lui m\u00eame avec en pr\u00e9fixes le nom aizynthfinder et l&#8217;indication de sa localisation. De plus dans la partie import on pourra distinguer les fonctions des classes \u00e0 importer et utiliser dans le code. Dans cette partie, on peut \u00e9galement rencontrer des instructions de type conditionnelle de type TYPE_CHECKING avec des instructions d&#8217;importation  associ\u00e9es. On a pris le pli de ne pas en tenir compte dans notre contexte.<\/p>\n\n\n\n<p>L&#8217;arborescence avec le point en d\u00e9limiteur pose des probl\u00e8mes dans le contexte <span class='tooltipsall tooltipsincontent classtoolTips3'>MongoDB<\/span>. En effet, le caract\u00e8re . est interpr\u00e9t\u00e9 lors de l&#8217;insertion dans la base \u00e0 partir de l&#8217;instruction <strong>mycol.insert_one(D_struct)<\/strong>. Alors que <span class='tooltipsall tooltipsincontent classtoolTips3'>MongoDB<\/span> autorise ce caract\u00e8re pour ses cl\u00e9s. Du coup, pour r\u00e9gler ce probl\u00e8me, on remplace le . par un &#8211;<\/p>\n\n\n\n<details class=\"wp-block-details is-layout-flow wp-block-details-is-layout-flow\"><summary>\u25bcD\u00e9tail de l&#8217;interpr\u00e9tation<\/summary>\n<div class=\"wp-block-columns is-layout-flex wp-container-core-columns-is-layout-9d6595d7 wp-block-columns-is-layout-flex\">\n<div class=\"wp-block-column is-layout-flow wp-block-column-is-layout-flow\" style=\"flex-basis:50%\">\n<pre class=\"wp-block-code\"><code>from __future__ import annotations\nimport os\nimport re\nfrom dataclasses import dataclass, field\nfrom typing import TYPE_CHECKING\nimport yaml\nfrom aizynthfinder.context.policy import ExpansionPolicy, FilterPolicy\nfrom aizynthfinder.context.scoring import ScorerCollection\nfrom aizynthfinder.context.stock import Stock\nfrom aizynthfinder.utils.logging import logger\nif TYPE_CHECKING:\n     from aizynthfinder.utils.type_utils import Any, Dict, List, Optional, StrDict, Union<\/code><\/pre>\n<\/div>\n\n\n\n<div class=\"wp-block-column is-layout-flow wp-block-column-is-layout-flow\" style=\"flex-basis:50%\">\n<pre class=\"wp-block-code\"><code>\n\"dependances\" : {\n   \"import\" : &#091;\"os\",\"re\",\"yaml\"],\n   \"import_as\" : &#091;],\n   \"from\" : &#091;\n        {\"__future__\" : \"annotations\"},\n        {\"dataclasses\" : \"dataclass, field\"},\n        {\"typing\" : \"TYPE_CHECKING\"},\n        {\"<strong><em>aizynthfinder-context-policy<\/em><\/strong>\" : \"ExpansionPolicy, FilterPolicy\"},\n        {\"<strong><em>aizynthfinder-context-scoring<\/em><\/strong>\" : \"ScorerCollection\"},\n        {\"<strong><em>aizynthfinder-context-stock<\/em><\/strong>\" : \"Stock\"},\n        {\"<strong><em>aizynthfinder-utils-logging<\/em><\/strong>\" : \"logger\"},\n        {\"<strong><em>aizynthfinder-utils-type_utils<\/em><\/strong>\" : \"Any, Dict, List, Optional, StrDict,Union\"}\n    ],\n    \"conditionnel\" : &#091;]\n},<\/code><\/pre>\n<\/div>\n<\/div>\n<\/details>\n\n\n\n<p class=\"has-pale-pink-color has-text-color has-link-color has-medium-font-size wp-elements-722c7524113c2d4818f69a743df4a9fd\">Les classes : <strong>mot cl\u00e9 (class<\/strong>)<\/p>\n\n\n\n<p>Dans le cadre de l&#8217;utilisation de classes on peut utiliser deux fa\u00e7ons de les d\u00e9crire  avec la directive @dataclass (avec comme pr\u00e9alable l&#8217;importation de dataclass,et de field) ou utiliser la mani\u00e8re classique on pr\u00e9fixant le nom des variables de self et les m\u00e9thodes de classes __init__ &#8230;. <\/p>\n\n\n\n<p>Le parser doit pouvoir discriminer les deux formes et reconstituer l&#8217;ensemble des attributs d&#8217;une classe. On va prendre d\u00e9crire le traitement \u00e0 faire dans ces deux cas: <\/p>\n\n\n\n<details class=\"wp-block-details is-layout-flow wp-block-details-is-layout-flow\"><summary>\u25bc Exemple de mise en oeuvre : sans directive<\/summary>\n<div class=\"wp-block-columns is-layout-flex wp-container-core-columns-is-layout-9d6595d7 wp-block-columns-is-layout-flex\">\n<div class=\"wp-block-column is-layout-flow wp-block-column-is-layout-flow\" style=\"flex-basis:50%\">\n<pre class=\"wp-block-code\"><code>class AiZynthFinder:\n   def __init__(self, configfile: Optional&#091;str] = None, configdict: Optional&#091;StrDict] = None ) -&gt; None:\n      self.<strong>_logger<\/strong> = logger()\n      if configfile:\n          self.<strong>config<\/strong> = Configuration.from_file(configfile)\n      elif configdict:\n          self.config = Configuration.from_dict(configdict)\n      else:\n          self.config = Configuration()\n      self.<strong>expansion_policy<\/strong> = self.config.expansion_policy\n      self.<strong>filter_policy<\/strong> = self.config.filter_policy\n      self.<strong>stock<\/strong> = self.config.stock\n      self.<strong>scorers<\/strong> = self.config.scorers\n      self.<strong>tree<\/strong>: Optional&#091;Union&#091;MctsSearchTree, AndOrSearchTreeBase]] = None\n      self.<strong>_target_mol<\/strong>: Optional&#091;Molecule] = None\n      self.<strong>search_stats<\/strong>: StrDict = dict()\n      self.<strong>routes<\/strong> = RouteCollection(&#091;])\n      self.<strong>analysis<\/strong>: Optional&#091;TreeAnalysis] = None\n      self.<strong>_num_objectives<\/strong> = len(\n          self.config.search.algorithm_config.get(\"search_rewards\", &#091;])\n      )<\/code><\/pre>\n<\/div>\n\n\n\n<div class=\"wp-block-column is-layout-flow wp-block-column-is-layout-flow\" style=\"flex-basis:50%\">\n<pre class=\"wp-block-code\"><code>\"classes\" : {\n     \"AiZynthFinder\" : {\n         \"attributs\" : {\n            \"_logger\" : {\"type\" : \"\"},\n            \"config\" : {\"type\" : \"\"},\n            \"expansion_policy\" : {\"type\" : \"\"},\n            \"filter_policy\" : {\"type\" : \"\"},\n            \"stock\" : {\"type\" : \"\"},\n            \"scorers\" : {\"type\" : \"\"},\n            \"routes\" : {\"type\" : \"\"},\n            \"_num_objectives\" : {\"type\" : \"\"},\n            \"target_mol\" : {\"type\" : \"\"},\n            \"tree\" : {\"type\" : \"\"},\n            \"_target_mol\" : {\"type\" : \"\"},\n            \"analysis\" : {\"type\" : \"\"},\n            \"search_stats\" : {\"type\" : \"\"}\n},<\/code><\/pre>\n<\/div>\n<\/div>\n<\/details>\n\n\n\n<details class=\"wp-block-details is-layout-flow wp-block-details-is-layout-flow\"><summary>\u25bc Exemple de mise en oeuvre : avec directive<\/summary>\n<div class=\"wp-block-columns is-layout-flex wp-container-core-columns-is-layout-9d6595d7 wp-block-columns-is-layout-flex\">\n<div class=\"wp-block-column is-layout-flow wp-block-column-is-layout-flow\" style=\"flex-basis:50%\">\n<pre class=\"wp-block-code\"><code>@dataclass\nclass _PostprocessingConfiguration:\n     min_routes: int = 5\n     max_routes: int = 25\n     all_routes: bool = False\n     route_distance_model: Optional&#091;str] = None\n     route_scorers: List&#091;str] = field(default_factory=lambda: &#091;])\n     scorer_weights: Optional&#091;List&#091;float]] = field(default_factory=lambda: None)<\/code><\/pre>\n<\/div>\n\n\n\n<div class=\"wp-block-column is-layout-flow wp-block-column-is-layout-flow\" style=\"flex-basis:50%\">\n<pre class=\"wp-block-code\"><code>\"classes\" : {\n   \"_PostprocessingConfiguration\" : {\n         \"attributs\" : {\n              \"min_routes\" : {\"type\" : \" int\"},\n              \"max_routes\" : {\"type\" : \" int\"},\n              \"all_routes\" : {\"type\" : \" bool\"},\n              \"route_distance_model\" : {\"type\" : \" Optional&#091;str]\"},\n              \"route_scorers\" : {\"type\" : \" List&#091;str]\"},\n              \"scorer_weights\" : {\"type\" : \" Optional&#091;List&#091;float]]\"}\n          },\n          \"def\" : {}\n    },<\/code><\/pre>\n<\/div>\n<\/div>\n<\/details>\n\n\n\n<p class=\"has-pale-pink-color has-text-color has-link-color has-medium-font-size wp-elements-3d136bcacef0f654e1ae5d8b5d0bd0ed\">Les variables :<\/p>\n\n\n\n<p>Recensement de l&#8217;ensemble des variables utilis\u00e9es par bloc d&#8217;instructions.<\/p>\n\n\n\n<p class=\"has-pale-pink-color has-text-color has-link-color has-medium-font-size wp-elements-bbb07ff4c48d7f415d13bb8de96f180d\">Les fonctions : <strong>mot cl\u00e9 (def<\/strong>)<\/p>\n\n\n\n<p>La description de la fonction peut se trouver dans le contexte d&#8217;une classe ou dans le contexte globale de votre source. cela signifie qu&#8217;il faut conserver le contexte au pr\u00e9alable et identifier lors de changement de tabulation si on sort du contexte d&#8217;une d\u00e9claration de classe. Dans un premier temps on va r\u00e9f\u00e9rencer la signature de la fonction et l&#8217;inventorier au bon endroit (dans le bon contexte). <\/p>\n\n\n\n<details class=\"wp-block-details is-layout-flow wp-block-details-is-layout-flow\"><summary>\u25bc Exemple de la structure compl\u00e8te<\/summary>\n<pre class=\"wp-block-code\"><code>{\n\"_id\" : ObjectId(\"6787c2017e9b73bd7d232b5c\"),\n\"description\" : \"\",\n\"dependances\" : {\n   \"import\" : &#091;\"os\",\"re\",\"yaml\"],\n   \"import_as\" : &#091;],\n   \"from\" : &#091;\n        {\"__future__\" : \"annotations\"},\n        {\"dataclasses\" : \"dataclass, field\"},\n        {\"typing\" : \"TYPE_CHECKING\"},\n        {\"<strong><em>aizynthfinder-context-policy<\/em><\/strong>\" : \"ExpansionPolicy, FilterPolicy\"},\n        {\"<strong><em>aizynthfinder-context-scoring<\/em><\/strong>\" : \"ScorerCollection\"},\n        {\"<strong><em>aizynthfinder-context-stock<\/em><\/strong>\" : \"Stock\"},\n        {\"<strong><em>aizynthfinder-utils-logging<\/em><\/strong>\" : \"logger\"},\n        {\"<strong><em>aizynthfinder-utils-type_utils<\/em><\/strong>\" : \"Any, Dict, List, Optional, StrDict,Union\"}\n    ],\n    \"conditionnel\" : &#091;]\n},\n\"def\" : {\n    \"_handle_bond_pair_tuples\" : {\"args\" : &#091;\"bonds: List&#091;List&#091;int]]\"],\"return\" : \"List&#091;List&#091;int]]\"}\n},\n\"comments\" : \"\",\n\"classes\" : {\n   \"_PostprocessingConfiguration\" : {\n         \"attributs\" : {\n              \"min_routes\" : {\"type\" : \" int\"},\n              \"max_routes\" : {\"type\" : \" int\"},\n              \"all_routes\" : {\"type\" : \" bool\"},\n              \"route_distance_model\" : {\"type\" : \" Optional&#091;str]\"},\n              \"route_scorers\" : {\"type\" : \" List&#091;str]\"},\n              \"scorer_weights\" : {\"type\" : \" Optional&#091;List&#091;float]]\"}\n          },\n          \"def\" : {}\n    },\n    \"_SearchConfiguration\" : {\n          \"attributs\" : {\n               \"algorithm\" : {\"type\" : \" str\"},\n               \"algorithm_config\" : {\"type\" : \" Dict&#091;str, Any]\"},\n               \"default_factor\" : {\"type\" : \"\"},\n               \"max_transforms\" : {\"type\" : \" int\"},\n               \"iteration_limit\" : {\"type\" : \" int\"},\n               \"time_limit\" : {\"type\" : \" int\"},\n               \"return_first\" : {\"type\" : \" bool\"},\n               \"exclude_target_from_stock\" : {\"type\" : \" bool\"},\n               \"break_bonds\" : {\"type\" : \" List&#091;List&#091;int]]\"},\n               \"freeze_bonds\" : {\"type\" : \" List&#091;List&#091;int]]\"},\n               \"break_bonds_operator\" : {\"type\" : \" str\"}\n           },\n           \"def\" : {}\n   },\n   \"Configuration\" : {\n           \"attributs\" : {},\n           \"def\" : {\n               \"_post_init\" : {\"args\" : &#091;\"self\"],\"return\" : \"None\"},\n               \"_eq\" : {\"args\" : &#091;\"self\",\"other: Any\"],\"return\" : \"bool\"},\n               \"from_dict\" : {\"args\" : &#091;\"cls\",\"source: StrDict\"],\"return\" : \"Configuration\",\"comments\" : \"Loads a configuration from a dictionary structure. The parameters not set in the dictionary are taken from the default values. The policies and stocks specified are directly loaded. :param source: the dictionary source :return: a Configuration object with settings from the source\"\n},\n                \"from_file\" : {\"args\" : &#091;\"cls\",\"filename: str\"],\"return\" : \"Configuration\",\"comments\" : \"Loads a configuration from a yaml file. The parameters not set in the yaml file are taken from the default values. The policies and stocks specified in the yaml file are directly loaded. The parameters in the yaml file may also contain environment variables as values. :param filename: the path to a yaml file :return: a Configuration object with settings from the yaml file :raises: ValueError: if parameter's value expects an environment variable that does not exist in the current environment\"\n                 },\n                 \"_update_from_config\" : {\"args\":&#091;\"self\",\"config: StrDict\"],\"return\" : \"None\"}\n                 },\n\"comments\" : \"Encapsulating the settings of the tree search, including the policy, the stock, the loaded scorers and various parameters.\"\n}\n}\n}<\/code><\/pre>\n\n\n\n<p><\/p>\n<\/details>\n\n\n\n<p><\/p>\n\n\n\n<p class=\"has-pale-cyan-blue-color has-text-color has-link-color has-medium-font-size wp-elements-0dc81a8c288e9a419822230dba7b3f9d\">Deuxi\u00e8me approche : \u00e9laboration des arbres de d\u00e9pendance et d&#8217;appel <\/p>\n\n\n\n<p>Dans cette partie, on va s&#8217;attacher au formalisme et aux diff\u00e9rentes repr\u00e9sentations souhait\u00e9es pour une aide \u00e0 la compr\u00e9hension. Pour ce faire, on va utiliser des instructions de <span class='tooltipsall tooltipsincontent classtoolTips5'>Neo4J<\/span> pour g\u00e9n\u00e9rer les n\u0153uds (Node) et les relations (Link) dans cette base. L&#8217;usage de MERGE va \u00eatre privil\u00e9gier car elle v\u00e9rifie avant la cr\u00e9ation de l&#8217;\u00e9l\u00e9ment si il existe d\u00e9j\u00e0 alors que l&#8217;instruction CREATE renvoie une erreur si l&#8217;on tente de cr\u00e9er d\u00e9j\u00e0 un \u00e9l\u00e9ment existant. <\/p>\n\n\n\n<p class=\"has-pale-cyan-blue-color has-text-color has-link-color has-medium-font-size wp-elements-a87c344c989326f6f6e077619e836048\">Exploration approfondie des fonctions :<\/p>\n\n\n\n<p>Quelles sont les informations \u00e0 remonter d&#8217;un bloc d&#8217;instructions contenant des fonctions et sous quelle forme compr\u00e9hensible faut-il les amener ? <\/p>\n\n\n\n<p>Si on prend un exemple pour guider le parsing :<\/p>\n\n\n\n<details class=\"wp-block-details is-layout-flow wp-block-details-is-layout-flow\"><summary>\u25bc D\u00e9tail d&#8217;une interpr\u00e9tation<\/summary>\n<div class=\"wp-block-columns is-layout-flex wp-container-core-columns-is-layout-9d6595d7 wp-block-columns-is-layout-flex\">\n<div class=\"wp-block-column is-layout-flow wp-block-column-is-layout-flow\" style=\"flex-basis:50%\">\n<pre class=\"wp-block-code\"><code>class ReactionTreeFromDict(ReactionTreeLoader):\n\"\"\"Creates a reaction tree object from a dictionary\"\"\"\n  def _load(self, tree_dict: StrDict) -&gt; None:  # type: ignore\n    if tree_dict.get(\"route_metadata\"):\n        self.tree.created_at_iteration = tree_dict&#091;\"route_metadata\"].get(\n            \"created_at_iteration\"\n        )\n    self._parse_tree_dict(tree_dict)\n\n  def _parse_tree_dict(self, tree_dict: StrDict, ncalls: int = 0) -&gt; UniqueMolecule:\n    product_node = UniqueMolecule(smiles=tree_dict&#091;\"smiles\"])\n    self._add_node(\n        product_node,\n        depth=2 * ncalls,\n        transform=ncalls,\n        hide=tree_dict.get(\"hide\", False),\n        in_stock=tree_dict&#091;\"in_stock\"],\n    )\n\n    rxn_tree_dict = tree_dict.get(\"children\", &#091;])\n    if not rxn_tree_dict:\n        return product_node\n\n    rxn_tree_dict = rxn_tree_dict&#091;0]\n    reaction_node = FixedRetroReaction(\n        product_node,\n        smiles=rxn_tree_dict&#091;\"smiles\"],\n        metadata=rxn_tree_dict.get(\"metadata\", {}),\n    )\n    self._add_node(\n        reaction_node, depth=2 * ncalls + 1, hide=rxn_tree_dict.get(\"hide\", False)\n    )\n    self.tree.graph.add_edge(product_node, reaction_node)\n\n    reactant_nodes = &#091;]\n    for reactant_tree in rxn_tree_dict.get(\"children\", &#091;]):\n        reactant_node = self._parse_tree_dict(reactant_tree, ncalls + 1)\n        self.tree.graph.add_edge(reaction_node, reactant_node)\n        reactant_nodes.append(reactant_node)\n    reaction_node.reactants = (tuple(reactant_nodes),)\n\n    return product_node<\/code><\/pre>\n<\/div>\n\n\n\n<div class=\"wp-block-column is-layout-flow wp-block-column-is-layout-flow\" style=\"flex-basis:50%\">\n<pre class=\"wp-block-code\"><code>Interpr\u00e9tation\nCLASS ReactionTreeFromDict\n   PARENT: ReactionTreeLoader\n   DOC : \"Creates a reaction .... dictionnary\"\n   DEF: _load()\n        COND:\n             AFF:  self.tree.created_at_iteration\n        CALL: self._parse_tree_dict()\n   DEF: _parse_tree_dict()\n        AFF: product_node &lt;- CALL: UniqueMolecule()\n        CALL: self.add_node()\n        AFF:  rxn_tree_dict &lt;- CALL: tree_dict.get()\n        COND: \n            RET:  product_node\n        AFF: rxn_tree_dict \n        AFF: reaction_node &lt;- CALL FixedRetroReaction()\n        CALL: self.add_node()\n        CALL: self.tree.graph.add_egde()\n        AFF: reactant_nodes\n        BOUCL_PAR: rxn_tree_dict \n           AFF: reacatant_nodes &lt;- CALL: self._parse_tree_dict()\n            CALL: self.tree.graph.add_edge()\n            CALL: reactant_nodes.append()\n        RET: product_node\n         <\/code><\/pre>\n<\/div>\n<\/div>\n<\/details>\n<script type=\"text\/javascript\"> toolTips('.classtoolTips0','<a style=\"text-decoration: none;\" href=\"https:\/\/www.visual-paradigm.com\/\"><img class=\"alignnone\" style=\"width: 100px;\" src=\"\/wp-content\/uploads\/2025\/01\/visualparadigm.jpg\" \/><\/a>'); <\/script><script type=\"text\/javascript\"> toolTips('.classtoolTips3','<a style=\"text-decoration: none;\" href=\"https:\/\/www.mongodb.com\/fr-fr\"><img style=\"width: 180px; height: 50px;\" src=\"\/wp-content\/uploads\/2025\/01\/mongodb-logo-rgb-scaled.jpg\" \/><\/a>'); <\/script><script type=\"text\/javascript\"> toolTips('.classtoolTips4','Create intelligent and beautiful documentation with ease <a href=\"https:\/\/www.sphinx-doc.org\/en\/master\/index.html\">url<\/a>'); <\/script><script type=\"text\/javascript\"> toolTips('.classtoolTips5','<a style=\"text-decoration: none;\" href=\"https:\/\/neo4j.com\/\"><img style=\"width: 180px; height: 50px;\" src=\"\/wp-content\/uploads\/2025\/01\/Neo4j-logo_color.png\" \/><\/a>'); <\/script>","protected":false},"excerpt":{"rendered":"<p>G\u00e9nie logiciel Dans le cadre de diff\u00e9rents projets, on est amen\u00e9 \u00e0 r\u00e9cup\u00e9rer diff\u00e9rents codes provenant de diff\u00e9rents concepteurs d\u00e9pos\u00e9s sur github. Dans une certaine mesure, ces codes dispose d&#8217;une documentation limit\u00e9e et peu d\u00e9taill\u00e9e mais qui permet rapidement de prendre en mains ces codes pour une ex\u00e9cution et obtenir le r\u00e9sultat souhait\u00e9. Maintenant dans [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"parent":0,"menu_order":0,"comment_status":"closed","ping_status":"closed","template":"","meta":{"footnotes":""},"class_list":["post-4418","page","type-page","status-publish","hentry"],"_links":{"self":[{"href":"https:\/\/spgoo.org\/index.php?rest_route=\/wp\/v2\/pages\/4418","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/spgoo.org\/index.php?rest_route=\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/spgoo.org\/index.php?rest_route=\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/spgoo.org\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/spgoo.org\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=4418"}],"version-history":[{"count":115,"href":"https:\/\/spgoo.org\/index.php?rest_route=\/wp\/v2\/pages\/4418\/revisions"}],"predecessor-version":[{"id":4718,"href":"https:\/\/spgoo.org\/index.php?rest_route=\/wp\/v2\/pages\/4418\/revisions\/4718"}],"wp:attachment":[{"href":"https:\/\/spgoo.org\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=4418"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}