Merge lp:~mitya57/ubuntu/trusty/python-coverage/merge-rc-bugfix into lp:ubuntu/trusty/python-coverage
- Trusty (14.04)
- merge-rc-bugfix
- Merge into trusty
Proposed by
Dmitry Shachnev
Status: | Merged |
---|---|
Merge reported by: | Martin Pitt |
Merged at revision: | not available |
Proposed branch: | lp:~mitya57/ubuntu/trusty/python-coverage/merge-rc-bugfix |
Merge into: | lp:ubuntu/trusty/python-coverage |
Diff against target: |
2654 lines (+656/-1404) 35 files modified
.pc/02.rename-public-programs.patch/setup.py (+196/-0) .pc/02.use-system-ecmascript-libraries.patch/coverage/html.py (+0/-387) .pc/03.rename-public-programs.patch/setup.py (+0/-196) .pc/applied-patches (+1/-2) CHANGES.txt (+9/-0) PKG-INFO (+2/-2) coverage.egg-info/PKG-INFO (+2/-2) coverage/annotate.py (+4/-3) coverage/cmdline.py (+5/-1) coverage/control.py (+5/-2) coverage/html.py (+21/-25) coverage/misc.py (+5/-1) coverage/parser.py (+46/-12) coverage/phystokens.py (+6/-4) coverage/results.py (+1/-1) coverage/templite.py (+136/-94) coverage/version.py (+1/-1) coverage/xmlreport.py (+1/-1) debian/changelog (+31/-0) debian/patches/01.omit-resource-files-from-distutils-setup.patch (+11/-0) debian/patches/02.rename-public-programs.patch (+50/-0) debian/patches/02.use-system-ecmascript-libraries.patch (+0/-48) debian/patches/03.rename-public-programs.patch (+0/-39) debian/patches/series (+1/-2) debian/python-coverage.1 (+0/-279) debian/python-coverage.1.tmp (+0/-278) debian/repack (+2/-2) debian/rules (+22/-8) doc/changes.rst (+16/-1) doc/cmd.rst (+2/-2) doc/index.rst (+2/-1) doc/install.rst (+3/-2) tests/coveragetest.py (+4/-3) tests/test_html.py (+23/-0) tests/test_templite.py (+48/-5) |
To merge this branch: | bzr merge lp:~mitya57/ubuntu/trusty/python-coverage/merge-rc-bugfix |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Martin Pitt | Approve | ||
Review via email: mp+209836@code.launchpad.net |
Commit message
Description of the change
This is a merge from Debian.
Upstream changes: new bugfix release.
Debian changes: fixes an RC bug (#740053) and another packaging bug (#736121).
To post a comment you must log in.
- 15. By Dmitry Shachnev
-
Merge with Debian unstable, remaining change:
- Add python3-coverage. preinst to correctly handle upgrades from
previous releases.
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | === added directory '.pc/02.rename-public-programs.patch' |
2 | === added file '.pc/02.rename-public-programs.patch/setup.py' |
3 | --- .pc/02.rename-public-programs.patch/setup.py 1970-01-01 00:00:00 +0000 |
4 | +++ .pc/02.rename-public-programs.patch/setup.py 2014-03-07 05:33:58 +0000 |
5 | @@ -0,0 +1,196 @@ |
6 | +# setup.py for coverage.py |
7 | + |
8 | +"""Code coverage measurement for Python |
9 | + |
10 | +Coverage.py measures code coverage, typically during test execution. It uses |
11 | +the code analysis tools and tracing hooks provided in the Python standard |
12 | +library to determine which lines are executable, and which have been executed. |
13 | + |
14 | +Coverage.py runs on Pythons 2.3 through 3.3, and PyPy 1.9. |
15 | + |
16 | +Documentation is at `nedbatchelder.com <%s>`_. Code repository and issue |
17 | +tracker are on `Bitbucket <http://bitbucket.org/ned/coveragepy>`_, with a |
18 | +mirrored repo on `Github <https://github.com/nedbat/coveragepy>`_. |
19 | + |
20 | +New in 3.7: ``--debug``, and 12 bugs closed. |
21 | + |
22 | +New in 3.6: ``--fail-under``, and >20 bugs closed. |
23 | + |
24 | +New in 3.5: Branch coverage exclusions, keyboard shortcuts in HTML report. |
25 | + |
26 | +New in 3.4: Better control over source to measure, and unexecuted files |
27 | +can be reported. |
28 | + |
29 | +New in 3.3: .coveragerc files. |
30 | + |
31 | +New in 3.2: Branch coverage! |
32 | +""" |
33 | + |
34 | +# This file is used unchanged under all versions of Python, 2.x and 3.x. |
35 | + |
36 | +classifiers = """\ |
37 | +Environment :: Console |
38 | +Intended Audience :: Developers |
39 | +License :: OSI Approved :: BSD License |
40 | +Operating System :: OS Independent |
41 | +Programming Language :: Python :: 2 |
42 | +Programming Language :: Python :: 3 |
43 | +Topic :: Software Development :: Quality Assurance |
44 | +Topic :: Software Development :: Testing |
45 | +""" |
46 | + |
47 | +# Pull in the tools we need. |
48 | +import os, sys |
49 | + |
50 | +from setuptools import setup |
51 | +from distutils.core import Extension # pylint: disable=E0611,F0401 |
52 | +from distutils.command.build_ext import build_ext # pylint: disable=E0611,F0401,C0301 |
53 | +from distutils import errors # pylint: disable=E0611,F0401 |
54 | + |
55 | +# Get or massage our metadata. We exec coverage/version.py so we can avoid |
56 | +# importing the product code into setup.py. |
57 | + |
58 | +doc = __doc__ # __doc__ will be overwritten by version.py. |
59 | +__version__ = __url__ = "" # Keep pylint happy. |
60 | + |
61 | +cov_ver_py = os.path.join(os.path.split(__file__)[0], "coverage/version.py") |
62 | +version_file = open(cov_ver_py) |
63 | +try: |
64 | + exec(compile(version_file.read(), cov_ver_py, 'exec')) |
65 | +finally: |
66 | + version_file.close() |
67 | + |
68 | +doclines = (doc % __url__).splitlines() |
69 | +classifier_list = classifiers.splitlines() |
70 | + |
71 | +if 'a' in __version__: |
72 | + devstat = "3 - Alpha" |
73 | +elif 'b' in __version__: |
74 | + devstat = "4 - Beta" |
75 | +else: |
76 | + devstat = "5 - Production/Stable" |
77 | +classifier_list.append("Development Status :: " + devstat) |
78 | + |
79 | +# Install a script as "coverage", and as "coverage[23]", and as |
80 | +# "coverage-2.7" (or whatever). |
81 | +scripts = [ |
82 | + 'coverage = coverage:main', |
83 | + 'coverage%d = coverage:main' % sys.version_info[:1], |
84 | + 'coverage-%d.%d = coverage:main' % sys.version_info[:2], |
85 | + ] |
86 | + |
87 | +# Create the keyword arguments for setup() |
88 | + |
89 | +setup_args = dict( |
90 | + name = 'coverage', |
91 | + version = __version__, |
92 | + |
93 | + packages = [ |
94 | + 'coverage', |
95 | + ], |
96 | + |
97 | + entry_points = {'console_scripts': scripts}, |
98 | + |
99 | + # We need to get HTML assets from our htmlfiles dir. |
100 | + zip_safe = False, |
101 | + |
102 | + author = 'Ned Batchelder and others', |
103 | + author_email = 'ned@nedbatchelder.com', |
104 | + description = doclines[0], |
105 | + long_description = '\n'.join(doclines[2:]), |
106 | + keywords = 'code coverage testing', |
107 | + license = 'BSD', |
108 | + classifiers = classifier_list, |
109 | + url = __url__, |
110 | + ) |
111 | + |
112 | +# A replacement for the build_ext command which raises a single exception |
113 | +# if the build fails, so we can fallback nicely. |
114 | + |
115 | +ext_errors = ( |
116 | + errors.CCompilerError, |
117 | + errors.DistutilsExecError, |
118 | + errors.DistutilsPlatformError, |
119 | +) |
120 | +if sys.platform == 'win32' and sys.version_info > (2, 6): |
121 | + # 2.6's distutils.msvc9compiler can raise an IOError when failing to |
122 | + # find the compiler |
123 | + ext_errors += (IOError,) |
124 | + |
125 | +class BuildFailed(Exception): |
126 | + """Raise this to indicate the C extension wouldn't build.""" |
127 | + def __init__(self): |
128 | + Exception.__init__(self) |
129 | + self.cause = sys.exc_info()[1] # work around py 2/3 different syntax |
130 | + |
131 | +class ve_build_ext(build_ext): |
132 | + """Build C extensions, but fail with a straightforward exception.""" |
133 | + |
134 | + def run(self): |
135 | + """Wrap `run` with `BuildFailed`.""" |
136 | + try: |
137 | + build_ext.run(self) |
138 | + except errors.DistutilsPlatformError: |
139 | + raise BuildFailed() |
140 | + |
141 | + def build_extension(self, ext): |
142 | + """Wrap `build_extension` with `BuildFailed`.""" |
143 | + try: |
144 | + # Uncomment to test compile failures: |
145 | + # raise errors.CCompilerError("OOPS") |
146 | + build_ext.build_extension(self, ext) |
147 | + except ext_errors: |
148 | + raise BuildFailed() |
149 | + except ValueError: |
150 | + # this can happen on Windows 64 bit, see Python issue 7511 |
151 | + if "'path'" in str(sys.exc_info()[1]): # works with both py 2/3 |
152 | + raise BuildFailed() |
153 | + raise |
154 | + |
155 | +# There are a few reasons we might not be able to compile the C extension. |
156 | +# Figure out if we should attempt the C extension or not. |
157 | + |
158 | +compile_extension = True |
159 | + |
160 | +if sys.platform.startswith('java'): |
161 | + # Jython can't compile C extensions |
162 | + compile_extension = False |
163 | + |
164 | +if '__pypy__' in sys.builtin_module_names: |
165 | + # Pypy can't compile C extensions |
166 | + compile_extension = False |
167 | + |
168 | +if compile_extension: |
169 | + setup_args.update(dict( |
170 | + ext_modules = [ |
171 | + Extension("coverage.tracer", sources=["coverage/tracer.c"]) |
172 | + ], |
173 | + cmdclass = { |
174 | + 'build_ext': ve_build_ext, |
175 | + }, |
176 | + )) |
177 | + |
178 | +# Py3.x-specific details. |
179 | + |
180 | +if sys.version_info >= (3, 0): |
181 | + setup_args.update(dict( |
182 | + use_2to3 = False, |
183 | + )) |
184 | + |
185 | +def main(): |
186 | + """Actually invoke setup() with the arguments we built above.""" |
187 | + # For a variety of reasons, it might not be possible to install the C |
188 | + # extension. Try it with, and if it fails, try it without. |
189 | + try: |
190 | + setup(**setup_args) |
191 | + except BuildFailed: |
192 | + msg = "Couldn't install with extension module, trying without it..." |
193 | + exc = sys.exc_info()[1] |
194 | + exc_msg = "%s: %s" % (exc.__class__.__name__, exc.cause) |
195 | + print("**\n** %s\n** %s\n**" % (msg, exc_msg)) |
196 | + |
197 | + del setup_args['ext_modules'] |
198 | + setup(**setup_args) |
199 | + |
200 | +if __name__ == '__main__': |
201 | + main() |
202 | |
203 | === removed directory '.pc/02.use-system-ecmascript-libraries.patch' |
204 | === removed directory '.pc/02.use-system-ecmascript-libraries.patch/coverage' |
205 | === removed file '.pc/02.use-system-ecmascript-libraries.patch/coverage/html.py' |
206 | --- .pc/02.use-system-ecmascript-libraries.patch/coverage/html.py 2013-10-15 13:16:36 +0000 |
207 | +++ .pc/02.use-system-ecmascript-libraries.patch/coverage/html.py 1970-01-01 00:00:00 +0000 |
208 | @@ -1,387 +0,0 @@ |
209 | -"""HTML reporting for Coverage.""" |
210 | - |
211 | -import os, re, shutil, sys |
212 | - |
213 | -import coverage |
214 | -from coverage.backward import pickle |
215 | -from coverage.misc import CoverageException, Hasher |
216 | -from coverage.phystokens import source_token_lines, source_encoding |
217 | -from coverage.report import Reporter |
218 | -from coverage.results import Numbers |
219 | -from coverage.templite import Templite |
220 | - |
221 | - |
222 | -# Static files are looked for in a list of places. |
223 | -STATIC_PATH = [ |
224 | - # The place Debian puts system Javascript libraries. |
225 | - "/usr/share/javascript", |
226 | - |
227 | - # Our htmlfiles directory. |
228 | - os.path.join(os.path.dirname(__file__), "htmlfiles"), |
229 | -] |
230 | - |
231 | -def data_filename(fname): |
232 | - """Return the path to a data file of ours. |
233 | - |
234 | - The file is searched for on `STATIC_PATH`, and the first place it's found, |
235 | - is returned. |
236 | - |
237 | - """ |
238 | - for static_dir in STATIC_PATH: |
239 | - static_filename = os.path.join(static_dir, fname) |
240 | - if os.path.exists(static_filename): |
241 | - return static_filename |
242 | - raise CoverageException("Couldn't find static file %r" % fname) |
243 | - |
244 | -def data(fname): |
245 | - """Return the contents of a data file of ours.""" |
246 | - data_file = open(data_filename(fname)) |
247 | - try: |
248 | - return data_file.read() |
249 | - finally: |
250 | - data_file.close() |
251 | - |
252 | - |
253 | -class HtmlReporter(Reporter): |
254 | - """HTML reporting.""" |
255 | - |
256 | - # These files will be copied from the htmlfiles dir to the output dir. |
257 | - STATIC_FILES = [ |
258 | - "style.css", |
259 | - "jquery.min.js", |
260 | - "jquery.hotkeys.js", |
261 | - "jquery.isonscreen.js", |
262 | - "jquery.tablesorter.min.js", |
263 | - "coverage_html.js", |
264 | - "keybd_closed.png", |
265 | - "keybd_open.png", |
266 | - ] |
267 | - |
268 | - def __init__(self, cov, config): |
269 | - super(HtmlReporter, self).__init__(cov, config) |
270 | - self.directory = None |
271 | - self.template_globals = { |
272 | - 'escape': escape, |
273 | - 'title': self.config.html_title, |
274 | - '__url__': coverage.__url__, |
275 | - '__version__': coverage.__version__, |
276 | - } |
277 | - self.source_tmpl = Templite( |
278 | - data("pyfile.html"), self.template_globals |
279 | - ) |
280 | - |
281 | - self.coverage = cov |
282 | - |
283 | - self.files = [] |
284 | - self.arcs = self.coverage.data.has_arcs() |
285 | - self.status = HtmlStatus() |
286 | - self.extra_css = None |
287 | - self.totals = Numbers() |
288 | - |
289 | - def report(self, morfs): |
290 | - """Generate an HTML report for `morfs`. |
291 | - |
292 | - `morfs` is a list of modules or filenames. |
293 | - |
294 | - """ |
295 | - assert self.config.html_dir, "must give a directory for html reporting" |
296 | - |
297 | - # Read the status data. |
298 | - self.status.read(self.config.html_dir) |
299 | - |
300 | - # Check that this run used the same settings as the last run. |
301 | - m = Hasher() |
302 | - m.update(self.config) |
303 | - these_settings = m.digest() |
304 | - if self.status.settings_hash() != these_settings: |
305 | - self.status.reset() |
306 | - self.status.set_settings_hash(these_settings) |
307 | - |
308 | - # The user may have extra CSS they want copied. |
309 | - if self.config.extra_css: |
310 | - self.extra_css = os.path.basename(self.config.extra_css) |
311 | - |
312 | - # Process all the files. |
313 | - self.report_files(self.html_file, morfs, self.config.html_dir) |
314 | - |
315 | - if not self.files: |
316 | - raise CoverageException("No data to report.") |
317 | - |
318 | - # Write the index file. |
319 | - self.index_file() |
320 | - |
321 | - self.make_local_static_report_files() |
322 | - |
323 | - return self.totals.pc_covered |
324 | - |
325 | - def make_local_static_report_files(self): |
326 | - """Make local instances of static files for HTML report.""" |
327 | - # The files we provide must always be copied. |
328 | - for static in self.STATIC_FILES: |
329 | - shutil.copyfile( |
330 | - data_filename(static), |
331 | - os.path.join(self.directory, static) |
332 | - ) |
333 | - |
334 | - # The user may have extra CSS they want copied. |
335 | - if self.extra_css: |
336 | - shutil.copyfile( |
337 | - self.config.extra_css, |
338 | - os.path.join(self.directory, self.extra_css) |
339 | - ) |
340 | - |
341 | - def write_html(self, fname, html): |
342 | - """Write `html` to `fname`, properly encoded.""" |
343 | - fout = open(fname, "wb") |
344 | - try: |
345 | - fout.write(html.encode('ascii', 'xmlcharrefreplace')) |
346 | - finally: |
347 | - fout.close() |
348 | - |
349 | - def file_hash(self, source, cu): |
350 | - """Compute a hash that changes if the file needs to be re-reported.""" |
351 | - m = Hasher() |
352 | - m.update(source) |
353 | - self.coverage.data.add_to_hash(cu.filename, m) |
354 | - return m.digest() |
355 | - |
356 | - def html_file(self, cu, analysis): |
357 | - """Generate an HTML file for one source file.""" |
358 | - source_file = cu.source_file() |
359 | - try: |
360 | - source = source_file.read() |
361 | - finally: |
362 | - source_file.close() |
363 | - |
364 | - # Find out if the file on disk is already correct. |
365 | - flat_rootname = cu.flat_rootname() |
366 | - this_hash = self.file_hash(source, cu) |
367 | - that_hash = self.status.file_hash(flat_rootname) |
368 | - if this_hash == that_hash: |
369 | - # Nothing has changed to require the file to be reported again. |
370 | - self.files.append(self.status.index_info(flat_rootname)) |
371 | - return |
372 | - |
373 | - self.status.set_file_hash(flat_rootname, this_hash) |
374 | - |
375 | - # If need be, determine the encoding of the source file. We use it |
376 | - # later to properly write the HTML. |
377 | - if sys.version_info < (3, 0): |
378 | - encoding = source_encoding(source) |
379 | - # Some UTF8 files have the dreaded UTF8 BOM. If so, junk it. |
380 | - if encoding.startswith("utf-8") and source[:3] == "\xef\xbb\xbf": |
381 | - source = source[3:] |
382 | - encoding = "utf-8" |
383 | - |
384 | - # Get the numbers for this file. |
385 | - nums = analysis.numbers |
386 | - |
387 | - missing_branch_arcs = analysis.missing_branch_arcs() |
388 | - |
389 | - # These classes determine which lines are highlighted by default. |
390 | - c_run = "run hide_run" |
391 | - c_exc = "exc" |
392 | - c_mis = "mis" |
393 | - c_par = "par " + c_run |
394 | - |
395 | - lines = [] |
396 | - |
397 | - for lineno, line in enumerate(source_token_lines(source)): |
398 | - lineno += 1 # 1-based line numbers. |
399 | - # Figure out how to mark this line. |
400 | - line_class = [] |
401 | - annotate_html = "" |
402 | - annotate_title = "" |
403 | - if lineno in analysis.statements: |
404 | - line_class.append("stm") |
405 | - if lineno in analysis.excluded: |
406 | - line_class.append(c_exc) |
407 | - elif lineno in analysis.missing: |
408 | - line_class.append(c_mis) |
409 | - elif self.arcs and lineno in missing_branch_arcs: |
410 | - line_class.append(c_par) |
411 | - annlines = [] |
412 | - for b in missing_branch_arcs[lineno]: |
413 | - if b < 0: |
414 | - annlines.append("exit") |
415 | - else: |
416 | - annlines.append(str(b)) |
417 | - annotate_html = " ".join(annlines) |
418 | - if len(annlines) > 1: |
419 | - annotate_title = "no jumps to these line numbers" |
420 | - elif len(annlines) == 1: |
421 | - annotate_title = "no jump to this line number" |
422 | - elif lineno in analysis.statements: |
423 | - line_class.append(c_run) |
424 | - |
425 | - # Build the HTML for the line |
426 | - html = [] |
427 | - for tok_type, tok_text in line: |
428 | - if tok_type == "ws": |
429 | - html.append(escape(tok_text)) |
430 | - else: |
431 | - tok_html = escape(tok_text) or ' ' |
432 | - html.append( |
433 | - "<span class='%s'>%s</span>" % (tok_type, tok_html) |
434 | - ) |
435 | - |
436 | - lines.append({ |
437 | - 'html': ''.join(html), |
438 | - 'number': lineno, |
439 | - 'class': ' '.join(line_class) or "pln", |
440 | - 'annotate': annotate_html, |
441 | - 'annotate_title': annotate_title, |
442 | - }) |
443 | - |
444 | - # Write the HTML page for this file. |
445 | - html = spaceless(self.source_tmpl.render({ |
446 | - 'c_exc': c_exc, 'c_mis': c_mis, 'c_par': c_par, 'c_run': c_run, |
447 | - 'arcs': self.arcs, 'extra_css': self.extra_css, |
448 | - 'cu': cu, 'nums': nums, 'lines': lines, |
449 | - })) |
450 | - |
451 | - if sys.version_info < (3, 0): |
452 | - html = html.decode(encoding) |
453 | - |
454 | - html_filename = flat_rootname + ".html" |
455 | - html_path = os.path.join(self.directory, html_filename) |
456 | - self.write_html(html_path, html) |
457 | - |
458 | - # Save this file's information for the index file. |
459 | - index_info = { |
460 | - 'nums': nums, |
461 | - 'html_filename': html_filename, |
462 | - 'name': cu.name, |
463 | - } |
464 | - self.files.append(index_info) |
465 | - self.status.set_index_info(flat_rootname, index_info) |
466 | - |
467 | - def index_file(self): |
468 | - """Write the index.html file for this report.""" |
469 | - index_tmpl = Templite( |
470 | - data("index.html"), self.template_globals |
471 | - ) |
472 | - |
473 | - self.totals = sum([f['nums'] for f in self.files]) |
474 | - |
475 | - html = index_tmpl.render({ |
476 | - 'arcs': self.arcs, |
477 | - 'extra_css': self.extra_css, |
478 | - 'files': self.files, |
479 | - 'totals': self.totals, |
480 | - }) |
481 | - |
482 | - if sys.version_info < (3, 0): |
483 | - html = html.decode("utf-8") |
484 | - self.write_html( |
485 | - os.path.join(self.directory, "index.html"), |
486 | - html |
487 | - ) |
488 | - |
489 | - # Write the latest hashes for next time. |
490 | - self.status.write(self.directory) |
491 | - |
492 | - |
493 | -class HtmlStatus(object): |
494 | - """The status information we keep to support incremental reporting.""" |
495 | - |
496 | - STATUS_FILE = "status.dat" |
497 | - STATUS_FORMAT = 1 |
498 | - |
499 | - def __init__(self): |
500 | - self.reset() |
501 | - |
502 | - def reset(self): |
503 | - """Initialize to empty.""" |
504 | - self.settings = '' |
505 | - self.files = {} |
506 | - |
507 | - def read(self, directory): |
508 | - """Read the last status in `directory`.""" |
509 | - usable = False |
510 | - try: |
511 | - status_file = os.path.join(directory, self.STATUS_FILE) |
512 | - fstatus = open(status_file, "rb") |
513 | - try: |
514 | - status = pickle.load(fstatus) |
515 | - finally: |
516 | - fstatus.close() |
517 | - except (IOError, ValueError): |
518 | - usable = False |
519 | - else: |
520 | - usable = True |
521 | - if status['format'] != self.STATUS_FORMAT: |
522 | - usable = False |
523 | - elif status['version'] != coverage.__version__: |
524 | - usable = False |
525 | - |
526 | - if usable: |
527 | - self.files = status['files'] |
528 | - self.settings = status['settings'] |
529 | - else: |
530 | - self.reset() |
531 | - |
532 | - def write(self, directory): |
533 | - """Write the current status to `directory`.""" |
534 | - status_file = os.path.join(directory, self.STATUS_FILE) |
535 | - status = { |
536 | - 'format': self.STATUS_FORMAT, |
537 | - 'version': coverage.__version__, |
538 | - 'settings': self.settings, |
539 | - 'files': self.files, |
540 | - } |
541 | - fout = open(status_file, "wb") |
542 | - try: |
543 | - pickle.dump(status, fout) |
544 | - finally: |
545 | - fout.close() |
546 | - |
547 | - def settings_hash(self): |
548 | - """Get the hash of the coverage.py settings.""" |
549 | - return self.settings |
550 | - |
551 | - def set_settings_hash(self, settings): |
552 | - """Set the hash of the coverage.py settings.""" |
553 | - self.settings = settings |
554 | - |
555 | - def file_hash(self, fname): |
556 | - """Get the hash of `fname`'s contents.""" |
557 | - return self.files.get(fname, {}).get('hash', '') |
558 | - |
559 | - def set_file_hash(self, fname, val): |
560 | - """Set the hash of `fname`'s contents.""" |
561 | - self.files.setdefault(fname, {})['hash'] = val |
562 | - |
563 | - def index_info(self, fname): |
564 | - """Get the information for index.html for `fname`.""" |
565 | - return self.files.get(fname, {}).get('index', {}) |
566 | - |
567 | - def set_index_info(self, fname, info): |
568 | - """Set the information for index.html for `fname`.""" |
569 | - self.files.setdefault(fname, {})['index'] = info |
570 | - |
571 | - |
572 | -# Helpers for templates and generating HTML |
573 | - |
574 | -def escape(t): |
575 | - """HTML-escape the text in `t`.""" |
576 | - return (t |
577 | - # Convert HTML special chars into HTML entities. |
578 | - .replace("&", "&").replace("<", "<").replace(">", ">") |
579 | - .replace("'", "'").replace('"', """) |
580 | - # Convert runs of spaces: "......" -> " . . ." |
581 | - .replace(" ", " ") |
582 | - # To deal with odd-length runs, convert the final pair of spaces |
583 | - # so that "....." -> " . ." |
584 | - .replace(" ", " ") |
585 | - ) |
586 | - |
587 | -def spaceless(html): |
588 | - """Squeeze out some annoying extra space from an HTML string. |
589 | - |
590 | - Nicely-formatted templates mean lots of extra space in the result. |
591 | - Get rid of some. |
592 | - |
593 | - """ |
594 | - html = re.sub(r">\s+<p ", ">\n<p ", html) |
595 | - return html |
596 | |
597 | === removed directory '.pc/03.rename-public-programs.patch' |
598 | === removed file '.pc/03.rename-public-programs.patch/setup.py' |
599 | --- .pc/03.rename-public-programs.patch/setup.py 2013-10-15 13:16:36 +0000 |
600 | +++ .pc/03.rename-public-programs.patch/setup.py 1970-01-01 00:00:00 +0000 |
601 | @@ -1,196 +0,0 @@ |
602 | -# setup.py for coverage.py |
603 | - |
604 | -"""Code coverage measurement for Python |
605 | - |
606 | -Coverage.py measures code coverage, typically during test execution. It uses |
607 | -the code analysis tools and tracing hooks provided in the Python standard |
608 | -library to determine which lines are executable, and which have been executed. |
609 | - |
610 | -Coverage.py runs on Pythons 2.3 through 3.3, and PyPy 1.9. |
611 | - |
612 | -Documentation is at `nedbatchelder.com <%s>`_. Code repository and issue |
613 | -tracker are on `Bitbucket <http://bitbucket.org/ned/coveragepy>`_, with a |
614 | -mirrored repo on `Github <https://github.com/nedbat/coveragepy>`_. |
615 | - |
616 | -New in 3.7: ``--debug``, and 12 bugs closed. |
617 | - |
618 | -New in 3.6: ``--fail-under``, and >20 bugs closed. |
619 | - |
620 | -New in 3.5: Branch coverage exclusions, keyboard shortcuts in HTML report. |
621 | - |
622 | -New in 3.4: Better control over source to measure, and unexecuted files |
623 | -can be reported. |
624 | - |
625 | -New in 3.3: .coveragerc files. |
626 | - |
627 | -New in 3.2: Branch coverage! |
628 | -""" |
629 | - |
630 | -# This file is used unchanged under all versions of Python, 2.x and 3.x. |
631 | - |
632 | -classifiers = """\ |
633 | -Environment :: Console |
634 | -Intended Audience :: Developers |
635 | -License :: OSI Approved :: BSD License |
636 | -Operating System :: OS Independent |
637 | -Programming Language :: Python :: 2 |
638 | -Programming Language :: Python :: 3 |
639 | -Topic :: Software Development :: Quality Assurance |
640 | -Topic :: Software Development :: Testing |
641 | -""" |
642 | - |
643 | -# Pull in the tools we need. |
644 | -import os, sys |
645 | - |
646 | -from setuptools import setup |
647 | -from distutils.core import Extension # pylint: disable=E0611,F0401 |
648 | -from distutils.command.build_ext import build_ext # pylint: disable=E0611,F0401,C0301 |
649 | -from distutils import errors # pylint: disable=E0611,F0401 |
650 | - |
651 | -# Get or massage our metadata. We exec coverage/version.py so we can avoid |
652 | -# importing the product code into setup.py. |
653 | - |
654 | -doc = __doc__ # __doc__ will be overwritten by version.py. |
655 | -__version__ = __url__ = "" # Keep pylint happy. |
656 | - |
657 | -cov_ver_py = os.path.join(os.path.split(__file__)[0], "coverage/version.py") |
658 | -version_file = open(cov_ver_py) |
659 | -try: |
660 | - exec(compile(version_file.read(), cov_ver_py, 'exec')) |
661 | -finally: |
662 | - version_file.close() |
663 | - |
664 | -doclines = (doc % __url__).splitlines() |
665 | -classifier_list = classifiers.splitlines() |
666 | - |
667 | -if 'a' in __version__: |
668 | - devstat = "3 - Alpha" |
669 | -elif 'b' in __version__: |
670 | - devstat = "4 - Beta" |
671 | -else: |
672 | - devstat = "5 - Production/Stable" |
673 | -classifier_list.append("Development Status :: " + devstat) |
674 | - |
675 | -# Install a script as "coverage", and as "coverage[23]", and as |
676 | -# "coverage-2.7" (or whatever). |
677 | -scripts = [ |
678 | - 'coverage = coverage:main', |
679 | - 'coverage%d = coverage:main' % sys.version_info[:1], |
680 | - 'coverage-%d.%d = coverage:main' % sys.version_info[:2], |
681 | - ] |
682 | - |
683 | -# Create the keyword arguments for setup() |
684 | - |
685 | -setup_args = dict( |
686 | - name = 'coverage', |
687 | - version = __version__, |
688 | - |
689 | - packages = [ |
690 | - 'coverage', |
691 | - ], |
692 | - |
693 | - entry_points = {'console_scripts': scripts}, |
694 | - |
695 | - # We need to get HTML assets from our htmlfiles dir. |
696 | - zip_safe = False, |
697 | - |
698 | - author = 'Ned Batchelder and others', |
699 | - author_email = 'ned@nedbatchelder.com', |
700 | - description = doclines[0], |
701 | - long_description = '\n'.join(doclines[2:]), |
702 | - keywords = 'code coverage testing', |
703 | - license = 'BSD', |
704 | - classifiers = classifier_list, |
705 | - url = __url__, |
706 | - ) |
707 | - |
708 | -# A replacement for the build_ext command which raises a single exception |
709 | -# if the build fails, so we can fallback nicely. |
710 | - |
711 | -ext_errors = ( |
712 | - errors.CCompilerError, |
713 | - errors.DistutilsExecError, |
714 | - errors.DistutilsPlatformError, |
715 | -) |
716 | -if sys.platform == 'win32' and sys.version_info > (2, 6): |
717 | - # 2.6's distutils.msvc9compiler can raise an IOError when failing to |
718 | - # find the compiler |
719 | - ext_errors += (IOError,) |
720 | - |
721 | -class BuildFailed(Exception): |
722 | - """Raise this to indicate the C extension wouldn't build.""" |
723 | - def __init__(self): |
724 | - Exception.__init__(self) |
725 | - self.cause = sys.exc_info()[1] # work around py 2/3 different syntax |
726 | - |
727 | -class ve_build_ext(build_ext): |
728 | - """Build C extensions, but fail with a straightforward exception.""" |
729 | - |
730 | - def run(self): |
731 | - """Wrap `run` with `BuildFailed`.""" |
732 | - try: |
733 | - build_ext.run(self) |
734 | - except errors.DistutilsPlatformError: |
735 | - raise BuildFailed() |
736 | - |
737 | - def build_extension(self, ext): |
738 | - """Wrap `build_extension` with `BuildFailed`.""" |
739 | - try: |
740 | - # Uncomment to test compile failures: |
741 | - # raise errors.CCompilerError("OOPS") |
742 | - build_ext.build_extension(self, ext) |
743 | - except ext_errors: |
744 | - raise BuildFailed() |
745 | - except ValueError: |
746 | - # this can happen on Windows 64 bit, see Python issue 7511 |
747 | - if "'path'" in str(sys.exc_info()[1]): # works with both py 2/3 |
748 | - raise BuildFailed() |
749 | - raise |
750 | - |
751 | -# There are a few reasons we might not be able to compile the C extension. |
752 | -# Figure out if we should attempt the C extension or not. |
753 | - |
754 | -compile_extension = True |
755 | - |
756 | -if sys.platform.startswith('java'): |
757 | - # Jython can't compile C extensions |
758 | - compile_extension = False |
759 | - |
760 | -if '__pypy__' in sys.builtin_module_names: |
761 | - # Pypy can't compile C extensions |
762 | - compile_extension = False |
763 | - |
764 | -if compile_extension: |
765 | - setup_args.update(dict( |
766 | - ext_modules = [ |
767 | - Extension("coverage.tracer", sources=["coverage/tracer.c"]) |
768 | - ], |
769 | - cmdclass = { |
770 | - 'build_ext': ve_build_ext, |
771 | - }, |
772 | - )) |
773 | - |
774 | -# Py3.x-specific details. |
775 | - |
776 | -if sys.version_info >= (3, 0): |
777 | - setup_args.update(dict( |
778 | - use_2to3 = False, |
779 | - )) |
780 | - |
781 | -def main(): |
782 | - """Actually invoke setup() with the arguments we built above.""" |
783 | - # For a variety of reasons, it might not be possible to install the C |
784 | - # extension. Try it with, and if it fails, try it without. |
785 | - try: |
786 | - setup(**setup_args) |
787 | - except BuildFailed: |
788 | - msg = "Couldn't install with extension module, trying without it..." |
789 | - exc = sys.exc_info()[1] |
790 | - exc_msg = "%s: %s" % (exc.__class__.__name__, exc.cause) |
791 | - print("**\n** %s\n** %s\n**" % (msg, exc_msg)) |
792 | - |
793 | - del setup_args['ext_modules'] |
794 | - setup(**setup_args) |
795 | - |
796 | -if __name__ == '__main__': |
797 | - main() |
798 | |
799 | === modified file '.pc/applied-patches' |
800 | --- .pc/applied-patches 2014-01-06 21:48:50 +0000 |
801 | +++ .pc/applied-patches 2014-03-07 05:33:58 +0000 |
802 | @@ -1,3 +1,2 @@ |
803 | 01.omit-resource-files-from-distutils-setup.patch |
804 | -02.use-system-ecmascript-libraries.patch |
805 | -03.rename-public-programs.patch |
806 | +02.rename-public-programs.patch |
807 | |
808 | === modified file 'CHANGES.txt' |
809 | --- CHANGES.txt 2014-01-06 21:48:50 +0000 |
810 | +++ CHANGES.txt 2014-03-07 05:33:58 +0000 |
811 | @@ -2,6 +2,15 @@ |
812 | Change history for Coverage.py |
813 | ------------------------------ |
814 | |
815 | +3.7.1 -- 13 December 2013 |
816 | +------------------------- |
817 | + |
818 | +- Improved the speed of HTML report generation by about 20%. |
819 | + |
820 | +- Fixed the mechanism for finding OS-installed static files for the HTML report |
821 | + so that it will actually find OS-installed static files. |
822 | + |
823 | + |
824 | 3.7 --- 6 October 2013 |
825 | ---------------------- |
826 | |
827 | |
828 | === modified file 'PKG-INFO' |
829 | --- PKG-INFO 2014-01-06 21:48:50 +0000 |
830 | +++ PKG-INFO 2014-03-07 05:33:58 +0000 |
831 | @@ -1,6 +1,6 @@ |
832 | -Metadata-Version: 1.1 |
833 | +Metadata-Version: 1.0 |
834 | Name: coverage |
835 | -Version: 3.7 |
836 | +Version: 3.7.1 |
837 | Summary: Code coverage measurement for Python |
838 | Home-page: http://nedbatchelder.com/code/coverage |
839 | Author: Ned Batchelder and others |
840 | |
841 | === modified file 'coverage.egg-info/PKG-INFO' |
842 | --- coverage.egg-info/PKG-INFO 2014-01-06 21:48:50 +0000 |
843 | +++ coverage.egg-info/PKG-INFO 2014-03-07 05:33:58 +0000 |
844 | @@ -1,6 +1,6 @@ |
845 | -Metadata-Version: 1.1 |
846 | +Metadata-Version: 1.0 |
847 | Name: coverage |
848 | -Version: 3.7 |
849 | +Version: 3.7.1 |
850 | Summary: Code coverage measurement for Python |
851 | Home-page: http://nedbatchelder.com/code/coverage |
852 | Author: Ned Batchelder and others |
853 | |
854 | === modified file 'coverage/annotate.py' |
855 | --- coverage/annotate.py 2014-01-06 21:48:50 +0000 |
856 | +++ coverage/annotate.py 2014-03-07 05:33:58 +0000 |
857 | @@ -2,6 +2,7 @@ |
858 | |
859 | import os, re |
860 | |
861 | +from coverage.backward import sorted # pylint: disable=W0622 |
862 | from coverage.report import Reporter |
863 | |
864 | class AnnotateReporter(Reporter): |
865 | @@ -59,9 +60,9 @@ |
866 | dest_file = filename + ",cover" |
867 | dest = open(dest_file, 'w') |
868 | |
869 | - statements = analysis.statements |
870 | - missing = analysis.missing |
871 | - excluded = analysis.excluded |
872 | + statements = sorted(analysis.statements) |
873 | + missing = sorted(analysis.missing) |
874 | + excluded = sorted(analysis.excluded) |
875 | |
876 | lineno = 0 |
877 | i = 0 |
878 | |
879 | === modified file 'coverage/cmdline.py' |
880 | --- coverage/cmdline.py 2014-01-06 21:48:50 +0000 |
881 | +++ coverage/cmdline.py 2014-03-07 05:33:58 +0000 |
882 | @@ -1,6 +1,6 @@ |
883 | """Command-line support for Coverage.""" |
884 | |
885 | -import optparse, os, sys, traceback |
886 | +import optparse, os, sys, time, traceback |
887 | |
888 | from coverage.backward import sorted # pylint: disable=W0622 |
889 | from coverage.execfile import run_python_file, run_python_module |
890 | @@ -717,7 +717,11 @@ |
891 | if argv is None: |
892 | argv = sys.argv[1:] |
893 | try: |
894 | + start = time.clock() |
895 | status = CoverageScript().command_line(argv) |
896 | + end = time.clock() |
897 | + if 0: |
898 | + print("time: %.3fs" % (end - start)) |
899 | except ExceptionDuringRun: |
900 | # An exception was caught while running the product code. The |
901 | # sys.exc_info() return tuple is packed into an ExceptionDuringRun |
902 | |
903 | === modified file 'coverage/control.py' |
904 | --- coverage/control.py 2014-01-06 21:48:50 +0000 |
905 | +++ coverage/control.py 2014-03-07 05:33:58 +0000 |
906 | @@ -572,8 +572,11 @@ |
907 | """ |
908 | analysis = self._analyze(morf) |
909 | return ( |
910 | - analysis.filename, analysis.statements, analysis.excluded, |
911 | - analysis.missing, analysis.missing_formatted() |
912 | + analysis.filename, |
913 | + sorted(analysis.statements), |
914 | + sorted(analysis.excluded), |
915 | + sorted(analysis.missing), |
916 | + analysis.missing_formatted(), |
917 | ) |
918 | |
919 | def _analyze(self, it): |
920 | |
921 | === modified file 'coverage/html.py' |
922 | --- coverage/html.py 2014-01-06 21:48:50 +0000 |
923 | +++ coverage/html.py 2014-03-07 05:33:58 +0000 |
924 | @@ -20,19 +20,27 @@ |
925 | os.path.join(os.path.dirname(__file__), "htmlfiles"), |
926 | ] |
927 | |
928 | -def data_filename(fname): |
929 | +def data_filename(fname, pkgdir=""): |
930 | """Return the path to a data file of ours. |
931 | |
932 | The file is searched for on `STATIC_PATH`, and the first place it's found, |
933 | is returned. |
934 | |
935 | + Each directory in `STATIC_PATH` is searched as-is, and also, if `pkgdir` |
936 | + is provided, at that subdirectory. |
937 | + |
938 | """ |
939 | for static_dir in STATIC_PATH: |
940 | static_filename = os.path.join(static_dir, fname) |
941 | if os.path.exists(static_filename): |
942 | return static_filename |
943 | + if pkgdir: |
944 | + static_filename = os.path.join(static_dir, pkgdir, fname) |
945 | + if os.path.exists(static_filename): |
946 | + return static_filename |
947 | raise CoverageException("Couldn't find static file %r" % fname) |
948 | |
949 | + |
950 | def data(fname): |
951 | """Return the contents of a data file of ours.""" |
952 | data_file = open(data_filename(fname)) |
953 | @@ -47,10 +55,14 @@ |
954 | |
955 | # These files will be copied from the htmlfiles dir to the output dir. |
956 | STATIC_FILES = [ |
957 | - "style.css", |
958 | - "coverage_html.js", |
959 | - "keybd_closed.png", |
960 | - "keybd_open.png", |
961 | + ("style.css", ""), |
962 | + ("jquery.min.js", "jquery"), |
963 | + ("jquery.hotkeys.js", "jquery-hotkeys"), |
964 | + ("jquery.isonscreen.js", "jquery-isonscreen"), |
965 | + ("jquery.tablesorter.min.js", "jquery-tablesorter"), |
966 | + ("coverage_html.js", ""), |
967 | + ("keybd_closed.png", ""), |
968 | + ("keybd_open.png", ""), |
969 | ] |
970 | |
971 | def __init__(self, cov, config): |
972 | @@ -113,29 +125,12 @@ |
973 | def make_local_static_report_files(self): |
974 | """Make local instances of static files for HTML report.""" |
975 | # The files we provide must always be copied. |
976 | - for static in self.STATIC_FILES: |
977 | + for static, pkgdir in self.STATIC_FILES: |
978 | shutil.copyfile( |
979 | - data_filename(static), |
980 | + data_filename(static, pkgdir), |
981 | os.path.join(self.directory, static) |
982 | ) |
983 | |
984 | - system_javascript_path = os.path.join( |
985 | - os.sep, "usr", "share", "javascript") |
986 | - system_javascript_libraries = { |
987 | - "jquery.min.js": |
988 | - os.path.join(system_javascript_path, "jquery"), |
989 | - "jquery.hotkeys.js": |
990 | - os.path.join(system_javascript_path, "jquery-hotkeys"), |
991 | - "jquery.isonscreen.js": |
992 | - os.path.join(system_javascript_path, "jquery-isonscreen"), |
993 | - "jquery.tablesorter.min.js": |
994 | - os.path.join(system_javascript_path, "jquery-tablesorter"), |
995 | - } |
996 | - for static, source_dir in system_javascript_libraries.items(): |
997 | - shutil.copyfile( |
998 | - os.path.join(source_dir, static), |
999 | - os.path.join(self.directory, static)) |
1000 | - |
1001 | # The user may have extra CSS they want copied. |
1002 | if self.extra_css: |
1003 | shutil.copyfile( |
1004 | @@ -189,7 +184,8 @@ |
1005 | # Get the numbers for this file. |
1006 | nums = analysis.numbers |
1007 | |
1008 | - missing_branch_arcs = analysis.missing_branch_arcs() |
1009 | + if self.arcs: |
1010 | + missing_branch_arcs = analysis.missing_branch_arcs() |
1011 | |
1012 | # These classes determine which lines are highlighted by default. |
1013 | c_run = "run hide_run" |
1014 | |
1015 | === modified file 'coverage/misc.py' |
1016 | --- coverage/misc.py 2014-01-06 21:48:50 +0000 |
1017 | +++ coverage/misc.py 2014-03-07 05:33:58 +0000 |
1018 | @@ -38,6 +38,8 @@ |
1019 | i = 0 |
1020 | j = 0 |
1021 | start = None |
1022 | + statements = sorted(statements) |
1023 | + lines = sorted(lines) |
1024 | while i < len(statements) and j < len(lines): |
1025 | if statements[i] == lines[j]: |
1026 | if start == None: |
1027 | @@ -113,8 +115,10 @@ |
1028 | self.md5.update(to_bytes(str(type(v)))) |
1029 | if isinstance(v, string_class): |
1030 | self.md5.update(to_bytes(v)) |
1031 | + elif v is None: |
1032 | + pass |
1033 | elif isinstance(v, (int, float)): |
1034 | - self.update(str(v)) |
1035 | + self.md5.update(to_bytes(str(v))) |
1036 | elif isinstance(v, (tuple, list)): |
1037 | for e in v: |
1038 | self.update(e) |
1039 | |
1040 | === modified file 'coverage/parser.py' |
1041 | --- coverage/parser.py 2014-01-06 21:48:50 +0000 |
1042 | +++ coverage/parser.py 2014-03-07 05:33:58 +0000 |
1043 | @@ -108,7 +108,7 @@ |
1044 | first_line = None |
1045 | empty = True |
1046 | |
1047 | - tokgen = tokenize.generate_tokens(StringIO(self.text).readline) |
1048 | + tokgen = generate_tokens(self.text) |
1049 | for toktype, ttext, (slineno, _), (elineno, _), ltext in tokgen: |
1050 | if self.show_tokens: # pragma: not covered |
1051 | print("%10s %5s %-20r %r" % ( |
1052 | @@ -175,16 +175,18 @@ |
1053 | first_line = line |
1054 | return first_line |
1055 | |
1056 | - def first_lines(self, lines, ignore=None): |
1057 | + def first_lines(self, lines, *ignores): |
1058 | """Map the line numbers in `lines` to the correct first line of the |
1059 | statement. |
1060 | |
1061 | - Skip any line mentioned in `ignore`. |
1062 | + Skip any line mentioned in any of the sequences in `ignores`. |
1063 | |
1064 | - Returns a sorted list of the first lines. |
1065 | + Returns a set of the first lines. |
1066 | |
1067 | """ |
1068 | - ignore = ignore or [] |
1069 | + ignore = set() |
1070 | + for ign in ignores: |
1071 | + ignore.update(ign) |
1072 | lset = set() |
1073 | for l in lines: |
1074 | if l in ignore: |
1075 | @@ -192,13 +194,13 @@ |
1076 | new_l = self.first_line(l) |
1077 | if new_l not in ignore: |
1078 | lset.add(new_l) |
1079 | - return sorted(lset) |
1080 | + return lset |
1081 | |
1082 | def parse_source(self): |
1083 | """Parse source text to find executable lines, excluded lines, etc. |
1084 | |
1085 | - Return values are 1) a sorted list of executable line numbers, and |
1086 | - 2) a sorted list of excluded line numbers. |
1087 | + Return values are 1) a set of executable line numbers, and 2) a set of |
1088 | + excluded line numbers. |
1089 | |
1090 | Reported line numbers are normalized to the first line of multi-line |
1091 | statements. |
1092 | @@ -215,8 +217,11 @@ |
1093 | ) |
1094 | |
1095 | excluded_lines = self.first_lines(self.excluded) |
1096 | - ignore = excluded_lines + list(self.docstrings) |
1097 | - lines = self.first_lines(self.statement_starts, ignore) |
1098 | + lines = self.first_lines( |
1099 | + self.statement_starts, |
1100 | + excluded_lines, |
1101 | + self.docstrings |
1102 | + ) |
1103 | |
1104 | return lines, excluded_lines |
1105 | |
1106 | @@ -444,14 +449,15 @@ |
1107 | |
1108 | # Get a set of all of the jump-to points. |
1109 | jump_to = set() |
1110 | - for bc in ByteCodes(self.code.co_code): |
1111 | + bytecodes = list(ByteCodes(self.code.co_code)) |
1112 | + for bc in bytecodes: |
1113 | if bc.jump_to >= 0: |
1114 | jump_to.add(bc.jump_to) |
1115 | |
1116 | chunk_lineno = 0 |
1117 | |
1118 | # Walk the byte codes building chunks. |
1119 | - for bc in ByteCodes(self.code.co_code): |
1120 | + for bc in bytecodes: |
1121 | # Maybe have to start a new chunk |
1122 | start_new_chunk = False |
1123 | first_chunk = False |
1124 | @@ -664,3 +670,31 @@ |
1125 | return "<%d+%d @%d%s %r>" % ( |
1126 | self.byte, self.length, self.line, bang, list(self.exits) |
1127 | ) |
1128 | + |
1129 | + |
1130 | +class CachedTokenizer(object): |
1131 | + """A one-element cache around tokenize.generate_tokens. |
1132 | + |
1133 | + When reporting, coverage.py tokenizes files twice, once to find the |
1134 | + structure of the file, and once to syntax-color it. Tokenizing is |
1135 | + expensive, and easily cached. |
1136 | + |
1137 | + This is a one-element cache so that our twice-in-a-row tokenizing doesn't |
1138 | + actually tokenize twice. |
1139 | + |
1140 | + """ |
1141 | + def __init__(self): |
1142 | + self.last_text = None |
1143 | + self.last_tokens = None |
1144 | + |
1145 | + def generate_tokens(self, text): |
1146 | + """A stand-in for `tokenize.generate_tokens`.""" |
1147 | + if text != self.last_text: |
1148 | + self.last_text = text |
1149 | + self.last_tokens = list( |
1150 | + tokenize.generate_tokens(StringIO(text).readline) |
1151 | + ) |
1152 | + return self.last_tokens |
1153 | + |
1154 | +# Create our generate_tokens cache as a callable replacement function. |
1155 | +generate_tokens = CachedTokenizer().generate_tokens |
1156 | |
1157 | === modified file 'coverage/phystokens.py' |
1158 | --- coverage/phystokens.py 2014-01-06 21:48:50 +0000 |
1159 | +++ coverage/phystokens.py 2014-03-07 05:33:58 +0000 |
1160 | @@ -1,7 +1,9 @@ |
1161 | """Better tokenizing for coverage.py.""" |
1162 | |
1163 | import codecs, keyword, re, sys, token, tokenize |
1164 | -from coverage.backward import StringIO # pylint: disable=W0622 |
1165 | +from coverage.backward import set # pylint: disable=W0622 |
1166 | +from coverage.parser import generate_tokens |
1167 | + |
1168 | |
1169 | def phys_tokens(toks): |
1170 | """Return all physical tokens, even line continuations. |
1171 | @@ -18,7 +20,7 @@ |
1172 | last_ttype = None |
1173 | for ttype, ttext, (slineno, scol), (elineno, ecol), ltext in toks: |
1174 | if last_lineno != elineno: |
1175 | - if last_line and last_line[-2:] == "\\\n": |
1176 | + if last_line and last_line.endswith("\\\n"): |
1177 | # We are at the beginning of a new line, and the last line |
1178 | # ended with a backslash. We probably have to inject a |
1179 | # backslash token into the stream. Unfortunately, there's more |
1180 | @@ -74,11 +76,11 @@ |
1181 | is indistinguishable from a final line with a newline. |
1182 | |
1183 | """ |
1184 | - ws_tokens = [token.INDENT, token.DEDENT, token.NEWLINE, tokenize.NL] |
1185 | + ws_tokens = set([token.INDENT, token.DEDENT, token.NEWLINE, tokenize.NL]) |
1186 | line = [] |
1187 | col = 0 |
1188 | source = source.expandtabs(8).replace('\r\n', '\n') |
1189 | - tokgen = tokenize.generate_tokens(StringIO(source).readline) |
1190 | + tokgen = generate_tokens(source) |
1191 | for ttype, ttext, (_, scol), (_, ecol), _ in phys_tokens(tokgen): |
1192 | mark_start = True |
1193 | for part in re.split('(\n)', ttext): |
1194 | |
1195 | === modified file 'coverage/results.py' |
1196 | --- coverage/results.py 2014-01-06 21:48:50 +0000 |
1197 | +++ coverage/results.py 2014-03-07 05:33:58 +0000 |
1198 | @@ -26,7 +26,7 @@ |
1199 | # Identify missing statements. |
1200 | executed = self.coverage.data.executed_lines(self.filename) |
1201 | exec1 = self.parser.first_lines(executed) |
1202 | - self.missing = sorted(set(self.statements) - set(exec1)) |
1203 | + self.missing = self.statements - exec1 |
1204 | |
1205 | if self.coverage.data.has_arcs(): |
1206 | self.no_branch = self.parser.lines_matching( |
1207 | |
1208 | === modified file 'coverage/templite.py' |
1209 | --- coverage/templite.py 2011-07-27 16:23:25 +0000 |
1210 | +++ coverage/templite.py 2014-03-07 05:33:58 +0000 |
1211 | @@ -2,7 +2,53 @@ |
1212 | |
1213 | # Coincidentally named the same as http://code.activestate.com/recipes/496702/ |
1214 | |
1215 | -import re, sys |
1216 | +import re |
1217 | + |
1218 | +from coverage.backward import set # pylint: disable=W0622 |
1219 | + |
1220 | + |
1221 | +class CodeBuilder(object): |
1222 | + """Build source code conveniently.""" |
1223 | + |
1224 | + def __init__(self, indent=0): |
1225 | + self.code = [] |
1226 | + self.indent_amount = indent |
1227 | + |
1228 | + def add_line(self, line): |
1229 | + """Add a line of source to the code. |
1230 | + |
1231 | + Don't include indentations or newlines. |
1232 | + |
1233 | + """ |
1234 | + self.code.append(" " * self.indent_amount) |
1235 | + self.code.append(line) |
1236 | + self.code.append("\n") |
1237 | + |
1238 | + def add_section(self): |
1239 | + """Add a section, a sub-CodeBuilder.""" |
1240 | + sect = CodeBuilder(self.indent_amount) |
1241 | + self.code.append(sect) |
1242 | + return sect |
1243 | + |
1244 | + def indent(self): |
1245 | + """Increase the current indent for following lines.""" |
1246 | + self.indent_amount += 4 |
1247 | + |
1248 | + def dedent(self): |
1249 | + """Decrease the current indent for following lines.""" |
1250 | + self.indent_amount -= 4 |
1251 | + |
1252 | + def __str__(self): |
1253 | + return "".join([str(c) for c in self.code]) |
1254 | + |
1255 | + def get_function(self, fn_name): |
1256 | + """Compile the code, and return the function `fn_name`.""" |
1257 | + assert self.indent_amount == 0 |
1258 | + g = {} |
1259 | + code_text = str(self) |
1260 | + exec(code_text, g) |
1261 | + return g[fn_name] |
1262 | + |
1263 | |
1264 | class Templite(object): |
1265 | """A simple template renderer, for a nano-subset of Django syntax. |
1266 | @@ -39,53 +85,104 @@ |
1267 | for context in contexts: |
1268 | self.context.update(context) |
1269 | |
1270 | + # We construct a function in source form, then compile it and hold onto |
1271 | + # it, and execute it to render the template. |
1272 | + code = CodeBuilder() |
1273 | + |
1274 | + code.add_line("def render(ctx, dot):") |
1275 | + code.indent() |
1276 | + vars_code = code.add_section() |
1277 | + self.all_vars = set() |
1278 | + self.loop_vars = set() |
1279 | + code.add_line("result = []") |
1280 | + code.add_line("a = result.append") |
1281 | + code.add_line("e = result.extend") |
1282 | + code.add_line("s = str") |
1283 | + |
1284 | + buffered = [] |
1285 | + def flush_output(): |
1286 | + """Force `buffered` to the code builder.""" |
1287 | + if len(buffered) == 1: |
1288 | + code.add_line("a(%s)" % buffered[0]) |
1289 | + elif len(buffered) > 1: |
1290 | + code.add_line("e([%s])" % ",".join(buffered)) |
1291 | + del buffered[:] |
1292 | + |
1293 | # Split the text to form a list of tokens. |
1294 | toks = re.split(r"(?s)({{.*?}}|{%.*?%}|{#.*?#})", text) |
1295 | |
1296 | - # Parse the tokens into a nested list of operations. Each item in the |
1297 | - # list is a tuple with an opcode, and arguments. They'll be |
1298 | - # interpreted by TempliteEngine. |
1299 | - # |
1300 | - # When parsing an action tag with nested content (if, for), the current |
1301 | - # ops list is pushed onto ops_stack, and the parsing continues in a new |
1302 | - # ops list that is part of the arguments to the if or for op. |
1303 | - ops = [] |
1304 | ops_stack = [] |
1305 | for tok in toks: |
1306 | if tok.startswith('{{'): |
1307 | - # Expression: ('exp', expr) |
1308 | - ops.append(('exp', tok[2:-2].strip())) |
1309 | + # An expression to evaluate. |
1310 | + buffered.append("s(%s)" % self.expr_code(tok[2:-2].strip())) |
1311 | elif tok.startswith('{#'): |
1312 | # Comment: ignore it and move on. |
1313 | continue |
1314 | elif tok.startswith('{%'): |
1315 | # Action tag: split into words and parse further. |
1316 | + flush_output() |
1317 | words = tok[2:-2].strip().split() |
1318 | if words[0] == 'if': |
1319 | - # If: ('if', (expr, body_ops)) |
1320 | - if_ops = [] |
1321 | + # An if statement: evaluate the expression to determine if. |
1322 | assert len(words) == 2 |
1323 | - ops.append(('if', (words[1], if_ops))) |
1324 | - ops_stack.append(ops) |
1325 | - ops = if_ops |
1326 | + ops_stack.append('if') |
1327 | + code.add_line("if %s:" % self.expr_code(words[1])) |
1328 | + code.indent() |
1329 | elif words[0] == 'for': |
1330 | - # For: ('for', (varname, listexpr, body_ops)) |
1331 | + # A loop: iterate over expression result. |
1332 | assert len(words) == 4 and words[2] == 'in' |
1333 | - for_ops = [] |
1334 | - ops.append(('for', (words[1], words[3], for_ops))) |
1335 | - ops_stack.append(ops) |
1336 | - ops = for_ops |
1337 | + ops_stack.append('for') |
1338 | + self.loop_vars.add(words[1]) |
1339 | + code.add_line( |
1340 | + "for c_%s in %s:" % ( |
1341 | + words[1], |
1342 | + self.expr_code(words[3]) |
1343 | + ) |
1344 | + ) |
1345 | + code.indent() |
1346 | elif words[0].startswith('end'): |
1347 | # Endsomething. Pop the ops stack |
1348 | - ops = ops_stack.pop() |
1349 | - assert ops[-1][0] == words[0][3:] |
1350 | + end_what = words[0][3:] |
1351 | + if ops_stack[-1] != end_what: |
1352 | + raise SyntaxError("Mismatched end tag: %r" % end_what) |
1353 | + ops_stack.pop() |
1354 | + code.dedent() |
1355 | else: |
1356 | - raise SyntaxError("Don't understand tag %r" % words) |
1357 | + raise SyntaxError("Don't understand tag: %r" % words[0]) |
1358 | else: |
1359 | - ops.append(('lit', tok)) |
1360 | - |
1361 | - assert not ops_stack, "Unmatched action tag: %r" % ops_stack[-1][0] |
1362 | - self.ops = ops |
1363 | + # Literal content. If it isn't empty, output it. |
1364 | + if tok: |
1365 | + buffered.append("%r" % tok) |
1366 | + flush_output() |
1367 | + |
1368 | + for var_name in self.all_vars - self.loop_vars: |
1369 | + vars_code.add_line("c_%s = ctx[%r]" % (var_name, var_name)) |
1370 | + |
1371 | + if ops_stack: |
1372 | + raise SyntaxError("Unmatched action tag: %r" % ops_stack[-1]) |
1373 | + |
1374 | + code.add_line("return ''.join(result)") |
1375 | + code.dedent() |
1376 | + self.render_function = code.get_function('render') |
1377 | + |
1378 | + def expr_code(self, expr): |
1379 | + """Generate a Python expression for `expr`.""" |
1380 | + if "|" in expr: |
1381 | + pipes = expr.split("|") |
1382 | + code = self.expr_code(pipes[0]) |
1383 | + for func in pipes[1:]: |
1384 | + self.all_vars.add(func) |
1385 | + code = "c_%s(%s)" % (func, code) |
1386 | + elif "." in expr: |
1387 | + dots = expr.split(".") |
1388 | + code = self.expr_code(dots[0]) |
1389 | + args = [repr(d) for d in dots[1:]] |
1390 | + code = "dot(%s, %s)" % (code, ", ".join(args)) |
1391 | + else: |
1392 | + self.all_vars.add(expr) |
1393 | + code = "c_%s" % expr |
1394 | + return code |
1395 | |
1396 | def render(self, context=None): |
1397 | """Render this template by applying it to `context`. |
1398 | @@ -97,70 +194,15 @@ |
1399 | ctx = dict(self.context) |
1400 | if context: |
1401 | ctx.update(context) |
1402 | - |
1403 | - # Run it through an engine, and return the result. |
1404 | - engine = _TempliteEngine(ctx) |
1405 | - engine.execute(self.ops) |
1406 | - return "".join(engine.result) |
1407 | - |
1408 | - |
1409 | -class _TempliteEngine(object): |
1410 | - """Executes Templite objects to produce strings.""" |
1411 | - def __init__(self, context): |
1412 | - self.context = context |
1413 | - self.result = [] |
1414 | - |
1415 | - def execute(self, ops): |
1416 | - """Execute `ops` in the engine. |
1417 | - |
1418 | - Called recursively for the bodies of if's and loops. |
1419 | - |
1420 | - """ |
1421 | - for op, args in ops: |
1422 | - if op == 'lit': |
1423 | - self.result.append(args) |
1424 | - elif op == 'exp': |
1425 | - try: |
1426 | - self.result.append(str(self.evaluate(args))) |
1427 | - except: |
1428 | - exc_class, exc, _ = sys.exc_info() |
1429 | - new_exc = exc_class("Couldn't evaluate {{ %s }}: %s" |
1430 | - % (args, exc)) |
1431 | - raise new_exc |
1432 | - elif op == 'if': |
1433 | - expr, body = args |
1434 | - if self.evaluate(expr): |
1435 | - self.execute(body) |
1436 | - elif op == 'for': |
1437 | - var, lis, body = args |
1438 | - vals = self.evaluate(lis) |
1439 | - for val in vals: |
1440 | - self.context[var] = val |
1441 | - self.execute(body) |
1442 | - else: |
1443 | - raise AssertionError("TempliteEngine doesn't grok op %r" % op) |
1444 | - |
1445 | - def evaluate(self, expr): |
1446 | - """Evaluate an expression. |
1447 | - |
1448 | - `expr` can have pipes and dots to indicate data access and filtering. |
1449 | - |
1450 | - """ |
1451 | - if "|" in expr: |
1452 | - pipes = expr.split("|") |
1453 | - value = self.evaluate(pipes[0]) |
1454 | - for func in pipes[1:]: |
1455 | - value = self.evaluate(func)(value) |
1456 | - elif "." in expr: |
1457 | - dots = expr.split('.') |
1458 | - value = self.evaluate(dots[0]) |
1459 | - for dot in dots[1:]: |
1460 | - try: |
1461 | - value = getattr(value, dot) |
1462 | - except AttributeError: |
1463 | - value = value[dot] |
1464 | - if hasattr(value, '__call__'): |
1465 | - value = value() |
1466 | - else: |
1467 | - value = self.context[expr] |
1468 | + return self.render_function(ctx, self.do_dots) |
1469 | + |
1470 | + def do_dots(self, value, *dots): |
1471 | + """Evaluate dotted expressions at runtime.""" |
1472 | + for dot in dots: |
1473 | + try: |
1474 | + value = getattr(value, dot) |
1475 | + except AttributeError: |
1476 | + value = value[dot] |
1477 | + if hasattr(value, '__call__'): |
1478 | + value = value() |
1479 | return value |
1480 | |
1481 | === modified file 'coverage/version.py' |
1482 | --- coverage/version.py 2014-01-06 21:48:50 +0000 |
1483 | +++ coverage/version.py 2014-03-07 05:33:58 +0000 |
1484 | @@ -1,7 +1,7 @@ |
1485 | """The version and URL for coverage.py""" |
1486 | # This file is exec'ed in setup.py, don't import anything! |
1487 | |
1488 | -__version__ = "3.7" # see detailed history in CHANGES.txt |
1489 | +__version__ = "3.7.1" # see detailed history in CHANGES.txt |
1490 | |
1491 | __url__ = "http://nedbatchelder.com/code/coverage" |
1492 | if max(__version__).isalpha(): |
1493 | |
1494 | === modified file 'coverage/xmlreport.py' |
1495 | --- coverage/xmlreport.py 2014-01-06 21:48:50 +0000 |
1496 | +++ coverage/xmlreport.py 2014-03-07 05:33:58 +0000 |
1497 | @@ -117,7 +117,7 @@ |
1498 | branch_stats = analysis.branch_stats() |
1499 | |
1500 | # For each statement, create an XML 'line' element. |
1501 | - for line in analysis.statements: |
1502 | + for line in sorted(analysis.statements): |
1503 | xline = self.xml_out.createElement("line") |
1504 | xline.setAttribute("number", str(line)) |
1505 | |
1506 | |
1507 | === modified file 'debian/changelog' |
1508 | --- debian/changelog 2014-02-19 20:37:07 +0000 |
1509 | +++ debian/changelog 2014-03-07 05:33:58 +0000 |
1510 | @@ -1,3 +1,34 @@ |
1511 | +python-coverage (3.7.1+dfsg.1-1ubuntu1) trusty; urgency=medium |
1512 | + |
1513 | + * Merge with Debian unstable, remaining change: |
1514 | + - Add python3-coverage.preinst to correctly handle upgrades from |
1515 | + previous releases. |
1516 | + |
1517 | + -- Dmitry Shachnev <mitya57@ubuntu.com> Fri, 07 Mar 2014 09:26:38 +0400 |
1518 | + |
1519 | +python-coverage (3.7.1+dfsg.1-1) unstable; urgency=medium |
1520 | + |
1521 | + * The “Ziauddin Yousafzai” release. |
1522 | + * Urgency “medium” because we fix a bug of severity “serious”. |
1523 | + * New upstream version. |
1524 | + (Closes: bug#735359) |
1525 | + * debian/patches/: |
1526 | + + Patches incorporated upstream: |
1527 | + * 02.use-system-ecmascript-libraries.patch |
1528 | + Remaining patch files re-sequenced contiguously. |
1529 | + + Add editor hints to patch files. |
1530 | + * debian/repack: |
1531 | + + Correct quoting of parameters (quote parameters used as filesystem |
1532 | + entry names, don't quote parameters used as numbers). |
1533 | + * debian/rules: |
1534 | + + Explicitly replace shebang for programs needing default Python |
1535 | + interpreter (Closes: bug#736121). |
1536 | + + Correct generation of Python version strings for object code |
1537 | + filenames (Closes: bug#740053). |
1538 | + Thanks to Dmitry Shachnev for the bug report and patch. |
1539 | + |
1540 | + -- Ben Finney <ben+debian@benfinney.id.au> Wed, 05 Mar 2014 13:14:27 +1100 |
1541 | + |
1542 | python-coverage (3.7+dfsg.1-4ubuntu2) trusty; urgency=medium |
1543 | |
1544 | * Build for python 3.4. |
1545 | |
1546 | === modified file 'debian/patches/01.omit-resource-files-from-distutils-setup.patch' |
1547 | --- debian/patches/01.omit-resource-files-from-distutils-setup.patch 2013-10-15 13:16:36 +0000 |
1548 | +++ debian/patches/01.omit-resource-files-from-distutils-setup.patch 2014-03-07 05:33:58 +0000 |
1549 | @@ -32,3 +32,14 @@ |
1550 | |
1551 | entry_points = {'console_scripts': scripts}, |
1552 | |
1553 | + |
1554 | + |
1555 | |
1556 | +Local variables: |
1557 | +coding: utf-8 |
1558 | +mode: diff |
1559 | +time-stamp-format: "%:y-%02m-%02d" |
1560 | +time-stamp-start: "^Last-Update:[ ]+" |
1561 | +time-stamp-end: "$" |
1562 | +time-stamp-line-limit: 20 |
1563 | +End: |
1564 | +vim: fileencoding=utf-8 filetype=diff : |
1565 | |
1566 | === added file 'debian/patches/02.rename-public-programs.patch' |
1567 | --- debian/patches/02.rename-public-programs.patch 1970-01-01 00:00:00 +0000 |
1568 | +++ debian/patches/02.rename-public-programs.patch 2014-03-07 05:33:58 +0000 |
1569 | @@ -0,0 +1,50 @@ |
1570 | +Description: Rename public programs to be clear what they're for. |
1571 | + . |
1572 | + The upstream choice of ‘coverage’ is too broad a command name for a |
1573 | + Python-specific programmer tool. |
1574 | + . |
1575 | + Created to work with “entry points” feature of Python's Distribute. |
1576 | +Bug: https://bitbucket.org/ned/coveragepy/issue/272/ |
1577 | +Author: Ben Finney <ben+debian@benfinney.id.au> |
1578 | +Last-Update: 2013-10-16 |
1579 | + |
1580 | +--- old/setup.py 2013-10-07 07:40:00.000000000 +1100 |
1581 | ++++ new/setup.py 2013-10-08 10:21:00.000000000 +1100 |
1582 | +@@ -1,3 +1,4 @@ |
1583 | ++# coding: utf-8 |
1584 | + # setup.py for coverage.py |
1585 | + |
1586 | + """Code coverage measurement for Python |
1587 | +@@ -71,13 +72,15 @@ |
1588 | + devstat = "5 - Production/Stable" |
1589 | + classifier_list.append("Development Status :: " + devstat) |
1590 | + |
1591 | +-# Install a script as "coverage", and as "coverage[23]", and as |
1592 | +-# "coverage-2.7" (or whatever). |
1593 | ++# Install a default ‘python-coverage’ program, and versioned as |
1594 | ++# ‘python2.7-coverage’, ‘python3-coverage’, etc. |
1595 | + scripts = [ |
1596 | +- 'coverage = coverage:main', |
1597 | +- 'coverage%d = coverage:main' % sys.version_info[:1], |
1598 | +- 'coverage-%d.%d = coverage:main' % sys.version_info[:2], |
1599 | +- ] |
1600 | ++ "python-coverage = coverage:main", |
1601 | ++ "python{version[0]}-coverage = coverage:main".format( |
1602 | ++ version=sys.version_info), |
1603 | ++ "python{version[0]}.{version[1]}-coverage = coverage:main".format( |
1604 | ++ version=sys.version_info), |
1605 | ++ ] |
1606 | + |
1607 | + # Create the keyword arguments for setup() |
1608 | + |
1609 | + |
1610 | + |
1611 | |
1612 | +Local variables: |
1613 | +coding: utf-8 |
1614 | +mode: diff |
1615 | +time-stamp-format: "%:y-%02m-%02d" |
1616 | +time-stamp-start: "^Last-Update:[ ]+" |
1617 | +time-stamp-end: "$" |
1618 | +time-stamp-line-limit: 20 |
1619 | +End: |
1620 | +vim: fileencoding=utf-8 filetype=diff : |
1621 | |
1622 | === removed file 'debian/patches/02.use-system-ecmascript-libraries.patch' |
1623 | --- debian/patches/02.use-system-ecmascript-libraries.patch 2013-10-15 13:16:36 +0000 |
1624 | +++ debian/patches/02.use-system-ecmascript-libraries.patch 1970-01-01 00:00:00 +0000 |
1625 | @@ -1,48 +0,0 @@ |
1626 | -Description: Use Debian packaged ECMAScript libraries. |
1627 | - . |
1628 | - Per Debian policy §4.13 “Convenience copies of code”, packages should not |
1629 | - bundle third-party code. Instead, the program should use the system |
1630 | - packages of those libraries. |
1631 | -Bug: https://bitbucket.org/ned/coveragepy/issue/259/ |
1632 | -Bug-Debian: http://bugs.debian.org/596212 |
1633 | -Author: Ben Finney <ben+debian@benfinney.id.au> |
1634 | -Last-Update: 2013-10-08 |
1635 | - |
1636 | -diff -ruN old/coverage/html.py new/coverage/html.py |
1637 | ---- old/coverage/html.py 2013-10-07 07:40:00.000000000 +1100 |
1638 | -+++ new/coverage/html.py 2013-10-08 10:21:00.000000000 +1100 |
1639 | -@@ -48,10 +48,6 @@ |
1640 | - # These files will be copied from the htmlfiles dir to the output dir. |
1641 | - STATIC_FILES = [ |
1642 | - "style.css", |
1643 | -- "jquery.min.js", |
1644 | -- "jquery.hotkeys.js", |
1645 | -- "jquery.isonscreen.js", |
1646 | -- "jquery.tablesorter.min.js", |
1647 | - "coverage_html.js", |
1648 | - "keybd_closed.png", |
1649 | - "keybd_open.png", |
1650 | -@@ -123,6 +119,23 @@ |
1651 | - os.path.join(self.directory, static) |
1652 | - ) |
1653 | - |
1654 | -+ system_javascript_path = os.path.join( |
1655 | -+ os.sep, "usr", "share", "javascript") |
1656 | -+ system_javascript_libraries = { |
1657 | -+ "jquery.min.js": |
1658 | -+ os.path.join(system_javascript_path, "jquery"), |
1659 | -+ "jquery.hotkeys.js": |
1660 | -+ os.path.join(system_javascript_path, "jquery-hotkeys"), |
1661 | -+ "jquery.isonscreen.js": |
1662 | -+ os.path.join(system_javascript_path, "jquery-isonscreen"), |
1663 | -+ "jquery.tablesorter.min.js": |
1664 | -+ os.path.join(system_javascript_path, "jquery-tablesorter"), |
1665 | -+ } |
1666 | -+ for static, source_dir in system_javascript_libraries.items(): |
1667 | -+ shutil.copyfile( |
1668 | -+ os.path.join(source_dir, static), |
1669 | -+ os.path.join(self.directory, static)) |
1670 | -+ |
1671 | - # The user may have extra CSS they want copied. |
1672 | - if self.extra_css: |
1673 | - shutil.copyfile( |
1674 | |
1675 | === removed file 'debian/patches/03.rename-public-programs.patch' |
1676 | --- debian/patches/03.rename-public-programs.patch 2013-10-29 09:13:11 +0000 |
1677 | +++ debian/patches/03.rename-public-programs.patch 1970-01-01 00:00:00 +0000 |
1678 | @@ -1,39 +0,0 @@ |
1679 | -Description: Rename public programs to be clear what they're for. |
1680 | - . |
1681 | - The upstream choice of ‘coverage’ is too broad a command name for a |
1682 | - Python-specific programmer tool. |
1683 | - . |
1684 | - Created to work with “entry points” feature of Python's Distribute. |
1685 | -Bug: https://bitbucket.org/ned/coveragepy/issue/272/ |
1686 | -Author: Ben Finney <ben+debian@benfinney.id.au> |
1687 | -Last-Update: 2013-10-16 |
1688 | - |
1689 | ---- old/setup.py 2013-10-07 07:40:00.000000000 +1100 |
1690 | -+++ new/setup.py 2013-10-08 10:21:00.000000000 +1100 |
1691 | -@@ -1,3 +1,4 @@ |
1692 | -+# coding: utf-8 |
1693 | - # setup.py for coverage.py |
1694 | - |
1695 | - """Code coverage measurement for Python |
1696 | -@@ -71,13 +72,15 @@ |
1697 | - devstat = "5 - Production/Stable" |
1698 | - classifier_list.append("Development Status :: " + devstat) |
1699 | - |
1700 | --# Install a script as "coverage", and as "coverage[23]", and as |
1701 | --# "coverage-2.7" (or whatever). |
1702 | -+# Install a default ‘python-coverage’ program, and versioned as |
1703 | -+# ‘python2.7-coverage’, ‘python3-coverage’, etc. |
1704 | - scripts = [ |
1705 | -- 'coverage = coverage:main', |
1706 | -- 'coverage%d = coverage:main' % sys.version_info[:1], |
1707 | -- 'coverage-%d.%d = coverage:main' % sys.version_info[:2], |
1708 | -- ] |
1709 | -+ "python-coverage = coverage:main", |
1710 | -+ "python{version[0]}-coverage = coverage:main".format( |
1711 | -+ version=sys.version_info), |
1712 | -+ "python{version[0]}.{version[1]}-coverage = coverage:main".format( |
1713 | -+ version=sys.version_info), |
1714 | -+ ] |
1715 | - |
1716 | - # Create the keyword arguments for setup() |
1717 | - |
1718 | |
1719 | === modified file 'debian/patches/series' |
1720 | --- debian/patches/series 2014-01-06 21:48:50 +0000 |
1721 | +++ debian/patches/series 2014-03-07 05:33:58 +0000 |
1722 | @@ -1,3 +1,2 @@ |
1723 | 01.omit-resource-files-from-distutils-setup.patch |
1724 | -02.use-system-ecmascript-libraries.patch |
1725 | -03.rename-public-programs.patch |
1726 | +02.rename-public-programs.patch |
1727 | |
1728 | === removed file 'debian/python-coverage.1' |
1729 | --- debian/python-coverage.1 2014-02-19 20:37:07 +0000 |
1730 | +++ debian/python-coverage.1 1970-01-01 00:00:00 +0000 |
1731 | @@ -1,279 +0,0 @@ |
1732 | -'\" -*- coding: utf-8 -*- |
1733 | -.\" Man page generated from reStructuredText. |
1734 | -. |
1735 | -.TH PYTHON-COVERAGE 1 "2013-10-07" "" "Coverage" |
1736 | -.SH NAME |
1737 | -python-coverage \- measure code coverage of Python program execution |
1738 | -. |
1739 | -.nr rst2man-indent-level 0 |
1740 | -. |
1741 | -.de1 rstReportMargin |
1742 | -\\$1 \\n[an-margin] |
1743 | -level \\n[rst2man-indent-level] |
1744 | -level margin: \\n[rst2man-indent\\n[rst2man-indent-level]] |
1745 | -- |
1746 | -\\n[rst2man-indent0] |
1747 | -\\n[rst2man-indent1] |
1748 | -\\n[rst2man-indent2] |
1749 | -.. |
1750 | -.de1 INDENT |
1751 | -.\" .rstReportMargin pre: |
1752 | -. RS \\$1 |
1753 | -. nr rst2man-indent\\n[rst2man-indent-level] \\n[an-margin] |
1754 | -. nr rst2man-indent-level +1 |
1755 | -.\" .rstReportMargin post: |
1756 | -.. |
1757 | -.de UNINDENT |
1758 | -. RE |
1759 | -.\" indent \\n[an-margin] |
1760 | -.\" old: \\n[rst2man-indent\\n[rst2man-indent-level]] |
1761 | -.nr rst2man-indent-level -1 |
1762 | -.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]] |
1763 | -.in \\n[rst2man-indent\\n[rst2man-indent-level]]u |
1764 | -.. |
1765 | -.SH SYNOPSIS |
1766 | -.nf |
1767 | -\fBpython\-coverage\fP \fIcommand\fP [ \fIoption\fP ... ] |
1768 | -\fBpython\-coverage\fP \fBhelp\fP [ \fIcommand\fP ] |
1769 | -\fBpython\-coverage\fP \fBhelp\fP \fBclassic\fP |
1770 | -.fi |
1771 | -.sp |
1772 | -.SH DESCRIPTION |
1773 | -.sp |
1774 | -\fBpython\-coverage\fP executes a Python program, measures which of its statements are |
1775 | -executed and which are not, and reports these coverage measurements. |
1776 | -.SH COMMAND OVERVIEW |
1777 | -.INDENT 0.0 |
1778 | -.TP |
1779 | -.B \fBpython\-coverage\fP \fBannotate\fP |
1780 | -Annotate source files with execution information. |
1781 | -.TP |
1782 | -.B \fBpython\-coverage\fP \fBcombine\fP |
1783 | -Combine a number of data files. |
1784 | -.TP |
1785 | -.B \fBpython\-coverage\fP \fBerase\fP |
1786 | -Erase previously collected coverage data. |
1787 | -.TP |
1788 | -.B \fBpython\-coverage\fP \fBhelp\fP |
1789 | -Get help on using coverage.py. |
1790 | -.TP |
1791 | -.B \fBpython\-coverage\fP \fBhtml\fP |
1792 | -Create an HTML report. |
1793 | -.TP |
1794 | -.B \fBpython\-coverage\fP \fBreport\fP |
1795 | -Report coverage stats on modules. |
1796 | -.TP |
1797 | -.B \fBpython\-coverage\fP \fBrun\fP |
1798 | -Run a Python program and measure code execution. |
1799 | -.TP |
1800 | -.B \fBpython\-coverage\fP \fBxml\fP |
1801 | -Create an XML report of coverage results. |
1802 | -.UNINDENT |
1803 | -.SH GLOBAL OPTIONS |
1804 | -.INDENT 0.0 |
1805 | -.TP |
1806 | -.B \fB\-\-help\fP, \fB\-h\fP |
1807 | -Describe how to use Coverage, in general or a command. |
1808 | -.TP |
1809 | -.B \fB\-\-rcfile\fP \fIRCFILE\fP |
1810 | -Specify configuration file \fIRCFILE\fP\&. Defaults to \fB\&.coveragerc\fP\&. |
1811 | -.TP |
1812 | -.B \fB\-\-omit\fP \fIPATTERN\fP ... |
1813 | -Omit files when their filename matches one of these PATTERNs. |
1814 | -Usually needs quoting on the command line. |
1815 | -.TP |
1816 | -.B \fB\-\-include\fP \fIPATTERN\fP ... |
1817 | -Include files only when their filename path matches one of these |
1818 | -PATTERNs. Usually needs quoting on the command line. |
1819 | -.UNINDENT |
1820 | -.SH COMMAND REFERENCE |
1821 | -.sp |
1822 | -\fBannotate\fP |
1823 | -.INDENT 0.0 |
1824 | -.INDENT 3.5 |
1825 | -Options: |
1826 | -.INDENT 0.0 |
1827 | -.TP |
1828 | -.B \-d \fIDIR\fP, \-\-directory \fIDIR\fP |
1829 | -Write the output files to DIR. |
1830 | -.TP |
1831 | -.B \-i, \-\-ignore\-errors |
1832 | -Ignore errors while reading source files. |
1833 | -.UNINDENT |
1834 | -.UNINDENT |
1835 | -.UNINDENT |
1836 | -.sp |
1837 | -\fBcombine\fP |
1838 | -.INDENT 0.0 |
1839 | -.INDENT 3.5 |
1840 | -Combine data from multiple coverage files collected with \fBrun \-p\fP\&. |
1841 | -The combined results are written to a single file representing the |
1842 | -union of the data. |
1843 | -.UNINDENT |
1844 | -.UNINDENT |
1845 | -.sp |
1846 | -\fBerase\fP |
1847 | -.INDENT 0.0 |
1848 | -.INDENT 3.5 |
1849 | -Erase previously collected coverage data. |
1850 | -.UNINDENT |
1851 | -.UNINDENT |
1852 | -.sp |
1853 | -\fBhelp\fP [ \fIcommand\fP ] |
1854 | -.INDENT 0.0 |
1855 | -.INDENT 3.5 |
1856 | -Describe how to use Coverage. |
1857 | -.UNINDENT |
1858 | -.UNINDENT |
1859 | -.sp |
1860 | -\fBhelp\fP \fBclassic\fP |
1861 | -.INDENT 0.0 |
1862 | -.INDENT 3.5 |
1863 | -Describe help on older command syntax. |
1864 | -.UNINDENT |
1865 | -.UNINDENT |
1866 | -.sp |
1867 | -\fBhtml\fP [ \fIoption\fP ... ] [ \fIMODULE\fP ... ] |
1868 | -.INDENT 0.0 |
1869 | -.INDENT 3.5 |
1870 | -Create an HTML report of the coverage of each \fIMODULE\fP file. Each file |
1871 | -gets its own page, with the source decorated to show executed, |
1872 | -excluded, and missed lines. |
1873 | -.sp |
1874 | -Options: |
1875 | -.INDENT 0.0 |
1876 | -.TP |
1877 | -.B \-d \fIDIR\fP, \-\-directory \fIDIR\fP |
1878 | -Write the output files to \fIDIR\fP\&. |
1879 | -.TP |
1880 | -.B \-\-title \fITITLE\fP |
1881 | -Use the text string \fITITLE\fP as the title on the HTML. |
1882 | -.TP |
1883 | -.B \-\-fail\-under \fIMIN\fP |
1884 | -Exit with a status of 2 if the total coverage is less than \fIMIN\fP\&. |
1885 | -.TP |
1886 | -.B \-i, \-\-ignore\-errors |
1887 | -Ignore errors while reading source files. |
1888 | -.UNINDENT |
1889 | -.UNINDENT |
1890 | -.UNINDENT |
1891 | -.sp |
1892 | -\fBreport\fP [ \fIoption\fP ... ] [ \fIMODULE\fP ... ] |
1893 | -.INDENT 0.0 |
1894 | -.INDENT 3.5 |
1895 | -Report coverage statistics on each \fIMODULE\fP\&. |
1896 | -.sp |
1897 | -Options: |
1898 | -.INDENT 0.0 |
1899 | -.TP |
1900 | -.B \-\-fail\-under \fIMIN\fP |
1901 | -Exit with a status of 2 if the total coverage is less than \fIMIN\fP\&. |
1902 | -.TP |
1903 | -.B \-i, \-\-ignore\-errors |
1904 | -Ignore errors while reading source files. |
1905 | -.TP |
1906 | -.B \-m, \-\-show\-missing |
1907 | -Show line numbers of statements in each module that weren\(aqt |
1908 | -executed. |
1909 | -.UNINDENT |
1910 | -.UNINDENT |
1911 | -.UNINDENT |
1912 | -.sp |
1913 | -\fBrun\fP [ \fIoptions\fP ... ] \fIPROGRAMFILE\fP [ \fIprogram_options\fP ] |
1914 | -.INDENT 0.0 |
1915 | -.INDENT 3.5 |
1916 | -Run a Python program \fIPROGRAMFILE\fP, measuring code execution. |
1917 | -.sp |
1918 | -Options: |
1919 | -.INDENT 0.0 |
1920 | -.TP |
1921 | -.B \-a, \-\-append |
1922 | -Append coverage data to .coverage, otherwise it is started clean |
1923 | -with each run. |
1924 | -.TP |
1925 | -.B \-\-branch |
1926 | -Measure branch coverage in addition to statement coverage. |
1927 | -.TP |
1928 | -.B \-\-debug \fIDEBUGOPT\fP,... |
1929 | -Debug options \fIDEBUGOPT\fP, separated by commas |
1930 | -.TP |
1931 | -.B \-L, \-\-pylib |
1932 | -Measure coverage even inside the Python installed library, which |
1933 | -isn\(aqt done by default. |
1934 | -.TP |
1935 | -.B \-p, \-\-parallel\-mode |
1936 | -Append the machine name, process id and random number to the |
1937 | -\fB\&.coverage\fP data file name to simplify collecting data from many |
1938 | -processes. |
1939 | -.TP |
1940 | -.B \-\-timid |
1941 | -Use a simpler but slower trace method. Try this if you get |
1942 | -seemingly impossible results! |
1943 | -.TP |
1944 | -.B \-\-source \fISOURCE\fP ... |
1945 | -A list of packages or directories of code to be measured. |
1946 | -.UNINDENT |
1947 | -.UNINDENT |
1948 | -.UNINDENT |
1949 | -.sp |
1950 | -\fBxml\fP [ \fIoptions\fP ... ] [ \fIMODULES\fP ... ] |
1951 | -.INDENT 0.0 |
1952 | -.INDENT 3.5 |
1953 | -Generate an XML report of coverage results on each \fIMODULE\fP\&. |
1954 | -.sp |
1955 | -Options: |
1956 | -.INDENT 0.0 |
1957 | -.TP |
1958 | -.B \-\-fail\-under \fIMIN\fP |
1959 | -Exit with a status of 2 if the total coverage is less than \fIMIN\fP\&. |
1960 | -.TP |
1961 | -.B \-i, \-\-ignore\-errors |
1962 | -Ignore errors while reading source files. |
1963 | -.TP |
1964 | -.B \-o \fIOUTFILE\fP |
1965 | -Write the XML report to \fIOUTFILE\fP\&. Defaults to \fBcoverage.xml\fP\&. |
1966 | -.UNINDENT |
1967 | -.UNINDENT |
1968 | -.UNINDENT |
1969 | -.SH ENVIRONMENT VARIABLES |
1970 | -.sp |
1971 | -COVERAGE_FILE |
1972 | -.INDENT 0.0 |
1973 | -.INDENT 3.5 |
1974 | -Path to the file where coverage measurements are collected to and |
1975 | -reported from. Default: \fB\&.coverage\fP in the current working directory. |
1976 | -.UNINDENT |
1977 | -.UNINDENT |
1978 | -.sp |
1979 | -COVERAGE_OPTIONS |
1980 | -.INDENT 0.0 |
1981 | -.INDENT 3.5 |
1982 | -Space\-separated series of command\-line options to \fBpython\-coverage\fP\&. Default: |
1983 | -empty. |
1984 | -.UNINDENT |
1985 | -.UNINDENT |
1986 | -.SH HISTORY |
1987 | -.sp |
1988 | -The \fBpython\-coverage\fP command is a Python program which calls the \fBcoverage\fP |
1989 | -Python library to do all the work. |
1990 | -.sp |
1991 | -The library was originally developed by Gareth Rees, and is now developed |
1992 | -by Ned Batchelder. |
1993 | -.sp |
1994 | -This manual page was written by Ben Finney <\fI\%ben+python@benfinney.id.au\fP>\&. |
1995 | -.\" Local variables: |
1996 | -.\" mode: rst |
1997 | -.\" coding: utf-8 |
1998 | -.\" time-stamp-format: "%:y-%02m-%02d" |
1999 | -.\" time-stamp-start: "^:Date:[ ]+" |
2000 | -.\" time-stamp-end: "$" |
2001 | -.\" time-stamp-line-limit: 20 |
2002 | -.\" End: |
2003 | -.\" vim: filetype=rst fileencoding=utf-8 : |
2004 | -. |
2005 | -.SH AUTHOR |
2006 | -Ben Finney <ben+python@benfinney.id.au> |
2007 | -.SH COPYRIGHT |
2008 | -BSD license, attribution and disclaimer required. |
2009 | -.\" Generated by docutils manpage writer. |
2010 | -. |
2011 | |
2012 | === removed file 'debian/python-coverage.1.tmp' |
2013 | --- debian/python-coverage.1.tmp 2014-02-19 20:37:07 +0000 |
2014 | +++ debian/python-coverage.1.tmp 1970-01-01 00:00:00 +0000 |
2015 | @@ -1,278 +0,0 @@ |
2016 | -.\" Man page generated from reStructuredText. |
2017 | -. |
2018 | -.TH PYTHON-COVERAGE 1 "2013-10-07" "" "Coverage" |
2019 | -.SH NAME |
2020 | -python-coverage \- measure code coverage of Python program execution |
2021 | -. |
2022 | -.nr rst2man-indent-level 0 |
2023 | -. |
2024 | -.de1 rstReportMargin |
2025 | -\\$1 \\n[an-margin] |
2026 | -level \\n[rst2man-indent-level] |
2027 | -level margin: \\n[rst2man-indent\\n[rst2man-indent-level]] |
2028 | -- |
2029 | -\\n[rst2man-indent0] |
2030 | -\\n[rst2man-indent1] |
2031 | -\\n[rst2man-indent2] |
2032 | -.. |
2033 | -.de1 INDENT |
2034 | -.\" .rstReportMargin pre: |
2035 | -. RS \\$1 |
2036 | -. nr rst2man-indent\\n[rst2man-indent-level] \\n[an-margin] |
2037 | -. nr rst2man-indent-level +1 |
2038 | -.\" .rstReportMargin post: |
2039 | -.. |
2040 | -.de UNINDENT |
2041 | -. RE |
2042 | -.\" indent \\n[an-margin] |
2043 | -.\" old: \\n[rst2man-indent\\n[rst2man-indent-level]] |
2044 | -.nr rst2man-indent-level -1 |
2045 | -.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]] |
2046 | -.in \\n[rst2man-indent\\n[rst2man-indent-level]]u |
2047 | -.. |
2048 | -.SH SYNOPSIS |
2049 | -.nf |
2050 | -\fBpython\-coverage\fP \fIcommand\fP [ \fIoption\fP ... ] |
2051 | -\fBpython\-coverage\fP \fBhelp\fP [ \fIcommand\fP ] |
2052 | -\fBpython\-coverage\fP \fBhelp\fP \fBclassic\fP |
2053 | -.fi |
2054 | -.sp |
2055 | -.SH DESCRIPTION |
2056 | -.sp |
2057 | -\fBpython\-coverage\fP executes a Python program, measures which of its statements are |
2058 | -executed and which are not, and reports these coverage measurements. |
2059 | -.SH COMMAND OVERVIEW |
2060 | -.INDENT 0.0 |
2061 | -.TP |
2062 | -.B \fBpython\-coverage\fP \fBannotate\fP |
2063 | -Annotate source files with execution information. |
2064 | -.TP |
2065 | -.B \fBpython\-coverage\fP \fBcombine\fP |
2066 | -Combine a number of data files. |
2067 | -.TP |
2068 | -.B \fBpython\-coverage\fP \fBerase\fP |
2069 | -Erase previously collected coverage data. |
2070 | -.TP |
2071 | -.B \fBpython\-coverage\fP \fBhelp\fP |
2072 | -Get help on using coverage.py. |
2073 | -.TP |
2074 | -.B \fBpython\-coverage\fP \fBhtml\fP |
2075 | -Create an HTML report. |
2076 | -.TP |
2077 | -.B \fBpython\-coverage\fP \fBreport\fP |
2078 | -Report coverage stats on modules. |
2079 | -.TP |
2080 | -.B \fBpython\-coverage\fP \fBrun\fP |
2081 | -Run a Python program and measure code execution. |
2082 | -.TP |
2083 | -.B \fBpython\-coverage\fP \fBxml\fP |
2084 | -Create an XML report of coverage results. |
2085 | -.UNINDENT |
2086 | -.SH GLOBAL OPTIONS |
2087 | -.INDENT 0.0 |
2088 | -.TP |
2089 | -.B \fB\-\-help\fP, \fB\-h\fP |
2090 | -Describe how to use Coverage, in general or a command. |
2091 | -.TP |
2092 | -.B \fB\-\-rcfile\fP \fIRCFILE\fP |
2093 | -Specify configuration file \fIRCFILE\fP\&. Defaults to \fB\&.coveragerc\fP\&. |
2094 | -.TP |
2095 | -.B \fB\-\-omit\fP \fIPATTERN\fP ... |
2096 | -Omit files when their filename matches one of these PATTERNs. |
2097 | -Usually needs quoting on the command line. |
2098 | -.TP |
2099 | -.B \fB\-\-include\fP \fIPATTERN\fP ... |
2100 | -Include files only when their filename path matches one of these |
2101 | -PATTERNs. Usually needs quoting on the command line. |
2102 | -.UNINDENT |
2103 | -.SH COMMAND REFERENCE |
2104 | -.sp |
2105 | -\fBannotate\fP |
2106 | -.INDENT 0.0 |
2107 | -.INDENT 3.5 |
2108 | -Options: |
2109 | -.INDENT 0.0 |
2110 | -.TP |
2111 | -.B \-d \fIDIR\fP, \-\-directory \fIDIR\fP |
2112 | -Write the output files to DIR. |
2113 | -.TP |
2114 | -.B \-i, \-\-ignore\-errors |
2115 | -Ignore errors while reading source files. |
2116 | -.UNINDENT |
2117 | -.UNINDENT |
2118 | -.UNINDENT |
2119 | -.sp |
2120 | -\fBcombine\fP |
2121 | -.INDENT 0.0 |
2122 | -.INDENT 3.5 |
2123 | -Combine data from multiple coverage files collected with \fBrun \-p\fP\&. |
2124 | -The combined results are written to a single file representing the |
2125 | -union of the data. |
2126 | -.UNINDENT |
2127 | -.UNINDENT |
2128 | -.sp |
2129 | -\fBerase\fP |
2130 | -.INDENT 0.0 |
2131 | -.INDENT 3.5 |
2132 | -Erase previously collected coverage data. |
2133 | -.UNINDENT |
2134 | -.UNINDENT |
2135 | -.sp |
2136 | -\fBhelp\fP [ \fIcommand\fP ] |
2137 | -.INDENT 0.0 |
2138 | -.INDENT 3.5 |
2139 | -Describe how to use Coverage. |
2140 | -.UNINDENT |
2141 | -.UNINDENT |
2142 | -.sp |
2143 | -\fBhelp\fP \fBclassic\fP |
2144 | -.INDENT 0.0 |
2145 | -.INDENT 3.5 |
2146 | -Describe help on older command syntax. |
2147 | -.UNINDENT |
2148 | -.UNINDENT |
2149 | -.sp |
2150 | -\fBhtml\fP [ \fIoption\fP ... ] [ \fIMODULE\fP ... ] |
2151 | -.INDENT 0.0 |
2152 | -.INDENT 3.5 |
2153 | -Create an HTML report of the coverage of each \fIMODULE\fP file. Each file |
2154 | -gets its own page, with the source decorated to show executed, |
2155 | -excluded, and missed lines. |
2156 | -.sp |
2157 | -Options: |
2158 | -.INDENT 0.0 |
2159 | -.TP |
2160 | -.B \-d \fIDIR\fP, \-\-directory \fIDIR\fP |
2161 | -Write the output files to \fIDIR\fP\&. |
2162 | -.TP |
2163 | -.B \-\-title \fITITLE\fP |
2164 | -Use the text string \fITITLE\fP as the title on the HTML. |
2165 | -.TP |
2166 | -.B \-\-fail\-under \fIMIN\fP |
2167 | -Exit with a status of 2 if the total coverage is less than \fIMIN\fP\&. |
2168 | -.TP |
2169 | -.B \-i, \-\-ignore\-errors |
2170 | -Ignore errors while reading source files. |
2171 | -.UNINDENT |
2172 | -.UNINDENT |
2173 | -.UNINDENT |
2174 | -.sp |
2175 | -\fBreport\fP [ \fIoption\fP ... ] [ \fIMODULE\fP ... ] |
2176 | -.INDENT 0.0 |
2177 | -.INDENT 3.5 |
2178 | -Report coverage statistics on each \fIMODULE\fP\&. |
2179 | -.sp |
2180 | -Options: |
2181 | -.INDENT 0.0 |
2182 | -.TP |
2183 | -.B \-\-fail\-under \fIMIN\fP |
2184 | -Exit with a status of 2 if the total coverage is less than \fIMIN\fP\&. |
2185 | -.TP |
2186 | -.B \-i, \-\-ignore\-errors |
2187 | -Ignore errors while reading source files. |
2188 | -.TP |
2189 | -.B \-m, \-\-show\-missing |
2190 | -Show line numbers of statements in each module that weren\(aqt |
2191 | -executed. |
2192 | -.UNINDENT |
2193 | -.UNINDENT |
2194 | -.UNINDENT |
2195 | -.sp |
2196 | -\fBrun\fP [ \fIoptions\fP ... ] \fIPROGRAMFILE\fP [ \fIprogram_options\fP ] |
2197 | -.INDENT 0.0 |
2198 | -.INDENT 3.5 |
2199 | -Run a Python program \fIPROGRAMFILE\fP, measuring code execution. |
2200 | -.sp |
2201 | -Options: |
2202 | -.INDENT 0.0 |
2203 | -.TP |
2204 | -.B \-a, \-\-append |
2205 | -Append coverage data to .coverage, otherwise it is started clean |
2206 | -with each run. |
2207 | -.TP |
2208 | -.B \-\-branch |
2209 | -Measure branch coverage in addition to statement coverage. |
2210 | -.TP |
2211 | -.B \-\-debug \fIDEBUGOPT\fP,... |
2212 | -Debug options \fIDEBUGOPT\fP, separated by commas |
2213 | -.TP |
2214 | -.B \-L, \-\-pylib |
2215 | -Measure coverage even inside the Python installed library, which |
2216 | -isn\(aqt done by default. |
2217 | -.TP |
2218 | -.B \-p, \-\-parallel\-mode |
2219 | -Append the machine name, process id and random number to the |
2220 | -\fB\&.coverage\fP data file name to simplify collecting data from many |
2221 | -processes. |
2222 | -.TP |
2223 | -.B \-\-timid |
2224 | -Use a simpler but slower trace method. Try this if you get |
2225 | -seemingly impossible results! |
2226 | -.TP |
2227 | -.B \-\-source \fISOURCE\fP ... |
2228 | -A list of packages or directories of code to be measured. |
2229 | -.UNINDENT |
2230 | -.UNINDENT |
2231 | -.UNINDENT |
2232 | -.sp |
2233 | -\fBxml\fP [ \fIoptions\fP ... ] [ \fIMODULES\fP ... ] |
2234 | -.INDENT 0.0 |
2235 | -.INDENT 3.5 |
2236 | -Generate an XML report of coverage results on each \fIMODULE\fP\&. |
2237 | -.sp |
2238 | -Options: |
2239 | -.INDENT 0.0 |
2240 | -.TP |
2241 | -.B \-\-fail\-under \fIMIN\fP |
2242 | -Exit with a status of 2 if the total coverage is less than \fIMIN\fP\&. |
2243 | -.TP |
2244 | -.B \-i, \-\-ignore\-errors |
2245 | -Ignore errors while reading source files. |
2246 | -.TP |
2247 | -.B \-o \fIOUTFILE\fP |
2248 | -Write the XML report to \fIOUTFILE\fP\&. Defaults to \fBcoverage.xml\fP\&. |
2249 | -.UNINDENT |
2250 | -.UNINDENT |
2251 | -.UNINDENT |
2252 | -.SH ENVIRONMENT VARIABLES |
2253 | -.sp |
2254 | -COVERAGE_FILE |
2255 | -.INDENT 0.0 |
2256 | -.INDENT 3.5 |
2257 | -Path to the file where coverage measurements are collected to and |
2258 | -reported from. Default: \fB\&.coverage\fP in the current working directory. |
2259 | -.UNINDENT |
2260 | -.UNINDENT |
2261 | -.sp |
2262 | -COVERAGE_OPTIONS |
2263 | -.INDENT 0.0 |
2264 | -.INDENT 3.5 |
2265 | -Space\-separated series of command\-line options to \fBpython\-coverage\fP\&. Default: |
2266 | -empty. |
2267 | -.UNINDENT |
2268 | -.UNINDENT |
2269 | -.SH HISTORY |
2270 | -.sp |
2271 | -The \fBpython\-coverage\fP command is a Python program which calls the \fBcoverage\fP |
2272 | -Python library to do all the work. |
2273 | -.sp |
2274 | -The library was originally developed by Gareth Rees, and is now developed |
2275 | -by Ned Batchelder. |
2276 | -.sp |
2277 | -This manual page was written by Ben Finney <\fI\%ben+python@benfinney.id.au\fP>\&. |
2278 | -.\" Local variables: |
2279 | -.\" mode: rst |
2280 | -.\" coding: utf-8 |
2281 | -.\" time-stamp-format: "%:y-%02m-%02d" |
2282 | -.\" time-stamp-start: "^:Date:[ ]+" |
2283 | -.\" time-stamp-end: "$" |
2284 | -.\" time-stamp-line-limit: 20 |
2285 | -.\" End: |
2286 | -.\" vim: filetype=rst fileencoding=utf-8 : |
2287 | -. |
2288 | -.SH AUTHOR |
2289 | -Ben Finney <ben+python@benfinney.id.au> |
2290 | -.SH COPYRIGHT |
2291 | -BSD license, attribution and disclaimer required. |
2292 | -.\" Generated by docutils manpage writer. |
2293 | -. |
2294 | |
2295 | === modified file 'debian/repack' |
2296 | --- debian/repack 2014-01-13 14:51:52 +0000 |
2297 | +++ debian/repack 2014-03-07 05:33:58 +0000 |
2298 | @@ -7,11 +7,11 @@ |
2299 | set -o nounset |
2300 | |
2301 | function usage() { |
2302 | - progname=$(basename $0) |
2303 | + progname="$(basename "$0")" |
2304 | printf "$progname --upstream-version VERSION FILENAME\n" |
2305 | } |
2306 | |
2307 | -if [ "$#" -ne "3" ] ; then |
2308 | +if [ $# -ne 3 ] ; then |
2309 | usage |
2310 | exit 1 |
2311 | fi |
2312 | |
2313 | === modified file 'debian/rules' |
2314 | --- debian/rules 2014-01-13 14:51:52 +0000 |
2315 | +++ debian/rules 2014-03-07 05:33:58 +0000 |
2316 | @@ -22,13 +22,22 @@ |
2317 | PYTHON3_VERSIONS = $(shell py3versions -vr) |
2318 | PYTHON_VERSIONS = ${PYTHON2_VERSIONS} ${PYTHON3_VERSIONS} |
2319 | |
2320 | +# For some ‘/usr/bin/*-coverage’ programs (and not others), we need the |
2321 | +# default, not current, Python interpreter in the shebang. The ‘dh-python’ |
2322 | +# helpers can re-write shebangs, but they are too eager, converting every |
2323 | +# program's shebang without allowing us to specify different interpreters |
2324 | +# per program. We resort to ‘sed’. |
2325 | +python3_program = ${package_install_bin_dir}/python3-coverage |
2326 | +shebang_line_regex = ^\#!.*$$ |
2327 | +python3_shebang_interpreter = /usr/bin/python3 |
2328 | + |
2329 | debug_object_exclude += _d.so |
2330 | |
2331 | # Unfortunately, ‘dh_install --exclude’ requires a substring, and a glob |
2332 | # wildcard will *not* work. So we need to specify the exact substring for |
2333 | # the Python 3 debug module filenames. |
2334 | python3_objcode_versions = $(shell \ |
2335 | - printf "%s" ${PYTHON3_VERSIONS} | sed -e 's/\.//g') |
2336 | + printf "%s\n" ${PYTHON3_VERSIONS} | sed -e 's/\.//g') |
2337 | DEB_HOST_MULTIARCH = $(shell dpkg-architecture -qDEB_HOST_MULTIARCH) |
2338 | debug_object_exclude += $(foreach ver,${python3_objcode_versions}, \ |
2339 | .cpython-${ver}dm-${DEB_HOST_MULTIARCH}.so) |
2340 | @@ -112,14 +121,14 @@ |
2341 | manpage-symlinks: ${versioned_manpage_paths} |
2342 | |
2343 | ${DOCUMENTATION_DIR}/${default_manpage_name}: ${package_working_root}/${default_manpage_name} |
2344 | - $(INSTALL) --mode=u=rw,go=r $< $@ |
2345 | + $(INSTALL) --mode=u=rw,go=r "$<" "$@" |
2346 | |
2347 | ${DOCUMENTATION_DIR}/%${MANPAGE_SUFFIX}: ${DOCUMENTATION_DIR}/${default_manpage_name} |
2348 | - ln -s ${default_manpage_name} $@ |
2349 | + ln -s ${default_manpage_name} "$@" |
2350 | |
2351 | %.1: %.1${RST_SUFFIX} |
2352 | - $(RST2MAN) $< > $@.tmp |
2353 | - cat debian/manpage_encoding_declaration.UTF-8 $@.tmp > $@ |
2354 | + $(RST2MAN) $< > "$@".tmp |
2355 | + cat debian/manpage_encoding_declaration.UTF-8 "$@".tmp > "$@" |
2356 | |
2357 | |
2358 | |
2359 | .PHONY: clean |
2360 | @@ -158,22 +167,27 @@ |
2361 | --exclude ${exclude_part}) |
2362 | |
2363 | ${package_install_resources_root}: |
2364 | - $(INSTALL) -d $@ |
2365 | + $(INSTALL) -d "$@" |
2366 | |
2367 | ${package_install_resources_root}/${htmlfiles_dirname}: ${HTMLFILES_DIR} ${package_install_resources_root} |
2368 | - $(INSTALL) -d $@ |
2369 | - $(INSTALL) --mode=u=rw,go=r $</* $@ |
2370 | + $(INSTALL) -d "$@" |
2371 | + $(INSTALL) --mode=u=rw,go=r "$<"/* "$@" |
2372 | |
2373 | .PHONY: install-resource-files |
2374 | install-resource-files: ${package_install_resources_root} |
2375 | install-resource-files: ${package_install_resources_root}/${htmlfiles_dirname} |
2376 | |
2377 | .PHONY: install-python% |
2378 | +install-python%: python_version_major = $(firstword $(subst ., ,$*)) |
2379 | install-python%: |
2380 | python$*-dbg setup.py install --install-layout=deb \ |
2381 | --root=$(CURDIR)/${package_install_root} |
2382 | python$* setup.py install --install-layout=deb \ |
2383 | --root=$(CURDIR)/${package_install_root} |
2384 | + if [ "${python_version_major}" = "3" ] ; then \ |
2385 | + sed -i -e '1 s,${shebang_line_regex},#! ${python3_shebang_interpreter},' \ |
2386 | + "${python3_program}" ; \ |
2387 | + fi |
2388 | |
2389 | |
2390 | |
2391 | .PHONY: binary-indep |
2392 | |
2393 | === modified file 'doc/changes.rst' |
2394 | --- doc/changes.rst 2014-01-06 21:48:50 +0000 |
2395 | +++ doc/changes.rst 2014-03-07 05:33:58 +0000 |
2396 | @@ -26,6 +26,7 @@ |
2397 | :history: 20121223T180600, updated for 3.6b2. |
2398 | :history: 20130105T173500, updated for 3.6 |
2399 | :history: 20131005T205700, updated for 3.7 |
2400 | +:history: 20131212T213100, updated for 3.7.1 |
2401 | |
2402 | |
2403 | These are the major changes for coverage.py. For a more complete change |
2404 | @@ -34,11 +35,25 @@ |
2405 | .. _CHANGES.txt: http://bitbucket.org/ned/coveragepy/src/tip/CHANGES.txt |
2406 | |
2407 | |
2408 | +.. _changes_371: |
2409 | + |
2410 | +Version 3.7.1 --- 13 December 2013 |
2411 | +---------------------------------- |
2412 | + |
2413 | +- Improved the speed of HTML report generation by about 20%. |
2414 | + |
2415 | +- Fixed the mechanism for finding OS-installed static files for the HTML report |
2416 | + so that it will actually find OS-installed static files. |
2417 | + |
2418 | + |
2419 | +.. _changes_37: |
2420 | + |
2421 | Version 3.7 --- 6 October 2013 |
2422 | ------------------------------ |
2423 | |
2424 | - Added the ``--debug`` switch to ``coverage run``. It accepts a list of |
2425 | - options indicating the type of internal activity to log to stderr. |
2426 | + options indicating the type of internal activity to log to stderr. For |
2427 | + details, see :ref:`the run --debug options <cmd_run_debug>`. |
2428 | |
2429 | - Improved the branch coverage facility, fixing `issue 92`_ and `issue 175`_. |
2430 | |
2431 | |
2432 | === modified file 'doc/cmd.rst' |
2433 | --- doc/cmd.rst 2014-01-06 21:48:50 +0000 |
2434 | +++ doc/cmd.rst 2014-03-07 05:33:58 +0000 |
2435 | @@ -152,9 +152,9 @@ |
2436 | |
2437 | * ``sys``: before starting, dump all the system and environment information, |
2438 | as with :ref:`coverage debug sys <cmd_debug>`. |
2439 | - |
2440 | + |
2441 | * ``dataio``: log when reading or writing any data file. |
2442 | - |
2443 | + |
2444 | * ``pid``: annotate all debug output with the process id. |
2445 | |
2446 | |
2447 | |
2448 | === modified file 'doc/index.rst' |
2449 | --- doc/index.rst 2014-01-06 21:48:50 +0000 |
2450 | +++ doc/index.rst 2014-03-07 05:33:58 +0000 |
2451 | @@ -30,6 +30,7 @@ |
2452 | :history: 20121229T112300, Updated for 3.6b3. |
2453 | :history: 20130105T174000, Updated for 3.6 |
2454 | :history: 20131005T210000, Updated for 3.7 |
2455 | +:history: 20131212T213300, Updated for 3.7.1 |
2456 | |
2457 | |
2458 | Coverage.py is a tool for measuring code coverage of Python programs. It |
2459 | @@ -42,7 +43,7 @@ |
2460 | |
2461 | .. ifconfig:: not prerelease |
2462 | |
2463 | - The latest version is coverage.py 3.7, released 6 October 2013. |
2464 | + The latest version is coverage.py 3.7.1, released 13 December 2013. |
2465 | It is supported on Python versions 2.3 through 3.4, and PyPy 2.1. |
2466 | |
2467 | .. ifconfig:: prerelease |
2468 | |
2469 | === modified file 'doc/install.rst' |
2470 | --- doc/install.rst 2014-01-06 21:48:50 +0000 |
2471 | +++ doc/install.rst 2014-03-07 05:33:58 +0000 |
2472 | @@ -19,6 +19,7 @@ |
2473 | :history: 20121229T112400, updated for 3.6b3. |
2474 | :history: 20130105T174400, updated for 3.6. |
2475 | :history: 20131005T210600, updated for 3.7. |
2476 | +:history: 20131212T213500, updated for 3.7.1. |
2477 | |
2478 | |
2479 | .. highlight:: console |
2480 | @@ -74,9 +75,9 @@ |
2481 | installed properly:: |
2482 | |
2483 | $ coverage --version |
2484 | - Coverage.py, version 3.7. http://nedbatchelder.com/code/coverage |
2485 | + Coverage.py, version 3.7.1. http://nedbatchelder.com/code/coverage |
2486 | |
2487 | You can also invoke coverage as a module:: |
2488 | |
2489 | $ python -m coverage --version |
2490 | - Coverage.py, version 3.7. http://nedbatchelder.com/code/coverage |
2491 | + Coverage.py, version 3.7.1. http://nedbatchelder.com/code/coverage |
2492 | |
2493 | === modified file 'tests/coveragetest.py' |
2494 | --- tests/coveragetest.py 2013-10-15 13:16:36 +0000 |
2495 | +++ tests/coveragetest.py 2014-03-07 05:33:58 +0000 |
2496 | @@ -355,20 +355,21 @@ |
2497 | |
2498 | # Get the analysis results, and check that they are right. |
2499 | analysis = cov._analyze(mod) |
2500 | + statements = sorted(analysis.statements) |
2501 | if lines is not None: |
2502 | if type(lines[0]) == type(1): |
2503 | # lines is just a list of numbers, it must match the statements |
2504 | # found in the code. |
2505 | - self.assertEqual(analysis.statements, lines) |
2506 | + self.assertEqual(statements, lines) |
2507 | else: |
2508 | # lines is a list of possible line number lists, one of them |
2509 | # must match. |
2510 | for line_list in lines: |
2511 | - if analysis.statements == line_list: |
2512 | + if statements == line_list: |
2513 | break |
2514 | else: |
2515 | self.fail("None of the lines choices matched %r" % |
2516 | - analysis.statements |
2517 | + statements |
2518 | ) |
2519 | |
2520 | if type(missing) == type(""): |
2521 | |
2522 | === modified file 'tests/test_html.py' |
2523 | --- tests/test_html.py 2013-10-15 13:16:36 +0000 |
2524 | +++ tests/test_html.py 2014-03-07 05:33:58 +0000 |
2525 | @@ -317,9 +317,32 @@ |
2526 | cov = coverage.coverage() |
2527 | self.start_import_stop(cov, "main") |
2528 | cov.html_report() |
2529 | + |
2530 | jquery = open("htmlcov/jquery.min.js").read() |
2531 | self.assertEqual(jquery, "Not Really JQuery!") |
2532 | |
2533 | + def test_copying_static_files_from_system_in_dir(self): |
2534 | + # Make a new place for static files. |
2535 | + INSTALLED = [ |
2536 | + "jquery/jquery.min.js", |
2537 | + "jquery-hotkeys/jquery.hotkeys.js", |
2538 | + "jquery-isonscreen/jquery.isonscreen.js", |
2539 | + "jquery-tablesorter/jquery.tablesorter.min.js", |
2540 | + ] |
2541 | + for fpath in INSTALLED: |
2542 | + self.make_file(os.path.join("static_here", fpath), "Not real.") |
2543 | + coverage.html.STATIC_PATH.insert(0, "static_here") |
2544 | + |
2545 | + self.make_file("main.py", "print(17)") |
2546 | + cov = coverage.coverage() |
2547 | + self.start_import_stop(cov, "main") |
2548 | + cov.html_report() |
2549 | + |
2550 | + for fpath in INSTALLED: |
2551 | + the_file = os.path.basename(fpath) |
2552 | + contents = open(os.path.join("htmlcov", the_file)).read() |
2553 | + self.assertEqual(contents, "Not real.") |
2554 | + |
2555 | def test_cant_find_static_files(self): |
2556 | # Make the path point to useless places. |
2557 | coverage.html.STATIC_PATH = ["/xyzzy"] |
2558 | |
2559 | === modified file 'tests/test_templite.py' |
2560 | --- tests/test_templite.py 2013-10-15 13:16:36 +0000 |
2561 | +++ tests/test_templite.py 2014-03-07 05:33:58 +0000 |
2562 | @@ -1,7 +1,7 @@ |
2563 | """Tests for coverage.templite.""" |
2564 | |
2565 | from coverage.templite import Templite |
2566 | -import unittest |
2567 | +from tests.coveragetest import CoverageTest |
2568 | |
2569 | # pylint: disable=W0612,E1101 |
2570 | # Disable W0612 (Unused variable) and |
2571 | @@ -18,9 +18,11 @@ |
2572 | setattr(self, n, v) |
2573 | |
2574 | |
2575 | -class TempliteTest(unittest.TestCase): |
2576 | +class TempliteTest(CoverageTest): |
2577 | """Tests for Templite.""" |
2578 | |
2579 | + run_in_temp_dir = False |
2580 | + |
2581 | def try_render(self, text, ctx, result): |
2582 | """Render `text` through `ctx`, and it had better be `result`.""" |
2583 | self.assertEqual(Templite(text).render(ctx), result) |
2584 | @@ -37,6 +39,14 @@ |
2585 | # Variables use {{var}} syntax. |
2586 | self.try_render("Hello, {{name}}!", {'name':'Ned'}, "Hello, Ned!") |
2587 | |
2588 | + def test_undefined_variables(self): |
2589 | + # Using undefined names is an error. |
2590 | + self.assertRaises( |
2591 | + Exception, |
2592 | + self.try_render, |
2593 | + "Hi, {{name}}!", {}, "xyz" |
2594 | + ) |
2595 | + |
2596 | def test_pipes(self): |
2597 | # Variables can be filtered with pipes. |
2598 | data = { |
2599 | @@ -165,6 +175,23 @@ |
2600 | "Hi, NEDBEN!" |
2601 | ) |
2602 | |
2603 | + def test_complex_if(self): |
2604 | + class Complex(AnyOldObject): |
2605 | + """A class to try out complex data access.""" |
2606 | + def getit(self): |
2607 | + """Return it.""" |
2608 | + return self.it |
2609 | + obj = Complex(it={'x':"Hello", 'y': 0}) |
2610 | + self.try_render( |
2611 | + "@" |
2612 | + "{% if obj.getit.x %}X{% endif %}" |
2613 | + "{% if obj.getit.y %}Y{% endif %}" |
2614 | + "{% if obj.getit.y|str %}S{% endif %}" |
2615 | + "!", |
2616 | + { 'obj': obj, 'str': str }, |
2617 | + "@XS!" |
2618 | + ) |
2619 | + |
2620 | def test_loop_if(self): |
2621 | self.try_render( |
2622 | "@{% for n in nums %}{% if n %}Z{% endif %}{{n}}{% endfor %}!", |
2623 | @@ -184,9 +211,11 @@ |
2624 | |
2625 | def test_nested_loops(self): |
2626 | self.try_render( |
2627 | - "@{% for n in nums %}" |
2628 | + "@" |
2629 | + "{% for n in nums %}" |
2630 | "{% for a in abc %}{{a}}{{n}}{% endfor %}" |
2631 | - "{% endfor %}!", |
2632 | + "{% endfor %}" |
2633 | + "!", |
2634 | {'nums': [0,1,2], 'abc': ['a', 'b', 'c']}, |
2635 | "@a0b0c0a1b1c1a2b2c2!" |
2636 | ) |
2637 | @@ -199,6 +228,20 @@ |
2638 | ) |
2639 | |
2640 | def test_bogus_tag_syntax(self): |
2641 | - self.assertRaises(SyntaxError, self.try_render, |
2642 | + self.assertRaisesRegexp( |
2643 | + SyntaxError, "Don't understand tag: 'bogus'", |
2644 | + self.try_render, |
2645 | "Huh: {% bogus %}!!{% endbogus %}??", {}, "" |
2646 | ) |
2647 | + |
2648 | + def test_bad_nesting(self): |
2649 | + self.assertRaisesRegexp( |
2650 | + SyntaxError, "Unmatched action tag: 'if'", |
2651 | + self.try_render, |
2652 | + "{% if x %}X", {}, "" |
2653 | + ) |
2654 | + self.assertRaisesRegexp( |
2655 | + SyntaxError, "Mismatched end tag: 'for'", |
2656 | + self.try_render, |
2657 | + "{% if x %}X{% endfor %}", {}, "" |
2658 | + ) |
Thanks! Sponsored.