summaryrefslogtreecommitdiffstats
path: root/contrib/tools/cython/Cython/Compiler/Annotate.py
diff options
context:
space:
mode:
authororivej <[email protected]>2022-02-10 16:44:49 +0300
committerDaniil Cherednik <[email protected]>2022-02-10 16:44:49 +0300
commit718c552901d703c502ccbefdfc3c9028d608b947 (patch)
tree46534a98bbefcd7b1f3faa5b52c138ab27db75b7 /contrib/tools/cython/Cython/Compiler/Annotate.py
parente9656aae26e0358d5378e5b63dcac5c8dbe0e4d0 (diff)
Restoring authorship annotation for <[email protected]>. Commit 1 of 2.
Diffstat (limited to 'contrib/tools/cython/Cython/Compiler/Annotate.py')
-rw-r--r--contrib/tools/cython/Cython/Compiler/Annotate.py228
1 files changed, 114 insertions, 114 deletions
diff --git a/contrib/tools/cython/Cython/Compiler/Annotate.py b/contrib/tools/cython/Cython/Compiler/Annotate.py
index 2ea38c00c74..c8a1d9be77d 100644
--- a/contrib/tools/cython/Cython/Compiler/Annotate.py
+++ b/contrib/tools/cython/Cython/Compiler/Annotate.py
@@ -3,21 +3,21 @@
from __future__ import absolute_import
import os
-import os.path
+import os.path
import re
import codecs
import textwrap
-from datetime import datetime
-from functools import partial
-from collections import defaultdict
+from datetime import datetime
+from functools import partial
+from collections import defaultdict
try:
from xml.sax.saxutils import escape as html_escape
except ImportError:
pass
-try:
- from StringIO import StringIO
-except ImportError:
- from io import StringIO # does not support writing 'str' in Py2
+try:
+ from StringIO import StringIO
+except ImportError:
+ from io import StringIO # does not support writing 'str' in Py2
from . import Version
from .Code import CCodeWriter
@@ -27,23 +27,23 @@ from .. import Utils
class AnnotationCCodeWriter(CCodeWriter):
def __init__(self, create_from=None, buffer=None, copy_formatting=True):
- CCodeWriter.__init__(self, create_from, buffer, copy_formatting=copy_formatting)
+ CCodeWriter.__init__(self, create_from, buffer, copy_formatting=copy_formatting)
if create_from is None:
self.annotation_buffer = StringIO()
- self.last_annotated_pos = None
- # annotations[filename][line] -> [(column, AnnotationItem)*]
- self.annotations = defaultdict(partial(defaultdict, list))
- # code[filename][line] -> str
- self.code = defaultdict(partial(defaultdict, str))
- # scopes[filename][line] -> set(scopes)
- self.scopes = defaultdict(partial(defaultdict, set))
+ self.last_annotated_pos = None
+ # annotations[filename][line] -> [(column, AnnotationItem)*]
+ self.annotations = defaultdict(partial(defaultdict, list))
+ # code[filename][line] -> str
+ self.code = defaultdict(partial(defaultdict, str))
+ # scopes[filename][line] -> set(scopes)
+ self.scopes = defaultdict(partial(defaultdict, set))
else:
# When creating an insertion point, keep references to the same database
self.annotation_buffer = create_from.annotation_buffer
self.annotations = create_from.annotations
self.code = create_from.code
- self.scopes = create_from.scopes
- self.last_annotated_pos = create_from.last_annotated_pos
+ self.scopes = create_from.scopes
+ self.last_annotated_pos = create_from.last_annotated_pos
def create_new(self, create_from, buffer, copy_formatting):
return AnnotationCCodeWriter(create_from, buffer, copy_formatting)
@@ -52,54 +52,54 @@ class AnnotationCCodeWriter(CCodeWriter):
CCodeWriter.write(self, s)
self.annotation_buffer.write(s)
- def mark_pos(self, pos, trace=True):
+ def mark_pos(self, pos, trace=True):
if pos is not None:
- CCodeWriter.mark_pos(self, pos, trace)
- if self.funcstate and self.funcstate.scope:
- # lambdas and genexprs can result in multiple scopes per line => keep them in a set
- self.scopes[pos[0].filename][pos[1]].add(self.funcstate.scope)
- if self.last_annotated_pos:
- source_desc, line, _ = self.last_annotated_pos
- pos_code = self.code[source_desc.filename]
- pos_code[line] += self.annotation_buffer.getvalue()
+ CCodeWriter.mark_pos(self, pos, trace)
+ if self.funcstate and self.funcstate.scope:
+ # lambdas and genexprs can result in multiple scopes per line => keep them in a set
+ self.scopes[pos[0].filename][pos[1]].add(self.funcstate.scope)
+ if self.last_annotated_pos:
+ source_desc, line, _ = self.last_annotated_pos
+ pos_code = self.code[source_desc.filename]
+ pos_code[line] += self.annotation_buffer.getvalue()
self.annotation_buffer = StringIO()
- self.last_annotated_pos = pos
+ self.last_annotated_pos = pos
def annotate(self, pos, item):
- self.annotations[pos[0].filename][pos[1]].append((pos[2], item))
+ self.annotations[pos[0].filename][pos[1]].append((pos[2], item))
def _css(self):
"""css template will later allow to choose a colormap"""
css = [self._css_template]
for i in range(255):
color = u"FFFF%02x" % int(255/(1+i/10.0))
- css.append('.cython.score-%d {background-color: #%s;}' % (i, color))
+ css.append('.cython.score-%d {background-color: #%s;}' % (i, color))
try:
from pygments.formatters import HtmlFormatter
except ImportError:
pass
- else:
- css.append(HtmlFormatter().get_style_defs('.cython'))
- return '\n'.join(css)
+ else:
+ css.append(HtmlFormatter().get_style_defs('.cython'))
+ return '\n'.join(css)
_css_template = textwrap.dedent("""
body.cython { font-family: courier; font-size: 12; }
.cython.tag { }
.cython.line { margin: 0em }
- .cython.code { font-size: 9; color: #444444; display: none; margin: 0px 0px 0px 8px; border-left: 8px none; }
-
- .cython.line .run { background-color: #B0FFB0; }
- .cython.line .mis { background-color: #FFB0B0; }
- .cython.code.run { border-left: 8px solid #B0FFB0; }
- .cython.code.mis { border-left: 8px solid #FFB0B0; }
+ .cython.code { font-size: 9; color: #444444; display: none; margin: 0px 0px 0px 8px; border-left: 8px none; }
+ .cython.line .run { background-color: #B0FFB0; }
+ .cython.line .mis { background-color: #FFB0B0; }
+ .cython.code.run { border-left: 8px solid #B0FFB0; }
+ .cython.code.mis { border-left: 8px solid #FFB0B0; }
+
.cython.code .py_c_api { color: red; }
.cython.code .py_macro_api { color: #FF7000; }
.cython.code .pyx_c_api { color: #FF3000; }
.cython.code .pyx_macro_api { color: #FF7000; }
.cython.code .refnanny { color: #FFA000; }
- .cython.code .trace { color: #FFA000; }
+ .cython.code .trace { color: #FFA000; }
.cython.code .error_goto { color: #FFA000; }
.cython.code .coerce { color: #008000; border: 1px dotted #008000 }
@@ -117,22 +117,22 @@ class AnnotationCCodeWriter(CCodeWriter):
).replace(' ', '') # poor dev's JS minification
)
- def save_annotation(self, source_filename, target_filename, coverage_xml=None):
+ def save_annotation(self, source_filename, target_filename, coverage_xml=None):
with Utils.open_source_file(source_filename) as f:
code = f.read()
generated_code = self.code.get(source_filename, {})
c_file = Utils.decode_filename(os.path.basename(target_filename))
html_filename = os.path.splitext(target_filename)[0] + ".html"
-
+
with codecs.open(html_filename, "w", encoding="UTF-8") as out_buffer:
- out_buffer.write(self._save_annotation(code, generated_code, c_file, source_filename, coverage_xml))
-
- def _save_annotation_header(self, c_file, source_filename, coverage_timestamp=None):
- coverage_info = ''
- if coverage_timestamp:
- coverage_info = u' with coverage data from {timestamp}'.format(
- timestamp=datetime.fromtimestamp(int(coverage_timestamp) // 1000))
-
+ out_buffer.write(self._save_annotation(code, generated_code, c_file, source_filename, coverage_xml))
+
+ def _save_annotation_header(self, c_file, source_filename, coverage_timestamp=None):
+ coverage_info = ''
+ if coverage_timestamp:
+ coverage_info = u' with coverage data from {timestamp}'.format(
+ timestamp=datetime.fromtimestamp(int(coverage_timestamp) // 1000))
+
outlist = [
textwrap.dedent(u'''\
<!DOCTYPE html>
@@ -140,20 +140,20 @@ class AnnotationCCodeWriter(CCodeWriter):
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
- <title>Cython: {filename}</title>
+ <title>Cython: {filename}</title>
<style type="text/css">
{css}
</style>
</head>
<body class="cython">
- <p><span style="border-bottom: solid 1px grey;">Generated by Cython {watermark}</span>{more_info}</p>
- <p>
- <span style="background-color: #FFFF00">Yellow lines</span> hint at Python interaction.<br />
- Click on a line that starts with a "<code>+</code>" to see the C code that Cython generated for it.
- </p>
+ <p><span style="border-bottom: solid 1px grey;">Generated by Cython {watermark}</span>{more_info}</p>
+ <p>
+ <span style="background-color: #FFFF00">Yellow lines</span> hint at Python interaction.<br />
+ Click on a line that starts with a "<code>+</code>" to see the C code that Cython generated for it.
+ </p>
''').format(css=self._css(), watermark=Version.watermark,
- filename=os.path.basename(source_filename) if source_filename else '',
- more_info=coverage_info)
+ filename=os.path.basename(source_filename) if source_filename else '',
+ more_info=coverage_info)
]
if c_file:
outlist.append(u'<p>Raw output: <a href="%s">%s</a></p>\n' % (c_file, c_file))
@@ -162,45 +162,45 @@ class AnnotationCCodeWriter(CCodeWriter):
def _save_annotation_footer(self):
return (u'</body></html>\n',)
- def _save_annotation(self, code, generated_code, c_file=None, source_filename=None, coverage_xml=None):
+ def _save_annotation(self, code, generated_code, c_file=None, source_filename=None, coverage_xml=None):
"""
lines : original cython source code split by lines
generated_code : generated c code keyed by line number in original file
target filename : name of the file in which to store the generated html
c_file : filename in which the c_code has been written
"""
- if coverage_xml is not None and source_filename:
- coverage_timestamp = coverage_xml.get('timestamp', '').strip()
- covered_lines = self._get_line_coverage(coverage_xml, source_filename)
- else:
- coverage_timestamp = covered_lines = None
- annotation_items = dict(self.annotations[source_filename])
- scopes = dict(self.scopes[source_filename])
-
+ if coverage_xml is not None and source_filename:
+ coverage_timestamp = coverage_xml.get('timestamp', '').strip()
+ covered_lines = self._get_line_coverage(coverage_xml, source_filename)
+ else:
+ coverage_timestamp = covered_lines = None
+ annotation_items = dict(self.annotations[source_filename])
+ scopes = dict(self.scopes[source_filename])
+
outlist = []
- outlist.extend(self._save_annotation_header(c_file, source_filename, coverage_timestamp))
- outlist.extend(self._save_annotation_body(code, generated_code, annotation_items, scopes, covered_lines))
+ outlist.extend(self._save_annotation_header(c_file, source_filename, coverage_timestamp))
+ outlist.extend(self._save_annotation_body(code, generated_code, annotation_items, scopes, covered_lines))
outlist.extend(self._save_annotation_footer())
return ''.join(outlist)
- def _get_line_coverage(self, coverage_xml, source_filename):
- coverage_data = None
- for entry in coverage_xml.iterfind('.//class'):
- if not entry.get('filename'):
- continue
- if (entry.get('filename') == source_filename or
- os.path.abspath(entry.get('filename')) == source_filename):
- coverage_data = entry
- break
- elif source_filename.endswith(entry.get('filename')):
- coverage_data = entry # but we might still find a better match...
- if coverage_data is None:
- return None
- return dict(
- (int(line.get('number')), int(line.get('hits')))
- for line in coverage_data.iterfind('lines/line')
- )
-
+ def _get_line_coverage(self, coverage_xml, source_filename):
+ coverage_data = None
+ for entry in coverage_xml.iterfind('.//class'):
+ if not entry.get('filename'):
+ continue
+ if (entry.get('filename') == source_filename or
+ os.path.abspath(entry.get('filename')) == source_filename):
+ coverage_data = entry
+ break
+ elif source_filename.endswith(entry.get('filename')):
+ coverage_data = entry # but we might still find a better match...
+ if coverage_data is None:
+ return None
+ return dict(
+ (int(line.get('number')), int(line.get('hits')))
+ for line in coverage_data.iterfind('lines/line')
+ )
+
def _htmlify_code(self, code):
try:
from pygments import highlight
@@ -215,12 +215,12 @@ class AnnotationCCodeWriter(CCodeWriter):
HtmlFormatter(nowrap=True))
return html_code
- def _save_annotation_body(self, cython_code, generated_code, annotation_items, scopes, covered_lines=None):
+ def _save_annotation_body(self, cython_code, generated_code, annotation_items, scopes, covered_lines=None):
outlist = [u'<div class="cython">']
pos_comment_marker = u'/* \N{HORIZONTAL ELLIPSIS} */\n'
new_calls_map = dict(
(name, 0) for name in
- 'refnanny trace py_macro_api py_c_api pyx_macro_api pyx_c_api error_goto'.split()
+ 'refnanny trace py_macro_api py_c_api pyx_macro_api pyx_c_api error_goto'.split()
).copy
self.mark_pos(None)
@@ -228,13 +228,13 @@ class AnnotationCCodeWriter(CCodeWriter):
def annotate(match):
group_name = match.lastgroup
calls[group_name] += 1
- return u"<span class='%s'>%s</span>" % (
+ return u"<span class='%s'>%s</span>" % (
group_name, match.group(group_name))
lines = self._htmlify_code(cython_code).splitlines()
lineno_width = len(str(len(lines)))
- if not covered_lines:
- covered_lines = None
+ if not covered_lines:
+ covered_lines = None
for k, line in enumerate(lines, 1):
try:
@@ -259,48 +259,48 @@ class AnnotationCCodeWriter(CCodeWriter):
onclick = ''
expandsymbol = '&#xA0;'
- covered = ''
- if covered_lines is not None and k in covered_lines:
- hits = covered_lines[k]
- if hits is not None:
- covered = 'run' if hits else 'mis'
-
+ covered = ''
+ if covered_lines is not None and k in covered_lines:
+ hits = covered_lines[k]
+ if hits is not None:
+ covered = 'run' if hits else 'mis'
+
outlist.append(
- u'<pre class="cython line score-{score}"{onclick}>'
+ u'<pre class="cython line score-{score}"{onclick}>'
# generate line number with expand symbol in front,
# and the right number of digit
- u'{expandsymbol}<span class="{covered}">{line:0{lineno_width}d}</span>: {code}</pre>\n'.format(
+ u'{expandsymbol}<span class="{covered}">{line:0{lineno_width}d}</span>: {code}</pre>\n'.format(
score=score,
expandsymbol=expandsymbol,
- covered=covered,
+ covered=covered,
lineno_width=lineno_width,
line=k,
code=line.rstrip(),
onclick=onclick,
))
if c_code:
- outlist.append(u"<pre class='cython code score-{score} {covered}'>{code}</pre>".format(
- score=score, covered=covered, code=c_code))
+ outlist.append(u"<pre class='cython code score-{score} {covered}'>{code}</pre>".format(
+ score=score, covered=covered, code=c_code))
outlist.append(u"</div>")
return outlist
-_parse_code = re.compile((
- br'(?P<refnanny>__Pyx_X?(?:GOT|GIVE)REF|__Pyx_RefNanny[A-Za-z]+)|'
- br'(?P<trace>__Pyx_Trace[A-Za-z]+)|'
- br'(?:'
- br'(?P<pyx_macro_api>__Pyx_[A-Z][A-Z_]+)|'
- br'(?P<pyx_c_api>(?:__Pyx_[A-Z][a-z_][A-Za-z_]*)|__pyx_convert_[A-Za-z_]*)|'
- br'(?P<py_macro_api>Py[A-Z][a-z]+_[A-Z][A-Z_]+)|'
- br'(?P<py_c_api>Py[A-Z][a-z]+_[A-Z][a-z][A-Za-z_]*)'
- br')(?=\()|' # look-ahead to exclude subsequent '(' from replacement
+_parse_code = re.compile((
+ br'(?P<refnanny>__Pyx_X?(?:GOT|GIVE)REF|__Pyx_RefNanny[A-Za-z]+)|'
+ br'(?P<trace>__Pyx_Trace[A-Za-z]+)|'
+ br'(?:'
+ br'(?P<pyx_macro_api>__Pyx_[A-Z][A-Z_]+)|'
+ br'(?P<pyx_c_api>(?:__Pyx_[A-Z][a-z_][A-Za-z_]*)|__pyx_convert_[A-Za-z_]*)|'
+ br'(?P<py_macro_api>Py[A-Z][a-z]+_[A-Z][A-Z_]+)|'
+ br'(?P<py_c_api>Py[A-Z][a-z]+_[A-Z][a-z][A-Za-z_]*)'
+ br')(?=\()|' # look-ahead to exclude subsequent '(' from replacement
br'(?P<error_goto>(?:(?<=;) *if [^;]* +)?__PYX_ERR\([^)]+\))'
-).decode('ascii')).sub
+).decode('ascii')).sub
_replace_pos_comment = re.compile(
# this matches what Cython generates as code line marker comment
- br'^\s*/\*(?:(?:[^*]|\*[^/])*\n)+\s*\*/\s*\n'.decode('ascii'),
+ br'^\s*/\*(?:(?:[^*]|\*[^/])*\n)+\s*\*/\s*\n'.decode('ascii'),
re.M
).sub