diff options
author | shadchin <shadchin@yandex-team.com> | 2023-07-22 00:59:02 +0300 |
---|---|---|
committer | shadchin <shadchin@yandex-team.com> | 2023-07-22 00:59:02 +0300 |
commit | 7ecf6c16ab762d4ed40a90ea329eebeb1b8cbca0 (patch) | |
tree | 13f625aacca47c9885d8fa31ba97151706ef63bd | |
parent | 91a8278c558cb2002069ca54215c83568ba6826e (diff) | |
download | ydb-7ecf6c16ab762d4ed40a90ea329eebeb1b8cbca0.tar.gz |
Update Cython to 0.29.36
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() |