aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorshadchin <shadchin@yandex-team.com>2023-07-22 00:59:02 +0300
committershadchin <shadchin@yandex-team.com>2023-07-22 00:59:02 +0300
commit7ecf6c16ab762d4ed40a90ea329eebeb1b8cbca0 (patch)
tree13f625aacca47c9885d8fa31ba97151706ef63bd
parent91a8278c558cb2002069ca54215c83568ba6826e (diff)
downloadydb-7ecf6c16ab762d4ed40a90ea329eebeb1b8cbca0.tar.gz
Update Cython to 0.29.36
-rw-r--r--contrib/tools/cython/.dist-info/METADATA2
-rw-r--r--contrib/tools/cython/.yandex_meta/__init__.py47
-rw-r--r--contrib/tools/cython/.yandex_meta/override.nix11
-rw-r--r--contrib/tools/cython/CHANGES.rst20
-rw-r--r--contrib/tools/cython/Cython/Compiler/Builtin.py5
-rw-r--r--contrib/tools/cython/Cython/Compiler/ModuleNode.py4
-rw-r--r--contrib/tools/cython/Cython/Compiler/Nodes.py4
-rw-r--r--contrib/tools/cython/Cython/Shadow.py2
-rw-r--r--contrib/tools/cython/Cython/Tempita/_tempita.py125
-rw-r--r--contrib/tools/cython/Cython/Utility/AsyncGen.c11
-rw-r--r--contrib/tools/cython/Cython/Utility/Exceptions.c26
-rw-r--r--contrib/tools/cython/Cython/Utility/ModuleSetupCode.c12
-rw-r--r--contrib/tools/cython/Cython/Utility/ObjectHandling.c4
-rwxr-xr-xcontrib/tools/cython/cython.py2
-rw-r--r--contrib/tools/cython/patches/5c5d70e-fix-embedded-dealloc-argv-more-3.5.patch17
-rw-r--r--contrib/tools/cython/patches/all-changes.patch937
-rw-r--r--contrib/tools/cython/patches/pr5096-fix-bitwise-instead-of-logical.patch39
-rw-r--r--contrib/tools/cython/patches/pr5210,5211-switch-from-deprecated-functions.patch52
-rw-r--r--contrib/tools/cython/patches/without-init.patch66
-rw-r--r--contrib/tools/cython/ya.make4
20 files changed, 1255 insertions, 135 deletions
diff --git a/contrib/tools/cython/.dist-info/METADATA b/contrib/tools/cython/.dist-info/METADATA
index bb58628f62..10f4b69cd5 100644
--- a/contrib/tools/cython/.dist-info/METADATA
+++ b/contrib/tools/cython/.dist-info/METADATA
@@ -1,6 +1,6 @@
Metadata-Version: 2.1
Name: Cython
-Version: 0.29.35
+Version: 0.29.36
Summary: The Cython compiler for writing C extensions for the Python language.
Home-page: http://cython.org/
Author: Robert Bradshaw, Stefan Behnel, Dag Seljebotn, Greg Ewing, et al.
diff --git a/contrib/tools/cython/.yandex_meta/__init__.py b/contrib/tools/cython/.yandex_meta/__init__.py
new file mode 100644
index 0000000000..3155ec718b
--- /dev/null
+++ b/contrib/tools/cython/.yandex_meta/__init__.py
@@ -0,0 +1,47 @@
+import os
+
+from devtools.yamaker.fileutil import re_sub_file
+from devtools.yamaker.project import NixProject
+from devtools.yamaker import python
+
+
+def post_install(self):
+ dist_files = python.extract_dist_info(self)
+
+ re_sub_file(
+ f"{self.dstdir}/cython.py",
+ r"# Change content of this file to change uids for cython programs - cython.*",
+ rf"# Change content of this file to change uids for cython programs - cython {self.version} r0",
+ )
+
+ self.yamakes.clear()
+ self.yamakes["."] = self.module(
+ module="PY3_LIBRARY",
+ NO_LINT=True,
+ RESOURCE_FILES=python.prepare_resource_files(self, *dist_files),
+ )
+
+ for path, dirs, files in os.walk(self.dstdir):
+ for file in files:
+ if file.endswith(".c"):
+ file = f"{path}/{file}"
+ with open(file) as f:
+ first_line = f.readline()
+ if first_line.startswith("/* Generated by Cython"):
+ os.remove(file)
+
+
+cython = NixProject(
+ owners=["g:python-contrib"],
+ arcdir="contrib/tools/cython",
+ nixattr=python.make_nixattr("cython"),
+ copy_sources=["Cython/", "cygdb.py", "cython.py"],
+ keep_paths=[
+ "Cython/Includes/numpy.pxd",
+ "Cython/Utility/CommonTypes.c",
+ "Cython/ya.make",
+ "generated_c_headers.h",
+ "generated_cpp_headers.h",
+ ],
+ post_install=post_install,
+)
diff --git a/contrib/tools/cython/.yandex_meta/override.nix b/contrib/tools/cython/.yandex_meta/override.nix
new file mode 100644
index 0000000000..57692631ea
--- /dev/null
+++ b/contrib/tools/cython/.yandex_meta/override.nix
@@ -0,0 +1,11 @@
+pkgs: attrs: with pkgs; with pkgs.python311.pkgs; with attrs; rec {
+ version = "0.29.36";
+
+ src = fetchPypi {
+ pname = "Cython";
+ inherit version;
+ sha256 = "sha256-QcDP0tdU44PJ7rle/8mqSrhH0Ml0cHfd18Dctow7wB8=";
+ };
+
+ patches = [];
+}
diff --git a/contrib/tools/cython/CHANGES.rst b/contrib/tools/cython/CHANGES.rst
index febc982c4e..829bfdcaff 100644
--- a/contrib/tools/cython/CHANGES.rst
+++ b/contrib/tools/cython/CHANGES.rst
@@ -2,6 +2,26 @@
Cython Changelog
================
+0.29.36 (2023-07-04)
+====================
+
+Bugs fixed
+----------
+
+* Async generators lost their return value in PyPy.
+ (Github issue :issue:`5465`)
+
+* The outdated C macro ``_PyGC_FINALIZED()`` is no longer used in Py3.9+.
+
+* The deprecated ``Py_OptimizeFlag`` is no longer used in Python 3.9+.
+ (Github issue :issue:`5343`)
+
+* Using the global ``__debug__`` variable but not assertions could lead to compile errors.
+
+* The broken HTML template support was removed from Tempita.
+ (Github issue :issue:`3309`)
+
+
0.29.35 (2023-05-24)
====================
diff --git a/contrib/tools/cython/Cython/Compiler/Builtin.py b/contrib/tools/cython/Cython/Compiler/Builtin.py
index e0d203ae02..c3e202e001 100644
--- a/contrib/tools/cython/Cython/Compiler/Builtin.py
+++ b/contrib/tools/cython/Cython/Compiler/Builtin.py
@@ -417,9 +417,10 @@ def init_builtins():
init_builtin_types()
init_builtin_funcs()
- builtin_scope.declare_var(
+ entry = builtin_scope.declare_var(
'__debug__', PyrexTypes.c_const_type(PyrexTypes.c_bint_type),
- pos=None, cname='(!Py_OptimizeFlag)', is_cdef=True)
+ pos=None, cname='__pyx_assertions_enabled()', is_cdef=True)
+ entry.utility_code = UtilityCode.load_cached("AssertionsEnabled", "Exceptions.c")
global list_type, tuple_type, dict_type, set_type, frozenset_type
global bytes_type, str_type, unicode_type, basestring_type, slice_type
diff --git a/contrib/tools/cython/Cython/Compiler/ModuleNode.py b/contrib/tools/cython/Cython/Compiler/ModuleNode.py
index 1e392a4e3a..fd998d419f 100644
--- a/contrib/tools/cython/Cython/Compiler/ModuleNode.py
+++ b/contrib/tools/cython/Cython/Compiler/ModuleNode.py
@@ -1469,10 +1469,10 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
# in Py3.4+, call tp_finalize() as early as possible
code.putln("#if CYTHON_USE_TP_FINALIZE")
if needs_gc:
- finalised_check = '!_PyGC_FINALIZED(o)'
+ finalised_check = '!__Pyx_PyObject_GC_IsFinalized(o)'
else:
finalised_check = (
- '(!PyType_IS_GC(Py_TYPE(o)) || !_PyGC_FINALIZED(o))')
+ '(!PyType_IS_GC(Py_TYPE(o)) || !__Pyx_PyObject_GC_IsFinalized(o))')
code.putln(
"if (unlikely(PyType_HasFeature(Py_TYPE(o), Py_TPFLAGS_HAVE_FINALIZE)"
" && Py_TYPE(o)->tp_finalize) && %s) {" % finalised_check)
diff --git a/contrib/tools/cython/Cython/Compiler/Nodes.py b/contrib/tools/cython/Cython/Compiler/Nodes.py
index f57ddf3dd3..db5d657829 100644
--- a/contrib/tools/cython/Cython/Compiler/Nodes.py
+++ b/contrib/tools/cython/Cython/Compiler/Nodes.py
@@ -6215,8 +6215,10 @@ class AssertStatNode(StatNode):
gil_message = "Raising exception"
def generate_execution_code(self, code):
+ code.globalstate.use_utility_code(
+ UtilityCode.load_cached("AssertionsEnabled", "Exceptions.c"))
code.putln("#ifndef CYTHON_WITHOUT_ASSERTIONS")
- code.putln("if (unlikely(!Py_OptimizeFlag)) {")
+ code.putln("if (unlikely(__pyx_assertions_enabled())) {")
code.mark_pos(self.pos)
self.cond.generate_evaluation_code(code)
code.putln(
diff --git a/contrib/tools/cython/Cython/Shadow.py b/contrib/tools/cython/Cython/Shadow.py
index 6c2b44ea37..a3991f0494 100644
--- a/contrib/tools/cython/Cython/Shadow.py
+++ b/contrib/tools/cython/Cython/Shadow.py
@@ -1,7 +1,7 @@
# cython.* namespace for pure mode.
from __future__ import absolute_import
-__version__ = "0.29.35"
+__version__ = "0.29.36"
try:
from __builtin__ import basestring
diff --git a/contrib/tools/cython/Cython/Tempita/_tempita.py b/contrib/tools/cython/Cython/Tempita/_tempita.py
index 587f6e4841..2af7d258ef 100644
--- a/contrib/tools/cython/Cython/Tempita/_tempita.py
+++ b/contrib/tools/cython/Cython/Tempita/_tempita.py
@@ -33,17 +33,6 @@ from __future__ import absolute_import
import re
import sys
-try:
- import cgi
-except ImportError:
- pass
-try:
- from urllib import quote as url_quote
-except ImportError: # Py3
- try:
- from urllib.parse import quote as url_quote
- except ImportError:
- pass
import os
import tokenize
from io import StringIO
@@ -51,8 +40,7 @@ from io import StringIO
from ._looper import looper
from .compat3 import bytes, unicode_, basestring_, next, is_unicode, coerce_text
-__all__ = ['TemplateError', 'Template', 'sub', 'HTMLTemplate',
- 'sub_html', 'html', 'bunch']
+__all__ = ['TemplateError', 'Template', 'sub', 'bunch']
in_re = re.compile(r'\s+in\s+')
var_re = re.compile(r'^[a-z_][a-z0-9_]*$', re.I)
@@ -150,9 +138,8 @@ class Template(object):
def from_filename(cls, filename, namespace=None, encoding=None,
default_inherit=None, get_template=get_file_template):
- f = open(filename, 'rb')
- c = f.read()
- f.close()
+ with open(filename, 'rb') as f:
+ c = f.read()
if encoding:
c = c.decode(encoding)
return cls(content=c, name=filename, namespace=namespace,
@@ -417,91 +404,6 @@ class bunch(dict):
self.__class__.__name__,
' '.join(['%s=%r' % (k, v) for k, v in sorted(self.items())]))
-############################################################
-## HTML Templating
-############################################################
-
-
-class html(object):
-
- def __init__(self, value):
- self.value = value
-
- def __str__(self):
- return self.value
-
- def __html__(self):
- return self.value
-
- def __repr__(self):
- return '<%s %r>' % (
- self.__class__.__name__, self.value)
-
-
-def html_quote(value, force=True):
- if not force and hasattr(value, '__html__'):
- return value.__html__()
- if value is None:
- return ''
- if not isinstance(value, basestring_):
- value = coerce_text(value)
- if sys.version >= "3" and isinstance(value, bytes):
- value = cgi.escape(value.decode('latin1'), 1)
- value = value.encode('latin1')
- else:
- value = cgi.escape(value, 1)
- if sys.version < "3":
- if is_unicode(value):
- value = value.encode('ascii', 'xmlcharrefreplace')
- return value
-
-
-def url(v):
- v = coerce_text(v)
- if is_unicode(v):
- v = v.encode('utf8')
- return url_quote(v)
-
-
-def attr(**kw):
- parts = []
- for name, value in sorted(kw.items()):
- if value is None:
- continue
- if name.endswith('_'):
- name = name[:-1]
- parts.append('%s="%s"' % (html_quote(name), html_quote(value)))
- return html(' '.join(parts))
-
-
-class HTMLTemplate(Template):
-
- default_namespace = Template.default_namespace.copy()
- default_namespace.update(dict(
- html=html,
- attr=attr,
- url=url,
- html_quote=html_quote,
- ))
-
- def _repr(self, value, pos):
- if hasattr(value, '__html__'):
- value = value.__html__()
- quote = False
- else:
- quote = True
- plain = Template._repr(self, value, pos)
- if quote:
- return html_quote(plain)
- else:
- return plain
-
-
-def sub_html(content, **kw):
- name = kw.get('__name')
- tmpl = HTMLTemplate(content, name=name)
- return tmpl.substitute(kw)
-
class TemplateDef(object):
def __init__(self, template, func_name, func_signature,
@@ -1137,11 +1039,6 @@ def fill_command(args=None):
metavar="FILENAME",
help="File to write output to (default stdout)")
parser.add_option(
- '--html',
- dest='use_html',
- action='store_true',
- help="Use HTML style filling (including automatic HTML quoting)")
- parser.add_option(
'--env',
dest='use_env',
action='store_true',
@@ -1168,19 +1065,13 @@ def fill_command(args=None):
template_content = sys.stdin.read()
template_name = '<stdin>'
else:
- f = open(template_name, 'rb')
- template_content = f.read()
- f.close()
- if options.use_html:
- TemplateClass = HTMLTemplate
- else:
- TemplateClass = Template
- template = TemplateClass(template_content, name=template_name)
+ with open(template_name, 'rb') as f:
+ template_content = f.read()
+ template = Template(template_content, name=template_name)
result = template.substitute(vars)
if options.output:
- f = open(options.output, 'wb')
- f.write(result)
- f.close()
+ with open(options.output, 'wb') as f:
+ f.write(result)
else:
sys.stdout.write(result)
diff --git a/contrib/tools/cython/Cython/Utility/AsyncGen.c b/contrib/tools/cython/Cython/Utility/AsyncGen.c
index dd4bf37280..e55b786578 100644
--- a/contrib/tools/cython/Cython/Utility/AsyncGen.c
+++ b/contrib/tools/cython/Cython/Utility/AsyncGen.c
@@ -202,7 +202,9 @@ __Pyx_async_gen_repr(__pyx_CoroutineObject *o)
static int
__Pyx_async_gen_init_hooks(__pyx_PyAsyncGenObject *o)
{
+#if !CYTHON_COMPILING_IN_PYPY
PyThreadState *tstate;
+#endif
PyObject *finalizer;
PyObject *firstiter;
@@ -212,15 +214,22 @@ __Pyx_async_gen_init_hooks(__pyx_PyAsyncGenObject *o)
o->ag_hooks_inited = 1;
+#if CYTHON_COMPILING_IN_PYPY
+ finalizer = _PyEval_GetAsyncGenFinalizer();
+#else
tstate = __Pyx_PyThreadState_Current;
-
finalizer = tstate->async_gen_finalizer;
+#endif
if (finalizer) {
Py_INCREF(finalizer);
o->ag_finalizer = finalizer;
}
+#if CYTHON_COMPILING_IN_PYPY
+ firstiter = _PyEval_GetAsyncGenFirstiter();
+#else
firstiter = tstate->async_gen_firstiter;
+#endif
if (firstiter) {
PyObject *res;
#if CYTHON_UNPACK_METHODS
diff --git a/contrib/tools/cython/Cython/Utility/Exceptions.c b/contrib/tools/cython/Cython/Utility/Exceptions.c
index 87d3a5cddb..8117b92d4b 100644
--- a/contrib/tools/cython/Cython/Utility/Exceptions.c
+++ b/contrib/tools/cython/Cython/Utility/Exceptions.c
@@ -6,6 +6,32 @@
// __Pyx_GetException()
+/////////////// AssertionsEnabled.init ///////////////
+__Pyx_init_assertions_enabled();
+
+/////////////// AssertionsEnabled.proto ///////////////
+
+#define __Pyx_init_assertions_enabled()
+
+#if CYTHON_COMPILING_IN_PYPY && PY_VERSION_HEX < 0x02070600 && !defined(Py_OptimizeFlag)
+ #define __pyx_assertions_enabled() (1)
+#elif PY_VERSION_HEX < 0x03080000 || CYTHON_COMPILING_IN_PYPY || defined(Py_LIMITED_API)
+ #define __pyx_assertions_enabled() (!Py_OptimizeFlag)
+#elif CYTHON_COMPILING_IN_CPYTHON && PY_VERSION_HEX >= 0x030900A6
+ // Py3.8+ has PyConfig from PEP 587, but only Py3.9 added read access to it.
+ // Py_OptimizeFlag is deprecated in Py3.12+
+ static int __pyx_assertions_enabled_flag;
+ #define __pyx_assertions_enabled() (__pyx_assertions_enabled_flag)
+
+ #undef __Pyx_init_assertions_enabled
+ static void __Pyx_init_assertions_enabled(void) {
+ __pyx_assertions_enabled_flag = ! _PyInterpreterState_GetConfig(__Pyx_PyThreadState_Current->interp)->optimization_level;
+ }
+#else
+ #define __pyx_assertions_enabled() (!Py_OptimizeFlag)
+#endif
+
+
/////////////// PyThreadStateGet.proto ///////////////
//@substitute: naming
diff --git a/contrib/tools/cython/Cython/Utility/ModuleSetupCode.c b/contrib/tools/cython/Cython/Utility/ModuleSetupCode.c
index 31a8fec231..8503679412 100644
--- a/contrib/tools/cython/Cython/Utility/ModuleSetupCode.c
+++ b/contrib/tools/cython/Cython/Utility/ModuleSetupCode.c
@@ -93,7 +93,7 @@
#define CYTHON_PEP489_MULTI_PHASE_INIT 1
#endif
#undef CYTHON_USE_TP_FINALIZE
- #define CYTHON_USE_TP_FINALIZE 0
+ #define CYTHON_USE_TP_FINALIZE (PY_VERSION_HEX >= 0x030400a1 && PYPY_VERSION_NUM >= 0x07030C00)
#undef CYTHON_USE_DICT_VERSIONS
#define CYTHON_USE_DICT_VERSIONS 0
#undef CYTHON_USE_EXC_INFO_STACK
@@ -455,10 +455,6 @@ class __Pyx_FakeReference {
/////////////// PythonCompatibility ///////////////
-#if CYTHON_COMPILING_IN_PYPY && PY_VERSION_HEX < 0x02070600 && !defined(Py_OptimizeFlag)
- #define Py_OptimizeFlag 0
-#endif
-
#define __PYX_BUILD_PY_SSIZE_T "n"
#define CYTHON_FORMAT_SSIZE_T "z"
@@ -547,6 +543,12 @@ class __Pyx_FakeReference {
#define __Pyx_DefaultClassType PyType_Type
#endif
+#if PY_VERSION_HEX >= 0x030900F0 && !CYTHON_COMPILING_IN_PYPY
+ #define __Pyx_PyObject_GC_IsFinalized(o) PyObject_GC_IsFinalized(o)
+#else
+ #define __Pyx_PyObject_GC_IsFinalized(o) _PyGC_FINALIZED(o)
+#endif
+
#ifndef Py_TPFLAGS_CHECKTYPES
#define Py_TPFLAGS_CHECKTYPES 0
#endif
diff --git a/contrib/tools/cython/Cython/Utility/ObjectHandling.c b/contrib/tools/cython/Cython/Utility/ObjectHandling.c
index 02574e46ec..5c4d9e1608 100644
--- a/contrib/tools/cython/Cython/Utility/ObjectHandling.c
+++ b/contrib/tools/cython/Cython/Utility/ObjectHandling.c
@@ -194,11 +194,11 @@ static CYTHON_INLINE PyObject *__Pyx_PyIter_Next2(PyObject* iterator, PyObject*
// We always do a quick slot check because calling PyIter_Check() is so wasteful.
iternextfunc iternext = Py_TYPE(iterator)->tp_iternext;
if (likely(iternext)) {
-#if CYTHON_USE_TYPE_SLOTS
+#if CYTHON_USE_TYPE_SLOTS || CYTHON_COMPILING_IN_PYPY
next = iternext(iterator);
if (likely(next))
return next;
- #if PY_VERSION_HEX >= 0x02070000
+ #if PY_VERSION_HEX >= 0x02070000 && CYTHON_COMPILING_IN_CPYTHON
if (unlikely(iternext == &_PyObject_NextNotImplemented))
return NULL;
#endif
diff --git a/contrib/tools/cython/cython.py b/contrib/tools/cython/cython.py
index 19568b3567..30315749d3 100755
--- a/contrib/tools/cython/cython.py
+++ b/contrib/tools/cython/cython.py
@@ -1,6 +1,6 @@
#!/usr/bin/env python
-# Change content of this file to change uids for cython programs - cython 0.29.35 r0
+# Change content of this file to change uids for cython programs - cython 0.29.36 r0
#
# Cython -- Main Program, generic
diff --git a/contrib/tools/cython/patches/5c5d70e-fix-embedded-dealloc-argv-more-3.5.patch b/contrib/tools/cython/patches/5c5d70e-fix-embedded-dealloc-argv-more-3.5.patch
new file mode 100644
index 0000000000..ba89a1443b
--- /dev/null
+++ b/contrib/tools/cython/patches/5c5d70e-fix-embedded-dealloc-argv-more-3.5.patch
@@ -0,0 +1,17 @@
+--- contrib/tools/cython/Cython/Utility/Embed.c (index)
++++ contrib/tools/cython/Cython/Utility/Embed.c (working tree)
+@@ -234,7 +234,12 @@ int
+ res = 0;
+ setlocale(LC_ALL, "");
+ for (i = 0; i < argc; i++) {
+- argv_copy2[i] = argv_copy[i] = __Pyx_char2wchar(argv[i]);
++ argv_copy2[i] = argv_copy[i] =
++#if PY_VERSION_HEX < 0x03050000
++ __Pyx_char2wchar(argv[i]);
++#else
++ Py_DecodeLocale(argv[i], NULL);
++#endif
+ if (!argv_copy[i]) res = 1; /* failure, but continue to simplify cleanup */
+ }
+ setlocale(LC_ALL, oldloc);
+ free(oldloc);
diff --git a/contrib/tools/cython/patches/all-changes.patch b/contrib/tools/cython/patches/all-changes.patch
new file mode 100644
index 0000000000..b9424c7ac4
--- /dev/null
+++ b/contrib/tools/cython/patches/all-changes.patch
@@ -0,0 +1,937 @@
+--- contrib/tools/cython/Cython/Compiler/Annotate.py (index)
++++ contrib/tools/cython/Cython/Compiler/Annotate.py (working tree)
+@@ -10,7 +10,10 @@ import textwrap
+ from datetime import datetime
+ from functools import partial
+ from collections import defaultdict
+-from xml.sax.saxutils import escape as html_escape
++try:
++ from xml.sax.saxutils import escape as html_escape
++except ImportError:
++ pass
+ try:
+ from StringIO import StringIO
+ except ImportError:
+--- contrib/tools/cython/Cython/Compiler/CmdLine.py (index)
++++ contrib/tools/cython/Cython/Compiler/CmdLine.py (working tree)
+@@ -152,6 +152,10 @@ def parse_command_line(args):
+ elif option == "--lenient":
+ Options.error_on_unknown_names = False
+ Options.error_on_uninitialized = False
++ elif option == '--init-suffix':
++ options.init_suffix = pop_arg()
++ elif option == '--source-root':
++ Options.source_root = pop_arg()
+ elif option == '-2':
+ options.language_level = 2
+ elif option == '-3':
+--- contrib/tools/cython/Cython/Compiler/ExprNodes.py (index)
++++ contrib/tools/cython/Cython/Compiler/ExprNodes.py (working tree)
+@@ -9543,6 +9543,8 @@ class CodeObjectNode(ExprNode):
+ func.name, identifier=True, is_str=False, unicode_value=func.name)
+ # FIXME: better way to get the module file path at module init time? Encoding to use?
+ file_path = StringEncoding.bytes_literal(func.pos[0].get_filenametable_entry().encode('utf8'), 'utf8')
++ # XXX Use get_description() to set arcadia root relative filename
++ file_path = StringEncoding.bytes_literal(func.pos[0].get_description().encode('utf8'), 'utf8')
+ file_path_const = code.get_py_string_const(file_path, identifier=False, is_str=True)
+
+ # This combination makes CPython create a new dict for "frame.f_locals" (see GH #1836).
+--- contrib/tools/cython/Cython/Compiler/Main.py (index)
++++ contrib/tools/cython/Cython/Compiler/Main.py (working tree)
+@@ -206,9 +206,7 @@ class Context(object):
+ if not pxd_pathname:
+ if debug_find_module:
+ print("...looking for pxd file")
+- # Only look in sys.path if we are explicitly looking
+- # for a .pxd file.
+- pxd_pathname = self.find_pxd_file(qualified_name, pos, sys_path=need_pxd)
++ pxd_pathname = self.find_pxd_file(qualified_name, pos)
+ if debug_find_module:
+ print("......found %s" % pxd_pathname)
+ if not pxd_pathname and need_pxd:
+@@ -228,6 +226,8 @@ class Context(object):
+ rel_path = module_name.replace('.', os.sep) + os.path.splitext(pxd_pathname)[1]
+ if not pxd_pathname.endswith(rel_path):
+ rel_path = pxd_pathname # safety measure to prevent printing incorrect paths
++ if Options.source_root:
++ rel_path = os.path.relpath(pxd_pathname, Options.source_root)
+ source_desc = FileSourceDescriptor(pxd_pathname, rel_path)
+ err, result = self.process_pxd(source_desc, scope, qualified_name)
+ if err:
+@@ -238,7 +238,7 @@ class Context(object):
+ pass
+ return scope
+
+- def find_pxd_file(self, qualified_name, pos, sys_path=True):
++ def find_pxd_file(self, qualified_name, pos, sys_path=False):
+ # Search include path (and sys.path if sys_path is True) for
+ # the .pxd file corresponding to the given fully-qualified
+ # module name.
+@@ -481,7 +481,7 @@ def run_pipeline(source, options, full_module_name=None, context=None):
+ # Set up source object
+ cwd = os.getcwd()
+ abs_path = os.path.abspath(source)
+- full_module_name = full_module_name or context.extract_module_name(source, options)
++ full_module_name = full_module_name or options.module_name or context.extract_module_name(source, options)
+
+ Utils.raise_error_if_module_name_forbidden(full_module_name)
+
+@@ -491,6 +491,8 @@ def run_pipeline(source, options, full_module_name=None, context=None):
+ rel_path = source # safety measure to prevent printing incorrect paths
+ else:
+ rel_path = abs_path
++ if Options.source_root:
++ rel_path = os.path.relpath(abs_path, Options.source_root)
+ source_desc = FileSourceDescriptor(abs_path, rel_path)
+ source = CompilationSource(source_desc, full_module_name, cwd)
+
+@@ -835,6 +837,21 @@ def search_include_directories(dirs, qualified_name, suffix, pos, include=False)
+ package_filename)
+ if os.path.exists(path):
+ return path
++
++ # Arcadia-specific lookup: search for packages in include paths,
++ # ignoring existence of __init__.py files as packages markers
++ # (they are not required by Arcadia build system)
++ if not include:
++ for dir in dirs:
++ package_dir = os.path.join(dir, *package_names)
++ path = os.path.join(package_dir, module_filename)
++ if os.path.exists(path):
++ return path
++ path = os.path.join(dir, package_dir, module_name,
++ package_filename)
++ if os.path.exists(path):
++ return path
++
+ return None
+
+
+@@ -903,6 +920,7 @@ default_options = dict(
+ language_level = None, # warn but default to 2
+ formal_grammar = False,
+ gdb_debug = False,
++ init_suffix = None,
+ compile_time_env = None,
+ common_utility_include_dir = None,
+ output_dir=None,
+--- contrib/tools/cython/Cython/Compiler/ModuleNode.py (index)
++++ contrib/tools/cython/Cython/Compiler/ModuleNode.py (working tree)
+@@ -208,9 +208,10 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
+ h_code.putln("/* It now returns a PyModuleDef instance instead of a PyModule instance. */")
+ h_code.putln("")
+ h_code.putln("#if PY_MAJOR_VERSION < 3")
+- h_code.putln("PyMODINIT_FUNC init%s(void);" % env.module_name)
++ init_name = 'init' + (options.init_suffix or env.module_name)
++ h_code.putln("PyMODINIT_FUNC %s(void);" % init_name)
+ h_code.putln("#else")
+- h_code.putln("PyMODINIT_FUNC %s(void);" % self.mod_init_func_cname('PyInit', env))
++ h_code.putln("PyMODINIT_FUNC %s(void);" % self.mod_init_func_cname('PyInit', env, options))
+ h_code.putln("#endif")
+ h_code.putln("")
+ h_code.putln("#endif /* !%s */" % h_guard)
+@@ -389,13 +390,13 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
+ self.generate_method_table(env, code)
+ if env.has_import_star:
+ self.generate_import_star(env, code)
+- self.generate_pymoduledef_struct(env, code)
++ self.generate_pymoduledef_struct(env, options, code)
+
+ # initialise the macro to reduce the code size of one-time functionality
+ code.putln(UtilityCode.load_as_string("SmallCodeConfig", "ModuleSetupCode.c")[0].strip())
+
+ # init_globals is inserted before this
+- self.generate_module_init_func(modules[:-1], env, globalstate['init_module'])
++ self.generate_module_init_func(modules[:-1], env, options, globalstate['init_module'])
+ self.generate_module_cleanup_func(env, globalstate['cleanup_module'])
+ if Options.embed:
+ self.generate_main_method(env, globalstate['main_method'])
+@@ -782,6 +783,9 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
+ if code.globalstate.filename_list:
+ for source_desc in code.globalstate.filename_list:
+ file_path = source_desc.get_filenametable_entry()
++ if Options.source_root:
++ # If source root specified, dump description - it's source root relative filename
++ file_path = source_desc.get_description()
+ if isabs(file_path):
+ file_path = basename(file_path) # never include absolute paths
+ escaped_filename = file_path.replace("\\", "\\\\").replace('"', r'\"')
+@@ -928,6 +932,8 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
+ constructor = None
+ destructor = None
+ for attr in scope.var_entries:
++ if attr.type.is_cfunction:
++ code.put("inline ")
+ if attr.type.is_cfunction and attr.type.is_static_method:
+ code.put("static ")
+ elif attr.name == "<init>":
+@@ -2308,14 +2314,15 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
+ code.putln(UtilityCode.load_as_string("ImportStar", "ImportExport.c")[1])
+ code.exit_cfunc_scope() # done with labels
+
+- def generate_module_init_func(self, imported_modules, env, code):
++ def generate_module_init_func(self, imported_modules, env, options, code):
+ subfunction = self.mod_init_subfunction(self.pos, self.scope, code)
+
+ code.enter_cfunc_scope(self.scope)
+ code.putln("")
+ code.putln(UtilityCode.load_as_string("PyModInitFuncType", "ModuleSetupCode.c")[0])
+- header2 = "__Pyx_PyMODINIT_FUNC init%s(void)" % env.module_name
+- header3 = "__Pyx_PyMODINIT_FUNC %s(void)" % self.mod_init_func_cname('PyInit', env)
++ init_name = 'init' + (options.init_suffix or env.module_name)
++ header2 = "__Pyx_PyMODINIT_FUNC %s(void)" % init_name
++ header3 = "__Pyx_PyMODINIT_FUNC %s(void)" % self.mod_init_func_cname('PyInit', env, options)
+ code.putln("#if PY_MAJOR_VERSION < 3")
+ # Optimise for small code size as the module init function is only executed once.
+ code.putln("%s CYTHON_SMALL_CODE; /*proto*/" % header2)
+@@ -2412,7 +2419,7 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
+ code.putln("#endif")
+
+ code.putln("/*--- Module creation code ---*/")
+- self.generate_module_creation_code(env, code)
++ self.generate_module_creation_code(env, options, code)
+
+ code.putln("/*--- Initialize various global constants etc. ---*/")
+ code.put_error_if_neg(self.pos, "__Pyx_InitGlobals()")
+@@ -2737,10 +2744,10 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
+ main_method=Options.embed,
+ wmain_method=wmain))
+
+- def mod_init_func_cname(self, prefix, env):
+- return '%s_%s' % (prefix, env.module_name)
++ def mod_init_func_cname(self, prefix, env, options=None):
++ return '%s_%s' % (prefix, options and options.init_suffix or env.module_name)
+
+- def generate_pymoduledef_struct(self, env, code):
++ def generate_pymoduledef_struct(self, env, options, code):
+ if env.doc:
+ doc = "%s" % code.get_string_const(env.doc)
+ else:
+@@ -2768,7 +2775,7 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
+ code.putln("")
+ code.putln("static struct PyModuleDef %s = {" % Naming.pymoduledef_cname)
+ code.putln(" PyModuleDef_HEAD_INIT,")
+- code.putln(' "%s",' % env.module_name)
++ code.putln(' "%s",' % (options.module_name or env.module_name))
+ code.putln(" %s, /* m_doc */" % doc)
+ code.putln("#if CYTHON_PEP489_MULTI_PHASE_INIT")
+ code.putln(" 0, /* m_size */")
+@@ -2787,7 +2794,7 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
+ code.putln("};")
+ code.putln("#endif")
+
+- def generate_module_creation_code(self, env, code):
++ def generate_module_creation_code(self, env, options, code):
+ # Generate code to create the module object and
+ # install the builtins.
+ if env.doc:
+@@ -2805,7 +2812,7 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
+ code.putln(
+ '%s = Py_InitModule4("%s", %s, %s, 0, PYTHON_API_VERSION); Py_XINCREF(%s);' % (
+ env.module_cname,
+- env.module_name,
++ options.module_name or env.module_name,
+ env.method_table_cname,
+ doc,
+ env.module_cname))
+--- contrib/tools/cython/Cython/Compiler/Nodes.py (index)
++++ contrib/tools/cython/Cython/Compiler/Nodes.py (working tree)
+@@ -4170,7 +4170,7 @@ class GeneratorBodyDefNode(DefNode):
+ self.declare_generator_body(env)
+
+ def generate_function_header(self, code, proto=False):
+- header = "static PyObject *%s(__pyx_CoroutineObject *%s, CYTHON_UNUSED PyThreadState *%s, PyObject *%s)" % (
++ header = "static PyObject *%s(PyObject *%s_obj, CYTHON_UNUSED PyThreadState *%s, PyObject *%s)" % (
+ self.entry.func_cname,
+ Naming.generator_cname,
+ Naming.local_tstate_cname,
+@@ -4196,6 +4196,7 @@ class GeneratorBodyDefNode(DefNode):
+ # ----- Function header
+ code.putln("")
+ self.generate_function_header(code)
++ code.putln("__pyx_CoroutineObject *%s = (__pyx_CoroutineObject *)%s_obj;" % (Naming.generator_cname, Naming.generator_cname))
+ closure_init_code = code.insertion_point()
+ # ----- Local variables
+ code.putln("PyObject *%s = NULL;" % Naming.retval_cname)
+--- contrib/tools/cython/Cython/Compiler/Options.py (index)
++++ contrib/tools/cython/Cython/Compiler/Options.py (working tree)
+@@ -150,6 +150,9 @@ buffer_max_dims = 8
+ #: Number of function closure instances to keep in a freelist (0: no freelists)
+ closure_freelist_size = 8
+
++# Arcadia specific
++source_root = None
++
+
+ def get_directive_defaults():
+ # To add an item to this list, all accesses should be changed to use the new
+--- contrib/tools/cython/Cython/Compiler/Parsing.py (index)
++++ contrib/tools/cython/Cython/Compiler/Parsing.py (working tree)
+@@ -2046,7 +2046,12 @@ def p_include_statement(s, ctx):
+ if include_file_path:
+ s.included_files.append(include_file_name)
+ with Utils.open_source_file(include_file_path) as f:
+- source_desc = FileSourceDescriptor(include_file_path)
++ if Options.source_root:
++ import os
++ rel_path = os.path.relpath(include_file_path, Options.source_root)
++ else:
++ rel_path = None
++ source_desc = FileSourceDescriptor(include_file_path, rel_path)
+ s2 = PyrexScanner(f, source_desc, s, source_encoding=f.encoding, parse_comments=s.parse_comments)
+ tree = p_statement_list(s2, ctx)
+ return tree
+@@ -3696,6 +3701,9 @@ def p_module(s, pxd, full_module_name, ctx=Ctx):
+ s.parse_comments = False
+
+ if s.context.language_level is None:
++ s.context.set_language_level(2) # Arcadia default.
++
++ if s.context.language_level is None:
+ s.context.set_language_level(2)
+ if pos[0].filename:
+ import warnings
+--- contrib/tools/cython/Cython/Compiler/PyrexTypes.py (index)
++++ contrib/tools/cython/Cython/Compiler/PyrexTypes.py (working tree)
+@@ -3483,7 +3483,7 @@ class CStructOrUnionType(CType):
+ return expr_code
+ return super(CStructOrUnionType, self).cast_code(expr_code)
+
+-cpp_string_conversions = ("std::string",)
++cpp_string_conversions = ("std::string", "TString", "TStringBuf")
+
+ builtin_cpp_conversions = {
+ # type element template params
+@@ -3495,6 +3495,11 @@ builtin_cpp_conversions = {
+ "std::map": 2,
+ "std::unordered_map": 2,
+ "std::complex": 1,
++ # arcadia_cpp_conversions
++ "TMaybe": 1,
++ "TVector": 1,
++ "THashMap": 2,
++ "TMap": 2,
+ }
+
+ class CppClassType(CType):
+@@ -3524,7 +3529,7 @@ class CppClassType(CType):
+ self.templates = templates
+ self.template_type = template_type
+ self.num_optional_templates = sum(is_optional_template_param(T) for T in templates or ())
+- if templates:
++ if templates and False: # https://github.com/cython/cython/issues/1868
+ self.specializations = {tuple(zip(templates, templates)): self}
+ else:
+ self.specializations = {}
+@@ -3570,8 +3575,10 @@ class CppClassType(CType):
+ if self.cname in cpp_string_conversions:
+ cls = 'string'
+ tags = type_identifier(self),
+- else:
++ elif self.cname.startswith('std::'):
+ cls = self.cname[5:]
++ else:
++ cls = 'arcadia_' + self.cname
+ cname = '__pyx_convert_%s_from_py_%s' % (cls, '__and_'.join(tags))
+ context.update({
+ 'cname': cname,
+@@ -3594,7 +3601,6 @@ class CppClassType(CType):
+ return False
+ return True
+
+-
+ def create_to_py_utility_code(self, env):
+ if self.to_py_function is not None:
+ return True
+@@ -3614,9 +3620,12 @@ class CppClassType(CType):
+ cls = 'string'
+ prefix = 'PyObject_' # gets specialised by explicit type casts in CoerceToPyTypeNode
+ tags = type_identifier(self),
+- else:
++ elif self.cname.startswith('std::'):
+ cls = self.cname[5:]
+ prefix = ''
++ else:
++ cls = 'arcadia_' + self.cname
++ prefix = ''
+ cname = "__pyx_convert_%s%s_to_py_%s" % (prefix, cls, "____".join(tags))
+ context.update({
+ 'cname': cname,
+--- contrib/tools/cython/Cython/Compiler/Scanning.py (index)
++++ contrib/tools/cython/Cython/Compiler/Scanning.py (working tree)
+@@ -245,6 +245,8 @@ class FileSourceDescriptor(SourceDescriptor):
+ return lines
+
+ def get_description(self):
++ # Dump path_description, it's already arcadia root relative (required for proper file matching in coverage)
++ return self.path_description
+ try:
+ return os.path.relpath(self.path_description)
+ except ValueError:
+--- contrib/tools/cython/Cython/Coverage.py (index)
++++ contrib/tools/cython/Cython/Coverage.py (working tree)
+@@ -65,10 +65,14 @@ class Plugin(CoveragePlugin):
+ """
+ Try to find a C source file for a file path found by the tracer.
+ """
++ # TODO We need to pxd-files to the include map. For more info see pybuild.py
++ # Currently skip such files, because they are not supported in Arcadia pybuild with coverage.
++ if os.path.splitext(filename)[-1] not in ('.pyx', '.pxi'):
++ return None
+ if filename.startswith('<') or filename.startswith('memory:'):
+ return None
+ c_file = py_file = None
+- filename = canonical_filename(os.path.abspath(filename))
++ filename = canonical_filename(filename)
+ if self._c_files_map and filename in self._c_files_map:
+ c_file = self._c_files_map[filename][0]
+
+@@ -98,16 +102,21 @@ class Plugin(CoveragePlugin):
+ # from coverage.python import PythonFileReporter
+ # return PythonFileReporter(filename)
+
+- filename = canonical_filename(os.path.abspath(filename))
++ filename = canonical_filename(filename)
+ if self._c_files_map and filename in self._c_files_map:
+ c_file, rel_file_path, code = self._c_files_map[filename]
+ else:
+ c_file, _ = self._find_source_files(filename)
+ if not c_file:
++ if standalone():
++ raise AssertionError(filename)
+ return None # unknown file
+ rel_file_path, code = self._read_source_lines(c_file, filename)
+ if code is None:
++ if standalone():
++ raise AssertionError(filename)
+ return None # no source found
++
+ return CythonModuleReporter(c_file, filename, rel_file_path, code)
+
+ def _find_source_files(self, filename):
+@@ -132,6 +141,8 @@ class Plugin(CoveragePlugin):
+ self._find_c_source_files(os.path.dirname(filename), filename)
+ if filename in self._c_files_map:
+ return self._c_files_map[filename][0], None
++ if standalone():
++ raise AssertionError(filename)
+ else:
+ # none of our business
+ return None, None
+@@ -152,8 +163,8 @@ class Plugin(CoveragePlugin):
+ py_source_file = None
+
+ try:
+- with open(c_file, 'rb') as f:
+- if b'/* Generated by Cython ' not in f.read(30):
++ with OpenFile(c_file) as f:
++ if '/* Generated by Cython ' not in f.read(30):
+ return None, None # not a Cython file
+ except (IOError, OSError):
+ c_file = None
+@@ -165,6 +176,20 @@ class Plugin(CoveragePlugin):
+ Desperately parse all C files in the directory or its package parents
+ (not re-descending) to find the (included) source file in one of them.
+ """
++ if standalone():
++ if os.environ.get('PYTHON_COVERAGE_CYTHON_BUILD_ROOT'):
++ broot = os.environ['PYTHON_COVERAGE_CYTHON_BUILD_ROOT']
++ iter_files = lambda: (os.path.join(root, filename) for root, _, files in os.walk(broot) for filename in files)
++ else:
++ import library.python.resource
++ iter_files = library.python.resource.resfs_files
++ for c_file in iter_files():
++ if os.path.splitext(c_file)[1] in C_FILE_EXTENSIONS:
++ self._read_source_lines(c_file, source_file)
++ if source_file in self._c_files_map:
++ return
++ raise AssertionError((source_file, os.environ.get('PYTHON_COVERAGE_CYTHON_BUILD_ROOT')))
++
+ if not os.path.isdir(dir_path):
+ return
+ splitext = os.path.splitext
+@@ -223,7 +248,7 @@ class Plugin(CoveragePlugin):
+ executable_lines = defaultdict(set)
+ current_filename = None
+
+- with open(c_file) as lines:
++ with OpenFile(c_file) as lines:
+ lines = iter(lines)
+ for line in lines:
+ match = match_source_path_line(line)
+@@ -280,7 +305,10 @@ class CythonModuleTracer(FileTracer):
+ return self._file_path_map[source_file]
+ except KeyError:
+ pass
+- abs_path = _find_dep_file_path(filename, source_file)
++ if standalone():
++ abs_path = self.module_file
++ else:
++ abs_path = _find_dep_file_path(filename, source_file)
+
+ if self.py_file and source_file[-3:].lower() == '.py':
+ # always let coverage.py handle this case itself
+@@ -303,6 +331,7 @@ class CythonModuleReporter(FileReporter):
+ self.name = rel_file_path
+ self.c_file = c_file
+ self._code = code
++ self._abs_filename = self._find_abs_filename()
+
+ def lines(self):
+ """
+@@ -323,8 +352,8 @@ class CythonModuleReporter(FileReporter):
+ """
+ Return the source code of the file as a string.
+ """
+- if os.path.exists(self.filename):
+- with open_source_file(self.filename) as f:
++ if os.path.exists(self._abs_filename):
++ with open_source_file(self._abs_filename) as f:
+ return f.read()
+ else:
+ return '\n'.join(
+@@ -335,14 +364,119 @@ class CythonModuleReporter(FileReporter):
+ """
+ Iterate over the source code tokens.
+ """
+- if os.path.exists(self.filename):
+- with open_source_file(self.filename) as f:
++ if os.path.exists(self._abs_filename):
++ with open_source_file(self._abs_filename) as f:
+ for line in f:
+ yield [('txt', line.rstrip('\n'))]
+ else:
+ for line in self._iter_source_tokens():
+- yield [('txt', line)]
++ yield line
++
++ def _find_abs_filename(self):
++ for root in [
++ os.environ.get('PYTHON_COVERAGE_ARCADIA_SOURCE_ROOT'),
++ os.environ.get('PYTHON_COVERAGE_CYTHON_BUILD_ROOT'),
++ ]:
++ if root:
++ abs_path = os.path.join(root, self.filename)
++ if root and os.path.exists(abs_path):
++ return abs_path
++ return self.filename
+
+
+ def coverage_init(reg, options):
+ reg.add_file_tracer(Plugin())
++
++
++# ========================== Arcadia specific =================================
++
++def standalone():
++ return getattr(sys, 'is_standalone_binary', False)
++
++
++class OpenFile(object):
++
++ def __init__(self, filename, mode='r'):
++ assert 'r' in mode, ('Read-only', mode)
++ self.filename = filename
++ self.mode = mode
++ self.file = None
++ self.build_root = os.environ.get('PYTHON_COVERAGE_CYTHON_BUILD_ROOT')
++
++ def __enter__(self):
++ # See redefined _find_c_source() description for more info
++ if self.build_root:
++ self.file = open(os.path.join(self.build_root, self.filename), self.mode)
++ return self.file
++ elif standalone():
++ import library.python.resource
++ from six import StringIO
++
++ content = library.python.resource.resfs_read(self.filename, builtin=True)
++ assert content, (self.filename, os.environ.items())
++ return StringIO(content.decode())
++ else:
++ self.file = open(self.filename, self.mode)
++ return self.file
++
++ def __exit__(self, exc_type, exc_val, exc_tb):
++ if self.file:
++ self.file.close()
++
++# ======================= Redefine some methods ===============================
++
++if standalone():
++ import itertools
++ import json
++
++ CYTHON_INCLUDE_MAP = {'undef': True}
++
++
++ def _find_c_source(base_path):
++ '''
++ There are two different coverage stages when c source file might be required:
++ * trace - python calls c_tracefunc on every line and CythonModuleTracer needs to match
++ pyd and pxi files with source files. This is test's runtime and tests' clean environment might
++ doesn't contain required sources and generated files (c, cpp), that's why we get files from resfs_src.
++ * report - coverage data contains only covered data and CythonModuleReporter needs to
++ parse source files to obtain missing lines and branches. This is test_tool's resolve/build_report step.
++ test_tools doesn't have compiled in sources, however, it can extract required files
++ from binary and set PYTHON_COVERAGE_CYTHON_BUILD_ROOT to guide coverage.
++ '''
++ if os.environ.get('PYTHON_COVERAGE_CYTHON_BUILD_ROOT'):
++ # Report stage (resolve)
++ def exists(filename):
++ return os.path.exists(os.path.join(os.environ['PYTHON_COVERAGE_CYTHON_BUILD_ROOT'], filename))
++ else:
++ # Trace stage (test's runtime)
++ def exists(filename):
++ import library.python.resource
++ return library.python.resource.resfs_src(filename, resfs_file=True)
++
++ if os.environ.get('PYTHON_COVERAGE_CYTHON_INCLUDE_MAP'):
++ if CYTHON_INCLUDE_MAP.get('undef'):
++ with open(os.environ['PYTHON_COVERAGE_CYTHON_INCLUDE_MAP']) as afile:
++ data = json.load(afile)
++ data = {os.path.splitext(k)[0]: v for k, v in data.items()}
++
++ CYTHON_INCLUDE_MAP.clear()
++ CYTHON_INCLUDE_MAP.update(data)
++
++ if base_path in CYTHON_INCLUDE_MAP:
++ # target file was included and should be sought inside another pyx file
++ base_path = CYTHON_INCLUDE_MAP[base_path]
++
++ # TODO (', '.py3', '.py2') -> ('.py3', '.py2'), when https://a.yandex-team.ru/review/3511262 is merged
++ suffixes = [''.join(x) for x in itertools.product(('.pyx',), ('', '.py3', '.py2'), ('.cpp', '.c'))]
++ suffixes += C_FILE_EXTENSIONS
++
++ for suffix in suffixes:
++ if exists(base_path + suffix):
++ return base_path + suffix
++
++ return None
++
++
++ def _find_dep_file_path(main_file, file_path, relative_path_search=False):
++ # file_path is already arcadia root relative
++ return canonical_filename(file_path)
+--- contrib/tools/cython/Cython/Utility/CppConvert.pyx (index)
++++ contrib/tools/cython/Cython/Utility/CppConvert.pyx (working tree)
+@@ -235,3 +235,150 @@ cdef object {{cname}}(const std_complex[X]& z):
+ tmp.real = <double>z.real()
+ tmp.imag = <double>z.imag()
+ return tmp
++
++
++#################### arcadia_TMaybe.from_py ####################
++
++cdef extern from *:
++ cdef cppclass TMaybe [T]:
++ TMaybe()
++ TMaybe(T&)
++ TMaybe& operator =(T&)
++
++@cname("{{cname}}")
++cdef TMaybe[X] {{cname}}(object o) except *:
++ cdef TMaybe[X] result
++ if o is not None:
++ result = <X>o
++ return result
++
++#################### arcadia_TMaybe.to_py ####################
++
++cdef extern from *:
++ cdef cppclass TMaybe [T]:
++ bint Defined()
++ T& GetRef()
++
++@cname("{{cname}}")
++cdef object {{cname}}(const TMaybe[X]& s):
++ if s.Defined():
++ return s.GetRef()
++ return None
++
++
++#################### arcadia_TVector.from_py ####################
++
++cdef extern from *:
++ cdef cppclass TVector [T]:
++ void push_back(T&)
++
++@cname("{{cname}}")
++cdef TVector[X] {{cname}}(object o) except *:
++ cdef TVector[X] v
++ for item in o:
++ v.push_back(<X>item)
++ return v
++
++
++#################### arcadia_TVector.to_py ####################
++
++cdef extern from *:
++ cdef cppclass TVector [T]:
++ size_t size()
++ T& operator[](size_t)
++
++@cname("{{cname}}")
++cdef object {{cname}}(const TVector[X]& v):
++ return [v[i] for i in range(v.size())]
++
++
++#################### arcadia_THashMap.from_py ####################
++
++cdef extern from *:
++ cdef cppclass pair "std::pair" [T, U]:
++ pair(T&, U&)
++ cdef cppclass THashMap [T, U]:
++ void insert(pair[T, U]&)
++
++
++@cname("{{cname}}")
++cdef THashMap[X,Y] {{cname}}(object o) except *:
++ cdef dict d = o
++ cdef THashMap[X,Y] m
++ for key, value in d.iteritems():
++ m.insert(pair[X,Y](<X>key, <Y>value))
++ return m
++
++
++#################### arcadia_THashMap.to_py ####################
++
++cimport cython
++
++cdef extern from *:
++ cdef cppclass THashMap [T, U]:
++ cppclass value_type:
++ T first
++ U second
++ cppclass const_iterator:
++ value_type& operator*()
++ const_iterator operator++()
++ bint operator!=(const_iterator)
++ const_iterator begin()
++ const_iterator end()
++
++@cname("{{cname}}")
++cdef dict {{cname}}(const THashMap[X,Y]& s):
++ cdef dict result = {}
++ cdef const THashMap[X,Y].value_type *key_value
++ cdef THashMap[X,Y].const_iterator iter = s.begin()
++ while iter != s.end():
++ key_value = &cython.operator.dereference(iter)
++ result[key_value.first] = key_value.second
++ cython.operator.preincrement(iter)
++ return result
++
++
++#################### arcadia_TMap.from_py ####################
++
++cdef extern from *:
++ cdef cppclass pair "std::pair" [T, U]:
++ pair(T&, U&)
++ cdef cppclass TMap [T, U]:
++ void insert(pair[T, U]&)
++
++
++@cname("{{cname}}")
++cdef TMap[X,Y] {{cname}}(object o) except *:
++ cdef dict d = o
++ cdef TMap[X,Y] m
++ for key, value in d.iteritems():
++ m.insert(pair[X,Y](<X>key, <Y>value))
++ return m
++
++
++#################### arcadia_TMap.to_py ####################
++
++cimport cython
++
++cdef extern from *:
++ cdef cppclass TMap [T, U]:
++ cppclass value_type:
++ T first
++ U second
++ cppclass const_iterator:
++ value_type& operator*()
++ const_iterator operator++()
++ bint operator!=(const_iterator)
++ const_iterator begin()
++ const_iterator end()
++
++@cname("{{cname}}")
++cdef dict {{cname}}(const TMap[X,Y]& s):
++ cdef dict result = {}
++ cdef const TMap[X,Y].value_type *key_value
++ cdef TMap[X,Y].const_iterator iter = s.begin()
++ while iter != s.end():
++ key_value = &cython.operator.dereference(iter)
++ result[key_value.first] = key_value.second
++ cython.operator.preincrement(iter)
++ return result
+--- contrib/tools/cython/Cython/Utility/Embed.c (index)
++++ contrib/tools/cython/Cython/Utility/Embed.c (working tree)
+@@ -5,6 +5,8 @@
+ #endif
+
+ #if PY_MAJOR_VERSION < 3
++void Py_InitArgcArgv(int argc, char **argv);
++
+ int %(main_method)s(int argc, char** argv) {
+ #elif defined(WIN32) || defined(MS_WINDOWS)
+ int %(wmain_method)s(int argc, wchar_t **argv) {
+@@ -22,8 +28,10 @@ static int __Pyx_main(int argc, wchar_t **argv) {
+ m = fpgetmask();
+ fpsetmask(m & ~FP_X_OFL);
+ #endif
+- if (argc && argv)
++ if (argc && argv) {
++ Py_InitArgcArgv(argc, argv);
+ Py_SetProgramName(argv[0]);
++ }
+ Py_Initialize();
+ if (argc && argv)
+ PySys_SetArgv(argc, argv);
+--- contrib/tools/cython/Cython/Utility/ModuleSetupCode.c (index)
++++ contrib/tools/cython/Cython/Utility/ModuleSetupCode.c (working tree)
+@@ -1,5 +1,15 @@
+ /////////////// CModulePreamble ///////////////
+
++#if defined(__GNUC__) || defined(__clang__)
++#pragma GCC diagnostic push
++#pragma GCC diagnostic ignored "-Wshadow"
++#pragma GCC diagnostic ignored "-Wunused-function"
++#if PY_VERSION_HEX >= 0x030800b4 && PY_VERSION_HEX < 0x03090000
++// Ignore tp_print initializer. Need for ya make -DUSE_SYSTEM_PYTHON=3.8
++#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
++#endif
++#endif
++
+ #include <stddef.h> /* For offsetof */
+ #ifndef offsetof
+ #define offsetof(type, member) ( (size_t) & ((type*)0) -> member )
+--- contrib/tools/cython/Cython/Utility/Optimize.c (index)
++++ contrib/tools/cython/Cython/Utility/Optimize.c (working tree)
+@@ -886,7 +886,7 @@ static {{c_ret_type}} {{cfunc_name}}(PyObject *op1, PyObject *op2, CYTHON_UNUSED
+ }
+ return PyInt_FromLong(x);
+ {{elif op == 'Lshift'}}
+- if (likely(b < (long) (sizeof(long)*8) && a == (a << b) >> b) || !a) {
++ if (likely(b < (int)(sizeof(long)*8) && a == (a << b) >> b) || !a) {
+ return PyInt_FromLong(a {{c_op}} b);
+ }
+ {{else}}
+@@ -980,12 +980,12 @@ static {{c_ret_type}} {{cfunc_name}}(PyObject *op1, PyObject *op2, CYTHON_UNUSED
+ x = a {{c_op}} b;
+ {{if op == 'Lshift'}}
+ #ifdef HAVE_LONG_LONG
+- if (unlikely(!(b < (long) (sizeof(long)*8) && a == x >> b)) && a) {
++ if (unlikely(!(b < (int)(sizeof(long)*8) && a == x >> b)) && a) {
+ ll{{ival}} = {{ival}};
+ goto long_long;
+ }
+ #else
+- if (likely(b < (long) (sizeof(long)*8) && a == x >> b) || !a) /* execute return statement below */
++ if (likely(b < (int)(sizeof(long)*8) && a == x >> b) || !a) /* execute return statement below */
+ #endif
+ {{endif}}
+ {{endif}}
+@@ -1039,9 +1039,9 @@ static {{c_ret_type}} {{cfunc_name}}(PyObject *op1, PyObject *op2, CYTHON_UNUSED
+ }
+ {{endif}}
+ // copied from floatobject.c in Py3.5:
+- PyFPE_START_PROTECT("{{op.lower() if not op.endswith('Divide') else 'divide'}}", return NULL)
++// PyFPE_START_PROTECT("{{op.lower() if not op.endswith('Divide') else 'divide'}}", return NULL)
+ result = ((double)a) {{c_op}} (double)b;
+- PyFPE_END_PROTECT(result)
++// PyFPE_END_PROTECT(result)
+ return PyFloat_FromDouble(result);
+ {{endif}}
+ }
+@@ -1178,7 +1178,7 @@ static {{c_ret_type}} {{cfunc_name}}(PyObject *op1, PyObject *op2, double floatv
+ {{else}}
+ // copied from floatobject.c in Py3.5:
+ {{if order == 'CObj' and c_op in '%/'}}{{zerodiv_check('b')}}{{endif}}
+- PyFPE_START_PROTECT("{{op.lower() if not op.endswith('Divide') else 'divide'}}", return NULL)
++// PyFPE_START_PROTECT("{{op.lower() if not op.endswith('Divide') else 'divide'}}", return NULL)
+ {{if c_op == '%'}}
+ result = fmod(a, b);
+ if (result)
+@@ -1188,7 +1188,7 @@ static {{c_ret_type}} {{cfunc_name}}(PyObject *op1, PyObject *op2, double floatv
+ {{else}}
+ result = a {{c_op}} b;
+ {{endif}}
+- PyFPE_END_PROTECT(result)
++// PyFPE_END_PROTECT(result)
+ return PyFloat_FromDouble(result);
+ {{endif}}
+ }
+--- contrib/tools/cython/Cython/Utility/Profile.c (index)
++++ contrib/tools/cython/Cython/Utility/Profile.c (working tree)
+@@ -235,6 +235,8 @@
+ #ifdef WITH_THREAD
+ #define __Pyx_TraceLine(lineno, nogil, goto_error) \
+ if (likely(!__Pyx_use_tracing)); else { \
++ // mark error label as used to avoid compiler warnings \
++ if ((1)); else goto_error; \
+ if (nogil) { \
+ if (CYTHON_TRACE_NOGIL) { \
+ int ret = 0; \
+@@ -245,23 +247,28 @@
+ ret = __Pyx_call_line_trace_func(tstate, $frame_cname, lineno); \
+ } \
+ PyGILState_Release(state); \
+- if (unlikely(ret)) goto_error; \
++ // XXX https://github.com/cython/cython/issues/2274 \
++ if (unlikely(ret)) { fprintf(stderr, "cython: line_trace_func returned %d\n", ret); } \
+ } \
+ } else { \
+ PyThreadState* tstate = __Pyx_PyThreadState_Current; \
+ if (__Pyx_IsTracing(tstate, 0, 0) && tstate->c_tracefunc && $frame_cname->f_trace) { \
+ int ret = __Pyx_call_line_trace_func(tstate, $frame_cname, lineno); \
+- if (unlikely(ret)) goto_error; \
++ // XXX https://github.com/cython/cython/issues/2274 \
++ if (unlikely(ret)) { fprintf(stderr, "cython: line_trace_func returned %d\n", ret); } \
+ } \
+ } \
+ }
+ #else
+ #define __Pyx_TraceLine(lineno, nogil, goto_error) \
+ if (likely(!__Pyx_use_tracing)); else { \
++ // mark error label as used to avoid compiler warnings \
++ if ((1)); else goto_error; \
+ PyThreadState* tstate = __Pyx_PyThreadState_Current; \
+ if (__Pyx_IsTracing(tstate, 0, 0) && tstate->c_tracefunc && $frame_cname->f_trace) { \
+ int ret = __Pyx_call_line_trace_func(tstate, $frame_cname, lineno); \
+- if (unlikely(ret)) goto_error; \
++ // XXX https://github.com/cython/cython/issues/2274 \
++ if (unlikely(ret)) { fprintf(stderr, "cython: line_trace_func returned %d\n", ret); } \
+ } \
+ }
+ #endif
+--- contrib/tools/cython/Cython/Utility/StringTools.c (index)
++++ contrib/tools/cython/Cython/Utility/StringTools.c (working tree)
+@@ -454,7 +454,7 @@ static CYTHON_INLINE PyObject *__Pyx_PyUnicode_DecodeUTF16BE(const char *s, Py_s
+ //@requires: decode_c_bytes
+
+ static CYTHON_INLINE PyObject* __Pyx_decode_cpp_string(
+- std::string cppstring, Py_ssize_t start, Py_ssize_t stop,
++ std::string_view cppstring, Py_ssize_t start, Py_ssize_t stop,
+ const char* encoding, const char* errors,
+ PyObject* (*decode_func)(const char *s, Py_ssize_t size, const char *errors)) {
+ return __Pyx_decode_c_bytes(
+--- contrib/tools/cython/cython.py (index)
++++ contrib/tools/cython/cython.py (working tree)
+@@ -1,5 +1,7 @@
+ #!/usr/bin/env python
+
++# Change content of this file to change uids for cython programs - cython
++
+ #
+ # Cython -- Main Program, generic
+ #
+@@ -8,6 +10,7 @@ if __name__ == '__main__':
+
+ import os
+ import sys
++ sys.dont_write_bytecode = True
+
+ # Make sure we import the right Cython
+ cythonpath, _ = os.path.split(os.path.realpath(__file__))
diff --git a/contrib/tools/cython/patches/pr5096-fix-bitwise-instead-of-logical.patch b/contrib/tools/cython/patches/pr5096-fix-bitwise-instead-of-logical.patch
new file mode 100644
index 0000000000..be96ab2286
--- /dev/null
+++ b/contrib/tools/cython/patches/pr5096-fix-bitwise-instead-of-logical.patch
@@ -0,0 +1,39 @@
+commit 6a52786492ecae0f590136de76d078257d60c52d
+merge: fea299b0c0bdcef400863015439b859f2251e5dc a6f39a4bfec4c4fbdaf8708ec84ce5b98f92732c
+author: shadchin
+date: 2023-01-10T10:47:25+03:00
+revision: 10630852
+
+ IGNIETFERRO-2000 Update Python from 3.10.9 to 3.11.1
+
+ REVIEW: 2519151
+
+--- contrib/tools/cython/Cython/Compiler/ModuleNode.py (fea299b0c0bdcef400863015439b859f2251e5dc)
++++ contrib/tools/cython/Cython/Compiler/ModuleNode.py (6a52786492ecae0f590136de76d078257d60c52d)
+@@ -1353,10 +1353,10 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
+ if is_final_type:
+ type_safety_check = ''
+ else:
+- type_safety_check = ' & ((t->tp_flags & (Py_TPFLAGS_IS_ABSTRACT | Py_TPFLAGS_HEAPTYPE)) == 0)'
++ type_safety_check = ' & (int)((t->tp_flags & (Py_TPFLAGS_IS_ABSTRACT | Py_TPFLAGS_HEAPTYPE)) == 0)'
+ obj_struct = type.declaration_code("", deref=True)
+ code.putln(
+- "if (CYTHON_COMPILING_IN_CPYTHON && likely((%s > 0) & (t->tp_basicsize == sizeof(%s))%s)) {" % (
++ "if (CYTHON_COMPILING_IN_CPYTHON & likely((int)(%s > 0) & (int)(t->tp_basicsize == sizeof(%s))%s)) {" % (
+ freecount_name, obj_struct, type_safety_check))
+ code.putln("o = (PyObject*)%s[--%s];" % (
+ freelist_name, freecount_name))
+@@ -1545,11 +1545,11 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
+ type_safety_check = ''
+ else:
+ type_safety_check = (
+- ' & ((Py_TYPE(o)->tp_flags & (Py_TPFLAGS_IS_ABSTRACT | Py_TPFLAGS_HEAPTYPE)) == 0)')
++ ' & (int)((Py_TYPE(o)->tp_flags & (Py_TPFLAGS_IS_ABSTRACT | Py_TPFLAGS_HEAPTYPE)) == 0)')
+
+ type = scope.parent_type
+ code.putln(
+- "if (CYTHON_COMPILING_IN_CPYTHON && ((%s < %d) & (Py_TYPE(o)->tp_basicsize == sizeof(%s))%s)) {" % (
++ "if (CYTHON_COMPILING_IN_CPYTHON & ((int)(%s < %d) & (int)(Py_TYPE(o)->tp_basicsize == sizeof(%s))%s)) {" % (
+ freecount_name,
+ freelist_size,
+ type.declaration_code("", deref=True),
diff --git a/contrib/tools/cython/patches/pr5210,5211-switch-from-deprecated-functions.patch b/contrib/tools/cython/patches/pr5210,5211-switch-from-deprecated-functions.patch
new file mode 100644
index 0000000000..56b8bc28a0
--- /dev/null
+++ b/contrib/tools/cython/patches/pr5210,5211-switch-from-deprecated-functions.patch
@@ -0,0 +1,52 @@
+https://github.com/cython/cython/pull/5210
+https://github.com/cython/cython/pull/5211
+
+--- contrib/tools/cython/Cython/Utility/Embed.c (19fe9379d5dd7e26afd2405b1890080712d1892c)
++++ contrib/tools/cython/Cython/Utility/Embed.c (bdf71953ac311b76dcfb2ffd7ec4b71a018ed416)
+@@ -28,6 +28,7 @@ static int __Pyx_main(int argc, wchar_t **argv) {
+ m = fpgetmask();
+ fpsetmask(m & ~FP_X_OFL);
+ #endif
++#if PY_VERSION_HEX < 0x03080000
+ if (argc && argv) {
+ Py_InitArgcArgv(argc, argv);
+ Py_SetProgramName(argv[0]);
+@@ -35,6 +36,38 @@ static int __Pyx_main(int argc, wchar_t **argv) {
+ Py_Initialize();
+ if (argc && argv)
+ PySys_SetArgv(argc, argv);
++#else
++ {
++ PyStatus status;
++
++ PyConfig config;
++ PyConfig_InitPythonConfig(&config);
++ // Disable parsing command line arguments
++ config.parse_argv = 0;
++
++ if (argc && argv) {
++ status = PyConfig_SetString(&config, &config.program_name, argv[0]);
++ if (PyStatus_Exception(status)) {
++ PyConfig_Clear(&config);
++ return 1;
++ }
++
++ status = PyConfig_SetArgv(&config, argc, argv);
++ if (PyStatus_Exception(status)) {
++ PyConfig_Clear(&config);
++ return 1;
++ }
++ }
++
++ status = Py_InitializeFromConfig(&config);
++ if (PyStatus_Exception(status)) {
++ PyConfig_Clear(&config);
++ return 1;
++ }
++
++ PyConfig_Clear(&config);
++ }
++#endif
+ { /* init module '%(module_name)s' as '__main__' */
+ PyObject* m = NULL;
+ %(module_is_main)s = 1;
diff --git a/contrib/tools/cython/patches/without-init.patch b/contrib/tools/cython/patches/without-init.patch
new file mode 100644
index 0000000000..83e386f46e
--- /dev/null
+++ b/contrib/tools/cython/patches/without-init.patch
@@ -0,0 +1,66 @@
+--- contrib/tools/cython/Cython/Compiler/Main.py (b77cbecdf03a4bc1fd125fecb66a5e8e8ce8cc5e)
++++ contrib/tools/cython/Cython/Compiler/Main.py (71a3090d95d1027557404facb18ee15edc4090fc)
+@@ -827,27 +827,15 @@ def search_include_directories(dirs, qualified_name, suffix, pos, include=False)
+ if os.path.exists(path):
+ return path
+
++ # Arcadia-specific lookup: search for packages in include paths,
++ # ignoring existence of __init__.py files as packages markers
++ # (they are not required by Arcadia build system)
+ if not include:
+- package_dir = Utils.check_package_dir(dirname, package_names)
+- if package_dir is not None:
+- path = os.path.join(package_dir, module_filename)
+- if os.path.exists(path):
+- return path
+- path = os.path.join(package_dir, module_name,
+- package_filename)
+- if os.path.exists(path):
+- return path
+-
+- # Arcadia-specific lookup: search for packages in include paths,
+- # ignoring existence of __init__.py files as packages markers
+- # (they are not required by Arcadia build system)
+- if not include:
+- for dir in dirs:
+- package_dir = os.path.join(dir, *package_names)
++ package_dir = os.path.join(dirname, *package_names)
+ path = os.path.join(package_dir, module_filename)
+ if os.path.exists(path):
+ return path
+- path = os.path.join(dir, package_dir, module_name,
++ path = os.path.join(dirname, package_dir, module_name,
+ package_filename)
+ if os.path.exists(path):
+ return path
+--- contrib/tools/cython/Cython/Compiler/Nodes.py (b77cbecdf03a4bc1fd125fecb66a5e8e8ce8cc5e)
++++ contrib/tools/cython/Cython/Compiler/Nodes.py (71a3090d95d1027557404facb18ee15edc4090fc)
+@@ -7992,7 +7992,7 @@ class FromCImportStatNode(StatNode):
+ if self.relative_level and self.relative_level > env.qualified_name.count('.'):
+ error(self.pos, "relative cimport beyond main package is not allowed")
+ return
+- module_scope = env.find_module(self.module_name, self.pos, relative_level=self.relative_level)
++ module_scope = env.find_module(self.module_name, self.pos, relative_level=self.relative_level, need_pxd=0)
+ module_name = module_scope.qualified_name
+ env.add_imported_module(module_scope)
+ for pos, name, as_name, kind in self.imported_names:
+--- contrib/tools/cython/Cython/Compiler/Symtab.py (b77cbecdf03a4bc1fd125fecb66a5e8e8ce8cc5e)
++++ contrib/tools/cython/Cython/Compiler/Symtab.py (71a3090d95d1027557404facb18ee15edc4090fc)
+@@ -1250,7 +1250,7 @@ class ModuleScope(Scope):
+ entry.qualified_name = self.builtin_scope().qualify_name(name)
+ return entry
+
+- def find_module(self, module_name, pos, relative_level=-1):
++ def find_module(self, module_name, pos, relative_level=-1, need_pxd=1):
+ # Find a module in the import namespace, interpreting
+ # relative imports relative to this module's parent.
+ # Finds and parses the module's .pxd file if the module
+@@ -1271,7 +1271,7 @@ class ModuleScope(Scope):
+
+ module_scope = self.global_scope()
+ return module_scope.context.find_module(
+- module_name, relative_to=relative_to, pos=pos, absolute_fallback=absolute_fallback)
++ module_name, relative_to=relative_to, pos=pos, absolute_fallback=absolute_fallback, need_pxd=need_pxd)
+
+ def find_submodule(self, name):
+ # Find and return scope for a submodule of this module,
diff --git a/contrib/tools/cython/ya.make b/contrib/tools/cython/ya.make
index b8441b72a8..fddaea9c02 100644
--- a/contrib/tools/cython/ya.make
+++ b/contrib/tools/cython/ya.make
@@ -11,9 +11,9 @@ LICENSE_TEXTS(.yandex_meta/licenses.list.txt)
OWNER(g:python-contrib)
-VERSION(0.29.35)
+VERSION(0.29.36)
-ORIGINAL_SOURCE(mirror://pypi/C/Cython/Cython-0.29.35.tar.gz)
+ORIGINAL_SOURCE(mirror://pypi/C/Cython/Cython-0.29.36.tar.gz)
NO_LINT()