Skip to content

Commit

Permalink
Merge branch 'master' into monitoring
Browse files Browse the repository at this point in the history
  • Loading branch information
scoder committed Jul 17, 2024
2 parents def6137 + 746627f commit 42519bf
Show file tree
Hide file tree
Showing 56 changed files with 1,209 additions and 327 deletions.
4 changes: 2 additions & 2 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -106,12 +106,12 @@ jobs:
- os: ubuntu-20.04
python-version: "3.7"
backend: "c,cpp"
env: { LIMITED_API: "--limited-api", EXCLUDE: "--no-file" }
env: { LIMITED_API: "--limited-api", NO_LIMITED_COMPILE: 1, EXCLUDE: "--no-file" }
extra_hash: "-limited_api"
- os: ubuntu-20.04
python-version: "3.8"
backend: "c,cpp"
env: { LIMITED_API: "--limited-api", EXCLUDE: "--no-file" }
env: { LIMITED_API: "--limited-api", NO_LIMITED_COMPILE: 1, EXCLUDE: "--no-file" }
extra_hash: "-limited_api"
- os: ubuntu-20.04
python-version: "3.11"
Expand Down
2 changes: 2 additions & 0 deletions Cython/Build/Tests/TestCythonizeArgsParser.py
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,8 @@ def test_directives_types(self):
options, args = self.parse_args(['-X', cmd])
self.assertFalse(args)
self.assertTrue(self.are_default(options, ['directives']), msg = "Error for option: "+cmd)
if value == 'str':
value = 'unicode'
self.assertEqual(options.directives[key], value, msg = "Error for option: "+cmd)

def test_directives_wrong(self):
Expand Down
37 changes: 13 additions & 24 deletions Cython/Compiler/Annotate.py
Original file line number Diff line number Diff line change
Expand Up @@ -69,8 +69,8 @@ def _css(self):
"""css template will later allow to choose a colormap"""
css = [self._css_template]
for i in range(255):
color = "FFFF%02x" % int(255.0 // (1.0 + i/10.0))
css.append('.cython.score-%d {background-color: #%s;}' % (i, color))
color_shade = int(255.0 // (1.0 + i/10.0))
css.append(f'.cython.score-{i:d} {{background-color: #FFFF{color_shade:02x};}}')
try:
from pygments.formatters import HtmlFormatter
except ImportError:
Expand Down Expand Up @@ -232,8 +232,7 @@ def _save_annotation_body(self, cython_code, generated_code, annotation_items, s
def annotate(match):
group_name = match.lastgroup
calls[group_name] += 1
return "<span class='%s'>%s</span>" % (
group_name, match.group(group_name))
return f"<span class='{group_name}'>{match.group(group_name)}</span>"

lines = self._htmlify_code(cython_code, "cython").splitlines()
lineno_width = len(str(len(lines)))
Expand Down Expand Up @@ -270,34 +269,24 @@ def annotate(match):
covered = 'run' if hits else 'mis'

outlist.append(
'<pre class="cython line score-{score}"{onclick}>'
f'<pre class="cython line score-{score}"{onclick}>'
# generate line number with expand symbol in front,
# and the right number of digit
'{expandsymbol}<span class="{covered}">{line:0{lineno_width}d}</span>: {code}</pre>\n'.format(
score=score,
expandsymbol=expandsymbol,
covered=covered,
lineno_width=lineno_width,
line=k,
code=line.rstrip(),
onclick=onclick,
))
f'{expandsymbol}<span class="{covered}">{k:0{lineno_width}d}</span>: {line.rstrip()}</pre>\n'
)
if c_code:
outlist.append("<pre class='cython code score-{score} {covered}'>{code}</pre>".format(
score=score, covered=covered, code=c_code))
outlist.append(f"<pre class='cython code score-{score} {covered}'>{c_code}</pre>")
outlist.append("</div>")

# now the whole c-code if needed:
if self.show_entire_c_code:
outlist.append('<p><div class="cython">')
onclick_title = "<pre class='cython line'{onclick}>+ {title}</pre>\n"
outlist.append(onclick_title.format(
onclick=self._onclick_attr,
title=AnnotationCCodeWriter.COMPLETE_CODE_TITLE,
))
complete_code_as_html = self._htmlify_code(self.buffer.getvalue(), "c/cpp")
outlist.append("<pre class='cython code'>{code}</pre>".format(code=complete_code_as_html))
outlist.append("</div></p>")
outlist.append(
'<p><div class="cython">'
f"<pre class='cython line'{self._onclick_attr}>+ {AnnotationCCodeWriter.COMPLETE_CODE_TITLE}</pre>\n"
f"<pre class='cython code'>{complete_code_as_html}</pre>"
"</div></p>"
)

return outlist

Expand Down
27 changes: 12 additions & 15 deletions Cython/Compiler/Code.py
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@
'IOError',
'ImportError',
'ImportWarning',
'IncompleteInputError',
'_IncompleteInputError',
'IndentationError',
'IndexError',
'InterruptedError',
Expand Down Expand Up @@ -217,7 +217,7 @@
# Global/builtin names that cannot be cached because they may or may not
# be available at import time, for various reasons:
## Python 3.13+
'IncompleteInputError',
'_IncompleteInputError',
'PythonFinalizationError',
## Python 3.11+
'BaseExceptionGroup',
Expand Down Expand Up @@ -789,18 +789,23 @@ def put_code(self, output):
self.cleanup(writer, output.module_pos)


def sub_tempita(s, context, file=None, name=None):
def sub_tempita(s, context, file=None, name=None, __cache={}):
"Run tempita on string s with given context."
if not s:
return None

if file:
context['__name'] = "%s:%s" % (file, name)
elif name:
name = f"{file}:{name}"
if name:
context['__name'] = name

from ..Tempita import sub
return sub(s, **context)
try:
template = __cache[s]
except KeyError:
from ..Tempita import Template
template = __cache[s] = Template(s, name=name)

return template.substitute(context)


class TempitaUtilityCode(UtilityCode):
Expand Down Expand Up @@ -2394,14 +2399,6 @@ def put(self, code):
elif fix_indent:
self.level += 1

def putln_tempita(self, code, **context):
from ..Tempita import sub
self.putln(sub(code, **context))

def put_tempita(self, code, **context):
from ..Tempita import sub
self.put(sub(code, **context))

def increase_indent(self):
self.level += 1

Expand Down
115 changes: 39 additions & 76 deletions Cython/Compiler/ExprNodes.py
Original file line number Diff line number Diff line change
Expand Up @@ -115,10 +115,10 @@ def find_coercion_error(type_tuple, default, env):
PyrexTypes.c_const_char_ptr_type, PyrexTypes.c_const_uchar_ptr_type))):
if type_tuple[1].is_pyobject:
return default
elif env.directives['c_string_encoding'] in ('ascii', 'default'):
elif env.directives['c_string_encoding'] in ('ascii', 'utf8'):
return default
else:
return "'%s' objects do not support coercion to C types with non-ascii or non-default c_string_encoding" % type_tuple[0].name
return "'%s' objects do not support coercion to C types with non-ascii or non-utf8 c_string_encoding" % type_tuple[0].name
else:
return err

Expand All @@ -127,7 +127,7 @@ def default_str_type(env):
return {
'bytes': bytes_type,
'bytearray': bytearray_type,
'str': str_type,
'str': unicode_type,
'unicode': unicode_type
}.get(env.directives['c_string_type'])

Expand Down Expand Up @@ -5499,103 +5499,66 @@ def generate_result_code(self, code):
"Slicing is not currently supported for '%s'." % self.type)
return

base_result = self.base.result()
base_type = self.base.type
result = self.result()
start_code = self.start_code()
stop_code = self.stop_code()
if self.base.type.is_string:
base_result = self.base.result()
if self.base.type not in (PyrexTypes.c_char_ptr_type, PyrexTypes.c_const_char_ptr_type):
base_result = '((const char*)%s)' % base_result

if base_type.is_string:
base_result = self.base.result_as(PyrexTypes.c_const_char_ptr_type)
if self.type is bytearray_type:
type_name = 'ByteArray'
elif self.type is str_type:
type_name = 'Unicode'
else:
type_name = self.type.name.title()

if self.stop is None:
code.putln(
"%s = __Pyx_Py%s_FromString(%s + %s); %s" % (
result,
type_name,
base_result,
start_code,
code.error_goto_if_null(result, self.pos)))
call = f"__Pyx_Py{type_name}_FromString({base_result} + {start_code})"
else:
code.putln(
"%s = __Pyx_Py%s_FromStringAndSize(%s + %s, %s - %s); %s" % (
result,
type_name,
base_result,
start_code,
stop_code,
start_code,
code.error_goto_if_null(result, self.pos)))
elif self.base.type.is_pyunicode_ptr:
base_result = self.base.result()
if self.base.type != PyrexTypes.c_py_unicode_ptr_type:
base_result = '((const Py_UNICODE*)%s)' % base_result
call = f"__Pyx_Py{type_name}_FromStringAndSize({base_result} + {start_code}, {stop_code} - {start_code})"

elif base_type.is_pyunicode_ptr:
base_result = self.base.result_as(PyrexTypes.c_const_py_unicode_ptr_type)
code.globalstate.use_utility_code(
UtilityCode.load_cached("pyunicode_from_unicode", "StringTools.c"))
if self.stop is None:
code.putln(
"%s = __Pyx_PyUnicode_FromUnicode(%s + %s); %s" % (
result,
base_result,
start_code,
code.error_goto_if_null(result, self.pos)))
code.globalstate.use_utility_code(
UtilityCode.load_cached("pyunicode_from_unicode", "StringTools.c"))
call = f"__Pyx_PyUnicode_FromUnicode({base_result} + {start_code})"
else:
code.putln(
"%s = __Pyx_PyUnicode_FromUnicodeAndLength(%s + %s, %s - %s); %s" % (
result,
base_result,
start_code,
stop_code,
start_code,
code.error_goto_if_null(result, self.pos)))
code.globalstate.use_utility_code(
UtilityCode.load_cached("pyunicode_from_unicode", "StringTools.c"))
call = f"__Pyx_PyUnicode_FromUnicodeAndLength({base_result} + {start_code}, {stop_code} - {start_code})"

elif self.base.type is unicode_type:
elif base_type is unicode_type:
base_result = self.base.result()
code.globalstate.use_utility_code(
UtilityCode.load_cached("PyUnicode_Substring", "StringTools.c"))
code.putln(
"%s = __Pyx_PyUnicode_Substring(%s, %s, %s); %s" % (
result,
base_result,
start_code,
stop_code,
code.error_goto_if_null(result, self.pos)))
UtilityCode.load_cached("PyUnicode_Substring", "StringTools.c"))
call = f"__Pyx_PyUnicode_Substring({base_result}, {start_code}, {stop_code})"

elif self.type is py_object_type:
base_result = self.base.py_result()
has_c_start, has_c_stop, c_start, c_stop, py_start, py_stop, py_slice = self.get_slice_config()
wraparound = bool(code.globalstate.directives['wraparound'])

code.globalstate.use_utility_code(self.get_slice_utility_code)
(has_c_start, has_c_stop, c_start, c_stop,
py_start, py_stop, py_slice) = self.get_slice_config()
code.putln(
"%s = __Pyx_PyObject_GetSlice(%s, %s, %s, %s, %s, %s, %d, %d, %d); %s" % (
result,
self.base.py_result(),
c_start, c_stop,
py_start, py_stop, py_slice,
has_c_start, has_c_stop,
bool(code.globalstate.directives['wraparound']),
code.error_goto_if_null(result, self.pos)))
call = ("__Pyx_PyObject_GetSlice("
f"{base_result}, {c_start}, {c_stop}, {py_start}, {py_stop}, {py_slice}, "
f"{has_c_start:d}, {has_c_stop:d}, {wraparound:d})"
)

else:
if self.base.type is list_type:
base_result = self.base.py_result()
if base_type is list_type:
code.globalstate.use_utility_code(
TempitaUtilityCode.load_cached("SliceTupleAndList", "ObjectHandling.c"))
cfunc = '__Pyx_PyList_GetSlice'
elif self.base.type is tuple_type:
elif base_type is tuple_type:
code.globalstate.use_utility_code(
TempitaUtilityCode.load_cached("SliceTupleAndList", "ObjectHandling.c"))
cfunc = '__Pyx_PyTuple_GetSlice'
else:
cfunc = 'PySequence_GetSlice'
code.putln(
"%s = %s(%s, %s, %s); %s" % (
result,
cfunc,
self.base.py_result(),
start_code,
stop_code,
code.error_goto_if_null(result, self.pos)))
call = f"{cfunc}({base_result}, {start_code}, {stop_code})"

code.putln(f"{result} = {call}; {code.error_goto_if_null(result, self.pos)}")
self.generate_gotref(code)

def generate_assignment_code(self, rhs, code, overloaded_assignment=False,
Expand Down
Loading

0 comments on commit 42519bf

Please sign in to comment.