Cython 3.3.0a1__cp315-cp315-win_amd64.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- Cython/Build/BuildExecutable.py +156 -0
- Cython/Build/Cache.py +199 -0
- Cython/Build/Cythonize.py +349 -0
- Cython/Build/Dependencies.py +1276 -0
- Cython/Build/Distutils.py +1 -0
- Cython/Build/Inline.py +467 -0
- Cython/Build/IpythonMagic.py +559 -0
- Cython/Build/SharedModule.py +84 -0
- Cython/Build/Tests/TestCyCache.py +195 -0
- Cython/Build/Tests/TestCythonizeArgsParser.py +480 -0
- Cython/Build/Tests/TestDependencies.py +133 -0
- Cython/Build/Tests/TestInline.py +177 -0
- Cython/Build/Tests/TestIpythonMagic.py +303 -0
- Cython/Build/Tests/TestRecythonize.py +212 -0
- Cython/Build/Tests/TestStripLiterals.py +155 -0
- Cython/Build/Tests/__init__.py +1 -0
- Cython/Build/__init__.py +11 -0
- Cython/CodeWriter.py +815 -0
- Cython/Compiler/AnalysedTreeTransforms.py +97 -0
- Cython/Compiler/Annotate.py +328 -0
- Cython/Compiler/AutoDocTransforms.py +320 -0
- Cython/Compiler/Buffer.py +680 -0
- Cython/Compiler/Builtin.py +997 -0
- Cython/Compiler/CmdLine.py +263 -0
- Cython/Compiler/Code.cp315-win_amd64.pyd +0 -0
- Cython/Compiler/Code.pxd +152 -0
- Cython/Compiler/Code.py +3907 -0
- Cython/Compiler/CodeGeneration.py +33 -0
- Cython/Compiler/CythonScope.py +194 -0
- Cython/Compiler/Dataclass.py +890 -0
- Cython/Compiler/DebugFlags.py +24 -0
- Cython/Compiler/Errors.py +310 -0
- Cython/Compiler/ExprNodes.py +15983 -0
- Cython/Compiler/FlowControl.cp315-win_amd64.pyd +0 -0
- Cython/Compiler/FlowControl.pxd +99 -0
- Cython/Compiler/FlowControl.py +1571 -0
- Cython/Compiler/FusedNode.cp315-win_amd64.pyd +0 -0
- Cython/Compiler/FusedNode.py +976 -0
- Cython/Compiler/Future.py +16 -0
- Cython/Compiler/Interpreter.py +57 -0
- Cython/Compiler/Lexicon.py +422 -0
- Cython/Compiler/LineTable.cp315-win_amd64.pyd +0 -0
- Cython/Compiler/LineTable.py +114 -0
- Cython/Compiler/Main.py +856 -0
- Cython/Compiler/MatchCaseNodes.py +2197 -0
- Cython/Compiler/MemoryView.py +930 -0
- Cython/Compiler/ModuleNode.py +4517 -0
- Cython/Compiler/Naming.py +367 -0
- Cython/Compiler/Nodes.py +10941 -0
- Cython/Compiler/Optimize.py +5455 -0
- Cython/Compiler/Options.py +838 -0
- Cython/Compiler/ParseTreeTransforms.pxd +79 -0
- Cython/Compiler/ParseTreeTransforms.py +4744 -0
- Cython/Compiler/Parsing.cp315-win_amd64.pyd +0 -0
- Cython/Compiler/Parsing.pxd +9 -0
- Cython/Compiler/Parsing.py +4792 -0
- Cython/Compiler/Pipeline.py +439 -0
- Cython/Compiler/PyrexTypes.py +6111 -0
- Cython/Compiler/Pythran.py +232 -0
- Cython/Compiler/Scanning.cp315-win_amd64.pyd +0 -0
- Cython/Compiler/Scanning.pxd +70 -0
- Cython/Compiler/Scanning.py +720 -0
- Cython/Compiler/StringEncoding.py +297 -0
- Cython/Compiler/Symtab.py +3092 -0
- Cython/Compiler/Tests/TestBuffer.py +105 -0
- Cython/Compiler/Tests/TestBuiltin.py +117 -0
- Cython/Compiler/Tests/TestCmdLine.py +587 -0
- Cython/Compiler/Tests/TestCode.py +145 -0
- Cython/Compiler/Tests/TestFlowControl.py +65 -0
- Cython/Compiler/Tests/TestGrammar.py +202 -0
- Cython/Compiler/Tests/TestMemView.py +71 -0
- Cython/Compiler/Tests/TestParseTreeTransforms.py +285 -0
- Cython/Compiler/Tests/TestScanning.py +132 -0
- Cython/Compiler/Tests/TestSignatureMatching.py +73 -0
- Cython/Compiler/Tests/TestStringEncoding.py +20 -0
- Cython/Compiler/Tests/TestTreeFragment.py +63 -0
- Cython/Compiler/Tests/TestTreePath.py +103 -0
- Cython/Compiler/Tests/TestTypes.py +118 -0
- Cython/Compiler/Tests/TestUtilityLoad.py +112 -0
- Cython/Compiler/Tests/TestVisitor.py +61 -0
- Cython/Compiler/Tests/Utils.py +36 -0
- Cython/Compiler/Tests/__init__.py +1 -0
- Cython/Compiler/TreeFragment.py +278 -0
- Cython/Compiler/TreePath.py +303 -0
- Cython/Compiler/TypeInference.py +611 -0
- Cython/Compiler/TypeSlots.py +1329 -0
- Cython/Compiler/UFuncs.py +311 -0
- Cython/Compiler/UtilNodes.py +413 -0
- Cython/Compiler/UtilityCode.py +348 -0
- Cython/Compiler/Version.py +8 -0
- Cython/Compiler/Visitor.cp315-win_amd64.pyd +0 -0
- Cython/Compiler/Visitor.pxd +53 -0
- Cython/Compiler/Visitor.py +864 -0
- Cython/Compiler/__init__.py +1 -0
- Cython/Coverage.py +448 -0
- Cython/Debugger/Cygdb.py +177 -0
- Cython/Debugger/DebugWriter.py +82 -0
- Cython/Debugger/Tests/TestLibCython.py +280 -0
- Cython/Debugger/Tests/__init__.py +1 -0
- Cython/Debugger/Tests/cfuncs.c +8 -0
- Cython/Debugger/Tests/codefile +49 -0
- Cython/Debugger/Tests/test_libcython_in_gdb.py +580 -0
- Cython/Debugger/Tests/test_libpython_in_gdb.py +90 -0
- Cython/Debugger/__init__.py +1 -0
- Cython/Debugger/libcython.py +1548 -0
- Cython/Debugger/libpython.py +2821 -0
- Cython/Debugging.py +20 -0
- Cython/Distutils/__init__.py +2 -0
- Cython/Distutils/build_ext.py +139 -0
- Cython/Distutils/extension.py +96 -0
- Cython/Distutils/old_build_ext.py +351 -0
- Cython/Includes/cpython/__init__.pxd +173 -0
- Cython/Includes/cpython/array.pxd +152 -0
- Cython/Includes/cpython/bool.pxd +37 -0
- Cython/Includes/cpython/buffer.pxd +112 -0
- Cython/Includes/cpython/bytearray.pxd +33 -0
- Cython/Includes/cpython/bytes.pxd +200 -0
- Cython/Includes/cpython/cellobject.pxd +35 -0
- Cython/Includes/cpython/ceval.pxd +8 -0
- Cython/Includes/cpython/codecs.pxd +121 -0
- Cython/Includes/cpython/complex.pxd +60 -0
- Cython/Includes/cpython/contextvars.pxd +145 -0
- Cython/Includes/cpython/conversion.pxd +36 -0
- Cython/Includes/cpython/datetime.pxd +395 -0
- Cython/Includes/cpython/descr.pxd +26 -0
- Cython/Includes/cpython/dict.pxd +268 -0
- Cython/Includes/cpython/exc.pxd +263 -0
- Cython/Includes/cpython/fileobject.pxd +57 -0
- Cython/Includes/cpython/float.pxd +56 -0
- Cython/Includes/cpython/frozendict.pxd +37 -0
- Cython/Includes/cpython/function.pxd +65 -0
- Cython/Includes/cpython/genobject.pxd +25 -0
- Cython/Includes/cpython/getargs.pxd +12 -0
- Cython/Includes/cpython/instance.pxd +25 -0
- Cython/Includes/cpython/iterator.pxd +36 -0
- Cython/Includes/cpython/iterobject.pxd +24 -0
- Cython/Includes/cpython/list.pxd +144 -0
- Cython/Includes/cpython/long.pxd +180 -0
- Cython/Includes/cpython/longintrepr.pxd +14 -0
- Cython/Includes/cpython/mapping.pxd +63 -0
- Cython/Includes/cpython/marshal.pxd +66 -0
- Cython/Includes/cpython/mem.pxd +120 -0
- Cython/Includes/cpython/memoryview.pxd +50 -0
- Cython/Includes/cpython/method.pxd +49 -0
- Cython/Includes/cpython/module.pxd +208 -0
- Cython/Includes/cpython/number.pxd +258 -0
- Cython/Includes/cpython/object.pxd +430 -0
- Cython/Includes/cpython/pycapsule.pxd +143 -0
- Cython/Includes/cpython/pylifecycle.pxd +68 -0
- Cython/Includes/cpython/pyport.pxd +8 -0
- Cython/Includes/cpython/pystate.pxd +95 -0
- Cython/Includes/cpython/pythread.pxd +53 -0
- Cython/Includes/cpython/ref.pxd +141 -0
- Cython/Includes/cpython/sentinel.pxd +17 -0
- Cython/Includes/cpython/sequence.pxd +134 -0
- Cython/Includes/cpython/set.pxd +119 -0
- Cython/Includes/cpython/slice.pxd +70 -0
- Cython/Includes/cpython/time.pxd +129 -0
- Cython/Includes/cpython/tuple.pxd +72 -0
- Cython/Includes/cpython/type.pxd +146 -0
- Cython/Includes/cpython/unicode.pxd +639 -0
- Cython/Includes/cpython/version.pxd +32 -0
- Cython/Includes/cpython/weakref.pxd +78 -0
- Cython/Includes/libc/__init__.pxd +1 -0
- Cython/Includes/libc/complex.pxd +35 -0
- Cython/Includes/libc/errno.pxd +127 -0
- Cython/Includes/libc/float.pxd +43 -0
- Cython/Includes/libc/limits.pxd +28 -0
- Cython/Includes/libc/locale.pxd +46 -0
- Cython/Includes/libc/math.pxd +209 -0
- Cython/Includes/libc/setjmp.pxd +10 -0
- Cython/Includes/libc/signal.pxd +64 -0
- Cython/Includes/libc/stddef.pxd +9 -0
- Cython/Includes/libc/stdint.pxd +105 -0
- Cython/Includes/libc/stdio.pxd +80 -0
- Cython/Includes/libc/stdlib.pxd +72 -0
- Cython/Includes/libc/string.pxd +50 -0
- Cython/Includes/libc/threads.pxd +234 -0
- Cython/Includes/libc/time.pxd +52 -0
- Cython/Includes/libcpp/__init__.pxd +4 -0
- Cython/Includes/libcpp/algorithm.pxd +320 -0
- Cython/Includes/libcpp/any.pxd +16 -0
- Cython/Includes/libcpp/atomic.pxd +59 -0
- Cython/Includes/libcpp/barrier.pxd +22 -0
- Cython/Includes/libcpp/bit.pxd +29 -0
- Cython/Includes/libcpp/cast.pxd +12 -0
- Cython/Includes/libcpp/cmath.pxd +518 -0
- Cython/Includes/libcpp/complex.pxd +106 -0
- Cython/Includes/libcpp/condition_variable.pxd +322 -0
- Cython/Includes/libcpp/deque.pxd +165 -0
- Cython/Includes/libcpp/exception.pxd +216 -0
- Cython/Includes/libcpp/execution.pxd +15 -0
- Cython/Includes/libcpp/forward_list.pxd +63 -0
- Cython/Includes/libcpp/functional.pxd +26 -0
- Cython/Includes/libcpp/future.pxd +103 -0
- Cython/Includes/libcpp/iterator.pxd +34 -0
- Cython/Includes/libcpp/latch.pxd +17 -0
- Cython/Includes/libcpp/limits.pxd +61 -0
- Cython/Includes/libcpp/list.pxd +117 -0
- Cython/Includes/libcpp/map.pxd +252 -0
- Cython/Includes/libcpp/memory.pxd +115 -0
- Cython/Includes/libcpp/mutex.pxd +387 -0
- Cython/Includes/libcpp/numbers.pxd +15 -0
- Cython/Includes/libcpp/numeric.pxd +131 -0
- Cython/Includes/libcpp/optional.pxd +34 -0
- Cython/Includes/libcpp/pair.pxd +1 -0
- Cython/Includes/libcpp/queue.pxd +25 -0
- Cython/Includes/libcpp/random.pxd +166 -0
- Cython/Includes/libcpp/semaphore.pxd +43 -0
- Cython/Includes/libcpp/set.pxd +228 -0
- Cython/Includes/libcpp/shared_mutex.pxd +96 -0
- Cython/Includes/libcpp/span.pxd +87 -0
- Cython/Includes/libcpp/stack.pxd +11 -0
- Cython/Includes/libcpp/stop_token.pxd +117 -0
- Cython/Includes/libcpp/string.pxd +355 -0
- Cython/Includes/libcpp/string_view.pxd +183 -0
- Cython/Includes/libcpp/typeindex.pxd +15 -0
- Cython/Includes/libcpp/typeinfo.pxd +10 -0
- Cython/Includes/libcpp/unordered_map.pxd +193 -0
- Cython/Includes/libcpp/unordered_set.pxd +152 -0
- Cython/Includes/libcpp/utility.pxd +30 -0
- Cython/Includes/libcpp/vector.pxd +186 -0
- Cython/Includes/numpy/math.pxd +150 -0
- Cython/Includes/openmp.pxd +50 -0
- Cython/Includes/posix/__init__.pxd +1 -0
- Cython/Includes/posix/dlfcn.pxd +14 -0
- Cython/Includes/posix/fcntl.pxd +86 -0
- Cython/Includes/posix/ioctl.pxd +4 -0
- Cython/Includes/posix/mman.pxd +101 -0
- Cython/Includes/posix/resource.pxd +57 -0
- Cython/Includes/posix/select.pxd +21 -0
- Cython/Includes/posix/signal.pxd +73 -0
- Cython/Includes/posix/stat.pxd +98 -0
- Cython/Includes/posix/stdio.pxd +37 -0
- Cython/Includes/posix/stdlib.pxd +29 -0
- Cython/Includes/posix/strings.pxd +9 -0
- Cython/Includes/posix/time.pxd +71 -0
- Cython/Includes/posix/types.pxd +30 -0
- Cython/Includes/posix/uio.pxd +26 -0
- Cython/Includes/posix/unistd.pxd +271 -0
- Cython/Includes/posix/wait.pxd +38 -0
- Cython/LZSS.py +170 -0
- Cython/Plex/Actions.cp315-win_amd64.pyd +0 -0
- Cython/Plex/Actions.pxd +24 -0
- Cython/Plex/Actions.py +119 -0
- Cython/Plex/DFA.cp315-win_amd64.pyd +0 -0
- Cython/Plex/DFA.pxd +14 -0
- Cython/Plex/DFA.py +164 -0
- Cython/Plex/Errors.py +48 -0
- Cython/Plex/Lexicons.py +178 -0
- Cython/Plex/Machines.cp315-win_amd64.pyd +0 -0
- Cython/Plex/Machines.pxd +36 -0
- Cython/Plex/Machines.py +238 -0
- Cython/Plex/Regexps.py +535 -0
- Cython/Plex/Scanners.cp315-win_amd64.pyd +0 -0
- Cython/Plex/Scanners.pxd +45 -0
- Cython/Plex/Scanners.py +328 -0
- Cython/Plex/Transitions.cp315-win_amd64.pyd +0 -0
- Cython/Plex/Transitions.pxd +14 -0
- Cython/Plex/Transitions.py +239 -0
- Cython/Plex/__init__.py +34 -0
- Cython/Runtime/__init__.py +1 -0
- Cython/Runtime/refnanny.cp315-win_amd64.pyd +0 -0
- Cython/Runtime/refnanny.pyx +237 -0
- Cython/Shadow.py +1167 -0
- Cython/StringIOTree.cp315-win_amd64.pyd +0 -0
- Cython/StringIOTree.py +169 -0
- Cython/Tempita/__init__.py +4 -0
- Cython/Tempita/_looper.py +154 -0
- Cython/Tempita/_tempita.cp315-win_amd64.pyd +0 -0
- Cython/Tempita/_tempita.py +1087 -0
- Cython/TestUtils.py +464 -0
- Cython/Tests/TestCodeWriter.py +128 -0
- Cython/Tests/TestCythonUtils.py +202 -0
- Cython/Tests/TestJediTyper.py +223 -0
- Cython/Tests/TestShadow.py +110 -0
- Cython/Tests/TestStringIOTree.py +68 -0
- Cython/Tests/TestTestUtils.py +89 -0
- Cython/Tests/__init__.py +1 -0
- Cython/Tests/xmlrunner.py +390 -0
- Cython/Utility/AsyncGen.c +1073 -0
- Cython/Utility/Buffer.c +866 -0
- Cython/Utility/BufferFormatFromTypeInfo.pxd +2 -0
- Cython/Utility/Builtins.c +933 -0
- Cython/Utility/CConvert.pyx +149 -0
- Cython/Utility/CMath.c +104 -0
- Cython/Utility/CommonStructures.c +244 -0
- Cython/Utility/Complex.c +378 -0
- Cython/Utility/Coroutine.c +2337 -0
- Cython/Utility/CpdefEnums.pyx +107 -0
- Cython/Utility/CppConvert.pyx +282 -0
- Cython/Utility/CppSupport.cpp +151 -0
- Cython/Utility/CythonFunction.c +2072 -0
- Cython/Utility/Dataclasses.c +101 -0
- Cython/Utility/Embed.c +129 -0
- Cython/Utility/Exceptions.c +1038 -0
- Cython/Utility/ExtensionTypes.c +1158 -0
- Cython/Utility/FunctionArguments.c +1045 -0
- Cython/Utility/FusedFunction.pyx +44 -0
- Cython/Utility/ImportExport.c +930 -0
- Cython/Utility/MatchCase.c +979 -0
- Cython/Utility/MatchCase_Cy.pyx +12 -0
- Cython/Utility/MemoryView.pxd +108 -0
- Cython/Utility/MemoryView.pyx +1499 -0
- Cython/Utility/MemoryView_C.c +1056 -0
- Cython/Utility/ModuleSetupCode.c +3352 -0
- Cython/Utility/NumpyImportArray.c +46 -0
- Cython/Utility/ObjectHandling.c +3372 -0
- Cython/Utility/Optimize.c +2563 -0
- Cython/Utility/Overflow.c +378 -0
- Cython/Utility/Profile.c +736 -0
- Cython/Utility/StringTools.c +1414 -0
- Cython/Utility/Synchronization.c +438 -0
- Cython/Utility/TString.c +369 -0
- Cython/Utility/TestCyUtilityLoader.pyx +8 -0
- Cython/Utility/TestCythonScope.pyx +75 -0
- Cython/Utility/TestUtilityLoader.c +12 -0
- Cython/Utility/TypeConversion.c +1556 -0
- Cython/Utility/UFuncs.pyx +50 -0
- Cython/Utility/UFuncs_C.c +89 -0
- Cython/Utility/__init__.py +28 -0
- Cython/Utility/arrayarray.h +172 -0
- Cython/Utils.cp315-win_amd64.pyd +0 -0
- Cython/Utils.py +677 -0
- Cython/__init__.py +12 -0
- Cython/py.typed +0 -0
- cython-3.3.0a1.dist-info/METADATA +394 -0
- cython-3.3.0a1.dist-info/RECORD +335 -0
- cython-3.3.0a1.dist-info/WHEEL +5 -0
- cython-3.3.0a1.dist-info/entry_points.txt +4 -0
- cython-3.3.0a1.dist-info/top_level.txt +3 -0
- cython.py +29 -0
- pyximport/__init__.py +4 -0
- pyximport/pyxbuild.py +160 -0
- pyximport/pyximport.py +482 -0
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Compile a Python script into an executable that embeds CPython.
|
|
3
|
+
Requires CPython to be built as a shared library ('libpythonX.Y').
|
|
4
|
+
|
|
5
|
+
Basic usage:
|
|
6
|
+
|
|
7
|
+
python -m Cython.Build.BuildExecutable [ARGS] somefile.py
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
DEBUG = True
|
|
12
|
+
|
|
13
|
+
import sys
|
|
14
|
+
import os
|
|
15
|
+
import sysconfig
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
def get_config_var(name, default=''):
|
|
19
|
+
return sysconfig.get_config_var(name) or default
|
|
20
|
+
|
|
21
|
+
INCDIR = sysconfig.get_path('include')
|
|
22
|
+
LIBDIR1 = get_config_var('LIBDIR')
|
|
23
|
+
LIBDIR2 = get_config_var('LIBPL')
|
|
24
|
+
PYLIB = get_config_var('LIBRARY')
|
|
25
|
+
PYLIB_DYN = get_config_var('LDLIBRARY')
|
|
26
|
+
if PYLIB_DYN == PYLIB:
|
|
27
|
+
# no shared library
|
|
28
|
+
PYLIB_DYN = ''
|
|
29
|
+
else:
|
|
30
|
+
PYLIB_DYN = os.path.splitext(PYLIB_DYN[3:])[0] # 'lib(XYZ).so' -> XYZ
|
|
31
|
+
|
|
32
|
+
CC = get_config_var('CC', os.environ.get('CC', ''))
|
|
33
|
+
CFLAGS = get_config_var('CFLAGS') + ' ' + os.environ.get('CFLAGS', '')
|
|
34
|
+
LINKCC = get_config_var('LINKCC', os.environ.get('LINKCC', CC))
|
|
35
|
+
LINKFORSHARED = get_config_var('LINKFORSHARED')
|
|
36
|
+
LIBS = get_config_var('LIBS')
|
|
37
|
+
SYSLIBS = get_config_var('SYSLIBS')
|
|
38
|
+
EXE_EXT = sysconfig.get_config_var('EXE')
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
def _debug(msg, *args):
|
|
42
|
+
if DEBUG:
|
|
43
|
+
if args:
|
|
44
|
+
msg = msg % args
|
|
45
|
+
sys.stderr.write(msg + '\n')
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
def dump_config():
|
|
49
|
+
_debug('INCDIR: %s', INCDIR)
|
|
50
|
+
_debug('LIBDIR1: %s', LIBDIR1)
|
|
51
|
+
_debug('LIBDIR2: %s', LIBDIR2)
|
|
52
|
+
_debug('PYLIB: %s', PYLIB)
|
|
53
|
+
_debug('PYLIB_DYN: %s', PYLIB_DYN)
|
|
54
|
+
_debug('CC: %s', CC)
|
|
55
|
+
_debug('CFLAGS: %s', CFLAGS)
|
|
56
|
+
_debug('LINKCC: %s', LINKCC)
|
|
57
|
+
_debug('LINKFORSHARED: %s', LINKFORSHARED)
|
|
58
|
+
_debug('LIBS: %s', LIBS)
|
|
59
|
+
_debug('SYSLIBS: %s', SYSLIBS)
|
|
60
|
+
_debug('EXE_EXT: %s', EXE_EXT)
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
def _parse_args(args):
|
|
64
|
+
cy_args = []
|
|
65
|
+
last_arg = None
|
|
66
|
+
for i, arg in enumerate(args):
|
|
67
|
+
if arg.startswith('-'):
|
|
68
|
+
cy_args.append(arg)
|
|
69
|
+
elif last_arg in ('-X', '--directive'):
|
|
70
|
+
cy_args.append(arg)
|
|
71
|
+
else:
|
|
72
|
+
input_file = arg
|
|
73
|
+
args = args[i+1:]
|
|
74
|
+
break
|
|
75
|
+
last_arg = arg
|
|
76
|
+
else:
|
|
77
|
+
raise ValueError('no input file provided')
|
|
78
|
+
|
|
79
|
+
return input_file, cy_args, args
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
def runcmd(cmd, shell=True):
|
|
83
|
+
if shell:
|
|
84
|
+
cmd = ' '.join(cmd)
|
|
85
|
+
_debug(cmd)
|
|
86
|
+
else:
|
|
87
|
+
_debug(' '.join(cmd))
|
|
88
|
+
|
|
89
|
+
import subprocess
|
|
90
|
+
returncode = subprocess.call(cmd, shell=shell)
|
|
91
|
+
|
|
92
|
+
if returncode:
|
|
93
|
+
sys.exit(returncode)
|
|
94
|
+
|
|
95
|
+
|
|
96
|
+
def clink(basename):
|
|
97
|
+
runcmd([LINKCC, '-o', basename + EXE_EXT, basename+'.o', '-L'+LIBDIR1, '-L'+LIBDIR2]
|
|
98
|
+
+ [PYLIB_DYN and ('-l'+PYLIB_DYN) or os.path.join(LIBDIR1, PYLIB)]
|
|
99
|
+
+ LIBS.split() + SYSLIBS.split() + LINKFORSHARED.split())
|
|
100
|
+
|
|
101
|
+
|
|
102
|
+
def ccompile(basename):
|
|
103
|
+
runcmd([CC, '-c', '-o', basename+'.o', basename+'.c', '-I' + INCDIR] + CFLAGS.split())
|
|
104
|
+
|
|
105
|
+
|
|
106
|
+
def cycompile(input_file, options=()):
|
|
107
|
+
from ..Compiler import Version, CmdLine, Main
|
|
108
|
+
options, sources = CmdLine.parse_command_line(list(options or ()) + ['--embed', input_file])
|
|
109
|
+
_debug('Using Cython %s to compile %s', Version.version, input_file)
|
|
110
|
+
result = Main.compile(sources, options)
|
|
111
|
+
if result.num_errors > 0:
|
|
112
|
+
sys.exit(1)
|
|
113
|
+
|
|
114
|
+
|
|
115
|
+
def exec_file(program_name, args=()):
|
|
116
|
+
runcmd([os.path.abspath(program_name)] + list(args), shell=False)
|
|
117
|
+
|
|
118
|
+
|
|
119
|
+
def build(input_file, compiler_args=(), force=False):
|
|
120
|
+
"""
|
|
121
|
+
Build an executable program from a Cython module.
|
|
122
|
+
|
|
123
|
+
Returns the name of the executable file.
|
|
124
|
+
"""
|
|
125
|
+
basename = os.path.splitext(input_file)[0]
|
|
126
|
+
exe_file = basename + EXE_EXT
|
|
127
|
+
if not force and os.path.abspath(exe_file) == os.path.abspath(input_file):
|
|
128
|
+
raise ValueError("Input and output file names are the same, refusing to overwrite")
|
|
129
|
+
if (not force and os.path.exists(exe_file) and os.path.exists(input_file)
|
|
130
|
+
and os.path.getmtime(input_file) <= os.path.getmtime(exe_file)):
|
|
131
|
+
_debug("File is up to date, not regenerating %s", exe_file)
|
|
132
|
+
return exe_file
|
|
133
|
+
cycompile(input_file, compiler_args)
|
|
134
|
+
ccompile(basename)
|
|
135
|
+
clink(basename)
|
|
136
|
+
return exe_file
|
|
137
|
+
|
|
138
|
+
|
|
139
|
+
def build_and_run(args):
|
|
140
|
+
"""
|
|
141
|
+
Build an executable program from a Cython module and run it.
|
|
142
|
+
|
|
143
|
+
Arguments after the module name will be passed verbatimly to the program.
|
|
144
|
+
"""
|
|
145
|
+
program_name, args = _build(args)
|
|
146
|
+
exec_file(program_name, args)
|
|
147
|
+
|
|
148
|
+
|
|
149
|
+
def _build(args):
|
|
150
|
+
input_file, cy_args, args = _parse_args(args)
|
|
151
|
+
program_name = build(input_file, cy_args)
|
|
152
|
+
return program_name, args
|
|
153
|
+
|
|
154
|
+
|
|
155
|
+
if __name__ == '__main__':
|
|
156
|
+
_build(sys.argv[1:])
|
Cython/Build/Cache.py
ADDED
|
@@ -0,0 +1,199 @@
|
|
|
1
|
+
from dataclasses import dataclass
|
|
2
|
+
import sys
|
|
3
|
+
import os
|
|
4
|
+
import hashlib
|
|
5
|
+
import shutil
|
|
6
|
+
import subprocess
|
|
7
|
+
from ..Utils import safe_makedirs, cached_function
|
|
8
|
+
import zipfile
|
|
9
|
+
from .. import __version__
|
|
10
|
+
|
|
11
|
+
try:
|
|
12
|
+
import zlib
|
|
13
|
+
|
|
14
|
+
zipfile_compression_mode = zipfile.ZIP_DEFLATED
|
|
15
|
+
except ImportError:
|
|
16
|
+
zipfile_compression_mode = zipfile.ZIP_STORED
|
|
17
|
+
|
|
18
|
+
try:
|
|
19
|
+
import gzip
|
|
20
|
+
|
|
21
|
+
gzip_open = gzip.open
|
|
22
|
+
gzip_ext = ".gz"
|
|
23
|
+
except ImportError:
|
|
24
|
+
gzip_open = open
|
|
25
|
+
gzip_ext = ""
|
|
26
|
+
|
|
27
|
+
zip_ext = ".zip"
|
|
28
|
+
|
|
29
|
+
MAX_CACHE_SIZE = 1024 * 1024 * 100
|
|
30
|
+
|
|
31
|
+
join_path = cached_function(os.path.join)
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
@cached_function
|
|
35
|
+
def file_hash(filename):
|
|
36
|
+
path = os.path.normpath(filename)
|
|
37
|
+
prefix = ("%d:%s" % (len(path), path)).encode("UTF-8")
|
|
38
|
+
m = hashlib.sha256(prefix)
|
|
39
|
+
with open(path, "rb") as f:
|
|
40
|
+
data = f.read(65000)
|
|
41
|
+
while data:
|
|
42
|
+
m.update(data)
|
|
43
|
+
data = f.read(65000)
|
|
44
|
+
return m.hexdigest()
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
@cached_function
|
|
48
|
+
def get_cython_cache_dir():
|
|
49
|
+
r"""
|
|
50
|
+
Return the base directory containing Cython's caches.
|
|
51
|
+
|
|
52
|
+
Priority:
|
|
53
|
+
|
|
54
|
+
1. CYTHON_CACHE_DIR
|
|
55
|
+
2. (OS X): ~/Library/Caches/Cython
|
|
56
|
+
(posix not OS X): XDG_CACHE_HOME/cython if XDG_CACHE_HOME defined
|
|
57
|
+
3. ~/.cython
|
|
58
|
+
|
|
59
|
+
"""
|
|
60
|
+
if "CYTHON_CACHE_DIR" in os.environ:
|
|
61
|
+
return os.environ["CYTHON_CACHE_DIR"]
|
|
62
|
+
|
|
63
|
+
parent = None
|
|
64
|
+
if os.name == "posix":
|
|
65
|
+
if sys.platform == "darwin":
|
|
66
|
+
parent = os.path.expanduser("~/Library/Caches")
|
|
67
|
+
else:
|
|
68
|
+
# this could fallback on ~/.cache
|
|
69
|
+
parent = os.environ.get("XDG_CACHE_HOME")
|
|
70
|
+
|
|
71
|
+
if parent and os.path.isdir(parent):
|
|
72
|
+
return join_path(parent, "cython")
|
|
73
|
+
|
|
74
|
+
# last fallback: ~/.cython
|
|
75
|
+
return os.path.expanduser(join_path("~", ".cython"))
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
@dataclass
|
|
79
|
+
class FingerprintFlags:
|
|
80
|
+
language: str = "c"
|
|
81
|
+
py_limited_api: bool = False
|
|
82
|
+
np_pythran: bool = False
|
|
83
|
+
|
|
84
|
+
def get_fingerprint(self):
|
|
85
|
+
return str((self.language, self.py_limited_api, self.np_pythran))
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
class Cache:
|
|
89
|
+
def __init__(self, path, cache_size=None):
|
|
90
|
+
if path is None:
|
|
91
|
+
self.path = join_path(get_cython_cache_dir(), "compiler")
|
|
92
|
+
else:
|
|
93
|
+
self.path = path
|
|
94
|
+
self.cache_size = cache_size if cache_size is not None else MAX_CACHE_SIZE
|
|
95
|
+
if not os.path.exists(self.path):
|
|
96
|
+
os.makedirs(self.path)
|
|
97
|
+
|
|
98
|
+
def transitive_fingerprint(
|
|
99
|
+
self, filename, dependencies, compilation_options, flags=FingerprintFlags()
|
|
100
|
+
):
|
|
101
|
+
r"""
|
|
102
|
+
Return a fingerprint of a cython file that is about to be cythonized.
|
|
103
|
+
|
|
104
|
+
Fingerprints are looked up in future compilations. If the fingerprint
|
|
105
|
+
is found, the cythonization can be skipped. The fingerprint must
|
|
106
|
+
incorporate everything that has an influence on the generated code.
|
|
107
|
+
"""
|
|
108
|
+
try:
|
|
109
|
+
m = hashlib.sha256(__version__.encode("UTF-8"))
|
|
110
|
+
m.update(file_hash(filename).encode("UTF-8"))
|
|
111
|
+
for x in sorted(dependencies):
|
|
112
|
+
if os.path.splitext(x)[1] not in (".c", ".cpp", ".h"):
|
|
113
|
+
m.update(file_hash(x).encode("UTF-8"))
|
|
114
|
+
# Include the module attributes that change the compilation result
|
|
115
|
+
# in the fingerprint. We do not iterate over module.__dict__ and
|
|
116
|
+
# include almost everything here as users might extend Extension
|
|
117
|
+
# with arbitrary (random) attributes that would lead to cache
|
|
118
|
+
# misses.
|
|
119
|
+
m.update(flags.get_fingerprint().encode("UTF-8"))
|
|
120
|
+
m.update(compilation_options.get_fingerprint().encode("UTF-8"))
|
|
121
|
+
return m.hexdigest()
|
|
122
|
+
except OSError:
|
|
123
|
+
return None
|
|
124
|
+
|
|
125
|
+
def fingerprint_file(self, cfile, fingerprint, ext):
|
|
126
|
+
return (
|
|
127
|
+
join_path(self.path, "%s-%s" % (os.path.basename(cfile), fingerprint)) + ext
|
|
128
|
+
)
|
|
129
|
+
|
|
130
|
+
def lookup_cache(self, c_file, fingerprint):
|
|
131
|
+
# Cython-generated c files are highly compressible.
|
|
132
|
+
# (E.g. a compression ratio of about 10 for Sage).
|
|
133
|
+
if not os.path.exists(self.path):
|
|
134
|
+
safe_makedirs(self.path)
|
|
135
|
+
gz_fingerprint_file = self.fingerprint_file(c_file, fingerprint, gzip_ext)
|
|
136
|
+
if os.path.exists(gz_fingerprint_file):
|
|
137
|
+
return gz_fingerprint_file
|
|
138
|
+
zip_fingerprint_file = self.fingerprint_file(c_file, fingerprint, zip_ext)
|
|
139
|
+
if os.path.exists(zip_fingerprint_file):
|
|
140
|
+
return zip_fingerprint_file
|
|
141
|
+
return None
|
|
142
|
+
|
|
143
|
+
def load_from_cache(self, c_file, cached):
|
|
144
|
+
ext = os.path.splitext(cached)[1]
|
|
145
|
+
if ext == gzip_ext:
|
|
146
|
+
os.utime(cached, None)
|
|
147
|
+
with gzip_open(cached, "rb") as g:
|
|
148
|
+
with open(c_file, "wb") as f:
|
|
149
|
+
shutil.copyfileobj(g, f)
|
|
150
|
+
elif ext == zip_ext:
|
|
151
|
+
os.utime(cached, None)
|
|
152
|
+
dirname = os.path.dirname(c_file)
|
|
153
|
+
with zipfile.ZipFile(cached) as z:
|
|
154
|
+
for artifact in z.namelist():
|
|
155
|
+
z.extract(artifact, dirname)
|
|
156
|
+
else:
|
|
157
|
+
raise ValueError(f"Unsupported cache file extension: {ext}")
|
|
158
|
+
|
|
159
|
+
def store_to_cache(self, c_file, fingerprint, compilation_result):
|
|
160
|
+
artifacts = compilation_result.get_generated_source_files()
|
|
161
|
+
if len(artifacts) == 1:
|
|
162
|
+
fingerprint_file = self.fingerprint_file(c_file, fingerprint, gzip_ext)
|
|
163
|
+
with open(c_file, "rb") as f:
|
|
164
|
+
with gzip_open(fingerprint_file + ".tmp", "wb") as g:
|
|
165
|
+
shutil.copyfileobj(f, g)
|
|
166
|
+
else:
|
|
167
|
+
fingerprint_file = self.fingerprint_file(c_file, fingerprint, zip_ext)
|
|
168
|
+
with zipfile.ZipFile(
|
|
169
|
+
fingerprint_file + ".tmp", "w", zipfile_compression_mode
|
|
170
|
+
) as zip:
|
|
171
|
+
for artifact in artifacts:
|
|
172
|
+
zip.write(artifact, os.path.basename(artifact))
|
|
173
|
+
os.rename(fingerprint_file + ".tmp", fingerprint_file)
|
|
174
|
+
|
|
175
|
+
def cleanup_cache(self, ratio=0.85):
|
|
176
|
+
try:
|
|
177
|
+
completed_process = subprocess.run(
|
|
178
|
+
["du", "-s", "-k", os.path.abspath(self.path)], stdout=subprocess.PIPE
|
|
179
|
+
)
|
|
180
|
+
stdout = completed_process.stdout
|
|
181
|
+
if completed_process.returncode == 0:
|
|
182
|
+
total_size = 1024 * int(stdout.strip().split()[0])
|
|
183
|
+
if total_size < self.cache_size:
|
|
184
|
+
return
|
|
185
|
+
except (OSError, ValueError):
|
|
186
|
+
pass
|
|
187
|
+
total_size = 0
|
|
188
|
+
all = []
|
|
189
|
+
for file in os.listdir(self.path):
|
|
190
|
+
path = join_path(self.path, file)
|
|
191
|
+
s = os.stat(path)
|
|
192
|
+
total_size += s.st_size
|
|
193
|
+
all.append((s.st_atime, s.st_size, path))
|
|
194
|
+
if total_size > self.cache_size:
|
|
195
|
+
for time, size, file in reversed(sorted(all)):
|
|
196
|
+
os.unlink(file)
|
|
197
|
+
total_size -= size
|
|
198
|
+
if total_size < self.cache_size * ratio:
|
|
199
|
+
break
|
|
@@ -0,0 +1,349 @@
|
|
|
1
|
+
import concurrent.futures
|
|
2
|
+
import os
|
|
3
|
+
import shutil
|
|
4
|
+
import sys
|
|
5
|
+
import tempfile
|
|
6
|
+
from collections import defaultdict
|
|
7
|
+
from contextlib import contextmanager
|
|
8
|
+
|
|
9
|
+
from .Dependencies import cythonize, extended_iglob
|
|
10
|
+
from ..Utils import is_package_dir
|
|
11
|
+
from ..Compiler import Options
|
|
12
|
+
|
|
13
|
+
try:
|
|
14
|
+
import multiprocessing
|
|
15
|
+
except ImportError:
|
|
16
|
+
multiprocessing = None
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
def find_package_base(path):
|
|
20
|
+
base_dir, package_path = os.path.split(path)
|
|
21
|
+
while is_package_dir(base_dir):
|
|
22
|
+
base_dir, parent = os.path.split(base_dir)
|
|
23
|
+
package_path = '%s/%s' % (parent, package_path)
|
|
24
|
+
return base_dir, package_path
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
def cython_compile(path_pattern, options):
|
|
28
|
+
all_paths = map(os.path.abspath, extended_iglob(path_pattern))
|
|
29
|
+
ext_modules_by_basedir = _cython_compile_files(all_paths, options)
|
|
30
|
+
_build(list(ext_modules_by_basedir.items()), options.parallel)
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
def _cython_compile_files(all_paths, options) -> dict:
|
|
34
|
+
ext_modules_to_build = defaultdict(list)
|
|
35
|
+
|
|
36
|
+
for path in all_paths:
|
|
37
|
+
if options.build_inplace:
|
|
38
|
+
base_dir = path
|
|
39
|
+
while not os.path.isdir(base_dir) or is_package_dir(base_dir):
|
|
40
|
+
base_dir = os.path.dirname(base_dir)
|
|
41
|
+
else:
|
|
42
|
+
base_dir = None
|
|
43
|
+
|
|
44
|
+
if os.path.isdir(path):
|
|
45
|
+
# recursively compiling a package
|
|
46
|
+
paths = [os.path.join(path, '**', '*.{py,pyx}')]
|
|
47
|
+
else:
|
|
48
|
+
# assume it's a file(-like thing)
|
|
49
|
+
paths = [path]
|
|
50
|
+
|
|
51
|
+
ext_modules = cythonize(
|
|
52
|
+
paths,
|
|
53
|
+
nthreads=options.parallel,
|
|
54
|
+
exclude_failures=options.keep_going,
|
|
55
|
+
exclude=options.excludes,
|
|
56
|
+
compiler_directives=options.directives,
|
|
57
|
+
compile_time_env=options.compile_time_env,
|
|
58
|
+
force=options.force,
|
|
59
|
+
quiet=options.quiet,
|
|
60
|
+
depfile=options.depfile,
|
|
61
|
+
language=options.language,
|
|
62
|
+
**options.options)
|
|
63
|
+
|
|
64
|
+
if ext_modules and options.build:
|
|
65
|
+
ext_modules_to_build[base_dir].extend(ext_modules)
|
|
66
|
+
|
|
67
|
+
return dict(ext_modules_to_build)
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
@contextmanager
|
|
71
|
+
def _interruptible_pool(pool_cm):
|
|
72
|
+
with pool_cm as proc_pool:
|
|
73
|
+
try:
|
|
74
|
+
yield proc_pool
|
|
75
|
+
except KeyboardInterrupt:
|
|
76
|
+
proc_pool.terminate_workers()
|
|
77
|
+
proc_pool.shutdown(cancel_futures=True)
|
|
78
|
+
raise
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
def _build(ext_modules, parallel):
|
|
82
|
+
modcount = sum(len(modules) for _, modules in ext_modules)
|
|
83
|
+
if not modcount:
|
|
84
|
+
return
|
|
85
|
+
|
|
86
|
+
serial_execution_mode = modcount == 1 or (
|
|
87
|
+
parallel is not None and parallel < 2)
|
|
88
|
+
|
|
89
|
+
try:
|
|
90
|
+
pool_cm = (
|
|
91
|
+
None if serial_execution_mode
|
|
92
|
+
else concurrent.futures.ProcessPoolExecutor(max_workers=parallel)
|
|
93
|
+
)
|
|
94
|
+
except (OSError, ImportError):
|
|
95
|
+
# `OSError` is a historic exception in `multiprocessing`
|
|
96
|
+
# `ImportError` happens e.g. under pyodide (`ModuleNotFoundError`)
|
|
97
|
+
serial_execution_mode = True
|
|
98
|
+
|
|
99
|
+
if serial_execution_mode:
|
|
100
|
+
for ext in ext_modules:
|
|
101
|
+
run_distutils(ext)
|
|
102
|
+
return
|
|
103
|
+
|
|
104
|
+
with _interruptible_pool(pool_cm) as proc_pool:
|
|
105
|
+
compiler_tasks = [
|
|
106
|
+
proc_pool.submit(run_distutils, (base_dir, [ext]))
|
|
107
|
+
for base_dir, modules in ext_modules
|
|
108
|
+
for ext in modules
|
|
109
|
+
]
|
|
110
|
+
|
|
111
|
+
concurrent.futures.wait(compiler_tasks, return_when=concurrent.futures.FIRST_EXCEPTION)
|
|
112
|
+
|
|
113
|
+
worker_exceptions = []
|
|
114
|
+
for task in compiler_tasks: # discover any crashes
|
|
115
|
+
try:
|
|
116
|
+
task.result()
|
|
117
|
+
except BaseException as proc_err: # could be SystemExit
|
|
118
|
+
worker_exceptions.append(proc_err)
|
|
119
|
+
|
|
120
|
+
if worker_exceptions:
|
|
121
|
+
exc_msg = 'Compiling Cython modules failed with these errors:\n\n'
|
|
122
|
+
exc_msg += '\n\t* '.join(('', *map(str, worker_exceptions)))
|
|
123
|
+
exc_msg += '\n\n'
|
|
124
|
+
|
|
125
|
+
non_base_exceptions = [
|
|
126
|
+
exc for exc in worker_exceptions
|
|
127
|
+
if isinstance(exc, Exception)
|
|
128
|
+
]
|
|
129
|
+
if sys.version_info[:2] >= (3, 11) and non_base_exceptions:
|
|
130
|
+
raise ExceptionGroup(exc_msg, non_base_exceptions)
|
|
131
|
+
else:
|
|
132
|
+
raise RuntimeError(exc_msg) from worker_exceptions[0]
|
|
133
|
+
|
|
134
|
+
|
|
135
|
+
def run_distutils(args):
|
|
136
|
+
try:
|
|
137
|
+
from distutils.core import setup
|
|
138
|
+
except ImportError:
|
|
139
|
+
try:
|
|
140
|
+
from setuptools import setup
|
|
141
|
+
except ImportError:
|
|
142
|
+
raise ImportError("'distutils' is not available. Please install 'setuptools' for binary builds.")
|
|
143
|
+
|
|
144
|
+
base_dir, ext_modules = args
|
|
145
|
+
script_args = ['build_ext', '-i']
|
|
146
|
+
cwd = os.getcwd()
|
|
147
|
+
temp_dir = None
|
|
148
|
+
try:
|
|
149
|
+
if base_dir:
|
|
150
|
+
os.chdir(base_dir)
|
|
151
|
+
temp_dir = tempfile.mkdtemp(dir=base_dir)
|
|
152
|
+
script_args.extend(['--build-temp', temp_dir])
|
|
153
|
+
setup(
|
|
154
|
+
script_name='setup.py',
|
|
155
|
+
script_args=script_args,
|
|
156
|
+
ext_modules=ext_modules,
|
|
157
|
+
)
|
|
158
|
+
finally:
|
|
159
|
+
if base_dir:
|
|
160
|
+
os.chdir(cwd)
|
|
161
|
+
if temp_dir and os.path.isdir(temp_dir):
|
|
162
|
+
shutil.rmtree(temp_dir)
|
|
163
|
+
|
|
164
|
+
|
|
165
|
+
def benchmark(code, setup_code=None, import_module=None, directives=None):
|
|
166
|
+
from Cython.Build.Inline import cymeit
|
|
167
|
+
|
|
168
|
+
timings, number = cymeit(code, setup_code, import_module, directives, repeat=9)
|
|
169
|
+
|
|
170
|
+
# Based on 'timeit.main()' in CPython 3.13.
|
|
171
|
+
units = {"nsec": 1e-9, "usec": 1e-6, "msec": 1e-3, "sec": 1.0}
|
|
172
|
+
scales = [(scale, unit) for unit, scale in reversed(units.items())] # biggest first
|
|
173
|
+
|
|
174
|
+
def format_time(t):
|
|
175
|
+
for scale, unit in scales:
|
|
176
|
+
if t >= scale:
|
|
177
|
+
break
|
|
178
|
+
else:
|
|
179
|
+
raise RuntimeError("Timing is below nanoseconds: {t:f}")
|
|
180
|
+
return f"{t / scale :.3f} {unit}"
|
|
181
|
+
|
|
182
|
+
timings.sort()
|
|
183
|
+
assert len(timings) & 1 == 1 # odd number of timings, for median position
|
|
184
|
+
fastest, median, slowest = timings[0], timings[len(timings) // 2], timings[-1]
|
|
185
|
+
|
|
186
|
+
print(f"{number} loops, best of {len(timings)}: {format_time(fastest)} per loop (median: {format_time(median)})")
|
|
187
|
+
|
|
188
|
+
if slowest > fastest * 4:
|
|
189
|
+
print(
|
|
190
|
+
"The timings are likely unreliable. "
|
|
191
|
+
f"The worst time ({format_time(slowest)}) was more than four times "
|
|
192
|
+
f"slower than the best time ({format_time(fastest)}).")
|
|
193
|
+
|
|
194
|
+
|
|
195
|
+
def create_args_parser():
|
|
196
|
+
from argparse import ArgumentParser, RawDescriptionHelpFormatter
|
|
197
|
+
from ..Compiler.CmdLine import ParseDirectivesAction, ParseOptionsAction, ParseCompileTimeEnvAction
|
|
198
|
+
|
|
199
|
+
parser = ArgumentParser(
|
|
200
|
+
formatter_class=RawDescriptionHelpFormatter,
|
|
201
|
+
epilog="""\
|
|
202
|
+
Environment variables:
|
|
203
|
+
CYTHON_FORCE_REGEN: if set to 1, forces cythonize to regenerate the output files regardless
|
|
204
|
+
of modification times and changes.
|
|
205
|
+
CYTHON_CACHE_DIR: the base directory containing Cython's caches.
|
|
206
|
+
Environment variables accepted by setuptools are supported to configure the C compiler and build:
|
|
207
|
+
https://setuptools.pypa.io/en/latest/userguide/ext_modules.html#compiler-and-linker-options"""
|
|
208
|
+
)
|
|
209
|
+
|
|
210
|
+
parser.add_argument('-X', '--directive', metavar='NAME=VALUE,...',
|
|
211
|
+
dest='directives', default={}, type=str,
|
|
212
|
+
action=ParseDirectivesAction,
|
|
213
|
+
help='set a compiler directive')
|
|
214
|
+
parser.add_argument('-E', '--compile-time-env', metavar='NAME=VALUE,...',
|
|
215
|
+
dest='compile_time_env', default={}, type=str,
|
|
216
|
+
action=ParseCompileTimeEnvAction,
|
|
217
|
+
help='set a compile time environment variable')
|
|
218
|
+
parser.add_argument('-s', '--option', metavar='NAME=VALUE',
|
|
219
|
+
dest='options', default={}, type=str,
|
|
220
|
+
action=ParseOptionsAction,
|
|
221
|
+
help='set a cythonize option')
|
|
222
|
+
parser.add_argument('-2', dest='language_level', action='store_const', const=2, default=None,
|
|
223
|
+
help='use Python 2 syntax mode by default')
|
|
224
|
+
parser.add_argument('-3', dest='language_level', action='store_const', const=3,
|
|
225
|
+
help='use Python 3 syntax mode by default')
|
|
226
|
+
parser.add_argument('--3str', dest='language_level', action='store_const', const=3,
|
|
227
|
+
help='use Python 3 syntax mode by default (deprecated alias for -3)')
|
|
228
|
+
parser.add_argument('-+', '--cplus', dest='language', action='store_const', const='c++', default=None,
|
|
229
|
+
help='Compile as C++ rather than C')
|
|
230
|
+
parser.add_argument('-a', '--annotate', action='store_const', const='default', dest='annotate',
|
|
231
|
+
help='Produce a colorized HTML version of the source.')
|
|
232
|
+
parser.add_argument('--annotate-fullc', action='store_const', const='fullc', dest='annotate',
|
|
233
|
+
help='Produce a colorized HTML version of the source '
|
|
234
|
+
'which includes entire generated C/C++-code.')
|
|
235
|
+
parser.add_argument('-x', '--exclude', metavar='PATTERN', dest='excludes',
|
|
236
|
+
action='append', default=[],
|
|
237
|
+
help='exclude certain file patterns from the compilation')
|
|
238
|
+
|
|
239
|
+
parser.add_argument('-b', '--build', dest='build', action='store_true', default=None,
|
|
240
|
+
help='build extension modules using distutils/setuptools')
|
|
241
|
+
parser.add_argument('-i', '--inplace', dest='build_inplace', action='store_true', default=None,
|
|
242
|
+
help='build extension modules in place using distutils/setuptools (implies -b)')
|
|
243
|
+
|
|
244
|
+
parser.add_argument('--timeit', dest='benchmark', metavar="CODESTRING", type=str, default=None,
|
|
245
|
+
help="build in place, then compile+run CODESTRING as benchmark in first module's namespace (implies -i)")
|
|
246
|
+
parser.add_argument('--setup', dest='benchmark_setup', metavar="CODESTRING", type=str, default=None,
|
|
247
|
+
help="use CODESTRING as pre-benchmark setup code for --bench")
|
|
248
|
+
|
|
249
|
+
parser.add_argument('-j', '--parallel', dest='parallel', metavar='N',
|
|
250
|
+
type=int, default=None,
|
|
251
|
+
help='run builds in N parallel jobs (default: CPU count)')
|
|
252
|
+
parser.add_argument('-f', '--force', dest='force', action='store_true', default=None,
|
|
253
|
+
help='force recompilation')
|
|
254
|
+
parser.add_argument('-q', '--quiet', dest='quiet', action='store_true', default=None,
|
|
255
|
+
help='be less verbose during compilation')
|
|
256
|
+
|
|
257
|
+
parser.add_argument('--lenient', dest='lenient', action='store_true', default=None,
|
|
258
|
+
help='increase Python compatibility by ignoring some compile time errors')
|
|
259
|
+
parser.add_argument('-k', '--keep-going', dest='keep_going', action='store_true', default=None,
|
|
260
|
+
help='compile as much as possible, ignore compilation failures')
|
|
261
|
+
parser.add_argument('--no-docstrings', dest='no_docstrings', action='store_true', default=None,
|
|
262
|
+
help='strip docstrings')
|
|
263
|
+
parser.add_argument('-M', '--depfile', action='store_true', help='produce depfiles for the sources')
|
|
264
|
+
parser.add_argument('sources', nargs='*')
|
|
265
|
+
return parser
|
|
266
|
+
|
|
267
|
+
|
|
268
|
+
def parse_args_raw(parser, args):
|
|
269
|
+
options, unknown = parser.parse_known_args(args)
|
|
270
|
+
sources = options.sources
|
|
271
|
+
# if positional arguments were interspersed
|
|
272
|
+
# some of them are in unknown
|
|
273
|
+
for option in unknown:
|
|
274
|
+
if option.startswith('-'):
|
|
275
|
+
parser.error("unknown option "+option)
|
|
276
|
+
else:
|
|
277
|
+
sources.append(option)
|
|
278
|
+
del options.sources
|
|
279
|
+
return (options, sources)
|
|
280
|
+
|
|
281
|
+
|
|
282
|
+
def parse_args(args):
|
|
283
|
+
parser = create_args_parser()
|
|
284
|
+
options, args = parse_args_raw(parser, args)
|
|
285
|
+
|
|
286
|
+
if options.benchmark is not None:
|
|
287
|
+
options.build_inplace = True
|
|
288
|
+
elif not args:
|
|
289
|
+
parser.error("no source files provided")
|
|
290
|
+
|
|
291
|
+
if options.build_inplace:
|
|
292
|
+
options.build = True
|
|
293
|
+
if multiprocessing is None:
|
|
294
|
+
options.parallel = 0
|
|
295
|
+
if options.language_level:
|
|
296
|
+
assert options.language_level in (2, 3, '3str')
|
|
297
|
+
options.options['language_level'] = options.language_level
|
|
298
|
+
|
|
299
|
+
if options.lenient:
|
|
300
|
+
# increase Python compatibility by ignoring compile time errors
|
|
301
|
+
Options.error_on_unknown_names = False
|
|
302
|
+
Options.error_on_uninitialized = False
|
|
303
|
+
|
|
304
|
+
if options.annotate:
|
|
305
|
+
Options.annotate = options.annotate
|
|
306
|
+
|
|
307
|
+
if options.no_docstrings:
|
|
308
|
+
Options.docstrings = False
|
|
309
|
+
|
|
310
|
+
return options, args
|
|
311
|
+
|
|
312
|
+
|
|
313
|
+
def main(args=None):
|
|
314
|
+
options, paths = parse_args(args)
|
|
315
|
+
|
|
316
|
+
all_paths = []
|
|
317
|
+
for path in paths:
|
|
318
|
+
expanded_path = [os.path.abspath(p) for p in extended_iglob(path)]
|
|
319
|
+
if not expanded_path:
|
|
320
|
+
print("{}: No such file or directory: '{}'".format(sys.argv[0], path), file=sys.stderr)
|
|
321
|
+
sys.exit(1)
|
|
322
|
+
all_paths.extend(expanded_path)
|
|
323
|
+
|
|
324
|
+
ext_modules_by_basedir = _cython_compile_files(all_paths, options)
|
|
325
|
+
|
|
326
|
+
if ext_modules_by_basedir and options.build:
|
|
327
|
+
_build(list(ext_modules_by_basedir.items()), options.parallel)
|
|
328
|
+
|
|
329
|
+
if options.benchmark is not None:
|
|
330
|
+
base_dir = import_module = None
|
|
331
|
+
if ext_modules_by_basedir:
|
|
332
|
+
base_dir, first_extensions = ext_modules_by_basedir.popitem()
|
|
333
|
+
if first_extensions:
|
|
334
|
+
import_module = first_extensions[0].name
|
|
335
|
+
|
|
336
|
+
if base_dir is not None:
|
|
337
|
+
sys.path.insert(0, base_dir)
|
|
338
|
+
|
|
339
|
+
benchmark(
|
|
340
|
+
options.benchmark, options.benchmark_setup,
|
|
341
|
+
import_module=import_module,
|
|
342
|
+
)
|
|
343
|
+
|
|
344
|
+
if base_dir is not None:
|
|
345
|
+
sys.path.remove(base_dir)
|
|
346
|
+
|
|
347
|
+
|
|
348
|
+
if __name__ == '__main__':
|
|
349
|
+
main()
|