diff options
| author | shadchin <[email protected]> | 2023-07-22 00:59:02 +0300 | 
|---|---|---|
| committer | shadchin <[email protected]> | 2023-07-22 00:59:02 +0300 | 
| commit | 7ecf6c16ab762d4ed40a90ea329eebeb1b8cbca0 (patch) | |
| tree | 13f625aacca47c9885d8fa31ba97151706ef63bd /contrib | |
| parent | 91a8278c558cb2002069ca54215c83568ba6826e (diff) | |
Update Cython to 0.29.36
Diffstat (limited to 'contrib')
20 files changed, 1255 insertions, 135 deletions
diff --git a/contrib/tools/cython/.dist-info/METADATA b/contrib/tools/cython/.dist-info/METADATA index bb58628f620..10f4b69cd5e 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 00000000000..3155ec718b8 --- /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 00000000000..57692631eae --- /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 febc982c4e2..829bfdcaff3 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 e0d203ae027..c3e202e0014 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 1e392a4e3a5..fd998d419fc 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 f57ddf3dd34..db5d6578297 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 6c2b44ea372..a3991f04941 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 587f6e4841f..2af7d258ef8 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 dd4bf37280b..e55b7865788 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 87d3a5cddb7..8117b92d4b7 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 31a8fec231b..85036794127 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 02574e46ecf..5c4d9e1608b 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 19568b35675..30315749d34 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 00000000000..ba89a1443b7 --- /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 00000000000..b9424c7ac4f --- /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 00000000000..be96ab22869 --- /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 00000000000..56b8bc28a0e --- /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 00000000000..83e386f46e7 --- /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 b8441b72a86..fddaea9c024 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()  | 
