]> SALOME platform Git repositories - tools/eficas.git/blob - Noyau/nommage.py
Salome HOME
431d3b067a823d0ca3857b665d1a9cbaac6504d2
[tools/eficas.git] / Noyau / nommage.py
1 #@ MODIF nommage Noyau  DATE 25/10/2011   AUTEUR COURTOIS M.COURTOIS 
2 # -*- coding: iso-8859-1 -*-
3 # RESPONSABLE COURTOIS M.COURTOIS
4 #            CONFIGURATION MANAGEMENT OF EDF VERSION
5 # ======================================================================
6 # COPYRIGHT (C) 1991 - 2011  EDF R&D                  WWW.CODE-ASTER.ORG
7 # THIS PROGRAM IS FREE SOFTWARE; YOU CAN REDISTRIBUTE IT AND/OR MODIFY
8 # IT UNDER THE TERMS OF THE GNU GENERAL PUBLIC LICENSE AS PUBLISHED BY
9 # THE FREE SOFTWARE FOUNDATION; EITHER VERSION 2 OF THE LICENSE, OR
10 # (AT YOUR OPTION) ANY LATER VERSION.
11 #
12 # THIS PROGRAM IS DISTRIBUTED IN THE HOPE THAT IT WILL BE USEFUL, BUT
13 # WITHOUT ANY WARRANTY; WITHOUT EVEN THE IMPLIED WARRANTY OF
14 # MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. SEE THE GNU
15 # GENERAL PUBLIC LICENSE FOR MORE DETAILS.
16 #
17 # YOU SHOULD HAVE RECEIVED A COPY OF THE GNU GENERAL PUBLIC LICENSE
18 # ALONG WITH THIS PROGRAM; IF NOT, WRITE TO EDF R&D CODE_ASTER,
19 #    1 AVENUE DU GENERAL DE GAULLE, 92141 CLAMART CEDEX, FRANCE.
20 #
21 #
22 # ======================================================================
23
24
25 """
26    Ce module sert à nommer les concepts produits par les commandes.
27    Le nom du concept est obtenu en appelant la fonction GetNomConceptResultat
28    du module avec le nom de la commande en argument.
29
30    Cette fonction parcourt le source dans lequel la commande se trouve, parse le
31    fichier et retrouve le nom du concept qui se trouve à gauche du signe = précédant
32    le nom de la commande.
33
34    Cette fonction utilise la fonction cur_frame du module N_utils qui retourne la frame
35    d'exécution Python située 2 niveaux au-dessus. C'est à partir de cette frame que
36    l'on retrouve le fichier source et le numéro de ligne où se trouve l'appel à la commande.
37
38 """
39
40 # Modules Python
41 import re,string
42 import linecache
43 from functools import partial
44
45 # Modules EFICAS
46 import N_utils
47
48 regex1='=?\s*%s\s*\('
49 #commentaire standard precede d'un nombre quelconque de blancs (pas multiligne)
50 pattern_comment   = re.compile(r"^\s*#.*")
51
52 def _GetNomConceptResultat(ope, level=2):
53   """
54      Cette fonction recherche dans la pile des appels, l'appel à la commande
55      qui doit etre situé à 2 niveaux au-dessus (cur_frame(2)).
56      On retrouve d'abord la frame d'exécution f. Puis le numéro de la ligne
57      dans le source f.f_lineno et le nom du fichier source (f.f_code.co_filename).
58      A partir de là, on récupère la ligne de source avec linecache.getline
59      et on vérifie que cette ligne correspond véritablement à l'appel.
60
61      En effet, lorsque les commandes tiennent sur plusieurs lignes, on retrouve
62      la dernière ligne. Il faut donc remonter dans le source jusqu'à la première
63      ligne.
64
65      Enfin la fonction evalnom forme un nom acceptable lorsque le concept est un
66      élément d'une liste, par exemple.
67
68   """
69   f=N_utils.cur_frame(level)
70   lineno = f.f_lineno     # XXX Too bad if -O is used
71   #lineno = f_lineno(f)  # Ne marche pas toujours
72   co = f.f_code
73   filename = co.co_filename
74   name = co.co_name
75   #print "NOMOP,FICHIER, LIGNE ",ope,filename,lineno
76   #pattern pour identifier le debut de la commande
77   pattern_oper=re.compile(regex1 % ope)
78
79   list=[]
80   while lineno > 0:
81     line = linecache.getline(filename, lineno)
82     lineno=lineno-1
83     if pattern_comment.match(line):continue
84     #print "LIGNE ",line
85     list.append(line)
86     if pattern_oper.search(line):
87       l=pattern_oper.split(line)
88       list.reverse()
89       #print "COMMANDE ",string.join(list)
90       #print "SPLIT ",l
91       # On suppose que le concept resultat a bien ete
92       # isole en tete de la ligne de source
93       m=evalnom(string.strip(l[0]),f.f_locals)
94       #print "NOMS ",m
95       if m!=[] :  return m[-1]
96       else : return ''
97   #print "appel inconnu"
98   return ""
99
100 def evalnom(text,d):
101   """
102    Retourne un nom pour le concept resultat identifie par text
103    Pour obtenir ce nom il y a plusieurs possibilites :
104     1. text est un identificateur python c'est le nom du concept
105     2. text est un element d'une liste on construit le nom en
106       evaluant la partie indice dans le contexte de l'appelant d
107   """
108   l=re.split('([\[\]]+)',text)
109   #print l
110   if l[-1] == '' :l=l[:-1]
111   lll=[]
112   i=0
113   while i<len(l):
114     s=l[i]
115     ll=string.split(s,',')
116     ll=re.split('[ ,]+',s)
117     if ll[0] == '' :ll=ll[1:]
118     if len(ll) == 1:
119       id0=ll[0]
120     else:
121       lll=lll+ll[0:-1]
122       id0=ll[-1]
123     if i+1<len(l) and l[i+1] == '[': # le nom est suivi d un subscript
124       sub=l[i+2]
125       nom=id0+'_'+str(eval(sub,d))
126       i=i+4
127     else:
128       nom=id0
129       i=i+1
130     lll.append(nom)
131   return lll
132
133 def f_lineno(f):
134    """
135       Calcule le numero de ligne courant
136       Devrait marcher meme avec -O
137       Semble ne pas marcher en présence de tuples longs
138    """
139    c=f.f_code
140    if not hasattr(c, 'co_lnotab'):return f.f_lineno
141    tab=c.co_lnotab
142    line = c.co_firstlineno
143    stopat = f.f_lasti
144    addr = 0
145    for i in range(0, len(tab), 2):
146        addr = addr + ord(tab[i])
147        if addr > stopat:
148            break
149        line = line + ord(tab[i+1])
150    return line
151
152
153 class NamingSystem:
154     """Cette classe définit un système de nommage dynamique des concepts."""
155     def __init__(self):
156         """Initialisation"""
157         self.native = _GetNomConceptResultat
158         self.use_global_naming()
159
160     def use_naming_function(self, function):
161         """Utilise une fonction particulière de nommage."""
162         self.naming_func = function
163
164     def use_global_naming(self):
165         """Utilise la fonction native de nommage."""
166         self.naming_func = partial(self.native, level=3)
167
168     def __call__(self, *args):
169         """Appel à la fonction de nommage."""
170         return self.naming_func(*args)
171
172 GetNomConceptResultat = NamingSystem()