ViewVC Help
View File | Revision Log | Show Annotations | Root Listing
root/cvsroot/COMP/WMCORE/setup.py
Revision: 1.37
Committed: Wed Oct 14 18:14:44 2009 UTC (15 years, 6 months ago) by metson
Content type: text/x-python
Branch: MAIN
Changes since 1.36: +13 -2 lines
Log Message:
Pick up how the lint score is calculated from the rc file

File Contents

# User Rev Content
1 fvlingen 1.1 #!/usr/bin/env python
2 metson 1.21 from distutils.core import setup, Command
3     from unittest import TextTestRunner, TestLoader, TestSuite
4     from glob import glob
5     from os.path import splitext, basename, join as pjoin, walk
6 metson 1.37 from ConfigParser import ConfigParser
7 metson 1.30 import os, sys
8 sfoulkes 1.29 try:
9     from pylint import lint
10 metson 1.36 #PyLinter
11 sfoulkes 1.29 except:
12     pass
13 fvlingen 1.1
14 metson 1.22 """
15     Build, clean and test the WMCore package.
16     """
17    
18 metson 1.36 def generate_filelist():
19     files = []
20     for dirpath, dirnames, filenames in os.walk('./src/python/'):
21     # skipping CVS directories and their contents
22     pathelements = dirpath.split('/')
23     result = []
24     if not 'CVS' in pathelements:
25     # to build up a list of file names which contain tests
26     for file in filenames:
27     if file.endswith('.py'):
28     filepath = '/'.join([dirpath, file])
29     files.append(filepath)
30     return files
31    
32     def lint_files(files):
33     """
34     lint a (list of) file(s) and return the results
35     """
36     input = ['--rcfile=standards/.pylintrc',
37     '--output-format=parseable',
38     '--reports=n', ]
39     input.extend(files)
40     lint_result = lint.Run(input)
41     return lint_result.linter.stats
42    
43 metson 1.21 class TestCommand(Command):
44 metson 1.22 """
45     Handle setup.py test with this class - walk through the directory structure
46     and build up a list of tests, then build a test suite and execute it.
47    
48     TODO: Pull database URL's from environment, and skip tests where database
49     URL is not present (e.g. for a slave without Oracle connection)
50     """
51 metson 1.21 user_options = [ ]
52    
53     def initialize_options(self):
54     self._dir = os.getcwd()
55    
56     def finalize_options(self):
57     pass
58    
59     def run(self):
60     '''
61 metson 1.25 Finds all the tests modules in test/python/WMCore_t, and runs them.
62 metson 1.21 '''
63     testfiles = [ ]
64 metson 1.26
65     # Add the test and src directory to the python path
66     testspypath = '/'.join([self._dir, 'test/python/'])
67     srcpypath = '/'.join([self._dir, 'src/python/'])
68 metson 1.30 sys.path.append(testspypath)
69     sys.path.append(srcpypath)
70    
71 metson 1.21 # Walk the directory tree
72     for dirpath, dirnames, filenames in os.walk('./test/python/WMCore_t'):
73     # skipping CVS directories and their contents
74     pathelements = dirpath.split('/')
75     if not 'CVS' in pathelements:
76     # to build up a list of file names which contain tests
77     for file in filenames:
78     if file not in ['__init__.py']:
79     if file.endswith('_t.py'):
80     testmodpath = pathelements[3:]
81     testmodpath.append(file.replace('.py',''))
82     testfiles.append('.'.join(testmodpath))
83    
84     testsuite = TestSuite()
85     for test in testfiles:
86     try:
87     testsuite.addTest(TestLoader().loadTestsFromName(test))
88     except Exception, e:
89     print "Could not load %s test - fix it!\n %s" % (test, e)
90     print "Running %s tests" % testsuite.countTestCases()
91    
92     t = TextTestRunner(verbosity = 1)
93 metson 1.32 result = t.run(testsuite)
94     if not result.wasSuccessful():
95     sys.exit("Tests unsuccessful. There were %s failures and %s errors"\
96     % (len(result.failures), len(result.errors)))
97    
98 metson 1.21 class CleanCommand(Command):
99 metson 1.22 """
100     Clean up (delete) compiled files
101     """
102 metson 1.21 user_options = [ ]
103    
104     def initialize_options(self):
105     self._clean_me = [ ]
106     for root, dirs, files in os.walk('.'):
107     for f in files:
108     if f.endswith('.pyc'):
109     self._clean_me.append(pjoin(root, f))
110    
111     def finalize_options(self):
112     pass
113    
114     def run(self):
115     for clean_me in self._clean_me:
116     try:
117     os.unlink(clean_me)
118     except:
119     pass
120    
121 metson 1.23 class LintCommand(Command):
122 metson 1.24 """
123     Lint all files in the src tree
124    
125     TODO: better format the test results, get some global result, make output
126     more buildbot friendly.
127     """
128    
129 metson 1.23 user_options = [ ]
130    
131     def initialize_options(self):
132     self._dir = os.getcwd()
133    
134     def finalize_options(self):
135     pass
136    
137     def run(self):
138     '''
139     Find the code and run lint on it
140     '''
141 metson 1.26 srcpypath = '/'.join([self._dir, 'src/python/'])
142 metson 1.30 sys.path.append(srcpypath)
143 metson 1.26
144 metson 1.36 result = []
145     for filepath in generate_filelist():
146     result.append(lint_files([filepath]))
147    
148     class ReportCommand(Command):
149     """
150     Generate a simple html report for ease of viewing in buildbot
151    
152     To contain:
153     average lint score
154     % code coverage
155     list of classes missing tests
156     etc.
157     """
158    
159     user_options = [ ]
160    
161     def initialize_options(self):
162     pass
163    
164     def finalize_options(self):
165     pass
166    
167     def run(self):
168     """
169     run all the tests needed to generate the report and make an
170     html table
171     """
172     files = generate_filelist()
173    
174     error = 0
175     warning = 0
176     refactor = 0
177     convention = 0
178     statement = 0
179    
180     srcpypath = '/'.join([os.getcwd(), 'src/python/'])
181     sys.path.append(srcpypath)
182 metson 1.37
183     cfg = ConfigParser()
184     cfg.read('standards/.pylintrc')
185    
186 metson 1.36
187     for stats in lint_files(files):
188     error += stats['error']
189     warning += stats['warning']
190     refactor += stats['refactor']
191     convention += stats['convention']
192     statement += stats['statement']
193 metson 1.37
194     stats = {'error': error,
195     'warning': warning,
196     'refactor': refactor,
197     'convention': convention,
198     'statement': statement}
199    
200     lint_score = eval(cfg.get('MASTER', 'evaluation'), {}, stats)
201 metson 1.36 coverage = 0 # TODO: calculate this
202     testless_classes = [] # TODO: generate this
203    
204     print "<table>"
205     print "<tr>"
206     print "<td colspan=2><h1>WMCore test report</h1></td>"
207     print "</tr>"
208     print "<tr>"
209     print "<td>Average lint score</td>"
210     print "<td>%.2f</td>" % lint_score
211     print "</tr>"
212     print "<tr>"
213     print "<td>% code coverage</td>"
214     print "<td>%s</td>" % coverage
215     print "</tr>"
216     print "<tr>"
217     print "<td>Classes missing tests</td>"
218     print "<td>"
219     if len(testless_classes) == 0:
220     print "None"
221     else:
222     print "<ul>"
223     for c in testless_classes:
224     print "<li>%c</li>" % c
225     print "</ul>"
226     print "</td>"
227     print "</tr>"
228     print "</table>"
229    
230     class CoverageCommand(Command):
231     """
232     Run code coverage tests
233     """
234    
235     user_options = [ ]
236    
237     def initialize_options(self):
238     pass
239    
240     def finalize_options(self):
241     pass
242    
243     def run(self):
244     """
245     Determine the code's test coverage and return that as a float
246    
247     http://nedbatchelder.com/code/coverage/
248     """
249     return 0.0
250    
251 metson 1.22 def getPackages(package_dirs = []):
252     packages = []
253     for dir in package_dirs:
254     for dirpath, dirnames, filenames in os.walk('./%s' % dir):
255     # Exclude things here
256     if dirpath not in ['./src/python/', './src/python/IMProv']:
257     pathelements = dirpath.split('/')
258     if not 'CVS' in pathelements:
259     path = pathelements[3:]
260     packages.append('.'.join(path))
261     return packages
262    
263     package_dir = {'WMCore': 'src/python/WMCore',
264     'WMComponent' : 'src/python/WMComponent',
265     'WMQuality' : 'src/python/WMQuality'}
266    
267     setup (name = 'wmcore',
268     version = '1.0',
269 metson 1.36 maintainer_email = 'hn-cms-wmDevelopment@cern.ch',
270     cmdclass = {'test': TestCommand,
271 metson 1.23 'clean': CleanCommand,
272 metson 1.36 'lint': LintCommand,
273     'report': ReportCommand,
274     'coverage': CoverageCommand },
275 metson 1.22 package_dir = package_dir,
276     packages = getPackages(package_dir.values()),)
277 fvlingen 1.7