diff options
Diffstat (limited to 'meta/recipes-devtools/python/python3-cython')
2 files changed, 73 insertions, 148 deletions
diff --git a/meta/recipes-devtools/python/python3-cython/0001-Output-import-relative-paths-in-generated-C-code.-GH.patch b/meta/recipes-devtools/python/python3-cython/0001-Output-import-relative-paths-in-generated-C-code.-GH.patch new file mode 100644 index 0000000000..bbafc29416 --- /dev/null +++ b/meta/recipes-devtools/python/python3-cython/0001-Output-import-relative-paths-in-generated-C-code.-GH.patch | |||
| @@ -0,0 +1,73 @@ | |||
| 1 | From 9b5f3b09f76899eba510c2d8f3ed2b0f752a4d1b Mon Sep 17 00:00:00 2001 | ||
| 2 | From: Oscar Benjamin <oscar.j.benjamin@gmail.com> | ||
| 3 | Date: Sat, 24 Aug 2024 08:30:31 +0100 | ||
| 4 | Subject: [PATCH] Output import-relative paths in generated C code. (GH-6341) | ||
| 5 | |||
| 6 | When cython is run on a file that is not in the current working directory, | ||
| 7 | it outputs filepaths that are either absolute or are basenames. | ||
| 8 | It is not good to output absolute paths in the generated C code and | ||
| 9 | basenames mess up coverage measurement. | ||
| 10 | |||
| 11 | Upstream-Status: Backport [20bceea6b19ffc2f65b9fba2e4f737f09e5a2b20] | ||
| 12 | Signed-off-by: Ross Burton <ross.burton@arm.com> | ||
| 13 | --- | ||
| 14 | Cython/Compiler/ExprNodes.py | 8 +++++++- | ||
| 15 | Cython/Compiler/ModuleNode.py | 9 ++++++--- | ||
| 16 | 2 files changed, 13 insertions(+), 4 deletions(-) | ||
| 17 | |||
| 18 | diff --git a/Cython/Compiler/ExprNodes.py b/Cython/Compiler/ExprNodes.py | ||
| 19 | index a6bb1688e..0fbb15368 100644 | ||
| 20 | --- a/Cython/Compiler/ExprNodes.py | ||
| 21 | +++ b/Cython/Compiler/ExprNodes.py | ||
| 22 | @@ -21,6 +21,7 @@ import re | ||
| 23 | import sys | ||
| 24 | import copy | ||
| 25 | import os.path | ||
| 26 | +import pathlib | ||
| 27 | import operator | ||
| 28 | |||
| 29 | from .Errors import ( | ||
| 30 | @@ -10072,7 +10073,12 @@ class CodeObjectNode(ExprNode): | ||
| 31 | func_name = code.get_py_string_const( | ||
| 32 | func.name, identifier=True, is_str=False, unicode_value=func.name) | ||
| 33 | # FIXME: better way to get the module file path at module init time? Encoding to use? | ||
| 34 | - file_path = StringEncoding.bytes_literal(func.pos[0].get_filenametable_entry().encode('utf8'), 'utf8') | ||
| 35 | + file_path = func.pos[0].get_filenametable_entry() | ||
| 36 | + if os.path.isabs(file_path): | ||
| 37 | + file_path = func.pos[0].get_description() | ||
| 38 | + # Always use / as separator | ||
| 39 | + file_path = pathlib.Path(file_path).as_posix() | ||
| 40 | + file_path = StringEncoding.bytes_literal(file_path.encode('utf-8'), 'utf8') | ||
| 41 | file_path_const = code.get_py_string_const(file_path, identifier=False, is_str=True) | ||
| 42 | |||
| 43 | # This combination makes CPython create a new dict for "frame.f_locals" (see GH #1836). | ||
| 44 | diff --git a/Cython/Compiler/ModuleNode.py b/Cython/Compiler/ModuleNode.py | ||
| 45 | index 43c6b5f07..8c29d6db7 100644 | ||
| 46 | --- a/Cython/Compiler/ModuleNode.py | ||
| 47 | +++ b/Cython/Compiler/ModuleNode.py | ||
| 48 | @@ -13,6 +13,7 @@ from collections import defaultdict | ||
| 49 | import json | ||
| 50 | import operator | ||
| 51 | import os | ||
| 52 | +import pathlib | ||
| 53 | import re | ||
| 54 | import sys | ||
| 55 | |||
| 56 | @@ -944,9 +945,11 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode): | ||
| 57 | for source_desc in code.globalstate.filename_list: | ||
| 58 | file_path = source_desc.get_filenametable_entry() | ||
| 59 | if isabs(file_path): | ||
| 60 | - file_path = basename(file_path) # never include absolute paths | ||
| 61 | - escaped_filename = file_path.replace("\\", "\\\\").replace('"', r'\"') | ||
| 62 | - escaped_filename = as_encoded_filename(escaped_filename) | ||
| 63 | + # never include absolute paths | ||
| 64 | + file_path = source_desc.get_description() | ||
| 65 | + # Always use / as separator | ||
| 66 | + file_path = pathlib.Path(file_path).as_posix() | ||
| 67 | + escaped_filename = as_encoded_filename(file_path) | ||
| 68 | code.putln('%s,' % escaped_filename.as_c_string_literal()) | ||
| 69 | else: | ||
| 70 | # Some C compilers don't like an empty array | ||
| 71 | -- | ||
| 72 | 2.34.1 | ||
| 73 | |||
diff --git a/meta/recipes-devtools/python/python3-cython/0001-WIP-prefix-map.patch b/meta/recipes-devtools/python/python3-cython/0001-WIP-prefix-map.patch deleted file mode 100644 index adc9463ffa..0000000000 --- a/meta/recipes-devtools/python/python3-cython/0001-WIP-prefix-map.patch +++ /dev/null | |||
| @@ -1,148 +0,0 @@ | |||
| 1 | From 4d1b7911372561b22e03c7f2b4ec807502b5b9c1 Mon Sep 17 00:00:00 2001 | ||
| 2 | From: Ross Burton <ross.burton@arm.com> | ||
| 3 | Date: Mon, 4 Nov 2024 15:36:39 +0000 | ||
| 4 | Subject: [PATCH] WIP prefix map | ||
| 5 | |||
| 6 | Upstream-Status: Inappropriate | ||
| 7 | Signed-off-by: Ross Burton <ross.burton@arm.com> | ||
| 8 | --- | ||
| 9 | Cython/Compiler/CmdLine.py | 9 ++++++++- | ||
| 10 | Cython/Compiler/Main.py | 9 +++++---- | ||
| 11 | Cython/Compiler/Options.py | 1 + | ||
| 12 | Cython/Compiler/Parsing.py | 1 + | ||
| 13 | Cython/Compiler/Scanning.py | 9 +++++++-- | ||
| 14 | 5 files changed, 22 insertions(+), 7 deletions(-) | ||
| 15 | |||
| 16 | diff --git a/Cython/Compiler/CmdLine.py b/Cython/Compiler/CmdLine.py | ||
| 17 | index 776636c..f5a7c79 100644 | ||
| 18 | --- a/Cython/Compiler/CmdLine.py | ||
| 19 | +++ b/Cython/Compiler/CmdLine.py | ||
| 20 | @@ -74,6 +74,12 @@ class SetAnnotateCoverageAction(Action): | ||
| 21 | namespace.annotate = True | ||
| 22 | namespace.annotate_coverage_xml = values | ||
| 23 | |||
| 24 | +class SetPrefixMapAction(Action): | ||
| 25 | + def __call__(self, parser, namespace, values, option_string=None): | ||
| 26 | + mappings = getattr(namespace, self.dest, {}) | ||
| 27 | + k, v = values.split("=", 1) | ||
| 28 | + mappings[k] = v | ||
| 29 | + setattr(namespace, self.dest, mappings) | ||
| 30 | |||
| 31 | def create_cython_argparser(): | ||
| 32 | description = "Cython (https://cython.org/) is a compiler for code written in the "\ | ||
| 33 | @@ -157,9 +163,10 @@ def create_cython_argparser(): | ||
| 34 | 'deduced from the import path if source file is in ' | ||
| 35 | 'a package, or equals the filename otherwise.') | ||
| 36 | parser.add_argument('-M', '--depfile', action='store_true', help='produce depfiles for the sources') | ||
| 37 | + # TODO: add help | ||
| 38 | + parser.add_argument("--prefix-map", action=SetPrefixMapAction) | ||
| 39 | parser.add_argument('sources', nargs='*', default=[]) | ||
| 40 | |||
| 41 | - # TODO: add help | ||
| 42 | parser.add_argument("-z", "--pre-import", dest='pre_import', action='store', type=str, help=SUPPRESS) | ||
| 43 | parser.add_argument("--convert-range", dest='convert_range', action='store_true', help=SUPPRESS) | ||
| 44 | parser.add_argument("--no-c-in-traceback", dest='c_line_in_traceback', action='store_false', help=SUPPRESS) | ||
| 45 | diff --git a/Cython/Compiler/Main.py b/Cython/Compiler/Main.py | ||
| 46 | index 80946c0..28cfe68 100644 | ||
| 47 | --- a/Cython/Compiler/Main.py | ||
| 48 | +++ b/Cython/Compiler/Main.py | ||
| 49 | @@ -70,7 +70,7 @@ class Context(object): | ||
| 50 | language_level = None # warn when not set but default to Py2 | ||
| 51 | |||
| 52 | def __init__(self, include_directories, compiler_directives, cpp=False, | ||
| 53 | - language_level=None, options=None): | ||
| 54 | + language_level=None, prefix_map=None, options=None): | ||
| 55 | # cython_scope is a hack, set to False by subclasses, in order to break | ||
| 56 | # an infinite loop. | ||
| 57 | # Better code organization would fix it. | ||
| 58 | @@ -83,6 +83,7 @@ class Context(object): | ||
| 59 | self.future_directives = set() | ||
| 60 | self.compiler_directives = compiler_directives | ||
| 61 | self.cpp = cpp | ||
| 62 | + self.prefix_map = prefix_map or {} | ||
| 63 | self.options = options | ||
| 64 | |||
| 65 | self.pxds = {} # full name -> node tree | ||
| 66 | @@ -98,7 +99,7 @@ class Context(object): | ||
| 67 | @classmethod | ||
| 68 | def from_options(cls, options): | ||
| 69 | return cls(options.include_path, options.compiler_directives, | ||
| 70 | - options.cplus, options.language_level, options=options) | ||
| 71 | + options.cplus, options.language_level, prefix_map=options.prefix_map, options=options) | ||
| 72 | |||
| 73 | def set_language_level(self, level): | ||
| 74 | from .Future import print_function, unicode_literals, absolute_import, division, generator_stop | ||
| 75 | @@ -259,7 +260,7 @@ class Context(object): | ||
| 76 | rel_path = module_name.replace('.', os.sep) + os.path.splitext(pxd_pathname)[1] | ||
| 77 | if not pxd_pathname.endswith(rel_path): | ||
| 78 | rel_path = pxd_pathname # safety measure to prevent printing incorrect paths | ||
| 79 | - source_desc = FileSourceDescriptor(pxd_pathname, rel_path) | ||
| 80 | + source_desc = FileSourceDescriptor(pxd_pathname, rel_path, prefix_map=self.prefix_map) | ||
| 81 | err, result = self.process_pxd(source_desc, scope, qualified_name) | ||
| 82 | if err: | ||
| 83 | raise err | ||
| 84 | @@ -509,7 +510,7 @@ def run_pipeline(source, options, full_module_name=None, context=None): | ||
| 85 | rel_path = source # safety measure to prevent printing incorrect paths | ||
| 86 | else: | ||
| 87 | rel_path = abs_path | ||
| 88 | - source_desc = FileSourceDescriptor(abs_path, rel_path) | ||
| 89 | + source_desc = FileSourceDescriptor(abs_path, rel_path, prefix_map=context.prefix_map) | ||
| 90 | source = CompilationSource(source_desc, full_module_name, cwd) | ||
| 91 | |||
| 92 | # Set up result object | ||
| 93 | diff --git a/Cython/Compiler/Options.py b/Cython/Compiler/Options.py | ||
| 94 | index 61950a7..cc52732 100644 | ||
| 95 | --- a/Cython/Compiler/Options.py | ||
| 96 | +++ b/Cython/Compiler/Options.py | ||
| 97 | @@ -796,4 +796,5 @@ default_options = dict( | ||
| 98 | create_extension=None, | ||
| 99 | np_pythran=False, | ||
| 100 | legacy_implicit_noexcept=None, | ||
| 101 | + prefix_map=dict(pair.split("=", 1) for pair in os.environ.get("CYTHON_PREFIX_MAP", "").split()), | ||
| 102 | ) | ||
| 103 | diff --git a/Cython/Compiler/Parsing.py b/Cython/Compiler/Parsing.py | ||
| 104 | index 25c0de9..6c0eccf 100644 | ||
| 105 | --- a/Cython/Compiler/Parsing.py | ||
| 106 | +++ b/Cython/Compiler/Parsing.py | ||
| 107 | @@ -2106,6 +2106,7 @@ def p_include_statement(s, ctx): | ||
| 108 | s.included_files.append(include_file_name) | ||
| 109 | with Utils.open_source_file(include_file_path) as f: | ||
| 110 | source_desc = FileSourceDescriptor(include_file_path) | ||
| 111 | + print(f"TODO Cannot use prefix map on {include_file_path}") | ||
| 112 | s2 = PyrexScanner(f, source_desc, s, source_encoding=f.encoding, parse_comments=s.parse_comments) | ||
| 113 | tree = p_statement_list(s2, ctx) | ||
| 114 | return tree | ||
| 115 | diff --git a/Cython/Compiler/Scanning.py b/Cython/Compiler/Scanning.py | ||
| 116 | index 372392b..0fa3b30 100644 | ||
| 117 | --- a/Cython/Compiler/Scanning.py | ||
| 118 | +++ b/Cython/Compiler/Scanning.py | ||
| 119 | @@ -195,7 +195,7 @@ class FileSourceDescriptor(SourceDescriptor): | ||
| 120 | optional name argument and will be passed back when asking for | ||
| 121 | the position()-tuple. | ||
| 122 | """ | ||
| 123 | - def __init__(self, filename, path_description=None): | ||
| 124 | + def __init__(self, filename, path_description=None, prefix_map={}): | ||
| 125 | filename = Utils.decode_filename(filename) | ||
| 126 | self.path_description = path_description or filename | ||
| 127 | self.filename = filename | ||
| 128 | @@ -205,6 +205,7 @@ class FileSourceDescriptor(SourceDescriptor): | ||
| 129 | self.set_file_type_from_name(filename) | ||
| 130 | self._cmp_name = filename | ||
| 131 | self._lines = {} | ||
| 132 | + self.prefix_map = prefix_map | ||
| 133 | |||
| 134 | def get_lines(self, encoding=None, error_handling=None): | ||
| 135 | # we cache the lines only the second time this is called, in | ||
| 136 | @@ -243,7 +244,11 @@ class FileSourceDescriptor(SourceDescriptor): | ||
| 137 | return path | ||
| 138 | |||
| 139 | def get_filenametable_entry(self): | ||
| 140 | - return self.file_path | ||
| 141 | + entry = self.file_path | ||
| 142 | + for k, v in self.prefix_map.items(): | ||
| 143 | + # TODO: should just replace the prefix | ||
| 144 | + entry = entry.replace(k, v) | ||
| 145 | + return entry | ||
| 146 | |||
| 147 | def __eq__(self, other): | ||
| 148 | return isinstance(other, FileSourceDescriptor) and self.filename == other.filename | ||
