~yacinechaouche/+junk/BZR

« back to all changes in this revision

Viewing changes to PROG/TAHAR-NG/tahar-r2.py

  • Committer: yacinechaouche at yahoo
  • Date: 2015-01-14 22:23:03 UTC
  • Revision ID: yacinechaouche@yahoo.com-20150114222303-6gbtqqxii717vyka
Ajout de CODE et PROD. Il faudra ensuite ajouter ce qu'il y avait dan TMP

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
"""
 
2
TODO :
 
3
 #1 : support for nested function and class definitions.
 
4
 --#2-- : support for directories in command line arguments.
 
5
 #3 : support stats for packages and subpackages
 
6
"""
 
7
 
 
8
import tokenize
 
9
import pprint
 
10
import sys,os
 
11
import dircache
 
12
 
 
13
def incr(obj,attr):
 
14
    setattr(obj,attr,attr+1)
 
15
 
 
16
def get_module(file_name):
 
17
    # if it's a directory return all modules and submodules recursively
 
18
    if os.path.isdir(file_name):
 
19
        dir_name = file_name
 
20
        files = dircache.listdir(dir_name)
 
21
        for one_file in files:
 
22
            complete_file_name = os.path.join(dir_name,one_file)
 
23
            for module in get_module(complete_file_name):
 
24
                yield module
 
25
        
 
26
    elif file_name.endswith(".py"):
 
27
        yield file_name
 
28
 
 
29
class Reader:
 
30
    def __init__(self,stats):
 
31
        self.stats                = stats
 
32
        self.in_def               = False
 
33
        self.in_class             = False
 
34
        
 
35
        # when set to True in the previous iteration, the actual token must be a class name and it used to capture that name.
 
36
        # It should be set to false immediatly afterwards.
 
37
        self.capture_class        = False
 
38
        
 
39
        # when set to True in the previous iteration, the actual token must be a function name and it used to capture that name.
 
40
        # It should be set to false immediatly afterwards.
 
41
        self.capture_def          = False
 
42
 
 
43
        # purpose :
 
44
        # when reaching 0, we're not in a function definition anymore
 
45
        self.def_depth            = 0
 
46
        
 
47
        # purpose :
 
48
        # when reaching 0, we're not in a class definition anymore
 
49
        self.class_depth          = 0
 
50
 
 
51
        
 
52
        # # # # # # # # # # # # # # # # #
 
53
        # when True, this attribute is useful to test if current line is comment or blank
 
54
        self.beginning_of_line    = True
 
55
        
 
56
        # used to determine if we should call self.stats.record_newline or not
 
57
        self.current_line_is_code = True
 
58
 
 
59
    ###############################################################        
 
60
    def __call__(self,token_type,token,start_cl,end_cl,line):
 
61
        self._check_flags(token)
 
62
        self._check_indents(token_type)
 
63
        
 
64
        if self.beginning_of_line :
 
65
            self._flag_line_of_code(token_type,line)
 
66
 
 
67
        if token_type in (tokenize.NL,tokenize.NEWLINE) :
 
68
            if self.current_line_is_code and not (line.strip().startswith("def") or line.strip().startswith("class")):
 
69
                self.stats.record_newline(line)
 
70
                
 
71
            self.beginning_of_line    = True # for next iteration                
 
72
            self.capture_def = False
 
73
            self.capture_class = False
 
74
        
 
75
    ###############################################################
 
76
    def _check_flags(self,token):
 
77
        if self.capture_def :
 
78
            self.stats.record_def(token)
 
79
            self.capture_def = False
 
80
 
 
81
        if self.capture_class :
 
82
            self.stats.record_class(token)
 
83
            self.capture_class = False
 
84
            
 
85
        if token == "def" and not self.in_def : #don't process nested functions
 
86
            self.capture_def = True
 
87
            self.in_def      = True
 
88
            
 
89
        elif token == "class" and not self.in_class : #don't process nested classes
 
90
            self.capture_class = True
 
91
            self.in_class      = True
 
92
            
 
93
    ###############################################################
 
94
    def _flag_line_of_code(self,token_type,line):
 
95
        if token_type in (tokenize.STRING, tokenize.COMMENT) or line.strip() == "" :
 
96
            self.current_line_is_code = False
 
97
        else :
 
98
            self.current_line_is_code = True # for next iteration
 
99
 
 
100
        if token_type not in (tokenize.INDENT, tokenize.DEDENT) : 
 
101
            self.beginning_of_line   = False # for next iteration
 
102
 
 
103
 
 
104
    ###############################################################
 
105
    def _check_indents(self,token_type):
 
106
        if token_type == tokenize.INDENT :
 
107
            self._incr_depth()
 
108
            
 
109
        if token_type == tokenize.DEDENT :
 
110
            self._decr_depth()
 
111
        
 
112
    ###############################################################            
 
113
    def _incr_depth(self,incr=1):
 
114
        if self.in_def :
 
115
            self.def_depth += incr
 
116
            if self.def_depth == 0 :
 
117
                self.in_def = False
 
118
                self.stats.end_def()
 
119
            
 
120
        if self.in_class :
 
121
            self.class_depth += incr
 
122
            if self.class_depth == 0 :
 
123
                self.in_class = False
 
124
                self.stats.end_class()
 
125
    ###############################################################
 
126
    def _decr_depth(self):
 
127
        self._incr_depth(-1)
 
128
        
 
129
 
 
130
    ###############################################################
 
131
class SourceStats:
 
132
    def __init__(self,file_name):
 
133
        self.lines          = open(file_name).readlines()
 
134
        self.stats         = {"#module":{"#loc":0,
 
135
                                         "#classes":{"#loc":0},
 
136
                                         "#functions":{"#loc":0},
 
137
                                         "#module_code":{"#loc":0}
 
138
                                         }
 
139
                              }
 
140
        self.current_name   = None
 
141
        self.current_class  = None
 
142
        self.current_def    = None
 
143
        self.current_node   = None
 
144
        self.current_module = self.stats["#module"]
 
145
 
 
146
    def create_new_stat_dict(self,stat_type,parent=None):
 
147
        d = {"#classes":{"#loc":0},"#loc":0,"#parent":parent}
 
148
        if stat_type == "class":
 
149
            d["#methods"]    = {"#loc":0,"#parent":d}
 
150
            d["#class_code"] = {"#loc":0,"#parent":d}
 
151
        elif stat_type == "function":
 
152
            d["#functions"] = {"#loc":0,"#parent":d}
 
153
        elif stat_type == "module":
 
154
            d["#functions"]   = {"#loc":0,"#parent":d}
 
155
            d["#module_code"] = {"#loc":0,"#parent":d}
 
156
        return d
 
157
 
 
158
    def _get_current_parent(self):
 
159
        if self.current_def :
 
160
            parent = self.current_def
 
161
            
 
162
        elif self.current_class :
 
163
            parent = self.current_class
 
164
            
 
165
        elif self.current_module :
 
166
            parent = self.current_module
 
167
            
 
168
        return parent
 
169
 
 
170
    def record_class(self,name):
 
171
        print "recording class",name
 
172
        self.current_name  = name
 
173
        parent             = self._get_current_parent()
 
174
        self.current_class = parent["#classes"][name] = self.create_new_stat_dict(parent=parent,stat_type="class")
 
175
        self.current_def   = None
 
176
 
 
177
    def record_def(self,name):
 
178
        print "recording function or method",name
 
179
        self.current_name = name
 
180
        parent            = self._get_current_parent()
 
181
        if parent.get("#methods"):
 
182
            key = '#methods'
 
183
        else :
 
184
            key = "#functions"
 
185
        self.current_def   = parent[key][name] = self.create_new_stat_dict(parent=parent,stat_type="function")
 
186
        self.current_class = None
 
187
 
 
188
    def record_newline(self,line):
 
189
        if self.current_def:
 
190
            self._incr_stat(self.current_def)
 
191
        elif self.current_class:
 
192
            self._incr_stat(self.current_class)
 
193
        else:
 
194
            self._incr_stat(self.current_module)
 
195
 
 
196
    def end_def(self):
 
197
        print "definition of function/method %s ended" % self.current_name
 
198
        self.current_def = "#parent" in self.current_def and  self.current_def["#parent"] or None
 
199
        
 
200
    def end_class(self):
 
201
        print "definition of class ended"
 
202
        print "self.current_class",self.current_class
 
203
        print "current_parent",pprint.pprint(self._get_current_parent())
 
204
        self.current_class = "#parent" in self.current_class and  self.current_class["#parent"] or None
 
205
        
 
206
    def process(self):
 
207
        tokenize.tokenize(iter(self.lines).next,Reader(self))
 
208
 
 
209
    def _incr_stat(self,stat):
 
210
        stat["#loc"]+=1
 
211
        if "#parent" in stat :
 
212
            parent = stat.get("#parent")
 
213
            if parent : 
 
214
                if "#methods" in parent :
 
215
                    parent["#methods"]["#loc"] += 1
 
216
                elif "#functions" in parent :
 
217
                    parent["#functions"]["#loc"] += 1
 
218
                if self.current_class and not self.current_def :
 
219
                    parent["#class_code"]["#loc"] += 1
 
220
                elif not self.current_class and not self.current_def :
 
221
                    parent["module_code"]["#loc"] += 1
 
222
                self._incr_stat(stat["#parent"])
 
223
 
 
224
def usage():
 
225
    print "no no no. Use %s like this : python %s path_to_file.py" % (sys.argv[0],sys.argv[0])
 
226
 
 
227
def main():
 
228
    ## file_path = "/home/chaouche/CODE/TEST/PYTHON/sample.py"
 
229
    ## file_path = "/home/chaouche/CODE/TEST/PYTHON/simple-sample.py"
 
230
    if len(sys.argv) < 2 :
 
231
        usage()
 
232
        exit(1)
 
233
    for file_path in sys.argv[1:]:
 
234
        for python_file in get_module(file_path) :
 
235
            print "file  :",python_file
 
236
            st = SourceStats(python_file)
 
237
            st.process()
 
238
            pprint.pprint(st.stats)
 
239
    
 
240
if __name__ == "__main__":
 
241
    main()
 
242