Rahul8827 commited on
Commit
6869fc3
1 Parent(s): 72e4a80

Upload 9572 files

Browse files
This view is limited to 50 files because it contains too many changes.   See raw diff
Files changed (50) hide show
  1. .gitattributes +12 -0
  2. venv/Lib/site-packages/Cython-0.29.36.dist-info/COPYING.txt +19 -0
  3. venv/Lib/site-packages/Cython-0.29.36.dist-info/INSTALLER +1 -0
  4. venv/Lib/site-packages/Cython-0.29.36.dist-info/LICENSE.txt +176 -0
  5. venv/Lib/site-packages/Cython-0.29.36.dist-info/METADATA +63 -0
  6. venv/Lib/site-packages/Cython-0.29.36.dist-info/RECORD +424 -0
  7. venv/Lib/site-packages/Cython-0.29.36.dist-info/WHEEL +6 -0
  8. venv/Lib/site-packages/Cython-0.29.36.dist-info/entry_points.txt +4 -0
  9. venv/Lib/site-packages/Cython-0.29.36.dist-info/top_level.txt +3 -0
  10. venv/Lib/site-packages/Cython/Build/BuildExecutable.py +142 -0
  11. venv/Lib/site-packages/Cython/Build/Cythonize.py +229 -0
  12. venv/Lib/site-packages/Cython/Build/Dependencies.py +1296 -0
  13. venv/Lib/site-packages/Cython/Build/Distutils.py +1 -0
  14. venv/Lib/site-packages/Cython/Build/Inline.py +377 -0
  15. venv/Lib/site-packages/Cython/Build/IpythonMagic.py +564 -0
  16. venv/Lib/site-packages/Cython/Build/Tests/TestCyCache.py +106 -0
  17. venv/Lib/site-packages/Cython/Build/Tests/TestInline.py +96 -0
  18. venv/Lib/site-packages/Cython/Build/Tests/TestIpythonMagic.py +205 -0
  19. venv/Lib/site-packages/Cython/Build/Tests/TestStripLiterals.py +57 -0
  20. venv/Lib/site-packages/Cython/Build/Tests/__init__.py +1 -0
  21. venv/Lib/site-packages/Cython/Build/Tests/__pycache__/TestCyCache.cpython-311.pyc +0 -0
  22. venv/Lib/site-packages/Cython/Build/Tests/__pycache__/TestInline.cpython-311.pyc +0 -0
  23. venv/Lib/site-packages/Cython/Build/Tests/__pycache__/TestIpythonMagic.cpython-311.pyc +0 -0
  24. venv/Lib/site-packages/Cython/Build/Tests/__pycache__/TestStripLiterals.cpython-311.pyc +0 -0
  25. venv/Lib/site-packages/Cython/Build/Tests/__pycache__/__init__.cpython-311.pyc +0 -0
  26. venv/Lib/site-packages/Cython/Build/__init__.py +2 -0
  27. venv/Lib/site-packages/Cython/Build/__pycache__/BuildExecutable.cpython-311.pyc +0 -0
  28. venv/Lib/site-packages/Cython/Build/__pycache__/Cythonize.cpython-311.pyc +0 -0
  29. venv/Lib/site-packages/Cython/Build/__pycache__/Dependencies.cpython-311.pyc +0 -0
  30. venv/Lib/site-packages/Cython/Build/__pycache__/Distutils.cpython-311.pyc +0 -0
  31. venv/Lib/site-packages/Cython/Build/__pycache__/Inline.cpython-311.pyc +0 -0
  32. venv/Lib/site-packages/Cython/Build/__pycache__/IpythonMagic.cpython-311.pyc +0 -0
  33. venv/Lib/site-packages/Cython/Build/__pycache__/__init__.cpython-311.pyc +0 -0
  34. venv/Lib/site-packages/Cython/CodeWriter.py +819 -0
  35. venv/Lib/site-packages/Cython/Compiler/AnalysedTreeTransforms.py +99 -0
  36. venv/Lib/site-packages/Cython/Compiler/Annotate.py +317 -0
  37. venv/Lib/site-packages/Cython/Compiler/AutoDocTransforms.py +214 -0
  38. venv/Lib/site-packages/Cython/Compiler/Buffer.py +740 -0
  39. venv/Lib/site-packages/Cython/Compiler/Builtin.py +445 -0
  40. venv/Lib/site-packages/Cython/Compiler/CmdLine.py +240 -0
  41. venv/Lib/site-packages/Cython/Compiler/Code.pxd +124 -0
  42. venv/Lib/site-packages/Cython/Compiler/Code.py +2597 -0
  43. venv/Lib/site-packages/Cython/Compiler/CodeGeneration.py +35 -0
  44. venv/Lib/site-packages/Cython/Compiler/CythonScope.py +164 -0
  45. venv/Lib/site-packages/Cython/Compiler/DebugFlags.py +21 -0
  46. venv/Lib/site-packages/Cython/Compiler/Errors.py +265 -0
  47. venv/Lib/site-packages/Cython/Compiler/ExprNodes.py +0 -0
  48. venv/Lib/site-packages/Cython/Compiler/FlowControl.pxd +111 -0
  49. venv/Lib/site-packages/Cython/Compiler/FlowControl.py +1325 -0
  50. venv/Lib/site-packages/Cython/Compiler/FusedNode.py +901 -0
.gitattributes CHANGED
@@ -33,3 +33,15 @@ saved_model/**/* filter=lfs diff=lfs merge=lfs -text
33
  *.zip filter=lfs diff=lfs merge=lfs -text
34
  *.zst filter=lfs diff=lfs merge=lfs -text
35
  *tfevents* filter=lfs diff=lfs merge=lfs -text
 
 
 
 
 
 
 
 
 
 
 
 
 
33
  *.zip filter=lfs diff=lfs merge=lfs -text
34
  *.zst filter=lfs diff=lfs merge=lfs -text
35
  *tfevents* filter=lfs diff=lfs merge=lfs -text
36
+ venv/Lib/site-packages/altair/vegalite/v5/schema/__pycache__/core.cpython-311.pyc filter=lfs diff=lfs merge=lfs -text
37
+ venv/Lib/site-packages/fitz/_fitz.cp311-win_amd64.pyd filter=lfs diff=lfs merge=lfs -text
38
+ venv/Lib/site-packages/gradio/templates/frontend/assets/index-0eddd93f.js.map filter=lfs diff=lfs merge=lfs -text
39
+ venv/Lib/site-packages/numpy/.libs/libopenblas64__v0.3.23-gcc_10_3_0.dll filter=lfs diff=lfs merge=lfs -text
40
+ venv/Lib/site-packages/numpy/core/_multiarray_umath.cp311-win_amd64.pyd filter=lfs diff=lfs merge=lfs -text
41
+ venv/Lib/site-packages/numpy/core/_simd.cp311-win_amd64.pyd filter=lfs diff=lfs merge=lfs -text
42
+ venv/Lib/site-packages/pandas/_libs/algos.cp311-win_amd64.pyd filter=lfs diff=lfs merge=lfs -text
43
+ venv/Lib/site-packages/pandas/_libs/groupby.cp311-win_amd64.pyd filter=lfs diff=lfs merge=lfs -text
44
+ venv/Lib/site-packages/pandas/_libs/hashtable.cp311-win_amd64.pyd filter=lfs diff=lfs merge=lfs -text
45
+ venv/Lib/site-packages/pandas/_libs/join.cp311-win_amd64.pyd filter=lfs diff=lfs merge=lfs -text
46
+ venv/Lib/site-packages/PIL/_imaging.cp311-win_amd64.pyd filter=lfs diff=lfs merge=lfs -text
47
+ venv/Lib/site-packages/PIL/_imagingft.cp311-win_amd64.pyd filter=lfs diff=lfs merge=lfs -text
venv/Lib/site-packages/Cython-0.29.36.dist-info/COPYING.txt ADDED
@@ -0,0 +1,19 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ The original Pyrex code as of 2006-04 is licensed under the following
2
+ license: "Copyright stuff: Pyrex is free of restrictions. You may use,
3
+ redistribute, modify and distribute modified versions."
4
+
5
+ ------------------
6
+
7
+ Cython, which derives from Pyrex, is licensed under the Apache 2.0
8
+ Software License. More precisely, all modifications and new code
9
+ made to go from Pyrex to Cython are so licensed.
10
+
11
+ See LICENSE.txt for more details.
12
+
13
+ ------------------
14
+
15
+ The output of a Cython compilation is NOT considered a derivative
16
+ work of Cython. Specifically, though the compilation process may
17
+ embed snippets of varying lengths into the final output, these
18
+ snippets, as embedded in the output, do not encumber the resulting
19
+ output with any license restrictions.
venv/Lib/site-packages/Cython-0.29.36.dist-info/INSTALLER ADDED
@@ -0,0 +1 @@
 
 
1
+ pip
venv/Lib/site-packages/Cython-0.29.36.dist-info/LICENSE.txt ADDED
@@ -0,0 +1,176 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ Apache License
2
+ Version 2.0, January 2004
3
+ http://www.apache.org/licenses/
4
+
5
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
6
+
7
+ 1. Definitions.
8
+
9
+ "License" shall mean the terms and conditions for use, reproduction,
10
+ and distribution as defined by Sections 1 through 9 of this document.
11
+
12
+ "Licensor" shall mean the copyright owner or entity authorized by
13
+ the copyright owner that is granting the License.
14
+
15
+ "Legal Entity" shall mean the union of the acting entity and all
16
+ other entities that control, are controlled by, or are under common
17
+ control with that entity. For the purposes of this definition,
18
+ "control" means (i) the power, direct or indirect, to cause the
19
+ direction or management of such entity, whether by contract or
20
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
21
+ outstanding shares, or (iii) beneficial ownership of such entity.
22
+
23
+ "You" (or "Your") shall mean an individual or Legal Entity
24
+ exercising permissions granted by this License.
25
+
26
+ "Source" form shall mean the preferred form for making modifications,
27
+ including but not limited to software source code, documentation
28
+ source, and configuration files.
29
+
30
+ "Object" form shall mean any form resulting from mechanical
31
+ transformation or translation of a Source form, including but
32
+ not limited to compiled object code, generated documentation,
33
+ and conversions to other media types.
34
+
35
+ "Work" shall mean the work of authorship, whether in Source or
36
+ Object form, made available under the License, as indicated by a
37
+ copyright notice that is included in or attached to the work
38
+ (an example is provided in the Appendix below).
39
+
40
+ "Derivative Works" shall mean any work, whether in Source or Object
41
+ form, that is based on (or derived from) the Work and for which the
42
+ editorial revisions, annotations, elaborations, or other modifications
43
+ represent, as a whole, an original work of authorship. For the purposes
44
+ of this License, Derivative Works shall not include works that remain
45
+ separable from, or merely link (or bind by name) to the interfaces of,
46
+ the Work and Derivative Works thereof.
47
+
48
+ "Contribution" shall mean any work of authorship, including
49
+ the original version of the Work and any modifications or additions
50
+ to that Work or Derivative Works thereof, that is intentionally
51
+ submitted to Licensor for inclusion in the Work by the copyright owner
52
+ or by an individual or Legal Entity authorized to submit on behalf of
53
+ the copyright owner. For the purposes of this definition, "submitted"
54
+ means any form of electronic, verbal, or written communication sent
55
+ to the Licensor or its representatives, including but not limited to
56
+ communication on electronic mailing lists, source code control systems,
57
+ and issue tracking systems that are managed by, or on behalf of, the
58
+ Licensor for the purpose of discussing and improving the Work, but
59
+ excluding communication that is conspicuously marked or otherwise
60
+ designated in writing by the copyright owner as "Not a Contribution."
61
+
62
+ "Contributor" shall mean Licensor and any individual or Legal Entity
63
+ on behalf of whom a Contribution has been received by Licensor and
64
+ subsequently incorporated within the Work.
65
+
66
+ 2. Grant of Copyright License. Subject to the terms and conditions of
67
+ this License, each Contributor hereby grants to You a perpetual,
68
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
69
+ copyright license to reproduce, prepare Derivative Works of,
70
+ publicly display, publicly perform, sublicense, and distribute the
71
+ Work and such Derivative Works in Source or Object form.
72
+
73
+ 3. Grant of Patent License. Subject to the terms and conditions of
74
+ this License, each Contributor hereby grants to You a perpetual,
75
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
76
+ (except as stated in this section) patent license to make, have made,
77
+ use, offer to sell, sell, import, and otherwise transfer the Work,
78
+ where such license applies only to those patent claims licensable
79
+ by such Contributor that are necessarily infringed by their
80
+ Contribution(s) alone or by combination of their Contribution(s)
81
+ with the Work to which such Contribution(s) was submitted. If You
82
+ institute patent litigation against any entity (including a
83
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
84
+ or a Contribution incorporated within the Work constitutes direct
85
+ or contributory patent infringement, then any patent licenses
86
+ granted to You under this License for that Work shall terminate
87
+ as of the date such litigation is filed.
88
+
89
+ 4. Redistribution. You may reproduce and distribute copies of the
90
+ Work or Derivative Works thereof in any medium, with or without
91
+ modifications, and in Source or Object form, provided that You
92
+ meet the following conditions:
93
+
94
+ (a) You must give any other recipients of the Work or
95
+ Derivative Works a copy of this License; and
96
+
97
+ (b) You must cause any modified files to carry prominent notices
98
+ stating that You changed the files; and
99
+
100
+ (c) You must retain, in the Source form of any Derivative Works
101
+ that You distribute, all copyright, patent, trademark, and
102
+ attribution notices from the Source form of the Work,
103
+ excluding those notices that do not pertain to any part of
104
+ the Derivative Works; and
105
+
106
+ (d) If the Work includes a "NOTICE" text file as part of its
107
+ distribution, then any Derivative Works that You distribute must
108
+ include a readable copy of the attribution notices contained
109
+ within such NOTICE file, excluding those notices that do not
110
+ pertain to any part of the Derivative Works, in at least one
111
+ of the following places: within a NOTICE text file distributed
112
+ as part of the Derivative Works; within the Source form or
113
+ documentation, if provided along with the Derivative Works; or,
114
+ within a display generated by the Derivative Works, if and
115
+ wherever such third-party notices normally appear. The contents
116
+ of the NOTICE file are for informational purposes only and
117
+ do not modify the License. You may add Your own attribution
118
+ notices within Derivative Works that You distribute, alongside
119
+ or as an addendum to the NOTICE text from the Work, provided
120
+ that such additional attribution notices cannot be construed
121
+ as modifying the License.
122
+
123
+ You may add Your own copyright statement to Your modifications and
124
+ may provide additional or different license terms and conditions
125
+ for use, reproduction, or distribution of Your modifications, or
126
+ for any such Derivative Works as a whole, provided Your use,
127
+ reproduction, and distribution of the Work otherwise complies with
128
+ the conditions stated in this License.
129
+
130
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
131
+ any Contribution intentionally submitted for inclusion in the Work
132
+ by You to the Licensor shall be under the terms and conditions of
133
+ this License, without any additional terms or conditions.
134
+ Notwithstanding the above, nothing herein shall supersede or modify
135
+ the terms of any separate license agreement you may have executed
136
+ with Licensor regarding such Contributions.
137
+
138
+ 6. Trademarks. This License does not grant permission to use the trade
139
+ names, trademarks, service marks, or product names of the Licensor,
140
+ except as required for reasonable and customary use in describing the
141
+ origin of the Work and reproducing the content of the NOTICE file.
142
+
143
+ 7. Disclaimer of Warranty. Unless required by applicable law or
144
+ agreed to in writing, Licensor provides the Work (and each
145
+ Contributor provides its Contributions) on an "AS IS" BASIS,
146
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
147
+ implied, including, without limitation, any warranties or conditions
148
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
149
+ PARTICULAR PURPOSE. You are solely responsible for determining the
150
+ appropriateness of using or redistributing the Work and assume any
151
+ risks associated with Your exercise of permissions under this License.
152
+
153
+ 8. Limitation of Liability. In no event and under no legal theory,
154
+ whether in tort (including negligence), contract, or otherwise,
155
+ unless required by applicable law (such as deliberate and grossly
156
+ negligent acts) or agreed to in writing, shall any Contributor be
157
+ liable to You for damages, including any direct, indirect, special,
158
+ incidental, or consequential damages of any character arising as a
159
+ result of this License or out of the use or inability to use the
160
+ Work (including but not limited to damages for loss of goodwill,
161
+ work stoppage, computer failure or malfunction, or any and all
162
+ other commercial damages or losses), even if such Contributor
163
+ has been advised of the possibility of such damages.
164
+
165
+ 9. Accepting Warranty or Additional Liability. While redistributing
166
+ the Work or Derivative Works thereof, You may choose to offer,
167
+ and charge a fee for, acceptance of support, warranty, indemnity,
168
+ or other liability obligations and/or rights consistent with this
169
+ License. However, in accepting such obligations, You may act only
170
+ on Your own behalf and on Your sole responsibility, not on behalf
171
+ of any other Contributor, and only if You agree to indemnify,
172
+ defend, and hold each Contributor harmless for any liability
173
+ incurred by, or claims asserted against, such Contributor by reason
174
+ of your accepting any such warranty or additional liability.
175
+
176
+ END OF TERMS AND CONDITIONS
venv/Lib/site-packages/Cython-0.29.36.dist-info/METADATA ADDED
@@ -0,0 +1,63 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ Metadata-Version: 2.1
2
+ Name: Cython
3
+ Version: 0.29.36
4
+ Summary: The Cython compiler for writing C extensions for the Python language.
5
+ Home-page: http://cython.org/
6
+ Author: Robert Bradshaw, Stefan Behnel, Dag Seljebotn, Greg Ewing, et al.
7
+ Author-email: cython-devel@python.org
8
+ License: Apache
9
+ Project-URL: Documentation, https://cython.readthedocs.io/
10
+ Project-URL: Donate, https://cython.readthedocs.io/en/latest/src/donating.html
11
+ Project-URL: Source Code, https://github.com/cython/cython
12
+ Project-URL: Bug Tracker, https://github.com/cython/cython/issues
13
+ Project-URL: User Group, https://groups.google.com/g/cython-users
14
+ Classifier: Development Status :: 5 - Production/Stable
15
+ Classifier: Intended Audience :: Developers
16
+ Classifier: License :: OSI Approved :: Apache Software License
17
+ Classifier: Operating System :: OS Independent
18
+ Classifier: Programming Language :: Python
19
+ Classifier: Programming Language :: Python :: 2
20
+ Classifier: Programming Language :: Python :: 2.6
21
+ Classifier: Programming Language :: Python :: 2.7
22
+ Classifier: Programming Language :: Python :: 3
23
+ Classifier: Programming Language :: Python :: 3.4
24
+ Classifier: Programming Language :: Python :: 3.5
25
+ Classifier: Programming Language :: Python :: 3.6
26
+ Classifier: Programming Language :: Python :: 3.7
27
+ Classifier: Programming Language :: Python :: 3.8
28
+ Classifier: Programming Language :: Python :: 3.9
29
+ Classifier: Programming Language :: Python :: 3.10
30
+ Classifier: Programming Language :: Python :: 3.11
31
+ Classifier: Programming Language :: Python :: Implementation :: CPython
32
+ Classifier: Programming Language :: Python :: Implementation :: PyPy
33
+ Classifier: Programming Language :: C
34
+ Classifier: Programming Language :: Cython
35
+ Classifier: Topic :: Software Development :: Code Generators
36
+ Classifier: Topic :: Software Development :: Compilers
37
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
38
+ Requires-Python: >=2.6, !=3.0.*, !=3.1.*, !=3.2.*
39
+ License-File: LICENSE.txt
40
+ License-File: COPYING.txt
41
+
42
+ The Cython language makes writing C extensions for the Python language as
43
+ easy as Python itself. Cython is a source code translator based on Pyrex_,
44
+ but supports more cutting edge functionality and optimizations.
45
+
46
+ The Cython language is a superset of the Python language (almost all Python
47
+ code is also valid Cython code), but Cython additionally supports optional
48
+ static typing to natively call C functions, operate with C++ classes and
49
+ declare fast C types on variables and class attributes. This allows the
50
+ compiler to generate very efficient C code from Cython code.
51
+
52
+ This makes Cython the ideal language for writing glue code for external
53
+ C/C++ libraries, and for fast C modules that speed up the execution of
54
+ Python code.
55
+
56
+ Note that for one-time builds, e.g. for CI/testing, on platforms that are not
57
+ covered by one of the wheel packages provided on PyPI *and* the pure Python wheel
58
+ that we provide is not used, it is substantially faster than a full source build
59
+ to install an uncompiled (slower) version of Cython with::
60
+
61
+ pip install Cython --install-option="--no-cython-compile"
62
+
63
+ .. _Pyrex: http://www.cosc.canterbury.ac.nz/greg.ewing/python/Pyrex/
venv/Lib/site-packages/Cython-0.29.36.dist-info/RECORD ADDED
@@ -0,0 +1,424 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ../../Scripts/cygdb.exe,sha256=TtvCgNdaCjR_8FEK2YfdTeMPizjaD1vpyRpzxOrYbSE,108425
2
+ ../../Scripts/cython.exe,sha256=hCVmdOApuN8hjUnpq3A1GpBqfr0CBtc9yymfhU9fPj0,108446
3
+ ../../Scripts/cythonize.exe,sha256=Y9377oZV9hSTY7x5874VV5x53dk4tq00d3TIhqFebZE,108426
4
+ Cython-0.29.36.dist-info/COPYING.txt,sha256=4escSahQjoFz2sMBV-SmQ5pErYhGGUdGxCT7w_wrldc,756
5
+ Cython-0.29.36.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4
6
+ Cython-0.29.36.dist-info/LICENSE.txt,sha256=psuoW8kuDP96RQsdhzwOqi6fyWv0ct8CR6Jr7He_P_k,10173
7
+ Cython-0.29.36.dist-info/METADATA,sha256=8M6LQI2NwyfVWTbrHtzm632MI8Q3CDEvvCz0dg-6abg,3147
8
+ Cython-0.29.36.dist-info/RECORD,,
9
+ Cython-0.29.36.dist-info/WHEEL,sha256=a-zpFRIJzOq5QfuhBzbhiA1eHTzNCJn8OdRvhdNX0Rk,110
10
+ Cython-0.29.36.dist-info/entry_points.txt,sha256=VU8NX8gnQyFbyqiWMzfh9BHvYMuoQRS3Nbm3kKcKQeY,139
11
+ Cython-0.29.36.dist-info/top_level.txt,sha256=jLV8tZV98iCbIfiJR4DVzTX5Ru1Y_pYMZ59wkMCe6SY,24
12
+ Cython/Build/BuildExecutable.py,sha256=9wjcOncQpbCT_Pu2Ljj5jufFLSY6T_oHOFt0uXYTdRk,4318
13
+ Cython/Build/Cythonize.py,sha256=OBSutgd93PXiRi5_6GRuhpfMZehw9YOfRgt1mxi6QLk,8359
14
+ Cython/Build/Dependencies.py,sha256=Ggsf_mtY-OjoOj1mVJtBkjUfjoTeUMAF9EkhTWgI_h0,49734
15
+ Cython/Build/Distutils.py,sha256=iO5tPX84Kc-ZWMocfuQbl_PqyC9HGGIRS-NiKI60-ZE,49
16
+ Cython/Build/Inline.py,sha256=3dSsczyUHASl8jzA9EOqVxLs92RumvcZfM8AlKFOtu4,13470
17
+ Cython/Build/IpythonMagic.py,sha256=0jwYS3BhztddJMDMMsxs8-fcL7U5EOaMXJJw6fnlKrc,21121
18
+ Cython/Build/Tests/TestCyCache.py,sha256=olOvphv4q1CLsNzMAhgmXnL77zhGGQKuKbYs_iSFFvA,4151
19
+ Cython/Build/Tests/TestInline.py,sha256=bp4XGXZYSyxY2zXI0q4bg58a0ARsclUzXSfWykn0dZw,2854
20
+ Cython/Build/Tests/TestIpythonMagic.py,sha256=H88J6_r3dP5V3-N7eSKZuE2l9G8BtkFF_o8wY7pifKU,6225
21
+ Cython/Build/Tests/TestStripLiterals.py,sha256=-QeUd22OnoL50rW2EgpfIA01UzRMutcBA5NrhkHiE7M,1550
22
+ Cython/Build/Tests/__init__.py,sha256=jOqtmPLCvMCq0xVMwGekuLpBmVgq0xtPFmUePySdOjs,13
23
+ Cython/Build/Tests/__pycache__/TestCyCache.cpython-311.pyc,,
24
+ Cython/Build/Tests/__pycache__/TestInline.cpython-311.pyc,,
25
+ Cython/Build/Tests/__pycache__/TestIpythonMagic.cpython-311.pyc,,
26
+ Cython/Build/Tests/__pycache__/TestStripLiterals.cpython-311.pyc,,
27
+ Cython/Build/Tests/__pycache__/__init__.cpython-311.pyc,,
28
+ Cython/Build/__init__.py,sha256=zBhW6hT9Mwk1ZybfuPi61iCa6A4srId1HJz9OiEd07o,69
29
+ Cython/Build/__pycache__/BuildExecutable.cpython-311.pyc,,
30
+ Cython/Build/__pycache__/Cythonize.cpython-311.pyc,,
31
+ Cython/Build/__pycache__/Dependencies.cpython-311.pyc,,
32
+ Cython/Build/__pycache__/Distutils.cpython-311.pyc,,
33
+ Cython/Build/__pycache__/Inline.cpython-311.pyc,,
34
+ Cython/Build/__pycache__/IpythonMagic.cpython-311.pyc,,
35
+ Cython/Build/__pycache__/__init__.cpython-311.pyc,,
36
+ Cython/CodeWriter.py,sha256=tNFcGTXXs7V90ukOORIZxyj1-1BW3bgmgV0gEBExcRM,23998
37
+ Cython/Compiler/AnalysedTreeTransforms.py,sha256=T2r1SLFeG7a4D9tt93hm8YRH_aGLwmK82PNpb1RsbnE,3826
38
+ Cython/Compiler/Annotate.py,sha256=bkVgdH3ItuIbaSpi9Qo5bKiIjOX3-J5sZORfcyk_eZY,12950
39
+ Cython/Compiler/AutoDocTransforms.py,sha256=le7k-xhGWDkvpRXRppZsqhJzkav6i41GmAOmDetxVmk,7517
40
+ Cython/Compiler/Buffer.py,sha256=6-YIUiLWtgpC2LRhs7116umzNiEbzA6cz1lnPkSEn30,29035
41
+ Cython/Compiler/Builtin.py,sha256=3ynoOxUd6AE8XOuEDWwcl7lnNZirdYYXgMQI_WD7XPM,22571
42
+ Cython/Compiler/CmdLine.py,sha256=mZIKTOwjX_K5lWdjHufuhqBHaeEaYpQVIzNiYx5VWKE,10819
43
+ Cython/Compiler/Code.pxd,sha256=XEZU44jXCOFoYTG15-R0X41krTrjpuo1wxRKjyzYwoY,3354
44
+ Cython/Compiler/Code.py,sha256=VqhIddTqD7JpJfGZnFR16CFq9KkaY48QFdu51omzjuo,97241
45
+ Cython/Compiler/CodeGeneration.py,sha256=jkcx2uX07nck0UZSgysIThRuJiPbdkSeXR4Z2uzbQU8,1108
46
+ Cython/Compiler/CythonScope.py,sha256=mNwmE509uePmR3S2djg3Dq6zOZ3hgK-U8NDeawys9WM,6027
47
+ Cython/Compiler/DebugFlags.py,sha256=5Zg9ETp0qPFEma6QMtrGUwu9Fn6NTYMBMWPI_GxFW0A,623
48
+ Cython/Compiler/Errors.py,sha256=GATz9x6onls09cM6TeDw3kdBgdCxUiKJBILwukBF6WI,7554
49
+ Cython/Compiler/ExprNodes.py,sha256=ZzkQzNrqSXdvpisV_BSqAXze3Z8-OjZQ76J8BS9knPQ,550360
50
+ Cython/Compiler/FlowControl.pxd,sha256=W8bqGCJLzvAhnL3d1OF8798ZDJg0QI0eA_ebnA4dkoQ,2918
51
+ Cython/Compiler/FlowControl.py,sha256=-I33Yd9sp1RCENjFkrufBM8Xrj3y5SI7KZ04Vz5Djiw,45981
52
+ Cython/Compiler/FusedNode.py,sha256=qmHVHylEPpllK_x-471xBG-zMzAt0RF52tLxt_-RZqs,37794
53
+ Cython/Compiler/Future.py,sha256=GwcWZ_Vti0atfbOARfS2kIvZOvRuPu38wbShIn4o4kA,587
54
+ Cython/Compiler/Interpreter.py,sha256=iNweexX2HDI5nZj2rzkW-lw9Rq3gzM__P7SBqH3uxbU,2106
55
+ Cython/Compiler/Lexicon.py,sha256=Cw_wIfQymcTEdkoo82V2xbV8kvCp30O-Pc7qF4hbfCI,4855
56
+ Cython/Compiler/Main.py,sha256=69AfwvXrHWoDo0MwWuEmeKIb_tH0ZgaKfnin0UvpvR0,37098
57
+ Cython/Compiler/MemoryView.py,sha256=c6J7PtQ6wccb9uBxvbLngia4jO-h2uea7viIzJNhDYU,30009
58
+ Cython/Compiler/ModuleNode.py,sha256=QttRKICtGBd8p_KS3WYk7jrlSxeCyKfuWpvIsj1s1sA,142306
59
+ Cython/Compiler/Naming.py,sha256=MpFzZ87EkODg_9SGj3pL8Y9WvvQwWgpc2Hg0vrlJg4k,6402
60
+ Cython/Compiler/Nodes.py,sha256=00MIN2ChPQt_eUJPkiOww0urLSVnT2LsKHYYpeMVS6Y,392028
61
+ Cython/Compiler/Optimize.py,sha256=MJ5w9bXi6qU-yvDaiiZdBMSnp8g-QhEhBhs1zpWVICQ,210296
62
+ Cython/Compiler/Options.py,sha256=MPnBwPqSHWTM1tf5c0VSI9RdSSFTmg4M4zlIbCIk_Zw,19742
63
+ Cython/Compiler/ParseTreeTransforms.pxd,sha256=oDSda3XYP79o8tCAxEm_epWWVPXSaPy8lYrprWYRyNk,2468
64
+ Cython/Compiler/ParseTreeTransforms.py,sha256=oLSgT3GwVZQ3wLE1mr0B5x-cJDyG-MpKLyPsYAbKnag,139345
65
+ Cython/Compiler/Parsing.pxd,sha256=pL_EQdVWaw7EZVTZrxzMcUvoSJeAoXXPRh8kCLudysk,8984
66
+ Cython/Compiler/Parsing.py,sha256=2xdvmTh6xjgX-TfbcsyvfsqBTegVwPzbgskVwNpWMAQ,130570
67
+ Cython/Compiler/Pipeline.py,sha256=6ravd0QCR5sCoKlz9HEz209A2UqgLp4Qp0VysoKa_mI,14061
68
+ Cython/Compiler/PyrexTypes.py,sha256=i46nr1fJazgCE47WDC5OFo1YEAdy9fZjOU3STi5mFnc,173999
69
+ Cython/Compiler/Pythran.py,sha256=NHIml0yx0jPLyTLRAHXZr0LHTyEyfYqspgYuV4vdNKI,7267
70
+ Cython/Compiler/Scanning.pxd,sha256=vjjPLZb5udPzMpk67DKojTTDUl31QU86oXyAMks7Hsw,2113
71
+ Cython/Compiler/Scanning.py,sha256=Gl7sU5rI-5H5v8z9QLZBh1hivS2cOGa9H878QdEpUU4,18438
72
+ Cython/Compiler/StringEncoding.py,sha256=dn3jVSL4JScbeYf1f56j5RJR9M58AnCDdJObC-cc3fg,10812
73
+ Cython/Compiler/Symtab.py,sha256=n0tdTnbPkSuU5EgPkr6nGBN98Lhbklbjt8o6NUFt264,111727
74
+ Cython/Compiler/Tests/TestBuffer.py,sha256=yw-KUu2pu4CnsqYaqxj5rpyYodmjJSEqUvQNxLwPL8I,4155
75
+ Cython/Compiler/Tests/TestCmdLine.py,sha256=mT673jQ9MekvTExZdnQLztNabCsAMRSuN__egQ7rZ9A,6658
76
+ Cython/Compiler/Tests/TestFlowControl.py,sha256=ge3iqBor6xe5MLaLbOtw7ETntJnAh8EequF1aetVzMw,1848
77
+ Cython/Compiler/Tests/TestGrammar.py,sha256=zWMvYG19nIH85Le8ragXt2vLBlWlGGNeMgrTdQO5JGM,3443
78
+ Cython/Compiler/Tests/TestMemView.py,sha256=yBAQ5tN8DVPTFRJ81dAzOepCt5Ly6fiaAssQve5ryy4,2515
79
+ Cython/Compiler/Tests/TestParseTreeTransforms.py,sha256=xiRKOWqHIMIT1bbYB1o5TefKJXC8oPpjt79tQFodMRc,8900
80
+ Cython/Compiler/Tests/TestSignatureMatching.py,sha256=qMiQZeg5_Eu8VfCY_lMawqpjpKNV0r6p6-9czKec1aY,3338
81
+ Cython/Compiler/Tests/TestStringEncoding.py,sha256=RL1YDXrOUe1sPLEbWmTJQ5VF-uEZ_KLz0jaeQoMx85k,2315
82
+ Cython/Compiler/Tests/TestTreeFragment.py,sha256=wHlnF0ApwxeITx9pzg46P9N_2lM-7mrPwhDeNlIQnXM,2206
83
+ Cython/Compiler/Tests/TestTreePath.py,sha256=x-2KBIhSE6-vT-2BPe2q-zaa1oHtc42ibKzVs_y8_So,4238
84
+ Cython/Compiler/Tests/TestTypes.py,sha256=YuFib5WCJfSPafrhy5yrCUdwajYw61yGPo4HveTyzUs,669
85
+ Cython/Compiler/Tests/TestUtilityLoad.py,sha256=Uzf4_bOjha-zwQaikNbsAOVQs3ZPX3YD7QQ5T4s66YY,3341
86
+ Cython/Compiler/Tests/TestVisitor.py,sha256=QAnBpUhnirSFKqXWiawo-OhXhxIRTQidWxEzGjJDz6M,2228
87
+ Cython/Compiler/Tests/__init__.py,sha256=jOqtmPLCvMCq0xVMwGekuLpBmVgq0xtPFmUePySdOjs,13
88
+ Cython/Compiler/Tests/__pycache__/TestBuffer.cpython-311.pyc,,
89
+ Cython/Compiler/Tests/__pycache__/TestCmdLine.cpython-311.pyc,,
90
+ Cython/Compiler/Tests/__pycache__/TestFlowControl.cpython-311.pyc,,
91
+ Cython/Compiler/Tests/__pycache__/TestGrammar.cpython-311.pyc,,
92
+ Cython/Compiler/Tests/__pycache__/TestMemView.cpython-311.pyc,,
93
+ Cython/Compiler/Tests/__pycache__/TestParseTreeTransforms.cpython-311.pyc,,
94
+ Cython/Compiler/Tests/__pycache__/TestSignatureMatching.cpython-311.pyc,,
95
+ Cython/Compiler/Tests/__pycache__/TestStringEncoding.cpython-311.pyc,,
96
+ Cython/Compiler/Tests/__pycache__/TestTreeFragment.cpython-311.pyc,,
97
+ Cython/Compiler/Tests/__pycache__/TestTreePath.cpython-311.pyc,,
98
+ Cython/Compiler/Tests/__pycache__/TestTypes.cpython-311.pyc,,
99
+ Cython/Compiler/Tests/__pycache__/TestUtilityLoad.cpython-311.pyc,,
100
+ Cython/Compiler/Tests/__pycache__/TestVisitor.cpython-311.pyc,,
101
+ Cython/Compiler/Tests/__pycache__/__init__.cpython-311.pyc,,
102
+ Cython/Compiler/TreeFragment.py,sha256=jQn4Lp2dNddJ-tjPquoFcyTcX9EIuTAbZKZAKs9-cGU,9408
103
+ Cython/Compiler/TreePath.py,sha256=3_lScMAd2Sly2ekZ8HO8dyZstGSruINl2MXXq9OYd2Q,7641
104
+ Cython/Compiler/TypeInference.py,sha256=s-GKZcq16KPPgY_OpF8cTlQmX1Cpu-qBMCtmAYDg8fc,22326
105
+ Cython/Compiler/TypeSlots.py,sha256=EEZNyJIQy50yiRcBRpAosN9DnsZ8_AiDJAHCcyU_3co,37868
106
+ Cython/Compiler/UtilNodes.py,sha256=mS6jlZ530p17WGU0ApbwvLecuByT18LFipVrKJg5jrM,11636
107
+ Cython/Compiler/UtilityCode.py,sha256=PbQtJt9fSwgm5xeXgYWQih6eUSmJL_RwTxOa5T9SrZU,9391
108
+ Cython/Compiler/Version.py,sha256=f2mS6aYYdu0DMRK3B4IuzMlCo-k-ffmehCao_vKlTdk,181
109
+ Cython/Compiler/Visitor.pxd,sha256=KvOZgHoEREMTVYXr1ZoAk9H4n__rpmhIwE2S11ajeYM,1792
110
+ Cython/Compiler/Visitor.py,sha256=iqtIsNaQwk8lSa6g_LnEU06CZtdnP7MDXbyodl4Ouwk,29984
111
+ Cython/Compiler/__init__.py,sha256=jOqtmPLCvMCq0xVMwGekuLpBmVgq0xtPFmUePySdOjs,13
112
+ Cython/Compiler/__pycache__/AnalysedTreeTransforms.cpython-311.pyc,,
113
+ Cython/Compiler/__pycache__/Annotate.cpython-311.pyc,,
114
+ Cython/Compiler/__pycache__/AutoDocTransforms.cpython-311.pyc,,
115
+ Cython/Compiler/__pycache__/Buffer.cpython-311.pyc,,
116
+ Cython/Compiler/__pycache__/Builtin.cpython-311.pyc,,
117
+ Cython/Compiler/__pycache__/CmdLine.cpython-311.pyc,,
118
+ Cython/Compiler/__pycache__/Code.cpython-311.pyc,,
119
+ Cython/Compiler/__pycache__/CodeGeneration.cpython-311.pyc,,
120
+ Cython/Compiler/__pycache__/CythonScope.cpython-311.pyc,,
121
+ Cython/Compiler/__pycache__/DebugFlags.cpython-311.pyc,,
122
+ Cython/Compiler/__pycache__/Errors.cpython-311.pyc,,
123
+ Cython/Compiler/__pycache__/ExprNodes.cpython-311.pyc,,
124
+ Cython/Compiler/__pycache__/FlowControl.cpython-311.pyc,,
125
+ Cython/Compiler/__pycache__/FusedNode.cpython-311.pyc,,
126
+ Cython/Compiler/__pycache__/Future.cpython-311.pyc,,
127
+ Cython/Compiler/__pycache__/Interpreter.cpython-311.pyc,,
128
+ Cython/Compiler/__pycache__/Lexicon.cpython-311.pyc,,
129
+ Cython/Compiler/__pycache__/Main.cpython-311.pyc,,
130
+ Cython/Compiler/__pycache__/MemoryView.cpython-311.pyc,,
131
+ Cython/Compiler/__pycache__/ModuleNode.cpython-311.pyc,,
132
+ Cython/Compiler/__pycache__/Naming.cpython-311.pyc,,
133
+ Cython/Compiler/__pycache__/Nodes.cpython-311.pyc,,
134
+ Cython/Compiler/__pycache__/Optimize.cpython-311.pyc,,
135
+ Cython/Compiler/__pycache__/Options.cpython-311.pyc,,
136
+ Cython/Compiler/__pycache__/ParseTreeTransforms.cpython-311.pyc,,
137
+ Cython/Compiler/__pycache__/Parsing.cpython-311.pyc,,
138
+ Cython/Compiler/__pycache__/Pipeline.cpython-311.pyc,,
139
+ Cython/Compiler/__pycache__/PyrexTypes.cpython-311.pyc,,
140
+ Cython/Compiler/__pycache__/Pythran.cpython-311.pyc,,
141
+ Cython/Compiler/__pycache__/Scanning.cpython-311.pyc,,
142
+ Cython/Compiler/__pycache__/StringEncoding.cpython-311.pyc,,
143
+ Cython/Compiler/__pycache__/Symtab.cpython-311.pyc,,
144
+ Cython/Compiler/__pycache__/TreeFragment.cpython-311.pyc,,
145
+ Cython/Compiler/__pycache__/TreePath.cpython-311.pyc,,
146
+ Cython/Compiler/__pycache__/TypeInference.cpython-311.pyc,,
147
+ Cython/Compiler/__pycache__/TypeSlots.cpython-311.pyc,,
148
+ Cython/Compiler/__pycache__/UtilNodes.cpython-311.pyc,,
149
+ Cython/Compiler/__pycache__/UtilityCode.cpython-311.pyc,,
150
+ Cython/Compiler/__pycache__/Version.cpython-311.pyc,,
151
+ Cython/Compiler/__pycache__/Visitor.cpython-311.pyc,,
152
+ Cython/Compiler/__pycache__/__init__.cpython-311.pyc,,
153
+ Cython/Coverage.py,sha256=FtCMjKLYWvtULxWIzN-y3RhbwQwL4GtLyIjj-B3-07E,13537
154
+ Cython/Debugger/Cygdb.py,sha256=CH_pXm0Jhl4SAe6sJXa5NS47vMmQ2KBbecyV56vLqFE,5751
155
+ Cython/Debugger/DebugWriter.py,sha256=Yzz28JR4qZepxvxeu_1rJxIjJ4JbNQm5vM5e_UtNuRo,1945
156
+ Cython/Debugger/Tests/TestLibCython.py,sha256=xrENLEahnp6WtOfokVtsALR6Ot2jFR6T5ZZRcaX0Vxk,8327
157
+ Cython/Debugger/Tests/__init__.py,sha256=jOqtmPLCvMCq0xVMwGekuLpBmVgq0xtPFmUePySdOjs,13
158
+ Cython/Debugger/Tests/__pycache__/TestLibCython.cpython-311.pyc,,
159
+ Cython/Debugger/Tests/__pycache__/__init__.cpython-311.pyc,,
160
+ Cython/Debugger/Tests/__pycache__/test_libcython_in_gdb.cpython-311.pyc,,
161
+ Cython/Debugger/Tests/__pycache__/test_libpython_in_gdb.cpython-311.pyc,,
162
+ Cython/Debugger/Tests/cfuncs.c,sha256=4SZurmnz5J1SiIs9N26Eu4zc2wvF_qMEKaN0eTcbDPo,71
163
+ Cython/Debugger/Tests/codefile,sha256=ugwpT9GPtYZIKe2Xco4PqikyA-poQAeYfE0icXmfb44,641
164
+ Cython/Debugger/Tests/test_libcython_in_gdb.py,sha256=EvPTYkd7nzR3JtFim-ASLI6wfcYhgWfI4BQrucLJbHY,15804
165
+ Cython/Debugger/Tests/test_libpython_in_gdb.py,sha256=1BD_FtMkmS4SoSQZq7MgAgDnvqIw3EcYZFVrtoCQmxo,4079
166
+ Cython/Debugger/__init__.py,sha256=jOqtmPLCvMCq0xVMwGekuLpBmVgq0xtPFmUePySdOjs,13
167
+ Cython/Debugger/__pycache__/Cygdb.cpython-311.pyc,,
168
+ Cython/Debugger/__pycache__/DebugWriter.cpython-311.pyc,,
169
+ Cython/Debugger/__pycache__/__init__.cpython-311.pyc,,
170
+ Cython/Debugger/__pycache__/libcython.cpython-311.pyc,,
171
+ Cython/Debugger/__pycache__/libpython.cpython-311.pyc,,
172
+ Cython/Debugger/libcython.py,sha256=Qs0qGzeUyeY___3jRDy_WWIDFGfSRH4al7On2XxkuNg,44949
173
+ Cython/Debugger/libpython.py,sha256=IyTEdtGLnpQmt2XPgZ7oskQ8qGWWV2_5TMgZ5NhTA0k,90489
174
+ Cython/Debugging.py,sha256=vFtJhn7QstMf5gnYru2qHIz5ZjPg1KSlZVGHr-pBCwM,552
175
+ Cython/Distutils/__init__.py,sha256=uyWaN2NJ_mKYLzVsDPi0qZCdIYoW5M_7YYEmAOIL3Ek,98
176
+ Cython/Distutils/__pycache__/__init__.cpython-311.pyc,,
177
+ Cython/Distutils/__pycache__/build_ext.cpython-311.pyc,,
178
+ Cython/Distutils/__pycache__/extension.cpython-311.pyc,,
179
+ Cython/Distutils/__pycache__/old_build_ext.cpython-311.pyc,,
180
+ Cython/Distutils/build_ext.py,sha256=Fc_cI5wN0fT1Mf2k5B5nH-PgZ8Gq2lL6OlzF_qzy3dA,1007
181
+ Cython/Distutils/extension.py,sha256=FHvtK3Tj9MqE17TuZ_jWg1Mh4X7e-CXIPUpJK7nqcQE,4706
182
+ Cython/Distutils/old_build_ext.py,sha256=Hy34A1HqhoDOyU-krN2gJUYXK2mYWc8E2EZB-stvmrE,13635
183
+ Cython/Includes/Deprecated/python.pxd,sha256=l7crg8H9cVRedMcjDf_9xDLdnUT57Vt1BxlZWom-h88,61
184
+ Cython/Includes/Deprecated/python_bool.pxd,sha256=qOaFbsP6_pKoB3HGTjQUkFhQqukXheCmcSnnBQLdKGQ,66
185
+ Cython/Includes/Deprecated/python_buffer.pxd,sha256=gv2a3ngcOnRKZZHSox_bW1WD8jGbxfH9NJm1-iUXf9U,68
186
+ Cython/Includes/Deprecated/python_bytes.pxd,sha256=07-Hk3YpN_i4mIlbWYbNgDkjEytQAYOepJLJTY1CrVk,67
187
+ Cython/Includes/Deprecated/python_cobject.pxd,sha256=V9F0DHQbFZPbJ8RRnN9mft2ipq4wubM8ghBCGHr6NwE,69
188
+ Cython/Includes/Deprecated/python_complex.pxd,sha256=ITmq55v0b1gibEpLSCTCz68ViljenSuGGjiWn_nvIvI,69
189
+ Cython/Includes/Deprecated/python_dict.pxd,sha256=gYhGkJhMmzWcrXoPnJHUcp-vdtcwUACbGlfv3wtGsKU,66
190
+ Cython/Includes/Deprecated/python_exc.pxd,sha256=irWdwDYRWU16-P54uGDNfUSUtkL5Sj_1zBDWext_80g,65
191
+ Cython/Includes/Deprecated/python_float.pxd,sha256=v1Hbpd4SF3hSF7ZL_olMaYJzmBNA9jWn0eO9ggLBlvc,67
192
+ Cython/Includes/Deprecated/python_function.pxd,sha256=lkYKySQy1W36hfyyAJsc3E-8d9bsx5k8OhIMFQ6k2jA,70
193
+ Cython/Includes/Deprecated/python_getargs.pxd,sha256=NEdeqPqu4di0YJm_7yLfvuS903CAe4K2Pzb13TRfBdE,69
194
+ Cython/Includes/Deprecated/python_instance.pxd,sha256=FX9UlYrSxDrzch7wUvh_Y5Ix-bsDYARkXzZJOg2FvEI,70
195
+ Cython/Includes/Deprecated/python_int.pxd,sha256=Cwd4J4KTKjxwEMz1BbCso0g0pOID9AnySKOC1g0kLqA,65
196
+ Cython/Includes/Deprecated/python_iterator.pxd,sha256=nPJ0nKSmnUVzI1SPrTSt9wSD7SQILyhONJdP0H_-FGc,70
197
+ Cython/Includes/Deprecated/python_list.pxd,sha256=VHpylsg46-5Ud8rwlPe63bb3zSToXm9R_fPorZrJsUE,66
198
+ Cython/Includes/Deprecated/python_long.pxd,sha256=pg8hOKNoKaW-Mslugzeq6NCeznJw939LT24AVQn_cqE,66
199
+ Cython/Includes/Deprecated/python_mapping.pxd,sha256=AZtJdYm37glDSNChduAsgavz-_DPDkxxQEAO9lDGy84,69
200
+ Cython/Includes/Deprecated/python_mem.pxd,sha256=Mxidel5P4yuJxJOvoYr0PN1FD78oCOIJUEMPYMYU7lE,65
201
+ Cython/Includes/Deprecated/python_method.pxd,sha256=x5ye5_8KqtsW2HrEon5NdFJmIkmVDV1KeVpFsuC2UZE,68
202
+ Cython/Includes/Deprecated/python_module.pxd,sha256=lKu5VYCgC6S7LSgFa22V2YTY9JfML0vABDZpChhxs60,68
203
+ Cython/Includes/Deprecated/python_number.pxd,sha256=X4MxGoITZuJNPtC2cFJ8lQwui8MOC6rQfEDbFIcWA9k,68
204
+ Cython/Includes/Deprecated/python_object.pxd,sha256=qr2OwYVot4ELK3_-mCfaktXgLJEaKWDyCEblQ2vXV-E,68
205
+ Cython/Includes/Deprecated/python_oldbuffer.pxd,sha256=QyY4Vn5-cFaOt0oZ27GuRXa3tLawgMZN8KMamn9F1yo,71
206
+ Cython/Includes/Deprecated/python_pycapsule.pxd,sha256=tHJfhgm1TrSwJQwQFdhwP7YE7oQFiegxhNhgCDmlB6A,71
207
+ Cython/Includes/Deprecated/python_ref.pxd,sha256=wv39G35V7tN5sIhcL1APpe5NuhCwYwVy6X5DPPm5g5A,65
208
+ Cython/Includes/Deprecated/python_sequence.pxd,sha256=9ycCua1ODfECKPd56_GBmeqzWrfdqmkjhbEmdt87NC0,70
209
+ Cython/Includes/Deprecated/python_set.pxd,sha256=_Z5KVXs0V_T8fpgLX-2LbDAZIY1HnuhO-eTUHHRYwu0,65
210
+ Cython/Includes/Deprecated/python_string.pxd,sha256=6VgAehwW9PcUC9Kp_HbRVMYPeF_Q-L8yr9o2ezuTzys,68
211
+ Cython/Includes/Deprecated/python_tuple.pxd,sha256=_ZTQh7dRBmrRs9mtmOFjP37d0IFItxs20kzFtKtkY-g,67
212
+ Cython/Includes/Deprecated/python_type.pxd,sha256=2OKmEdSqoyK8fXttlHG3NRguZ-ZikUUet-kjKLq-eEU,66
213
+ Cython/Includes/Deprecated/python_unicode.pxd,sha256=TF8-N0un1WdyccTDo9hZVABc53SYzKnC3MEKrGb3vV0,69
214
+ Cython/Includes/Deprecated/python_version.pxd,sha256=ZXrK0UGUt8vHbYPxm7PTdhMe1_h7Yj6Lo74oFxjnNns,69
215
+ Cython/Includes/Deprecated/python_weakref.pxd,sha256=CUWMSmClrWPoTnlClOFCSHa6Xd55qDgIlcDCD6tfEhM,69
216
+ Cython/Includes/Deprecated/stdio.pxd,sha256=lNc2YuvWJ-LNSSdN7adDo1lf-C2M0r10hH4bysha9Sg,64
217
+ Cython/Includes/Deprecated/stdlib.pxd,sha256=PbCbjT8MjDjVRjx5Rod79gi22-9YI35jTulePAKCPXE,65
218
+ Cython/Includes/Deprecated/stl.pxd,sha256=tHpByeYgNiclr3YtCdKKAeEs3CHJflqacC7YgV7YN8k,2187
219
+ Cython/Includes/cpython/__init__.pxd,sha256=8URNRvb7JkYhqDZv2J0bVsdeZBEJBu7u2QFYkDyXPG8,8254
220
+ Cython/Includes/cpython/array.pxd,sha256=g6apBiXJG_7a0mjGqkFaqlcQjsg64uKK1VlXFFyXVCk,6056
221
+ Cython/Includes/cpython/bool.pxd,sha256=FaNn8K-Toq8FAws8BguKMk0IPM7IJm9IiUUGARSrKYk,1359
222
+ Cython/Includes/cpython/buffer.pxd,sha256=wm7aHygGUof_H3-JyICOek_xiU6Oks178ark1Nfk-a0,4870
223
+ Cython/Includes/cpython/bytearray.pxd,sha256=m0VdoHgouF1T0VtRjFLXZ5fi22vaMdVwFWpF3IxB6m4,1443
224
+ Cython/Includes/cpython/bytes.pxd,sha256=tGLuiBMzQjurK_pq77CM7P0C-Hn0KUIDZCXW9QvlJAI,9906
225
+ Cython/Includes/cpython/cellobject.pxd,sha256=DXdTjSN1RP1m4CsaGuggyIA1nGiIO4Kr7-c0ZWfrpRo,1390
226
+ Cython/Includes/cpython/ceval.pxd,sha256=h6fBetZCUvWTcCn3bkXZg2kqnIuyC5ZSChyhOocxVus,236
227
+ Cython/Includes/cpython/cobject.pxd,sha256=ZeMdbpZLqpcTywdv2VoppMTWD4X_yghL6Qox7LVfOyg,1524
228
+ Cython/Includes/cpython/codecs.pxd,sha256=3fyudEljkNGQ7e3dJPst6udXGcAeNKvlMK9U8EB1gXc,5084
229
+ Cython/Includes/cpython/complex.pxd,sha256=-bu0Cq91tS_U5tTra18S0jqt1FgSJTHXJ5J8rk-MOAA,1777
230
+ Cython/Includes/cpython/conversion.pxd,sha256=dbbFuZJF0SscmcaNCUf0tlBQDRdKYf5tH8yzhTU_XYI,1696
231
+ Cython/Includes/cpython/datetime.pxd,sha256=wQqB8i3tMZOTw9qrLdbHJRkxgZqscGEqmq0tIDfkkqw,6776
232
+ Cython/Includes/cpython/dict.pxd,sha256=F-mrlcAfNmTSUkpJed63bp1IaO0cwG56t_DLk7f0xv0,6877
233
+ Cython/Includes/cpython/exc.pxd,sha256=29-bGESwfoMqx1XU3MMggkIr8pz_l0UPruzy6KIzHxg,13606
234
+ Cython/Includes/cpython/float.pxd,sha256=RD1qEAUocXG9qXrRiT8aCSSfGEyTzjTc9HQkv5xg1ZE,1424
235
+ Cython/Includes/cpython/function.pxd,sha256=IoJUprbz8F10DEKh-vSSpY6nWkCHw7SqG9p2f-4gHek,2671
236
+ Cython/Includes/cpython/genobject.pxd,sha256=emC1JPgkuvBbGC0rgeZapKDaXYEj48uWiDC-xF0Mx2I,1052
237
+ Cython/Includes/cpython/getargs.pxd,sha256=268twKzdiAkQMXMsetNiNlNqaqzlKtiBENKbhOHd8x4,775
238
+ Cython/Includes/cpython/instance.pxd,sha256=qCbxPeHKOJbuszDu3UEaI-KLX9lTopuaNCcpoHJ9ngU,985
239
+ Cython/Includes/cpython/int.pxd,sha256=d9a0zUw_M3pRycCESWIjtfXWRvdvFOWxjdOjkcbX2gs,4131
240
+ Cython/Includes/cpython/iterator.pxd,sha256=o52mLHbdm14Kqant2hR2zAdYzqK4fkSWZtBcRmpoP-I,1319
241
+ Cython/Includes/cpython/iterobject.pxd,sha256=5UEZZwG5zyzxoCpknoQuh91zPUV11Uxr6F1taJdTv8k,1036
242
+ Cython/Includes/cpython/list.pxd,sha256=t-xo7ROcewe6-0ztrNjsxMKV2KxD-ILUzemQ2tTuI7E,4084
243
+ Cython/Includes/cpython/long.pxd,sha256=d6jHN1XJj7WL5PPAUK8U93IPyjWtlTmyhrBEVmxmGF8,7051
244
+ Cython/Includes/cpython/longintrepr.pxd,sha256=czvKr3fQdYIwIRu3gojXssT9LFXH-nstM7f_lPt7lE4,480
245
+ Cython/Includes/cpython/mapping.pxd,sha256=OIdvNVUoIpVCSQnkbLceTicSN0D_jRw6wQmbtxtxKuQ,2693
246
+ Cython/Includes/cpython/mem.pxd,sha256=AWVinanXFBZXvU141we2dD8dkOqMJ8W3KAAzpBJqB5g,5386
247
+ Cython/Includes/cpython/memoryview.pxd,sha256=l97J5-hbH3hp9aMbdXp3n73hJFNNsng6uyh40pc8P7I,2504
248
+ Cython/Includes/cpython/method.pxd,sha256=UWXflhIlP4y7B5XDbH9rQ15iADciGW-iqV1-dlw2Wwg,2196
249
+ Cython/Includes/cpython/module.pxd,sha256=Vc0Up7q1Mir38bN293E8RMugxWfuzjLFHM4g2dviPBM,9226
250
+ Cython/Includes/cpython/number.pxd,sha256=tYJ0nn0k_llUx3ilniW9iXd2rKVejA-J5UUiIJ36Kww,11922
251
+ Cython/Includes/cpython/object.pxd,sha256=AK5D-LrDbvisO6wpkh29G6xjA71sBF_KfKUyn0k2hzg,18366
252
+ Cython/Includes/cpython/oldbuffer.pxd,sha256=v0-YZ_Iwwj3ZQdM8VE5NPTQcbBlJdWwJGtNO9DonGgw,2916
253
+ Cython/Includes/cpython/pycapsule.pxd,sha256=-l_Rx3jjHx2Ff5H1xyJKI6HyXEBMDisaD02u0U7_1d0,5701
254
+ Cython/Includes/cpython/pylifecycle.pxd,sha256=LziJZHclGdtsr3yT28fULHNZ_n67bs1DmI9s8YzrBGg,2000
255
+ Cython/Includes/cpython/pystate.pxd,sha256=xgf1BBkv36qvqMaR77zZWYOuonAwe4RfNKE2g91A6fk,3683
256
+ Cython/Includes/cpython/pythread.pxd,sha256=0375TaYmtNCDDkWBh9WY4oJ_jhoTxhu_RR5QiOsXmYg,1946
257
+ Cython/Includes/cpython/ref.pxd,sha256=2AmgyGDhwA4scts0jcBTdGTCG0b2P8-eYAKFJk44x0I,2557
258
+ Cython/Includes/cpython/sequence.pxd,sha256=iTp3C6wOvTdvjLmdj3k9GqQqCGDlQFpzWi07wVQqSS4,6008
259
+ Cython/Includes/cpython/set.pxd,sha256=ewHRPVMbHUGDInZ3NziisCq68LvtmEJ-SXFbzmuJxLc,5383
260
+ Cython/Includes/cpython/slice.pxd,sha256=Rzgn8diAsN7lS2xGTq4VZucV3ziFNra4oz4tKGEAkMo,3111
261
+ Cython/Includes/cpython/string.pxd,sha256=EKjDGFnPcjnkndwGMJqRrszDV390Mc6o7AADChnNCiA,9944
262
+ Cython/Includes/cpython/tuple.pxd,sha256=eOLfH75ftJeYszztGFWWZP7LnyFOgw8GNuE7PQ9hAvs,3206
263
+ Cython/Includes/cpython/type.pxd,sha256=FOypwX0ZYamPc4uO8bejzO-HzgiaSRaXEPsxxxPIneI,1831
264
+ Cython/Includes/cpython/unicode.pxd,sha256=ymXBenUGMeamRMv9bQ8_FbwIeId7Xi7Xjzs0Nhravyw,27009
265
+ Cython/Includes/cpython/version.pxd,sha256=l5KXt04isEv3qbGRJZ8fNlCYGO24HsA2l4EM3RxTEhE,847
266
+ Cython/Includes/cpython/weakref.pxd,sha256=UU9H_ovHG07FFgP_kY2xhGv3yJDr_8iujCZnxH2jnlo,1984
267
+ Cython/Includes/libc/__init__.pxd,sha256=jOqtmPLCvMCq0xVMwGekuLpBmVgq0xtPFmUePySdOjs,13
268
+ Cython/Includes/libc/errno.pxd,sha256=j5hcKx7zinivU2b6SFMy8LZ9sJIQY5XLrp9cQUKv5AQ,2050
269
+ Cython/Includes/libc/float.pxd,sha256=IhvZJljpTG0fZtcIp7EBO2Sqddozxoxwj4RFNVcKLpY,966
270
+ Cython/Includes/libc/limits.pxd,sha256=xHlIyuDIKpjqclvRRYzZIcfd5G1re5QtbmoDMqZR_Ec,621
271
+ Cython/Includes/libc/locale.pxd,sha256=sixG8EJ6wiVb0HIR1LWJ3lXTjTv463GJ9C_40HRovN4,1140
272
+ Cython/Includes/libc/math.pxd,sha256=51YUxSe01R96_rr3sj4n4MLW-eOmQbcwdNn8YthTxqg,2948
273
+ Cython/Includes/libc/setjmp.pxd,sha256=XRh-gSuhvFLl0nRvz5OhSWYe9eqX2attAck3JI7mwa4,297
274
+ Cython/Includes/libc/signal.pxd,sha256=XOScPDA5vzlfEmu4D7DFT1-5Eu3qMpYdUarjt-fqlbw,1170
275
+ Cython/Includes/libc/stddef.pxd,sha256=0rCyoocCfDL-1OQo3pxHQ-6fW20SAYktOLPoa4d97w8,164
276
+ Cython/Includes/libc/stdint.pxd,sha256=qHJXzpWCrbvJWSaHYZL27VJPupQreTZl9VGj0jgLdRU,3449
277
+ Cython/Includes/libc/stdio.pxd,sha256=qUaxEwNrQl1-4yHLorzzJZ-a-y5_-Rm_m7Z5meaRqH0,2476
278
+ Cython/Includes/libc/stdlib.pxd,sha256=p62xq2XfB24WfNCjRXgD6cOYoRuV47AnYijkjWv4ugE,2444
279
+ Cython/Includes/libc/string.pxd,sha256=tzYGbRrnccedFLes-KGgJqM0FEtwHF_q4f2fqltNvyE,2038
280
+ Cython/Includes/libc/time.pxd,sha256=-IRH7fTq3wKBKmQQnpZRhaLsnl7D_qXFz_4BLB9O3u0,1317
281
+ Cython/Includes/libcpp/__init__.pxd,sha256=PCx8ZRfOeoyMRu41PPlPY9uo2kZmt_7d0KR4Epzfe7c,94
282
+ Cython/Includes/libcpp/algorithm.pxd,sha256=-2V0oR_cFbHHzeWT9RcfLvi5Oy-s_V2lO3OI6ZtX6fM,1770
283
+ Cython/Includes/libcpp/cast.pxd,sha256=En4LBubdinfpm9Rel077tK_LGwg_3k4FAu9mlIbKjuw,501
284
+ Cython/Includes/libcpp/complex.pxd,sha256=IjL8y9sAglhGbTKhqsJbW0mgMTYEUbYM1ekr5VDhQgY,3012
285
+ Cython/Includes/libcpp/deque.pxd,sha256=aWqZ9j3OgQuqFLkqRO_U2FIwbSe2fKmmYDRAfD0vGqU,3106
286
+ Cython/Includes/libcpp/forward_list.pxd,sha256=-So1ExEOkoPfsSdMlJSlI5665-zyWLMoUxlmm2Dlokk,2392
287
+ Cython/Includes/libcpp/functional.pxd,sha256=BXPYkffEOlKO1erTLqlkBLex6Gb5byDMF4hq_MZ2aVI,381
288
+ Cython/Includes/libcpp/iterator.pxd,sha256=mVc1rsAYfn_ARrdQ4JG-Ut5il5ynIa1CRXLk8Be8Zks,1432
289
+ Cython/Includes/libcpp/limits.pxd,sha256=RKV3wPvk4tV_vX5CYQRJIK5m5xXav7SeBxltlLyk8es,1661
290
+ Cython/Includes/libcpp/list.pxd,sha256=rGQfB3_mDcRkGKtMBuvDQvAPmgzR5jxSf3eOSRgR4YA,2658
291
+ Cython/Includes/libcpp/map.pxd,sha256=GF2sDnFBHZoU3Rcuo1rn6yKh45nhkX0_iH29xj581ow,2551
292
+ Cython/Includes/libcpp/memory.pxd,sha256=Hj20aSnmUTPAhFCrlmF_aeHJKiMiZ2bDKhaYn2yybJo,3600
293
+ Cython/Includes/libcpp/pair.pxd,sha256=UBJXw43uHkDlNsr0Pu1aP5tZ-ILXhUAyOLam2qdWmZA,27
294
+ Cython/Includes/libcpp/queue.pxd,sha256=FbL4Q7C3lgtZ2YzictU1XBXzQ7G-6y9i_7l2eqzA3Xc,649
295
+ Cython/Includes/libcpp/set.pxd,sha256=3y5Ir2TjGD7g3VRvlkXV1a3V3ZYzJvwOAfeTv8ucOCw,2170
296
+ Cython/Includes/libcpp/stack.pxd,sha256=zM3SQOqMWONVqud13ag3bUupA-ozU_YMq4Ad2QkL6fI,292
297
+ Cython/Includes/libcpp/string.pxd,sha256=zsvzyW6IggIDFqcF-UuLjxiNAHPtToAoc9VhKKG2U5A,8731
298
+ Cython/Includes/libcpp/typeindex.pxd,sha256=mIHr5Mq6Lol0SlzqeK6w_giVERh3uAjZm78yPDLXzc4,524
299
+ Cython/Includes/libcpp/typeinfo.pxd,sha256=tITsqurrdaZjsEGFksem9xZtVhSxQRxHZxcoC-4Y-DY,304
300
+ Cython/Includes/libcpp/unordered_map.pxd,sha256=eNna4hRAucQLnliBfEMu7Unfd_lB18I42iwKmsCO0-M,2867
301
+ Cython/Includes/libcpp/unordered_set.pxd,sha256=eUYSOMT5Gt8kZWCUKezQGyXWzatEyNg6-nmAlmcBo-k,2622
302
+ Cython/Includes/libcpp/utility.pxd,sha256=hTbvp7c12pnU2yvzzMvflZB-MAc_--3xh3PXtD_VIwg,1040
303
+ Cython/Includes/libcpp/vector.pxd,sha256=GYqLb74owhMmNQHUCcZSxGcYPgNuw6qULsfWKr7g6OQ,3350
304
+ Cython/Includes/numpy/__init__.pxd,sha256=CbLwvA4u-xj7RHxbO9Hs2o6hXd7GaJJlGEn9XJVH4c4,38138
305
+ Cython/Includes/numpy/math.pxd,sha256=qZEdamaPgCFW4J7Itc6BWgOrQSKZdxDT6kbU_gqx2g4,5807
306
+ Cython/Includes/openmp.pxd,sha256=orCIBYFuVPtLdRdhhCm5uhGbeV_fgVCA2Jk2Bts1e2g,1713
307
+ Cython/Includes/posix/__init__.pxd,sha256=jOqtmPLCvMCq0xVMwGekuLpBmVgq0xtPFmUePySdOjs,13
308
+ Cython/Includes/posix/dlfcn.pxd,sha256=2IFcGBfZEmArdE0BxB71eT_Yb7n9STaVM11AtUcg_pE,355
309
+ Cython/Includes/posix/fcntl.pxd,sha256=oRL8-OsgcplHMGcYq5-W5twISvxK-vDfzAaEfuQHC-4,1194
310
+ Cython/Includes/posix/ioctl.pxd,sha256=2RC5zejPOCTkarDZM_6Vd2wc4oBuN7iaiL_C5MPBs90,99
311
+ Cython/Includes/posix/mman.pxd,sha256=juJcLi92N9Bc6L2p4zrUmYQIgNmrTsZ6hExbl1181pc,3362
312
+ Cython/Includes/posix/resource.pxd,sha256=MQe1bCTYQFVMsago3pgOvR6t6NElQElg7rhVANxYRcE,1254
313
+ Cython/Includes/posix/select.pxd,sha256=e4nhGHR8TRw6Xs9du5JoFtkd8U9sm3gX_BHq2FfmU6E,546
314
+ Cython/Includes/posix/signal.pxd,sha256=wFJI5UthdtU9mZWjEBeZ9IIfeX252JVwDk2tsbW_q3U,1876
315
+ Cython/Includes/posix/stat.pxd,sha256=ZOcPCpXnxlRRHcUkvg559hrFfB75uTbIYRWoQeyBCYs,1734
316
+ Cython/Includes/posix/stdio.pxd,sha256=K8DEH38hWMvy2A8zcKbHRrHSGsgwTIrQ9qCzU-0cWS0,1054
317
+ Cython/Includes/posix/stdlib.pxd,sha256=uGRPa00_HWZ6Chv5E13F96eut0xWHSfR7IioK9rKVLY,934
318
+ Cython/Includes/posix/strings.pxd,sha256=GNEteqND2wgXXSvkv6U9eKSC9oIom3C7o2zQ6W_J_S4,374
319
+ Cython/Includes/posix/time.pxd,sha256=wPUD7AjxpxmnUYmogTMFjroB2VzcPh8-b_8NEj-yG14,1980
320
+ Cython/Includes/posix/types.pxd,sha256=tWEWxST4EGHIgYS-Ce2SGjZ-KgmM2SVe1eggdcgv3JQ,1162
321
+ Cython/Includes/posix/unistd.pxd,sha256=w9B4d9NaXBsQ62XOr2xe9UFPGewmEk5BG6sqiRWdoM8,8061
322
+ Cython/Includes/posix/wait.pxd,sha256=WNogQvKu2hMfEQiCyaANfVWFnyJSk6TxBU0c6npeJrA,1244
323
+ Cython/Plex/Actions.pxd,sha256=FC-6ffzWR4i3rR6VSL2C64Xxs1qBhpBEzRsU7WpLn1Y,585
324
+ Cython/Plex/Actions.py,sha256=Caxkx8Kup9m4sx24ZcDTq-fAfPGG06TAHu2NI1D9zPs,2545
325
+ Cython/Plex/DFA.py,sha256=w4vl2ejXv6ptILtkTCbB8NcvF8ylwc6DaQ2gPFrWuo4,6012
326
+ Cython/Plex/Errors.py,sha256=As5uuGmqZe4w0B7Dm981lZTnDG-nlXSHYqiGUKnhrrY,1169
327
+ Cython/Plex/Lexicons.py,sha256=ay3yy9fqI5y5lfgpJ4ubBjYZQ53gFDVgNGbmoSl5DxI,6907
328
+ Cython/Plex/Machines.py,sha256=bIKg3-yxD_r7x-zEowJ7EsPBWlgXm_XhIozqsLQBeTk,7760
329
+ Cython/Plex/Regexps.py,sha256=qaP-Fr-GgKNmBVsMyXO3ltl2HH1JQcQiFmX2oyUyeOA,16208
330
+ Cython/Plex/Scanners.pxd,sha256=oSfcDUZ3syc2ag73udwU5xoaIGDxiNd8a2F_LLw5PzY,1481
331
+ Cython/Plex/Scanners.py,sha256=-TXAxKW43ZbQNCSEkMWEJ0SmqYVVCkSOT9UngOCRZnQ,12259
332
+ Cython/Plex/Timing.py,sha256=-VgQveS-Ip_2ErjrVxh4w7cXpyVBkUaSaiLadyD3bw0,472
333
+ Cython/Plex/Traditional.py,sha256=cAT-pZnqIwCJaqgSqgKODSznFZ5DunUw_MLWx8Y650c,4120
334
+ Cython/Plex/Transitions.py,sha256=Tvp7cFXR3ZBPPHm0TAhUMC_-uiRR9YdOkF4t0wtk-f0,7187
335
+ Cython/Plex/__init__.py,sha256=dvMeQpSyZE75W0gkf4Xo5LAxgQLNhkAXiQoIOtcOkZ0,1282
336
+ Cython/Plex/__pycache__/Actions.cpython-311.pyc,,
337
+ Cython/Plex/__pycache__/DFA.cpython-311.pyc,,
338
+ Cython/Plex/__pycache__/Errors.cpython-311.pyc,,
339
+ Cython/Plex/__pycache__/Lexicons.cpython-311.pyc,,
340
+ Cython/Plex/__pycache__/Machines.cpython-311.pyc,,
341
+ Cython/Plex/__pycache__/Regexps.cpython-311.pyc,,
342
+ Cython/Plex/__pycache__/Scanners.cpython-311.pyc,,
343
+ Cython/Plex/__pycache__/Timing.cpython-311.pyc,,
344
+ Cython/Plex/__pycache__/Traditional.cpython-311.pyc,,
345
+ Cython/Plex/__pycache__/Transitions.cpython-311.pyc,,
346
+ Cython/Plex/__pycache__/__init__.cpython-311.pyc,,
347
+ Cython/Runtime/__init__.py,sha256=jOqtmPLCvMCq0xVMwGekuLpBmVgq0xtPFmUePySdOjs,13
348
+ Cython/Runtime/__pycache__/__init__.cpython-311.pyc,,
349
+ Cython/Runtime/refnanny.pyx,sha256=f2p1_0YxK25lm8Qfsu2ytvl0Im7GYyix1Q9krEBwC6c,6279
350
+ Cython/Shadow.py,sha256=MVEHAbarZ56-h0-_TjoHyZJ6GBJbvDMs5x2dfqYZzrE,13007
351
+ Cython/StringIOTree.py,sha256=GX-TWn9XHwY5ecb4in8ovsTS5CtPTsSxZpanLWmQxgE,3336
352
+ Cython/Tempita/__init__.py,sha256=YHujYHiLoYUwFNNswJCgzSrDuie3sV08JsWT9Nbmp78,152
353
+ Cython/Tempita/__pycache__/__init__.cpython-311.pyc,,
354
+ Cython/Tempita/__pycache__/_looper.cpython-311.pyc,,
355
+ Cython/Tempita/__pycache__/_tempita.cpython-311.pyc,,
356
+ Cython/Tempita/__pycache__/compat3.cpython-311.pyc,,
357
+ Cython/Tempita/_looper.py,sha256=jlStYhz9Pgp6NatX86k-netBNBmvwaeWxCRS_S8vcIM,4168
358
+ Cython/Tempita/_tempita.py,sha256=ZUBoFcXHnLrzg_aOjd3N2JoRcNlZL9KGD97Sz-Rd4SM,37038
359
+ Cython/Tempita/compat3.py,sha256=cjW1y266vRF5Xvh8kAu7_qHGT8AGGu2kGSJRK6DI-0E,903
360
+ Cython/TestUtils.py,sha256=fzpic9xU-LP0wempXqwUQWZapBvXnFgbW_W9--IKpIA,7979
361
+ Cython/Tests/TestCodeWriter.py,sha256=qKad43J3hN7PLp7mVbEDESt96qsk8y3ELRwwIp9jnNw,2316
362
+ Cython/Tests/TestCythonUtils.py,sha256=XF4Fw4J5HZ4jUPLVv7ea8ZZcl2i9yXn5cx27WTtrcmU,474
363
+ Cython/Tests/TestJediTyper.py,sha256=F6MUG8SdzGXQwkbw6Wv1PqVlmlIT1z_7lH2buVOFT_I,6996
364
+ Cython/Tests/TestStringIOTree.py,sha256=vTuu3z32WTcmJaf0fBq62NMghYtaPL2rRnfdl2WM--4,1946
365
+ Cython/Tests/__init__.py,sha256=jOqtmPLCvMCq0xVMwGekuLpBmVgq0xtPFmUePySdOjs,13
366
+ Cython/Tests/__pycache__/TestCodeWriter.cpython-311.pyc,,
367
+ Cython/Tests/__pycache__/TestCythonUtils.cpython-311.pyc,,
368
+ Cython/Tests/__pycache__/TestJediTyper.cpython-311.pyc,,
369
+ Cython/Tests/__pycache__/TestStringIOTree.cpython-311.pyc,,
370
+ Cython/Tests/__pycache__/__init__.cpython-311.pyc,,
371
+ Cython/Tests/__pycache__/xmlrunner.cpython-311.pyc,,
372
+ Cython/Tests/xmlrunner.py,sha256=N1Z_C4Q_rSWFNQxm3L99qX-SaIWEksXbmfXOd_srg3s,14801
373
+ Cython/Utility/AsyncGen.c,sha256=vPzUFEDh8EYaFqWhXLJA-0PBM4Z5BpS-HOiQmDaKK5A,41775
374
+ Cython/Utility/Buffer.c,sha256=VUF4xHKJGX7QMTvpJO40aI1JUL-SERLEvlXXXEk2dHU,29654
375
+ Cython/Utility/Builtins.c,sha256=gYObNoiK_NVWRuzSFRePMb-dtw-XCp_Dx_Ztjmpq7as,16818
376
+ Cython/Utility/CConvert.pyx,sha256=fbZVHvm2vlWj2rgm8ajBt5jrbN30nY7dEmHlBCGomlU,4338
377
+ Cython/Utility/CMath.c,sha256=GIc7gd2WzaZryDJM3tefqXifLJpUJs6_T_c_mFrr-s8,2566
378
+ Cython/Utility/Capsule.c,sha256=SOeU7E7T7piQEx894T2QFH2RlSG-MmsiyuY4lVN1yso,505
379
+ Cython/Utility/CommonStructures.c,sha256=p65HHgTrf7h7Tj7JK7tIgkLrrCrjouL8HL90EHfoMoU,2558
380
+ Cython/Utility/Complex.c,sha256=6YPGWtZUNI2ig5LRn3KWURB7z3cfhSNasW1S1Ejl7ao,10062
381
+ Cython/Utility/Coroutine.c,sha256=6tGqnflttVUZatqW7SdFBAydrKb0gM8R0Xo7keTzrnY,90224
382
+ Cython/Utility/CpdefEnums.pyx,sha256=XMg8sdltQSNj2wGVfnHIWRvyHFCcLK8ZfpKznKi4lhY,1893
383
+ Cython/Utility/CppConvert.pyx,sha256=-e5i3_J1SS_GbctsflQwylx9cqdk_CJ2SfQSEDHa71k,6098
384
+ Cython/Utility/CppSupport.cpp,sha256=NTnSRCmi2PHuT3J6Qy15xMZGx0bf9l-MaxAbW6OVk6s,2234
385
+ Cython/Utility/CythonFunction.c,sha256=KpQykNHRfC6b6Jl2TGX1Ir9hLUNXC4SrtGgzVNEcSw0,46746
386
+ Cython/Utility/Embed.c,sha256=sMDv7XVJswaGRTQbQHtEDThZaAmvbn-6yeIqrUzboL4,6854
387
+ Cython/Utility/Exceptions.c,sha256=vULhDRn0lSdjDysXspvXmv8Bcu3BaxB07jUxmQ5s-jU,28348
388
+ Cython/Utility/ExtensionTypes.c,sha256=doPkCDEsyClYfDa1386DxwVj0D4jYvKQlnbXQo2REHM,11664
389
+ Cython/Utility/FunctionArguments.c,sha256=IH9Y5aV_tNrJLo_CWHskEnFai9fp9cKLvRkIZYl2UGQ,12040
390
+ Cython/Utility/ImportExport.c,sha256=VbB1KiTkt4WAVSZ-DZiYd-b3t_ESWOnSsP6IRYa_3r8,23448
391
+ Cython/Utility/MemoryView.pyx,sha256=5WnL5DJF0nuSQBN5oBeEHFYE8aYm4C0-hY9Azm-toY4,49749
392
+ Cython/Utility/MemoryView_C.c,sha256=wlIKZ6UxkH--BFA-ENr83FtUw0KtStkqjAvB24Q0y_s,29072
393
+ Cython/Utility/ModuleSetupCode.c,sha256=FwNj8IxvfOjuMuQngRRvp9xOp0GafLTINf6cwxU52L4,58901
394
+ Cython/Utility/ObjectHandling.c,sha256=ZNaN2UoxX7HGfJZQhVDuyZfhsrzJ2kijaRvoA-qR5qU,89084
395
+ Cython/Utility/Optimize.c,sha256=xtKZ8WhOe8l4UYONGVDilNFhzGMueJxA7nYJn8QIWmc,45184
396
+ Cython/Utility/Overflow.c,sha256=_KXlJsbMIi-jzdCotwxkN6mtqo6jHRNnPJ1ZKwXVhpE,12424
397
+ Cython/Utility/Printing.c,sha256=o8XnfjNIT8Ub5KY4FAp_FNw-OE3xqjy0MgmYWgDcWao,5103
398
+ Cython/Utility/Profile.c,sha256=3aq_eC7h_nUnZe-Np7td20ublCC4OowfHoV3FoW9UnU,17922
399
+ Cython/Utility/StringTools.c,sha256=UyWngTrFElFXl4NIi7n36QCM7HL3MCNGhvqpPYLLY6o,42215
400
+ Cython/Utility/TestCyUtilityLoader.pyx,sha256=91lWWJub7l_6xNn3ncrvQZZ94RpkQzEx2NtAaFpvrxY,152
401
+ Cython/Utility/TestCythonScope.pyx,sha256=HQm5E5Eehr3tkDDURURyVnDputKG3-Wn2k2aIAoru9g,1595
402
+ Cython/Utility/TestUtilityLoader.c,sha256=dGy6ZWL2kBqtmUY7kF75UEox5kadQZ__BmZKscwg2aY,279
403
+ Cython/Utility/TypeConversion.c,sha256=ydxFNzBNOWIKoDA_z_U8a1wcZxdyeieiac8KQDN6pok,36333
404
+ Cython/Utility/__init__.py,sha256=t2bpY-TYSX8lJdbKuBFJ1kBfpWVzgGw4xoZlCKfyj_s,1159
405
+ Cython/Utility/__pycache__/__init__.cpython-311.pyc,,
406
+ Cython/Utility/arrayarray.h,sha256=3Ll8Gd_S4rv8HaTfg5i6-aaoB9taI1vzwTp7NeA7Wy0,4089
407
+ Cython/Utils.py,sha256=gb4MDFuC2NidOkhLVpsOm0NE3opVgFLWPw6ydmo_Mq4,14300
408
+ Cython/__init__.py,sha256=GMnkoIas6hfN_meqZAJF9BEs1NuY4-4B2L0Uls7hXaA,358
409
+ Cython/__pycache__/CodeWriter.cpython-311.pyc,,
410
+ Cython/__pycache__/Coverage.cpython-311.pyc,,
411
+ Cython/__pycache__/Debugging.cpython-311.pyc,,
412
+ Cython/__pycache__/Shadow.cpython-311.pyc,,
413
+ Cython/__pycache__/StringIOTree.cpython-311.pyc,,
414
+ Cython/__pycache__/TestUtils.cpython-311.pyc,,
415
+ Cython/__pycache__/Utils.cpython-311.pyc,,
416
+ Cython/__pycache__/__init__.cpython-311.pyc,,
417
+ __pycache__/cython.cpython-311.pyc,,
418
+ cython.py,sha256=z2AtgHBGh0x0h0ZcGje7IhYlR6nGH_MmOh1fFMjqYn0,520
419
+ pyximport/__init__.py,sha256=9hOyKolFtOerPiVEyktKrT1VtzbGexq9UmORzo52iHI,79
420
+ pyximport/__pycache__/__init__.cpython-311.pyc,,
421
+ pyximport/__pycache__/pyxbuild.cpython-311.pyc,,
422
+ pyximport/__pycache__/pyximport.cpython-311.pyc,,
423
+ pyximport/pyxbuild.py,sha256=TiAkhtSxSbRW04JKtgO3FP3hfVzQ1mjjzCh5PqZDOrM,5702
424
+ pyximport/pyximport.py,sha256=Vjxp3kbmFRf9j0ya4f0m0Ahytkjjmv2UkFueasXxL5A,23578
venv/Lib/site-packages/Cython-0.29.36.dist-info/WHEEL ADDED
@@ -0,0 +1,6 @@
 
 
 
 
 
 
 
1
+ Wheel-Version: 1.0
2
+ Generator: bdist_wheel (0.40.0)
3
+ Root-Is-Purelib: true
4
+ Tag: py2-none-any
5
+ Tag: py3-none-any
6
+
venv/Lib/site-packages/Cython-0.29.36.dist-info/entry_points.txt ADDED
@@ -0,0 +1,4 @@
 
 
 
 
 
1
+ [console_scripts]
2
+ cygdb = Cython.Debugger.Cygdb:main
3
+ cython = Cython.Compiler.Main:setuptools_main
4
+ cythonize = Cython.Build.Cythonize:main
venv/Lib/site-packages/Cython-0.29.36.dist-info/top_level.txt ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ Cython
2
+ cython
3
+ pyximport
venv/Lib/site-packages/Cython/Build/BuildExecutable.py ADDED
@@ -0,0 +1,142 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ Compile a Python script into an executable that embeds CPython and run it.
3
+ Requires CPython to be built as a shared library ('libpythonX.Y').
4
+
5
+ Basic usage:
6
+
7
+ python cythonrun somefile.py [ARGS]
8
+ """
9
+
10
+ from __future__ import absolute_import
11
+
12
+ DEBUG = True
13
+
14
+ import sys
15
+ import os
16
+ from distutils import sysconfig
17
+
18
+
19
+ def get_config_var(name, default=''):
20
+ return sysconfig.get_config_var(name) or default
21
+
22
+ INCDIR = sysconfig.get_python_inc()
23
+ LIBDIR1 = get_config_var('LIBDIR')
24
+ LIBDIR2 = get_config_var('LIBPL')
25
+ PYLIB = get_config_var('LIBRARY')
26
+ PYLIB_DYN = get_config_var('LDLIBRARY')
27
+ if PYLIB_DYN == PYLIB:
28
+ # no shared library
29
+ PYLIB_DYN = ''
30
+ else:
31
+ PYLIB_DYN = os.path.splitext(PYLIB_DYN[3:])[0] # 'lib(XYZ).so' -> XYZ
32
+
33
+ CC = get_config_var('CC', os.environ.get('CC', ''))
34
+ CFLAGS = get_config_var('CFLAGS') + ' ' + os.environ.get('CFLAGS', '')
35
+ LINKCC = get_config_var('LINKCC', os.environ.get('LINKCC', CC))
36
+ LINKFORSHARED = get_config_var('LINKFORSHARED')
37
+ LIBS = get_config_var('LIBS')
38
+ SYSLIBS = get_config_var('SYSLIBS')
39
+ EXE_EXT = sysconfig.get_config_var('EXE')
40
+
41
+ def _debug(msg, *args):
42
+ if DEBUG:
43
+ if args:
44
+ msg = msg % args
45
+ sys.stderr.write(msg + '\n')
46
+
47
+ def dump_config():
48
+ _debug('INCDIR: %s', INCDIR)
49
+ _debug('LIBDIR1: %s', LIBDIR1)
50
+ _debug('LIBDIR2: %s', LIBDIR2)
51
+ _debug('PYLIB: %s', PYLIB)
52
+ _debug('PYLIB_DYN: %s', PYLIB_DYN)
53
+ _debug('CC: %s', CC)
54
+ _debug('CFLAGS: %s', CFLAGS)
55
+ _debug('LINKCC: %s', LINKCC)
56
+ _debug('LINKFORSHARED: %s', LINKFORSHARED)
57
+ _debug('LIBS: %s', LIBS)
58
+ _debug('SYSLIBS: %s', SYSLIBS)
59
+ _debug('EXE_EXT: %s', EXE_EXT)
60
+
61
+ def runcmd(cmd, shell=True):
62
+ if shell:
63
+ cmd = ' '.join(cmd)
64
+ _debug(cmd)
65
+ else:
66
+ _debug(' '.join(cmd))
67
+
68
+ try:
69
+ import subprocess
70
+ except ImportError: # Python 2.3 ...
71
+ returncode = os.system(cmd)
72
+ else:
73
+ returncode = subprocess.call(cmd, shell=shell)
74
+
75
+ if returncode:
76
+ sys.exit(returncode)
77
+
78
+ def clink(basename):
79
+ runcmd([LINKCC, '-o', basename + EXE_EXT, basename+'.o', '-L'+LIBDIR1, '-L'+LIBDIR2]
80
+ + [PYLIB_DYN and ('-l'+PYLIB_DYN) or os.path.join(LIBDIR1, PYLIB)]
81
+ + LIBS.split() + SYSLIBS.split() + LINKFORSHARED.split())
82
+
83
+ def ccompile(basename):
84
+ runcmd([CC, '-c', '-o', basename+'.o', basename+'.c', '-I' + INCDIR] + CFLAGS.split())
85
+
86
+ def cycompile(input_file, options=()):
87
+ from ..Compiler import Version, CmdLine, Main
88
+ options, sources = CmdLine.parse_command_line(list(options or ()) + ['--embed', input_file])
89
+ _debug('Using Cython %s to compile %s', Version.version, input_file)
90
+ result = Main.compile(sources, options)
91
+ if result.num_errors > 0:
92
+ sys.exit(1)
93
+
94
+ def exec_file(program_name, args=()):
95
+ runcmd([os.path.abspath(program_name)] + list(args), shell=False)
96
+
97
+ def build(input_file, compiler_args=(), force=False):
98
+ """
99
+ Build an executable program from a Cython module.
100
+
101
+ Returns the name of the executable file.
102
+ """
103
+ basename = os.path.splitext(input_file)[0]
104
+ exe_file = basename + EXE_EXT
105
+ if not force and os.path.abspath(exe_file) == os.path.abspath(input_file):
106
+ raise ValueError("Input and output file names are the same, refusing to overwrite")
107
+ if (not force and os.path.exists(exe_file) and os.path.exists(input_file)
108
+ and os.path.getmtime(input_file) <= os.path.getmtime(exe_file)):
109
+ _debug("File is up to date, not regenerating %s", exe_file)
110
+ return exe_file
111
+ cycompile(input_file, compiler_args)
112
+ ccompile(basename)
113
+ clink(basename)
114
+ return exe_file
115
+
116
+ def build_and_run(args):
117
+ """
118
+ Build an executable program from a Cython module and runs it.
119
+
120
+ Arguments after the module name will be passed verbatimely to the
121
+ program.
122
+ """
123
+ cy_args = []
124
+ last_arg = None
125
+ for i, arg in enumerate(args):
126
+ if arg.startswith('-'):
127
+ cy_args.append(arg)
128
+ elif last_arg in ('-X', '--directive'):
129
+ cy_args.append(arg)
130
+ else:
131
+ input_file = arg
132
+ args = args[i+1:]
133
+ break
134
+ last_arg = arg
135
+ else:
136
+ raise ValueError('no input file provided')
137
+
138
+ program_name = build(input_file, cy_args)
139
+ exec_file(program_name, args)
140
+
141
+ if __name__ == '__main__':
142
+ build_and_run(sys.argv[1:])
venv/Lib/site-packages/Cython/Build/Cythonize.py ADDED
@@ -0,0 +1,229 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env python
2
+
3
+ from __future__ import absolute_import
4
+
5
+ import os
6
+ import shutil
7
+ import tempfile
8
+ from distutils.core import setup
9
+
10
+ from .Dependencies import cythonize, extended_iglob
11
+ from ..Utils import is_package_dir
12
+ from ..Compiler import Options
13
+
14
+ try:
15
+ import multiprocessing
16
+ parallel_compiles = int(multiprocessing.cpu_count() * 1.5)
17
+ except ImportError:
18
+ multiprocessing = None
19
+ parallel_compiles = 0
20
+
21
+
22
+ class _FakePool(object):
23
+ def map_async(self, func, args):
24
+ try:
25
+ from itertools import imap
26
+ except ImportError:
27
+ imap=map
28
+ for _ in imap(func, args):
29
+ pass
30
+
31
+ def close(self):
32
+ pass
33
+
34
+ def terminate(self):
35
+ pass
36
+
37
+ def join(self):
38
+ pass
39
+
40
+
41
+ def parse_directives(option, name, value, parser):
42
+ dest = option.dest
43
+ old_directives = dict(getattr(parser.values, dest,
44
+ Options.get_directive_defaults()))
45
+ directives = Options.parse_directive_list(
46
+ value, relaxed_bool=True, current_settings=old_directives)
47
+ setattr(parser.values, dest, directives)
48
+
49
+
50
+ def parse_options(option, name, value, parser):
51
+ dest = option.dest
52
+ options = dict(getattr(parser.values, dest, {}))
53
+ for opt in value.split(','):
54
+ if '=' in opt:
55
+ n, v = opt.split('=', 1)
56
+ v = v.lower() not in ('false', 'f', '0', 'no')
57
+ else:
58
+ n, v = opt, True
59
+ options[n] = v
60
+ setattr(parser.values, dest, options)
61
+
62
+
63
+ def parse_compile_time_env(option, name, value, parser):
64
+ dest = option.dest
65
+ old_env = dict(getattr(parser.values, dest, {}))
66
+ new_env = Options.parse_compile_time_env(value, current_settings=old_env)
67
+ setattr(parser.values, dest, new_env)
68
+
69
+
70
+ def find_package_base(path):
71
+ base_dir, package_path = os.path.split(path)
72
+ while os.path.isfile(os.path.join(base_dir, '__init__.py')):
73
+ base_dir, parent = os.path.split(base_dir)
74
+ package_path = '%s/%s' % (parent, package_path)
75
+ return base_dir, package_path
76
+
77
+
78
+ def cython_compile(path_pattern, options):
79
+ pool = None
80
+ all_paths = map(os.path.abspath, extended_iglob(path_pattern))
81
+ try:
82
+ for path in all_paths:
83
+ if options.build_inplace:
84
+ base_dir = path
85
+ while not os.path.isdir(base_dir) or is_package_dir(base_dir):
86
+ base_dir = os.path.dirname(base_dir)
87
+ else:
88
+ base_dir = None
89
+
90
+ if os.path.isdir(path):
91
+ # recursively compiling a package
92
+ paths = [os.path.join(path, '**', '*.{py,pyx}')]
93
+ else:
94
+ # assume it's a file(-like thing)
95
+ paths = [path]
96
+
97
+ ext_modules = cythonize(
98
+ paths,
99
+ nthreads=options.parallel,
100
+ exclude_failures=options.keep_going,
101
+ exclude=options.excludes,
102
+ compiler_directives=options.directives,
103
+ compile_time_env=options.compile_time_env,
104
+ force=options.force,
105
+ quiet=options.quiet,
106
+ depfile=options.depfile,
107
+ **options.options)
108
+
109
+ if ext_modules and options.build:
110
+ if len(ext_modules) > 1 and options.parallel > 1:
111
+ if pool is None:
112
+ try:
113
+ pool = multiprocessing.Pool(options.parallel)
114
+ except OSError:
115
+ pool = _FakePool()
116
+ pool.map_async(run_distutils, [
117
+ (base_dir, [ext]) for ext in ext_modules])
118
+ else:
119
+ run_distutils((base_dir, ext_modules))
120
+ except:
121
+ if pool is not None:
122
+ pool.terminate()
123
+ raise
124
+ else:
125
+ if pool is not None:
126
+ pool.close()
127
+ pool.join()
128
+
129
+
130
+ def run_distutils(args):
131
+ base_dir, ext_modules = args
132
+ script_args = ['build_ext', '-i']
133
+ cwd = os.getcwd()
134
+ temp_dir = None
135
+ try:
136
+ if base_dir:
137
+ os.chdir(base_dir)
138
+ temp_dir = tempfile.mkdtemp(dir=base_dir)
139
+ script_args.extend(['--build-temp', temp_dir])
140
+ setup(
141
+ script_name='setup.py',
142
+ script_args=script_args,
143
+ ext_modules=ext_modules,
144
+ )
145
+ finally:
146
+ if base_dir:
147
+ os.chdir(cwd)
148
+ if temp_dir and os.path.isdir(temp_dir):
149
+ shutil.rmtree(temp_dir)
150
+
151
+
152
+ def parse_args(args):
153
+ from optparse import OptionParser
154
+ parser = OptionParser(usage='%prog [options] [sources and packages]+')
155
+
156
+ parser.add_option('-X', '--directive', metavar='NAME=VALUE,...',
157
+ dest='directives', default={}, type="str",
158
+ action='callback', callback=parse_directives,
159
+ help='set a compiler directive')
160
+ parser.add_option('-E', '--compile-time-env', metavar='NAME=VALUE,...',
161
+ dest='compile_time_env', default={}, type="str",
162
+ action='callback', callback=parse_compile_time_env,
163
+ help='set a compile time environment variable')
164
+ parser.add_option('-s', '--option', metavar='NAME=VALUE',
165
+ dest='options', default={}, type="str",
166
+ action='callback', callback=parse_options,
167
+ help='set a cythonize option')
168
+ parser.add_option('-2', dest='language_level', action='store_const', const=2, default=None,
169
+ help='use Python 2 syntax mode by default')
170
+ parser.add_option('-3', dest='language_level', action='store_const', const=3,
171
+ help='use Python 3 syntax mode by default')
172
+ parser.add_option('--3str', dest='language_level', action='store_const', const='3str',
173
+ help='use Python 3 syntax mode by default')
174
+ parser.add_option('-a', '--annotate', dest='annotate', action='store_true',
175
+ help='generate annotated HTML page for source files')
176
+
177
+ parser.add_option('-x', '--exclude', metavar='PATTERN', dest='excludes',
178
+ action='append', default=[],
179
+ help='exclude certain file patterns from the compilation')
180
+
181
+ parser.add_option('-b', '--build', dest='build', action='store_true',
182
+ help='build extension modules using distutils')
183
+ parser.add_option('-i', '--inplace', dest='build_inplace', action='store_true',
184
+ help='build extension modules in place using distutils (implies -b)')
185
+ parser.add_option('-j', '--parallel', dest='parallel', metavar='N',
186
+ type=int, default=parallel_compiles,
187
+ help=('run builds in N parallel jobs (default: %d)' %
188
+ parallel_compiles or 1))
189
+ parser.add_option('-f', '--force', dest='force', action='store_true',
190
+ help='force recompilation')
191
+ parser.add_option('-q', '--quiet', dest='quiet', action='store_true',
192
+ help='be less verbose during compilation')
193
+
194
+ parser.add_option('--lenient', dest='lenient', action='store_true',
195
+ help='increase Python compatibility by ignoring some compile time errors')
196
+ parser.add_option('-k', '--keep-going', dest='keep_going', action='store_true',
197
+ help='compile as much as possible, ignore compilation failures')
198
+ parser.add_option('-M', '--depfile', action='store_true', help='produce depfiles for the sources')
199
+
200
+ options, args = parser.parse_args(args)
201
+ if not args:
202
+ parser.error("no source files provided")
203
+ if options.build_inplace:
204
+ options.build = True
205
+ if multiprocessing is None:
206
+ options.parallel = 0
207
+ if options.language_level:
208
+ assert options.language_level in (2, 3, '3str')
209
+ options.options['language_level'] = options.language_level
210
+ return options, args
211
+
212
+
213
+ def main(args=None):
214
+ options, paths = parse_args(args)
215
+
216
+ if options.lenient:
217
+ # increase Python compatibility by ignoring compile time errors
218
+ Options.error_on_unknown_names = False
219
+ Options.error_on_uninitialized = False
220
+
221
+ if options.annotate:
222
+ Options.annotate = True
223
+
224
+ for path in paths:
225
+ cython_compile(path, options)
226
+
227
+
228
+ if __name__ == '__main__':
229
+ main()
venv/Lib/site-packages/Cython/Build/Dependencies.py ADDED
@@ -0,0 +1,1296 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from __future__ import absolute_import, print_function
2
+
3
+ import cython
4
+ from .. import __version__
5
+
6
+ import collections
7
+ import contextlib
8
+ import hashlib
9
+ import os
10
+ import shutil
11
+ import subprocess
12
+ import re, sys, time
13
+ import warnings
14
+ from glob import iglob
15
+ from io import open as io_open
16
+ from os.path import relpath as _relpath
17
+ from distutils.extension import Extension
18
+ from distutils.util import strtobool
19
+ import zipfile
20
+
21
+ try:
22
+ from collections.abc import Iterable
23
+ except ImportError:
24
+ from collections import Iterable
25
+
26
+ try:
27
+ import gzip
28
+ gzip_open = gzip.open
29
+ gzip_ext = '.gz'
30
+ except ImportError:
31
+ gzip_open = open
32
+ gzip_ext = ''
33
+
34
+ try:
35
+ import zlib
36
+ zipfile_compression_mode = zipfile.ZIP_DEFLATED
37
+ except ImportError:
38
+ zipfile_compression_mode = zipfile.ZIP_STORED
39
+
40
+ try:
41
+ import pythran
42
+ except:
43
+ pythran = None
44
+
45
+ from .. import Utils
46
+ from ..Utils import (cached_function, cached_method, path_exists, write_depfile,
47
+ safe_makedirs, copy_file_to_dir_if_newer, is_package_dir, replace_suffix)
48
+ from ..Compiler.Main import Context, CompilationOptions, default_options
49
+
50
+ join_path = cached_function(os.path.join)
51
+ copy_once_if_newer = cached_function(copy_file_to_dir_if_newer)
52
+ safe_makedirs_once = cached_function(safe_makedirs)
53
+
54
+ if sys.version_info[0] < 3:
55
+ # stupid Py2 distutils enforces str type in list of sources
56
+ _fs_encoding = sys.getfilesystemencoding()
57
+ if _fs_encoding is None:
58
+ _fs_encoding = sys.getdefaultencoding()
59
+ def encode_filename_in_py2(filename):
60
+ if not isinstance(filename, bytes):
61
+ return filename.encode(_fs_encoding)
62
+ return filename
63
+ else:
64
+ def encode_filename_in_py2(filename):
65
+ return filename
66
+ basestring = str
67
+
68
+
69
+ def _make_relative(file_paths, base=None):
70
+ if not base:
71
+ base = os.getcwd()
72
+ if base[-1] != os.path.sep:
73
+ base += os.path.sep
74
+ return [_relpath(path, base) if path.startswith(base) else path
75
+ for path in file_paths]
76
+
77
+
78
+ def extended_iglob(pattern):
79
+ if '{' in pattern:
80
+ m = re.match('(.*){([^}]+)}(.*)', pattern)
81
+ if m:
82
+ before, switch, after = m.groups()
83
+ for case in switch.split(','):
84
+ for path in extended_iglob(before + case + after):
85
+ yield path
86
+ return
87
+ if '**/' in pattern:
88
+ seen = set()
89
+ first, rest = pattern.split('**/', 1)
90
+ if first:
91
+ first = iglob(first+'/')
92
+ else:
93
+ first = ['']
94
+ for root in first:
95
+ for path in extended_iglob(join_path(root, rest)):
96
+ if path not in seen:
97
+ seen.add(path)
98
+ yield path
99
+ for path in extended_iglob(join_path(root, '*', '**/' + rest)):
100
+ if path not in seen:
101
+ seen.add(path)
102
+ yield path
103
+ else:
104
+ for path in iglob(pattern):
105
+ yield path
106
+
107
+
108
+ def nonempty(it, error_msg="expected non-empty iterator"):
109
+ empty = True
110
+ for value in it:
111
+ empty = False
112
+ yield value
113
+ if empty:
114
+ raise ValueError(error_msg)
115
+
116
+
117
+ @cached_function
118
+ def file_hash(filename):
119
+ path = os.path.normpath(filename)
120
+ prefix = ('%d:%s' % (len(path), path)).encode("UTF-8")
121
+ m = hashlib.md5(prefix)
122
+ with open(path, 'rb') as f:
123
+ data = f.read(65000)
124
+ while data:
125
+ m.update(data)
126
+ data = f.read(65000)
127
+ return m.hexdigest()
128
+
129
+
130
+ def update_pythran_extension(ext):
131
+ if pythran is None:
132
+ raise RuntimeError("You first need to install Pythran to use the np_pythran directive.")
133
+ try:
134
+ pythran_ext = pythran.config.make_extension(python=True)
135
+ except TypeError: # older pythran version only
136
+ pythran_ext = pythran.config.make_extension()
137
+
138
+ ext.include_dirs.extend(pythran_ext['include_dirs'])
139
+ ext.extra_compile_args.extend(pythran_ext['extra_compile_args'])
140
+ ext.extra_link_args.extend(pythran_ext['extra_link_args'])
141
+ ext.define_macros.extend(pythran_ext['define_macros'])
142
+ ext.undef_macros.extend(pythran_ext['undef_macros'])
143
+ ext.library_dirs.extend(pythran_ext['library_dirs'])
144
+ ext.libraries.extend(pythran_ext['libraries'])
145
+ ext.language = 'c++'
146
+
147
+ # These options are not compatible with the way normal Cython extensions work
148
+ for bad_option in ["-fwhole-program", "-fvisibility=hidden"]:
149
+ try:
150
+ ext.extra_compile_args.remove(bad_option)
151
+ except ValueError:
152
+ pass
153
+
154
+
155
+ def parse_list(s):
156
+ """
157
+ >>> parse_list("")
158
+ []
159
+ >>> parse_list("a")
160
+ ['a']
161
+ >>> parse_list("a b c")
162
+ ['a', 'b', 'c']
163
+ >>> parse_list("[a, b, c]")
164
+ ['a', 'b', 'c']
165
+ >>> parse_list('a " " b')
166
+ ['a', ' ', 'b']
167
+ >>> parse_list('[a, ",a", "a,", ",", ]')
168
+ ['a', ',a', 'a,', ',']
169
+ """
170
+ if len(s) >= 2 and s[0] == '[' and s[-1] == ']':
171
+ s = s[1:-1]
172
+ delimiter = ','
173
+ else:
174
+ delimiter = ' '
175
+ s, literals = strip_string_literals(s)
176
+ def unquote(literal):
177
+ literal = literal.strip()
178
+ if literal[0] in "'\"":
179
+ return literals[literal[1:-1]]
180
+ else:
181
+ return literal
182
+ return [unquote(item) for item in s.split(delimiter) if item.strip()]
183
+
184
+
185
+ transitive_str = object()
186
+ transitive_list = object()
187
+ bool_or = object()
188
+
189
+ distutils_settings = {
190
+ 'name': str,
191
+ 'sources': list,
192
+ 'define_macros': list,
193
+ 'undef_macros': list,
194
+ 'libraries': transitive_list,
195
+ 'library_dirs': transitive_list,
196
+ 'runtime_library_dirs': transitive_list,
197
+ 'include_dirs': transitive_list,
198
+ 'extra_objects': list,
199
+ 'extra_compile_args': transitive_list,
200
+ 'extra_link_args': transitive_list,
201
+ 'export_symbols': list,
202
+ 'depends': transitive_list,
203
+ 'language': transitive_str,
204
+ 'np_pythran': bool_or
205
+ }
206
+
207
+
208
+ @cython.locals(start=cython.Py_ssize_t, end=cython.Py_ssize_t)
209
+ def line_iter(source):
210
+ if isinstance(source, basestring):
211
+ start = 0
212
+ while True:
213
+ end = source.find('\n', start)
214
+ if end == -1:
215
+ yield source[start:]
216
+ return
217
+ yield source[start:end]
218
+ start = end+1
219
+ else:
220
+ for line in source:
221
+ yield line
222
+
223
+
224
+ class DistutilsInfo(object):
225
+
226
+ def __init__(self, source=None, exn=None):
227
+ self.values = {}
228
+ if source is not None:
229
+ for line in line_iter(source):
230
+ line = line.lstrip()
231
+ if not line:
232
+ continue
233
+ if line[0] != '#':
234
+ break
235
+ line = line[1:].lstrip()
236
+ kind = next((k for k in ("distutils:","cython:") if line.startswith(k)), None)
237
+ if kind is not None:
238
+ key, _, value = [s.strip() for s in line[len(kind):].partition('=')]
239
+ type = distutils_settings.get(key, None)
240
+ if line.startswith("cython:") and type is None: continue
241
+ if type in (list, transitive_list):
242
+ value = parse_list(value)
243
+ if key == 'define_macros':
244
+ value = [tuple(macro.split('=', 1))
245
+ if '=' in macro else (macro, None)
246
+ for macro in value]
247
+ if type is bool_or:
248
+ value = strtobool(value)
249
+ self.values[key] = value
250
+ elif exn is not None:
251
+ for key in distutils_settings:
252
+ if key in ('name', 'sources','np_pythran'):
253
+ continue
254
+ value = getattr(exn, key, None)
255
+ if value:
256
+ self.values[key] = value
257
+
258
+ def merge(self, other):
259
+ if other is None:
260
+ return self
261
+ for key, value in other.values.items():
262
+ type = distutils_settings[key]
263
+ if type is transitive_str and key not in self.values:
264
+ self.values[key] = value
265
+ elif type is transitive_list:
266
+ if key in self.values:
267
+ # Change a *copy* of the list (Trac #845)
268
+ all = self.values[key][:]
269
+ for v in value:
270
+ if v not in all:
271
+ all.append(v)
272
+ value = all
273
+ self.values[key] = value
274
+ elif type is bool_or:
275
+ self.values[key] = self.values.get(key, False) | value
276
+ return self
277
+
278
+ def subs(self, aliases):
279
+ if aliases is None:
280
+ return self
281
+ resolved = DistutilsInfo()
282
+ for key, value in self.values.items():
283
+ type = distutils_settings[key]
284
+ if type in [list, transitive_list]:
285
+ new_value_list = []
286
+ for v in value:
287
+ if v in aliases:
288
+ v = aliases[v]
289
+ if isinstance(v, list):
290
+ new_value_list += v
291
+ else:
292
+ new_value_list.append(v)
293
+ value = new_value_list
294
+ else:
295
+ if value in aliases:
296
+ value = aliases[value]
297
+ resolved.values[key] = value
298
+ return resolved
299
+
300
+ def apply(self, extension):
301
+ for key, value in self.values.items():
302
+ type = distutils_settings[key]
303
+ if type in [list, transitive_list]:
304
+ value = getattr(extension, key) + list(value)
305
+ setattr(extension, key, value)
306
+
307
+
308
+ @cython.locals(start=cython.Py_ssize_t, q=cython.Py_ssize_t,
309
+ single_q=cython.Py_ssize_t, double_q=cython.Py_ssize_t,
310
+ hash_mark=cython.Py_ssize_t, end=cython.Py_ssize_t,
311
+ k=cython.Py_ssize_t, counter=cython.Py_ssize_t, quote_len=cython.Py_ssize_t)
312
+ def strip_string_literals(code, prefix='__Pyx_L'):
313
+ """
314
+ Normalizes every string literal to be of the form '__Pyx_Lxxx',
315
+ returning the normalized code and a mapping of labels to
316
+ string literals.
317
+ """
318
+ new_code = []
319
+ literals = {}
320
+ counter = 0
321
+ start = q = 0
322
+ in_quote = False
323
+ hash_mark = single_q = double_q = -1
324
+ code_len = len(code)
325
+ quote_type = None
326
+ quote_len = -1
327
+
328
+ while True:
329
+ if hash_mark < q:
330
+ hash_mark = code.find('#', q)
331
+ if single_q < q:
332
+ single_q = code.find("'", q)
333
+ if double_q < q:
334
+ double_q = code.find('"', q)
335
+ q = min(single_q, double_q)
336
+ if q == -1:
337
+ q = max(single_q, double_q)
338
+
339
+ # We're done.
340
+ if q == -1 and hash_mark == -1:
341
+ new_code.append(code[start:])
342
+ break
343
+
344
+ # Try to close the quote.
345
+ elif in_quote:
346
+ if code[q-1] == u'\\':
347
+ k = 2
348
+ while q >= k and code[q-k] == u'\\':
349
+ k += 1
350
+ if k % 2 == 0:
351
+ q += 1
352
+ continue
353
+ if code[q] == quote_type and (
354
+ quote_len == 1 or (code_len > q + 2 and quote_type == code[q+1] == code[q+2])):
355
+ counter += 1
356
+ label = "%s%s_" % (prefix, counter)
357
+ literals[label] = code[start+quote_len:q]
358
+ full_quote = code[q:q+quote_len]
359
+ new_code.append(full_quote)
360
+ new_code.append(label)
361
+ new_code.append(full_quote)
362
+ q += quote_len
363
+ in_quote = False
364
+ start = q
365
+ else:
366
+ q += 1
367
+
368
+ # Process comment.
369
+ elif -1 != hash_mark and (hash_mark < q or q == -1):
370
+ new_code.append(code[start:hash_mark+1])
371
+ end = code.find('\n', hash_mark)
372
+ counter += 1
373
+ label = "%s%s_" % (prefix, counter)
374
+ if end == -1:
375
+ end_or_none = None
376
+ else:
377
+ end_or_none = end
378
+ literals[label] = code[hash_mark+1:end_or_none]
379
+ new_code.append(label)
380
+ if end == -1:
381
+ break
382
+ start = q = end
383
+
384
+ # Open the quote.
385
+ else:
386
+ if code_len >= q+3 and (code[q] == code[q+1] == code[q+2]):
387
+ quote_len = 3
388
+ else:
389
+ quote_len = 1
390
+ in_quote = True
391
+ quote_type = code[q]
392
+ new_code.append(code[start:q])
393
+ start = q
394
+ q += quote_len
395
+
396
+ return "".join(new_code), literals
397
+
398
+
399
+ # We need to allow spaces to allow for conditional compilation like
400
+ # IF ...:
401
+ # cimport ...
402
+ dependency_regex = re.compile(r"(?:^\s*from +([0-9a-zA-Z_.]+) +cimport)|"
403
+ r"(?:^\s*cimport +([0-9a-zA-Z_.]+(?: *, *[0-9a-zA-Z_.]+)*))|"
404
+ r"(?:^\s*cdef +extern +from +['\"]([^'\"]+)['\"])|"
405
+ r"(?:^\s*include +['\"]([^'\"]+)['\"])", re.M)
406
+ dependency_after_from_regex = re.compile(
407
+ r"(?:^\s+\(([0-9a-zA-Z_., ]*)\)[#\n])|"
408
+ r"(?:^\s+([0-9a-zA-Z_., ]*)[#\n])",
409
+ re.M)
410
+
411
+
412
+ def normalize_existing(base_path, rel_paths):
413
+ return normalize_existing0(os.path.dirname(base_path), tuple(set(rel_paths)))
414
+
415
+
416
+ @cached_function
417
+ def normalize_existing0(base_dir, rel_paths):
418
+ """
419
+ Given some base directory ``base_dir`` and a list of path names
420
+ ``rel_paths``, normalize each relative path name ``rel`` by
421
+ replacing it by ``os.path.join(base, rel)`` if that file exists.
422
+
423
+ Return a couple ``(normalized, needed_base)`` where ``normalized``
424
+ if the list of normalized file names and ``needed_base`` is
425
+ ``base_dir`` if we actually needed ``base_dir``. If no paths were
426
+ changed (for example, if all paths were already absolute), then
427
+ ``needed_base`` is ``None``.
428
+ """
429
+ normalized = []
430
+ needed_base = None
431
+ for rel in rel_paths:
432
+ if os.path.isabs(rel):
433
+ normalized.append(rel)
434
+ continue
435
+ path = join_path(base_dir, rel)
436
+ if path_exists(path):
437
+ normalized.append(os.path.normpath(path))
438
+ needed_base = base_dir
439
+ else:
440
+ normalized.append(rel)
441
+ return (normalized, needed_base)
442
+
443
+
444
+ def resolve_depends(depends, include_dirs):
445
+ include_dirs = tuple(include_dirs)
446
+ resolved = []
447
+ for depend in depends:
448
+ path = resolve_depend(depend, include_dirs)
449
+ if path is not None:
450
+ resolved.append(path)
451
+ return resolved
452
+
453
+
454
+ @cached_function
455
+ def resolve_depend(depend, include_dirs):
456
+ if depend[0] == '<' and depend[-1] == '>':
457
+ return None
458
+ for dir in include_dirs:
459
+ path = join_path(dir, depend)
460
+ if path_exists(path):
461
+ return os.path.normpath(path)
462
+ return None
463
+
464
+
465
+ @cached_function
466
+ def package(filename):
467
+ dir = os.path.dirname(os.path.abspath(str(filename)))
468
+ if dir != filename and is_package_dir(dir):
469
+ return package(dir) + (os.path.basename(dir),)
470
+ else:
471
+ return ()
472
+
473
+
474
+ @cached_function
475
+ def fully_qualified_name(filename):
476
+ module = os.path.splitext(os.path.basename(filename))[0]
477
+ return '.'.join(package(filename) + (module,))
478
+
479
+
480
+ @cached_function
481
+ def parse_dependencies(source_filename):
482
+ # Actual parsing is way too slow, so we use regular expressions.
483
+ # The only catch is that we must strip comments and string
484
+ # literals ahead of time.
485
+ with Utils.open_source_file(source_filename, error_handling='ignore') as fh:
486
+ source = fh.read()
487
+ distutils_info = DistutilsInfo(source)
488
+ source, literals = strip_string_literals(source)
489
+ source = source.replace('\\\n', ' ').replace('\t', ' ')
490
+
491
+ # TODO: pure mode
492
+ cimports = []
493
+ includes = []
494
+ externs = []
495
+ for m in dependency_regex.finditer(source):
496
+ cimport_from, cimport_list, extern, include = m.groups()
497
+ if cimport_from:
498
+ cimports.append(cimport_from)
499
+ m_after_from = dependency_after_from_regex.search(source, pos=m.end())
500
+ if m_after_from:
501
+ multiline, one_line = m_after_from.groups()
502
+ subimports = multiline or one_line
503
+ cimports.extend("{0}.{1}".format(cimport_from, s.strip())
504
+ for s in subimports.split(','))
505
+
506
+ elif cimport_list:
507
+ cimports.extend(x.strip() for x in cimport_list.split(","))
508
+ elif extern:
509
+ externs.append(literals[extern])
510
+ else:
511
+ includes.append(literals[include])
512
+ return cimports, includes, externs, distutils_info
513
+
514
+
515
+ class DependencyTree(object):
516
+
517
+ def __init__(self, context, quiet=False):
518
+ self.context = context
519
+ self.quiet = quiet
520
+ self._transitive_cache = {}
521
+
522
+ def parse_dependencies(self, source_filename):
523
+ if path_exists(source_filename):
524
+ source_filename = os.path.normpath(source_filename)
525
+ return parse_dependencies(source_filename)
526
+
527
+ @cached_method
528
+ def included_files(self, filename):
529
+ # This is messy because included files are textually included, resolving
530
+ # cimports (but not includes) relative to the including file.
531
+ all = set()
532
+ for include in self.parse_dependencies(filename)[1]:
533
+ include_path = join_path(os.path.dirname(filename), include)
534
+ if not path_exists(include_path):
535
+ include_path = self.context.find_include_file(include, None)
536
+ if include_path:
537
+ if '.' + os.path.sep in include_path:
538
+ include_path = os.path.normpath(include_path)
539
+ all.add(include_path)
540
+ all.update(self.included_files(include_path))
541
+ elif not self.quiet:
542
+ print("Unable to locate '%s' referenced from '%s'" % (filename, include))
543
+ return all
544
+
545
+ @cached_method
546
+ def cimports_externs_incdirs(self, filename):
547
+ # This is really ugly. Nested cimports are resolved with respect to the
548
+ # includer, but includes are resolved with respect to the includee.
549
+ cimports, includes, externs = self.parse_dependencies(filename)[:3]
550
+ cimports = set(cimports)
551
+ externs = set(externs)
552
+ incdirs = set()
553
+ for include in self.included_files(filename):
554
+ included_cimports, included_externs, included_incdirs = self.cimports_externs_incdirs(include)
555
+ cimports.update(included_cimports)
556
+ externs.update(included_externs)
557
+ incdirs.update(included_incdirs)
558
+ externs, incdir = normalize_existing(filename, externs)
559
+ if incdir:
560
+ incdirs.add(incdir)
561
+ return tuple(cimports), externs, incdirs
562
+
563
+ def cimports(self, filename):
564
+ return self.cimports_externs_incdirs(filename)[0]
565
+
566
+ def package(self, filename):
567
+ return package(filename)
568
+
569
+ def fully_qualified_name(self, filename):
570
+ return fully_qualified_name(filename)
571
+
572
+ @cached_method
573
+ def find_pxd(self, module, filename=None):
574
+ is_relative = module[0] == '.'
575
+ if is_relative and not filename:
576
+ raise NotImplementedError("New relative imports.")
577
+ if filename is not None:
578
+ module_path = module.split('.')
579
+ if is_relative:
580
+ module_path.pop(0) # just explicitly relative
581
+ package_path = list(self.package(filename))
582
+ while module_path and not module_path[0]:
583
+ try:
584
+ package_path.pop()
585
+ except IndexError:
586
+ return None # FIXME: error?
587
+ module_path.pop(0)
588
+ relative = '.'.join(package_path + module_path)
589
+ pxd = self.context.find_pxd_file(relative, None)
590
+ if pxd:
591
+ return pxd
592
+ if is_relative:
593
+ return None # FIXME: error?
594
+ return self.context.find_pxd_file(module, None)
595
+
596
+ @cached_method
597
+ def cimported_files(self, filename):
598
+ if filename[-4:] == '.pyx' and path_exists(filename[:-4] + '.pxd'):
599
+ pxd_list = [filename[:-4] + '.pxd']
600
+ else:
601
+ pxd_list = []
602
+ # Cimports generates all possible combinations package.module
603
+ # when imported as from package cimport module.
604
+ for module in self.cimports(filename):
605
+ if module[:7] == 'cython.' or module == 'cython':
606
+ continue
607
+ pxd_file = self.find_pxd(module, filename)
608
+ if pxd_file is not None:
609
+ pxd_list.append(pxd_file)
610
+ return tuple(pxd_list)
611
+
612
+ @cached_method
613
+ def immediate_dependencies(self, filename):
614
+ all = set([filename])
615
+ all.update(self.cimported_files(filename))
616
+ all.update(self.included_files(filename))
617
+ return all
618
+
619
+ def all_dependencies(self, filename):
620
+ return self.transitive_merge(filename, self.immediate_dependencies, set.union)
621
+
622
+ @cached_method
623
+ def timestamp(self, filename):
624
+ return os.path.getmtime(filename)
625
+
626
+ def extract_timestamp(self, filename):
627
+ return self.timestamp(filename), filename
628
+
629
+ def newest_dependency(self, filename):
630
+ return max([self.extract_timestamp(f) for f in self.all_dependencies(filename)])
631
+
632
+ def transitive_fingerprint(self, filename, module, compilation_options):
633
+ r"""
634
+ Return a fingerprint of a cython file that is about to be cythonized.
635
+
636
+ Fingerprints are looked up in future compilations. If the fingerprint
637
+ is found, the cythonization can be skipped. The fingerprint must
638
+ incorporate everything that has an influence on the generated code.
639
+ """
640
+ try:
641
+ m = hashlib.md5(__version__.encode('UTF-8'))
642
+ m.update(file_hash(filename).encode('UTF-8'))
643
+ for x in sorted(self.all_dependencies(filename)):
644
+ if os.path.splitext(x)[1] not in ('.c', '.cpp', '.h'):
645
+ m.update(file_hash(x).encode('UTF-8'))
646
+ # Include the module attributes that change the compilation result
647
+ # in the fingerprint. We do not iterate over module.__dict__ and
648
+ # include almost everything here as users might extend Extension
649
+ # with arbitrary (random) attributes that would lead to cache
650
+ # misses.
651
+ m.update(str((
652
+ module.language,
653
+ getattr(module, 'py_limited_api', False),
654
+ getattr(module, 'np_pythran', False)
655
+ )).encode('UTF-8'))
656
+
657
+ m.update(compilation_options.get_fingerprint().encode('UTF-8'))
658
+ return m.hexdigest()
659
+ except IOError:
660
+ return None
661
+
662
+ def distutils_info0(self, filename):
663
+ info = self.parse_dependencies(filename)[3]
664
+ kwds = info.values
665
+ cimports, externs, incdirs = self.cimports_externs_incdirs(filename)
666
+ basedir = os.getcwd()
667
+ # Add dependencies on "cdef extern from ..." files
668
+ if externs:
669
+ externs = _make_relative(externs, basedir)
670
+ if 'depends' in kwds:
671
+ kwds['depends'] = list(set(kwds['depends']).union(externs))
672
+ else:
673
+ kwds['depends'] = list(externs)
674
+ # Add include_dirs to ensure that the C compiler will find the
675
+ # "cdef extern from ..." files
676
+ if incdirs:
677
+ include_dirs = list(kwds.get('include_dirs', []))
678
+ for inc in _make_relative(incdirs, basedir):
679
+ if inc not in include_dirs:
680
+ include_dirs.append(inc)
681
+ kwds['include_dirs'] = include_dirs
682
+ return info
683
+
684
+ def distutils_info(self, filename, aliases=None, base=None):
685
+ return (self.transitive_merge(filename, self.distutils_info0, DistutilsInfo.merge)
686
+ .subs(aliases)
687
+ .merge(base))
688
+
689
+ def transitive_merge(self, node, extract, merge):
690
+ try:
691
+ seen = self._transitive_cache[extract, merge]
692
+ except KeyError:
693
+ seen = self._transitive_cache[extract, merge] = {}
694
+ return self.transitive_merge_helper(
695
+ node, extract, merge, seen, {}, self.cimported_files)[0]
696
+
697
+ def transitive_merge_helper(self, node, extract, merge, seen, stack, outgoing):
698
+ if node in seen:
699
+ return seen[node], None
700
+ deps = extract(node)
701
+ if node in stack:
702
+ return deps, node
703
+ try:
704
+ stack[node] = len(stack)
705
+ loop = None
706
+ for next in outgoing(node):
707
+ sub_deps, sub_loop = self.transitive_merge_helper(next, extract, merge, seen, stack, outgoing)
708
+ if sub_loop is not None:
709
+ if loop is not None and stack[loop] < stack[sub_loop]:
710
+ pass
711
+ else:
712
+ loop = sub_loop
713
+ deps = merge(deps, sub_deps)
714
+ if loop == node:
715
+ loop = None
716
+ if loop is None:
717
+ seen[node] = deps
718
+ return deps, loop
719
+ finally:
720
+ del stack[node]
721
+
722
+
723
+ _dep_tree = None
724
+
725
+ def create_dependency_tree(ctx=None, quiet=False):
726
+ global _dep_tree
727
+ if _dep_tree is None:
728
+ if ctx is None:
729
+ ctx = Context(["."], CompilationOptions(default_options))
730
+ _dep_tree = DependencyTree(ctx, quiet=quiet)
731
+ return _dep_tree
732
+
733
+
734
+ # If this changes, change also docs/src/reference/compilation.rst
735
+ # which mentions this function
736
+ def default_create_extension(template, kwds):
737
+ if 'depends' in kwds:
738
+ include_dirs = kwds.get('include_dirs', []) + ["."]
739
+ depends = resolve_depends(kwds['depends'], include_dirs)
740
+ kwds['depends'] = sorted(set(depends + template.depends))
741
+
742
+ t = template.__class__
743
+ ext = t(**kwds)
744
+ metadata = dict(distutils=kwds, module_name=kwds['name'])
745
+ return (ext, metadata)
746
+
747
+
748
+ # This may be useful for advanced users?
749
+ def create_extension_list(patterns, exclude=None, ctx=None, aliases=None, quiet=False, language=None,
750
+ exclude_failures=False):
751
+ if language is not None:
752
+ print('Warning: passing language={0!r} to cythonize() is deprecated. '
753
+ 'Instead, put "# distutils: language={0}" in your .pyx or .pxd file(s)'.format(language))
754
+ if exclude is None:
755
+ exclude = []
756
+ if patterns is None:
757
+ return [], {}
758
+ elif isinstance(patterns, basestring) or not isinstance(patterns, Iterable):
759
+ patterns = [patterns]
760
+ explicit_modules = set([m.name for m in patterns if isinstance(m, Extension)])
761
+ seen = set()
762
+ deps = create_dependency_tree(ctx, quiet=quiet)
763
+ to_exclude = set()
764
+ if not isinstance(exclude, list):
765
+ exclude = [exclude]
766
+ for pattern in exclude:
767
+ to_exclude.update(map(os.path.abspath, extended_iglob(pattern)))
768
+
769
+ module_list = []
770
+ module_metadata = {}
771
+
772
+ # workaround for setuptools
773
+ if 'setuptools' in sys.modules:
774
+ Extension_distutils = sys.modules['setuptools.extension']._Extension
775
+ Extension_setuptools = sys.modules['setuptools'].Extension
776
+ else:
777
+ # dummy class, in case we do not have setuptools
778
+ Extension_distutils = Extension
779
+ class Extension_setuptools(Extension): pass
780
+
781
+ # if no create_extension() function is defined, use a simple
782
+ # default function.
783
+ create_extension = ctx.options.create_extension or default_create_extension
784
+
785
+ for pattern in patterns:
786
+ if isinstance(pattern, str):
787
+ filepattern = pattern
788
+ template = Extension(pattern, []) # Fake Extension without sources
789
+ name = '*'
790
+ base = None
791
+ ext_language = language
792
+ elif isinstance(pattern, (Extension_distutils, Extension_setuptools)):
793
+ cython_sources = [s for s in pattern.sources
794
+ if os.path.splitext(s)[1] in ('.py', '.pyx')]
795
+ if cython_sources:
796
+ filepattern = cython_sources[0]
797
+ if len(cython_sources) > 1:
798
+ print("Warning: Multiple cython sources found for extension '%s': %s\n"
799
+ "See http://cython.readthedocs.io/en/latest/src/userguide/sharing_declarations.html "
800
+ "for sharing declarations among Cython files." % (pattern.name, cython_sources))
801
+ else:
802
+ # ignore non-cython modules
803
+ module_list.append(pattern)
804
+ continue
805
+ template = pattern
806
+ name = template.name
807
+ base = DistutilsInfo(exn=template)
808
+ ext_language = None # do not override whatever the Extension says
809
+ else:
810
+ msg = str("pattern is not of type str nor subclass of Extension (%s)"
811
+ " but of type %s and class %s" % (repr(Extension),
812
+ type(pattern),
813
+ pattern.__class__))
814
+ raise TypeError(msg)
815
+
816
+ for file in nonempty(sorted(extended_iglob(filepattern)), "'%s' doesn't match any files" % filepattern):
817
+ if os.path.abspath(file) in to_exclude:
818
+ continue
819
+ module_name = deps.fully_qualified_name(file)
820
+ if '*' in name:
821
+ if module_name in explicit_modules:
822
+ continue
823
+ elif name:
824
+ module_name = name
825
+
826
+ Utils.raise_error_if_module_name_forbidden(module_name)
827
+
828
+ if module_name not in seen:
829
+ try:
830
+ kwds = deps.distutils_info(file, aliases, base).values
831
+ except Exception:
832
+ if exclude_failures:
833
+ continue
834
+ raise
835
+ if base is not None:
836
+ for key, value in base.values.items():
837
+ if key not in kwds:
838
+ kwds[key] = value
839
+
840
+ kwds['name'] = module_name
841
+
842
+ sources = [file] + [m for m in template.sources if m != filepattern]
843
+ if 'sources' in kwds:
844
+ # allow users to add .c files etc.
845
+ for source in kwds['sources']:
846
+ source = encode_filename_in_py2(source)
847
+ if source not in sources:
848
+ sources.append(source)
849
+ kwds['sources'] = sources
850
+
851
+ if ext_language and 'language' not in kwds:
852
+ kwds['language'] = ext_language
853
+
854
+ np_pythran = kwds.pop('np_pythran', False)
855
+
856
+ # Create the new extension
857
+ m, metadata = create_extension(template, kwds)
858
+ m.np_pythran = np_pythran or getattr(m, 'np_pythran', False)
859
+ if m.np_pythran:
860
+ update_pythran_extension(m)
861
+ module_list.append(m)
862
+
863
+ # Store metadata (this will be written as JSON in the
864
+ # generated C file but otherwise has no purpose)
865
+ module_metadata[module_name] = metadata
866
+
867
+ if file not in m.sources:
868
+ # Old setuptools unconditionally replaces .pyx with .c/.cpp
869
+ target_file = os.path.splitext(file)[0] + ('.cpp' if m.language == 'c++' else '.c')
870
+ try:
871
+ m.sources.remove(target_file)
872
+ except ValueError:
873
+ # never seen this in the wild, but probably better to warn about this unexpected case
874
+ print("Warning: Cython source file not found in sources list, adding %s" % file)
875
+ m.sources.insert(0, file)
876
+ seen.add(name)
877
+ return module_list, module_metadata
878
+
879
+
880
+ # This is the user-exposed entry point.
881
+ def cythonize(module_list, exclude=None, nthreads=0, aliases=None, quiet=False, force=False, language=None,
882
+ exclude_failures=False, **options):
883
+ """
884
+ Compile a set of source modules into C/C++ files and return a list of distutils
885
+ Extension objects for them.
886
+
887
+ :param module_list: As module list, pass either a glob pattern, a list of glob
888
+ patterns or a list of Extension objects. The latter
889
+ allows you to configure the extensions separately
890
+ through the normal distutils options.
891
+ You can also pass Extension objects that have
892
+ glob patterns as their sources. Then, cythonize
893
+ will resolve the pattern and create a
894
+ copy of the Extension for every matching file.
895
+
896
+ :param exclude: When passing glob patterns as ``module_list``, you can exclude certain
897
+ module names explicitly by passing them into the ``exclude`` option.
898
+
899
+ :param nthreads: The number of concurrent builds for parallel compilation
900
+ (requires the ``multiprocessing`` module).
901
+
902
+ :param aliases: If you want to use compiler directives like ``# distutils: ...`` but
903
+ can only know at compile time (when running the ``setup.py``) which values
904
+ to use, you can use aliases and pass a dictionary mapping those aliases
905
+ to Python strings when calling :func:`cythonize`. As an example, say you
906
+ want to use the compiler
907
+ directive ``# distutils: include_dirs = ../static_libs/include/``
908
+ but this path isn't always fixed and you want to find it when running
909
+ the ``setup.py``. You can then do ``# distutils: include_dirs = MY_HEADERS``,
910
+ find the value of ``MY_HEADERS`` in the ``setup.py``, put it in a python
911
+ variable called ``foo`` as a string, and then call
912
+ ``cythonize(..., aliases={'MY_HEADERS': foo})``.
913
+
914
+ :param quiet: If True, Cython won't print error, warning, or status messages during the
915
+ compilation.
916
+
917
+ :param force: Forces the recompilation of the Cython modules, even if the timestamps
918
+ don't indicate that a recompilation is necessary.
919
+
920
+ :param language: To globally enable C++ mode, you can pass ``language='c++'``. Otherwise, this
921
+ will be determined at a per-file level based on compiler directives. This
922
+ affects only modules found based on file names. Extension instances passed
923
+ into :func:`cythonize` will not be changed. It is recommended to rather
924
+ use the compiler directive ``# distutils: language = c++`` than this option.
925
+
926
+ :param exclude_failures: For a broad 'try to compile' mode that ignores compilation
927
+ failures and simply excludes the failed extensions,
928
+ pass ``exclude_failures=True``. Note that this only
929
+ really makes sense for compiling ``.py`` files which can also
930
+ be used without compilation.
931
+
932
+ :param annotate: If ``True``, will produce a HTML file for each of the ``.pyx`` or ``.py``
933
+ files compiled. The HTML file gives an indication
934
+ of how much Python interaction there is in
935
+ each of the source code lines, compared to plain C code.
936
+ It also allows you to see the C/C++ code
937
+ generated for each line of Cython code. This report is invaluable when
938
+ optimizing a function for speed,
939
+ and for determining when to :ref:`release the GIL <nogil>`:
940
+ in general, a ``nogil`` block may contain only "white" code.
941
+ See examples in :ref:`determining_where_to_add_types` or
942
+ :ref:`primes`.
943
+
944
+ :param compiler_directives: Allow to set compiler directives in the ``setup.py`` like this:
945
+ ``compiler_directives={'embedsignature': True}``.
946
+ See :ref:`compiler-directives`.
947
+
948
+ :param depfile: produce depfiles for the sources if True.
949
+ """
950
+ if exclude is None:
951
+ exclude = []
952
+ if 'include_path' not in options:
953
+ options['include_path'] = ['.']
954
+ if 'common_utility_include_dir' in options:
955
+ safe_makedirs(options['common_utility_include_dir'])
956
+
957
+ depfile = options.pop('depfile', None)
958
+
959
+ if pythran is None:
960
+ pythran_options = None
961
+ else:
962
+ pythran_options = CompilationOptions(**options)
963
+ pythran_options.cplus = True
964
+ pythran_options.np_pythran = True
965
+
966
+ if force is None:
967
+ force = os.environ.get("CYTHON_FORCE_REGEN") == "1" # allow global overrides for build systems
968
+
969
+ c_options = CompilationOptions(**options)
970
+ cpp_options = CompilationOptions(**options); cpp_options.cplus = True
971
+ ctx = c_options.create_context()
972
+ options = c_options
973
+ module_list, module_metadata = create_extension_list(
974
+ module_list,
975
+ exclude=exclude,
976
+ ctx=ctx,
977
+ quiet=quiet,
978
+ exclude_failures=exclude_failures,
979
+ language=language,
980
+ aliases=aliases)
981
+ deps = create_dependency_tree(ctx, quiet=quiet)
982
+ build_dir = getattr(options, 'build_dir', None)
983
+
984
+ def copy_to_build_dir(filepath, root=os.getcwd()):
985
+ filepath_abs = os.path.abspath(filepath)
986
+ if os.path.isabs(filepath):
987
+ filepath = filepath_abs
988
+ if filepath_abs.startswith(root):
989
+ # distutil extension depends are relative to cwd
990
+ mod_dir = join_path(build_dir,
991
+ os.path.dirname(_relpath(filepath, root)))
992
+ copy_once_if_newer(filepath_abs, mod_dir)
993
+
994
+ modules_by_cfile = collections.defaultdict(list)
995
+ to_compile = []
996
+ for m in module_list:
997
+ if build_dir:
998
+ for dep in m.depends:
999
+ copy_to_build_dir(dep)
1000
+
1001
+ cy_sources = [
1002
+ source for source in m.sources
1003
+ if os.path.splitext(source)[1] in ('.pyx', '.py')]
1004
+ if len(cy_sources) == 1:
1005
+ # normal "special" case: believe the Extension module name to allow user overrides
1006
+ full_module_name = m.name
1007
+ else:
1008
+ # infer FQMN from source files
1009
+ full_module_name = None
1010
+
1011
+ new_sources = []
1012
+ for source in m.sources:
1013
+ base, ext = os.path.splitext(source)
1014
+ if ext in ('.pyx', '.py'):
1015
+ if m.np_pythran:
1016
+ c_file = base + '.cpp'
1017
+ options = pythran_options
1018
+ elif m.language == 'c++':
1019
+ c_file = base + '.cpp'
1020
+ options = cpp_options
1021
+ else:
1022
+ c_file = base + '.c'
1023
+ options = c_options
1024
+
1025
+ # setup for out of place build directory if enabled
1026
+ if build_dir:
1027
+ if os.path.isabs(c_file):
1028
+ warnings.warn("build_dir has no effect for absolute source paths")
1029
+ c_file = os.path.join(build_dir, c_file)
1030
+ dir = os.path.dirname(c_file)
1031
+ safe_makedirs_once(dir)
1032
+
1033
+ # write out the depfile, if requested
1034
+ if depfile:
1035
+ dependencies = deps.all_dependencies(source)
1036
+ write_depfile(c_file, source, dependencies)
1037
+
1038
+ if os.path.exists(c_file):
1039
+ c_timestamp = os.path.getmtime(c_file)
1040
+ else:
1041
+ c_timestamp = -1
1042
+
1043
+ # Priority goes first to modified files, second to direct
1044
+ # dependents, and finally to indirect dependents.
1045
+ if c_timestamp < deps.timestamp(source):
1046
+ dep_timestamp, dep = deps.timestamp(source), source
1047
+ priority = 0
1048
+ else:
1049
+ dep_timestamp, dep = deps.newest_dependency(source)
1050
+ priority = 2 - (dep in deps.immediate_dependencies(source))
1051
+ if force or c_timestamp < dep_timestamp:
1052
+ if not quiet and not force:
1053
+ if source == dep:
1054
+ print("Compiling %s because it changed." % source)
1055
+ else:
1056
+ print("Compiling %s because it depends on %s." % (source, dep))
1057
+ if not force and options.cache:
1058
+ fingerprint = deps.transitive_fingerprint(source, m, options)
1059
+ else:
1060
+ fingerprint = None
1061
+ to_compile.append((
1062
+ priority, source, c_file, fingerprint, quiet,
1063
+ options, not exclude_failures, module_metadata.get(m.name),
1064
+ full_module_name))
1065
+ new_sources.append(c_file)
1066
+ modules_by_cfile[c_file].append(m)
1067
+ else:
1068
+ new_sources.append(source)
1069
+ if build_dir:
1070
+ copy_to_build_dir(source)
1071
+ m.sources = new_sources
1072
+
1073
+ if options.cache:
1074
+ if not os.path.exists(options.cache):
1075
+ os.makedirs(options.cache)
1076
+ to_compile.sort()
1077
+ # Drop "priority" component of "to_compile" entries and add a
1078
+ # simple progress indicator.
1079
+ N = len(to_compile)
1080
+ progress_fmt = "[{0:%d}/{1}] " % len(str(N))
1081
+ for i in range(N):
1082
+ progress = progress_fmt.format(i+1, N)
1083
+ to_compile[i] = to_compile[i][1:] + (progress,)
1084
+
1085
+ if N <= 1:
1086
+ nthreads = 0
1087
+ if nthreads:
1088
+ # Requires multiprocessing (or Python >= 2.6)
1089
+ try:
1090
+ import multiprocessing
1091
+ pool = multiprocessing.Pool(
1092
+ nthreads, initializer=_init_multiprocessing_helper)
1093
+ except (ImportError, OSError):
1094
+ print("multiprocessing required for parallel cythonization")
1095
+ nthreads = 0
1096
+ else:
1097
+ # This is a bit more involved than it should be, because KeyboardInterrupts
1098
+ # break the multiprocessing workers when using a normal pool.map().
1099
+ # See, for example:
1100
+ # http://noswap.com/blog/python-multiprocessing-keyboardinterrupt
1101
+ try:
1102
+ result = pool.map_async(cythonize_one_helper, to_compile, chunksize=1)
1103
+ pool.close()
1104
+ while not result.ready():
1105
+ try:
1106
+ result.get(99999) # seconds
1107
+ except multiprocessing.TimeoutError:
1108
+ pass
1109
+ except KeyboardInterrupt:
1110
+ pool.terminate()
1111
+ raise
1112
+ pool.join()
1113
+ if not nthreads:
1114
+ for args in to_compile:
1115
+ cythonize_one(*args)
1116
+
1117
+ if exclude_failures:
1118
+ failed_modules = set()
1119
+ for c_file, modules in modules_by_cfile.items():
1120
+ if not os.path.exists(c_file):
1121
+ failed_modules.update(modules)
1122
+ elif os.path.getsize(c_file) < 200:
1123
+ f = io_open(c_file, 'r', encoding='iso8859-1')
1124
+ try:
1125
+ if f.read(len('#error ')) == '#error ':
1126
+ # dead compilation result
1127
+ failed_modules.update(modules)
1128
+ finally:
1129
+ f.close()
1130
+ if failed_modules:
1131
+ for module in failed_modules:
1132
+ module_list.remove(module)
1133
+ print("Failed compilations: %s" % ', '.join(sorted([
1134
+ module.name for module in failed_modules])))
1135
+
1136
+ if options.cache:
1137
+ cleanup_cache(options.cache, getattr(options, 'cache_size', 1024 * 1024 * 100))
1138
+ # cythonize() is often followed by the (non-Python-buffered)
1139
+ # compiler output, flush now to avoid interleaving output.
1140
+ sys.stdout.flush()
1141
+ return module_list
1142
+
1143
+
1144
+ if os.environ.get('XML_RESULTS'):
1145
+ compile_result_dir = os.environ['XML_RESULTS']
1146
+ def record_results(func):
1147
+ def with_record(*args):
1148
+ t = time.time()
1149
+ success = True
1150
+ try:
1151
+ try:
1152
+ func(*args)
1153
+ except:
1154
+ success = False
1155
+ finally:
1156
+ t = time.time() - t
1157
+ module = fully_qualified_name(args[0])
1158
+ name = "cythonize." + module
1159
+ failures = 1 - success
1160
+ if success:
1161
+ failure_item = ""
1162
+ else:
1163
+ failure_item = "failure"
1164
+ output = open(os.path.join(compile_result_dir, name + ".xml"), "w")
1165
+ output.write("""
1166
+ <?xml version="1.0" ?>
1167
+ <testsuite name="%(name)s" errors="0" failures="%(failures)s" tests="1" time="%(t)s">
1168
+ <testcase classname="%(name)s" name="cythonize">
1169
+ %(failure_item)s
1170
+ </testcase>
1171
+ </testsuite>
1172
+ """.strip() % locals())
1173
+ output.close()
1174
+ return with_record
1175
+ else:
1176
+ def record_results(func):
1177
+ return func
1178
+
1179
+
1180
+ # TODO: Share context? Issue: pyx processing leaks into pxd module
1181
+ @record_results
1182
+ def cythonize_one(pyx_file, c_file, fingerprint, quiet, options=None,
1183
+ raise_on_failure=True, embedded_metadata=None, full_module_name=None,
1184
+ progress=""):
1185
+ from ..Compiler.Main import compile_single, default_options
1186
+ from ..Compiler.Errors import CompileError, PyrexError
1187
+
1188
+ if fingerprint:
1189
+ if not os.path.exists(options.cache):
1190
+ safe_makedirs(options.cache)
1191
+ # Cython-generated c files are highly compressible.
1192
+ # (E.g. a compression ratio of about 10 for Sage).
1193
+ fingerprint_file_base = join_path(
1194
+ options.cache, "%s-%s" % (os.path.basename(c_file), fingerprint))
1195
+ gz_fingerprint_file = fingerprint_file_base + gzip_ext
1196
+ zip_fingerprint_file = fingerprint_file_base + '.zip'
1197
+ if os.path.exists(gz_fingerprint_file) or os.path.exists(zip_fingerprint_file):
1198
+ if not quiet:
1199
+ print("%sFound compiled %s in cache" % (progress, pyx_file))
1200
+ if os.path.exists(gz_fingerprint_file):
1201
+ os.utime(gz_fingerprint_file, None)
1202
+ with contextlib.closing(gzip_open(gz_fingerprint_file, 'rb')) as g:
1203
+ with contextlib.closing(open(c_file, 'wb')) as f:
1204
+ shutil.copyfileobj(g, f)
1205
+ else:
1206
+ os.utime(zip_fingerprint_file, None)
1207
+ dirname = os.path.dirname(c_file)
1208
+ with contextlib.closing(zipfile.ZipFile(zip_fingerprint_file)) as z:
1209
+ for artifact in z.namelist():
1210
+ z.extract(artifact, os.path.join(dirname, artifact))
1211
+ return
1212
+ if not quiet:
1213
+ print("%sCythonizing %s" % (progress, pyx_file))
1214
+ if options is None:
1215
+ options = CompilationOptions(default_options)
1216
+ options.output_file = c_file
1217
+ options.embedded_metadata = embedded_metadata
1218
+
1219
+ any_failures = 0
1220
+ try:
1221
+ result = compile_single(pyx_file, options, full_module_name=full_module_name)
1222
+ if result.num_errors > 0:
1223
+ any_failures = 1
1224
+ except (EnvironmentError, PyrexError) as e:
1225
+ sys.stderr.write('%s\n' % e)
1226
+ any_failures = 1
1227
+ # XXX
1228
+ import traceback
1229
+ traceback.print_exc()
1230
+ except Exception:
1231
+ if raise_on_failure:
1232
+ raise
1233
+ import traceback
1234
+ traceback.print_exc()
1235
+ any_failures = 1
1236
+ if any_failures:
1237
+ if raise_on_failure:
1238
+ raise CompileError(None, pyx_file)
1239
+ elif os.path.exists(c_file):
1240
+ os.remove(c_file)
1241
+ elif fingerprint:
1242
+ artifacts = list(filter(None, [
1243
+ getattr(result, attr, None)
1244
+ for attr in ('c_file', 'h_file', 'api_file', 'i_file')]))
1245
+ if len(artifacts) == 1:
1246
+ fingerprint_file = gz_fingerprint_file
1247
+ with contextlib.closing(open(c_file, 'rb')) as f:
1248
+ with contextlib.closing(gzip_open(fingerprint_file + '.tmp', 'wb')) as g:
1249
+ shutil.copyfileobj(f, g)
1250
+ else:
1251
+ fingerprint_file = zip_fingerprint_file
1252
+ with contextlib.closing(zipfile.ZipFile(
1253
+ fingerprint_file + '.tmp', 'w', zipfile_compression_mode)) as zip:
1254
+ for artifact in artifacts:
1255
+ zip.write(artifact, os.path.basename(artifact))
1256
+ os.rename(fingerprint_file + '.tmp', fingerprint_file)
1257
+
1258
+
1259
+ def cythonize_one_helper(m):
1260
+ import traceback
1261
+ try:
1262
+ return cythonize_one(*m)
1263
+ except Exception:
1264
+ traceback.print_exc()
1265
+ raise
1266
+
1267
+
1268
+ def _init_multiprocessing_helper():
1269
+ # KeyboardInterrupt kills workers, so don't let them get it
1270
+ import signal
1271
+ signal.signal(signal.SIGINT, signal.SIG_IGN)
1272
+
1273
+
1274
+ def cleanup_cache(cache, target_size, ratio=.85):
1275
+ try:
1276
+ p = subprocess.Popen(['du', '-s', '-k', os.path.abspath(cache)], stdout=subprocess.PIPE)
1277
+ res = p.wait()
1278
+ if res == 0:
1279
+ total_size = 1024 * int(p.stdout.read().strip().split()[0])
1280
+ if total_size < target_size:
1281
+ return
1282
+ except (OSError, ValueError):
1283
+ pass
1284
+ total_size = 0
1285
+ all = []
1286
+ for file in os.listdir(cache):
1287
+ path = join_path(cache, file)
1288
+ s = os.stat(path)
1289
+ total_size += s.st_size
1290
+ all.append((s.st_atime, s.st_size, path))
1291
+ if total_size > target_size:
1292
+ for time, size, file in reversed(sorted(all)):
1293
+ os.unlink(file)
1294
+ total_size -= size
1295
+ if total_size < target_size * ratio:
1296
+ break
venv/Lib/site-packages/Cython/Build/Distutils.py ADDED
@@ -0,0 +1 @@
 
 
1
+ from Cython.Distutils.build_ext import build_ext
venv/Lib/site-packages/Cython/Build/Inline.py ADDED
@@ -0,0 +1,377 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from __future__ import absolute_import
2
+
3
+ import hashlib
4
+ import inspect
5
+ import os
6
+ import re
7
+ import sys
8
+
9
+ from distutils.core import Distribution, Extension
10
+ from distutils.command.build_ext import build_ext
11
+
12
+ import Cython
13
+ from ..Compiler.Main import Context, default_options
14
+
15
+ from ..Compiler.Visitor import CythonTransform, EnvTransform
16
+ from ..Compiler.ParseTreeTransforms import SkipDeclarations
17
+ from ..Compiler.TreeFragment import parse_from_strings
18
+ from ..Compiler.StringEncoding import _unicode
19
+ from .Dependencies import strip_string_literals, cythonize, cached_function
20
+ from ..Compiler import Pipeline
21
+ from ..Utils import get_cython_cache_dir
22
+ import cython as cython_module
23
+
24
+
25
+ IS_PY3 = sys.version_info >= (3,)
26
+
27
+ # A utility function to convert user-supplied ASCII strings to unicode.
28
+ if not IS_PY3:
29
+ def to_unicode(s):
30
+ if isinstance(s, bytes):
31
+ return s.decode('ascii')
32
+ else:
33
+ return s
34
+ else:
35
+ to_unicode = lambda x: x
36
+
37
+ if sys.version_info < (3, 5):
38
+ import imp
39
+ def load_dynamic(name, module_path):
40
+ return imp.load_dynamic(name, module_path)
41
+ else:
42
+ import importlib.util
43
+ from importlib.machinery import ExtensionFileLoader
44
+
45
+ def load_dynamic(name, path):
46
+ spec = importlib.util.spec_from_file_location(name, loader=ExtensionFileLoader(name, path))
47
+ module = importlib.util.module_from_spec(spec)
48
+ spec.loader.exec_module(module)
49
+ return module
50
+
51
+ class UnboundSymbols(EnvTransform, SkipDeclarations):
52
+ def __init__(self):
53
+ CythonTransform.__init__(self, None)
54
+ self.unbound = set()
55
+ def visit_NameNode(self, node):
56
+ if not self.current_env().lookup(node.name):
57
+ self.unbound.add(node.name)
58
+ return node
59
+ def __call__(self, node):
60
+ super(UnboundSymbols, self).__call__(node)
61
+ return self.unbound
62
+
63
+
64
+ @cached_function
65
+ def unbound_symbols(code, context=None):
66
+ code = to_unicode(code)
67
+ if context is None:
68
+ context = Context([], default_options)
69
+ from ..Compiler.ParseTreeTransforms import AnalyseDeclarationsTransform
70
+ tree = parse_from_strings('(tree fragment)', code)
71
+ for phase in Pipeline.create_pipeline(context, 'pyx'):
72
+ if phase is None:
73
+ continue
74
+ tree = phase(tree)
75
+ if isinstance(phase, AnalyseDeclarationsTransform):
76
+ break
77
+ try:
78
+ import builtins
79
+ except ImportError:
80
+ import __builtin__ as builtins
81
+ return tuple(UnboundSymbols()(tree) - set(dir(builtins)))
82
+
83
+
84
+ def unsafe_type(arg, context=None):
85
+ py_type = type(arg)
86
+ if py_type is int:
87
+ return 'long'
88
+ else:
89
+ return safe_type(arg, context)
90
+
91
+
92
+ def safe_type(arg, context=None):
93
+ py_type = type(arg)
94
+ if py_type in (list, tuple, dict, str):
95
+ return py_type.__name__
96
+ elif py_type is complex:
97
+ return 'double complex'
98
+ elif py_type is float:
99
+ return 'double'
100
+ elif py_type is bool:
101
+ return 'bint'
102
+ elif 'numpy' in sys.modules and isinstance(arg, sys.modules['numpy'].ndarray):
103
+ return 'numpy.ndarray[numpy.%s_t, ndim=%s]' % (arg.dtype.name, arg.ndim)
104
+ else:
105
+ for base_type in py_type.__mro__:
106
+ if base_type.__module__ in ('__builtin__', 'builtins'):
107
+ return 'object'
108
+ module = context.find_module(base_type.__module__, need_pxd=False)
109
+ if module:
110
+ entry = module.lookup(base_type.__name__)
111
+ if entry.is_type:
112
+ return '%s.%s' % (base_type.__module__, base_type.__name__)
113
+ return 'object'
114
+
115
+
116
+ def _get_build_extension():
117
+ dist = Distribution()
118
+ # Ensure the build respects distutils configuration by parsing
119
+ # the configuration files
120
+ config_files = dist.find_config_files()
121
+ dist.parse_config_files(config_files)
122
+ build_extension = build_ext(dist)
123
+ build_extension.finalize_options()
124
+ return build_extension
125
+
126
+
127
+ @cached_function
128
+ def _create_context(cython_include_dirs):
129
+ return Context(list(cython_include_dirs), default_options)
130
+
131
+
132
+ _cython_inline_cache = {}
133
+ _cython_inline_default_context = _create_context(('.',))
134
+
135
+
136
+ def _populate_unbound(kwds, unbound_symbols, locals=None, globals=None):
137
+ for symbol in unbound_symbols:
138
+ if symbol not in kwds:
139
+ if locals is None or globals is None:
140
+ calling_frame = inspect.currentframe().f_back.f_back.f_back
141
+ if locals is None:
142
+ locals = calling_frame.f_locals
143
+ if globals is None:
144
+ globals = calling_frame.f_globals
145
+ if symbol in locals:
146
+ kwds[symbol] = locals[symbol]
147
+ elif symbol in globals:
148
+ kwds[symbol] = globals[symbol]
149
+ else:
150
+ print("Couldn't find %r" % symbol)
151
+
152
+
153
+ def _inline_key(orig_code, arg_sigs, language_level):
154
+ key = orig_code, arg_sigs, sys.version_info, sys.executable, language_level, Cython.__version__
155
+ return hashlib.sha1(_unicode(key).encode('utf-8')).hexdigest()
156
+
157
+
158
+ def cython_inline(code, get_type=unsafe_type,
159
+ lib_dir=os.path.join(get_cython_cache_dir(), 'inline'),
160
+ cython_include_dirs=None, cython_compiler_directives=None,
161
+ force=False, quiet=False, locals=None, globals=None, language_level=None, **kwds):
162
+
163
+ if get_type is None:
164
+ get_type = lambda x: 'object'
165
+ ctx = _create_context(tuple(cython_include_dirs)) if cython_include_dirs else _cython_inline_default_context
166
+
167
+ cython_compiler_directives = dict(cython_compiler_directives) if cython_compiler_directives else {}
168
+ if language_level is None and 'language_level' not in cython_compiler_directives:
169
+ language_level = '3str'
170
+ if language_level is not None:
171
+ cython_compiler_directives['language_level'] = language_level
172
+
173
+ # Fast path if this has been called in this session.
174
+ _unbound_symbols = _cython_inline_cache.get(code)
175
+ if _unbound_symbols is not None:
176
+ _populate_unbound(kwds, _unbound_symbols, locals, globals)
177
+ args = sorted(kwds.items())
178
+ arg_sigs = tuple([(get_type(value, ctx), arg) for arg, value in args])
179
+ key_hash = _inline_key(code, arg_sigs, language_level)
180
+ invoke = _cython_inline_cache.get((code, arg_sigs, key_hash))
181
+ if invoke is not None:
182
+ arg_list = [arg[1] for arg in args]
183
+ return invoke(*arg_list)
184
+
185
+ orig_code = code
186
+ code = to_unicode(code)
187
+ code, literals = strip_string_literals(code)
188
+ code = strip_common_indent(code)
189
+ if locals is None:
190
+ locals = inspect.currentframe().f_back.f_back.f_locals
191
+ if globals is None:
192
+ globals = inspect.currentframe().f_back.f_back.f_globals
193
+ try:
194
+ _cython_inline_cache[orig_code] = _unbound_symbols = unbound_symbols(code)
195
+ _populate_unbound(kwds, _unbound_symbols, locals, globals)
196
+ except AssertionError:
197
+ if not quiet:
198
+ # Parsing from strings not fully supported (e.g. cimports).
199
+ print("Could not parse code as a string (to extract unbound symbols).")
200
+
201
+ cimports = []
202
+ for name, arg in list(kwds.items()):
203
+ if arg is cython_module:
204
+ cimports.append('\ncimport cython as %s' % name)
205
+ del kwds[name]
206
+ arg_names = sorted(kwds)
207
+ arg_sigs = tuple([(get_type(kwds[arg], ctx), arg) for arg in arg_names])
208
+ key_hash = _inline_key(orig_code, arg_sigs, language_level)
209
+ module_name = "_cython_inline_" + key_hash
210
+
211
+ if module_name in sys.modules:
212
+ module = sys.modules[module_name]
213
+
214
+ else:
215
+ build_extension = None
216
+ if cython_inline.so_ext is None:
217
+ # Figure out and cache current extension suffix
218
+ build_extension = _get_build_extension()
219
+ cython_inline.so_ext = build_extension.get_ext_filename('')
220
+
221
+ module_path = os.path.join(lib_dir, module_name + cython_inline.so_ext)
222
+
223
+ if not os.path.exists(lib_dir):
224
+ os.makedirs(lib_dir)
225
+ if force or not os.path.isfile(module_path):
226
+ cflags = []
227
+ c_include_dirs = []
228
+ qualified = re.compile(r'([.\w]+)[.]')
229
+ for type, _ in arg_sigs:
230
+ m = qualified.match(type)
231
+ if m:
232
+ cimports.append('\ncimport %s' % m.groups()[0])
233
+ # one special case
234
+ if m.groups()[0] == 'numpy':
235
+ import numpy
236
+ c_include_dirs.append(numpy.get_include())
237
+ # cflags.append('-Wno-unused')
238
+ module_body, func_body = extract_func_code(code)
239
+ params = ', '.join(['%s %s' % a for a in arg_sigs])
240
+ module_code = """
241
+ %(module_body)s
242
+ %(cimports)s
243
+ def __invoke(%(params)s):
244
+ %(func_body)s
245
+ return locals()
246
+ """ % {'cimports': '\n'.join(cimports),
247
+ 'module_body': module_body,
248
+ 'params': params,
249
+ 'func_body': func_body }
250
+ for key, value in literals.items():
251
+ module_code = module_code.replace(key, value)
252
+ pyx_file = os.path.join(lib_dir, module_name + '.pyx')
253
+ fh = open(pyx_file, 'w')
254
+ try:
255
+ fh.write(module_code)
256
+ finally:
257
+ fh.close()
258
+ extension = Extension(
259
+ name = module_name,
260
+ sources = [pyx_file],
261
+ include_dirs = c_include_dirs,
262
+ extra_compile_args = cflags)
263
+ if build_extension is None:
264
+ build_extension = _get_build_extension()
265
+ build_extension.extensions = cythonize(
266
+ [extension],
267
+ include_path=cython_include_dirs or ['.'],
268
+ compiler_directives=cython_compiler_directives,
269
+ quiet=quiet)
270
+ build_extension.build_temp = os.path.dirname(pyx_file)
271
+ build_extension.build_lib = lib_dir
272
+ build_extension.run()
273
+
274
+ module = load_dynamic(module_name, module_path)
275
+
276
+ _cython_inline_cache[orig_code, arg_sigs, key_hash] = module.__invoke
277
+ arg_list = [kwds[arg] for arg in arg_names]
278
+ return module.__invoke(*arg_list)
279
+
280
+
281
+ # Cached suffix used by cython_inline above. None should get
282
+ # overridden with actual value upon the first cython_inline invocation
283
+ cython_inline.so_ext = None
284
+
285
+ _find_non_space = re.compile('[^ ]').search
286
+
287
+
288
+ def strip_common_indent(code):
289
+ min_indent = None
290
+ lines = code.splitlines()
291
+ for line in lines:
292
+ match = _find_non_space(line)
293
+ if not match:
294
+ continue # blank
295
+ indent = match.start()
296
+ if line[indent] == '#':
297
+ continue # comment
298
+ if min_indent is None or min_indent > indent:
299
+ min_indent = indent
300
+ for ix, line in enumerate(lines):
301
+ match = _find_non_space(line)
302
+ if not match or not line or line[indent:indent+1] == '#':
303
+ continue
304
+ lines[ix] = line[min_indent:]
305
+ return '\n'.join(lines)
306
+
307
+
308
+ module_statement = re.compile(r'^((cdef +(extern|class))|cimport|(from .+ cimport)|(from .+ import +[*]))')
309
+ def extract_func_code(code):
310
+ module = []
311
+ function = []
312
+ current = function
313
+ code = code.replace('\t', ' ')
314
+ lines = code.split('\n')
315
+ for line in lines:
316
+ if not line.startswith(' '):
317
+ if module_statement.match(line):
318
+ current = module
319
+ else:
320
+ current = function
321
+ current.append(line)
322
+ return '\n'.join(module), ' ' + '\n '.join(function)
323
+
324
+
325
+ try:
326
+ from inspect import getcallargs
327
+ except ImportError:
328
+ def getcallargs(func, *arg_values, **kwd_values):
329
+ all = {}
330
+ args, varargs, kwds, defaults = inspect.getargspec(func)
331
+ if varargs is not None:
332
+ all[varargs] = arg_values[len(args):]
333
+ for name, value in zip(args, arg_values):
334
+ all[name] = value
335
+ for name, value in list(kwd_values.items()):
336
+ if name in args:
337
+ if name in all:
338
+ raise TypeError("Duplicate argument %s" % name)
339
+ all[name] = kwd_values.pop(name)
340
+ if kwds is not None:
341
+ all[kwds] = kwd_values
342
+ elif kwd_values:
343
+ raise TypeError("Unexpected keyword arguments: %s" % list(kwd_values))
344
+ if defaults is None:
345
+ defaults = ()
346
+ first_default = len(args) - len(defaults)
347
+ for ix, name in enumerate(args):
348
+ if name not in all:
349
+ if ix >= first_default:
350
+ all[name] = defaults[ix - first_default]
351
+ else:
352
+ raise TypeError("Missing argument: %s" % name)
353
+ return all
354
+
355
+
356
+ def get_body(source):
357
+ ix = source.index(':')
358
+ if source[:5] == 'lambda':
359
+ return "return %s" % source[ix+1:]
360
+ else:
361
+ return source[ix+1:]
362
+
363
+
364
+ # Lots to be done here... It would be especially cool if compiled functions
365
+ # could invoke each other quickly.
366
+ class RuntimeCompiledFunction(object):
367
+
368
+ def __init__(self, f):
369
+ self._f = f
370
+ self._body = get_body(inspect.getsource(f))
371
+
372
+ def __call__(self, *args, **kwds):
373
+ all = getcallargs(self._f, *args, **kwds)
374
+ if IS_PY3:
375
+ return cython_inline(self._body, locals=self._f.__globals__, globals=self._f.__globals__, **all)
376
+ else:
377
+ return cython_inline(self._body, locals=self._f.func_globals, globals=self._f.func_globals, **all)
venv/Lib/site-packages/Cython/Build/IpythonMagic.py ADDED
@@ -0,0 +1,564 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # -*- coding: utf-8 -*-
2
+ """
3
+ =====================
4
+ Cython related magics
5
+ =====================
6
+
7
+ Magic command interface for interactive work with Cython
8
+
9
+ .. note::
10
+
11
+ The ``Cython`` package needs to be installed separately. It
12
+ can be obtained using ``easy_install`` or ``pip``.
13
+
14
+ Usage
15
+ =====
16
+
17
+ To enable the magics below, execute ``%load_ext cython``.
18
+
19
+ ``%%cython``
20
+
21
+ {CYTHON_DOC}
22
+
23
+ ``%%cython_inline``
24
+
25
+ {CYTHON_INLINE_DOC}
26
+
27
+ ``%%cython_pyximport``
28
+
29
+ {CYTHON_PYXIMPORT_DOC}
30
+
31
+ Author:
32
+ * Brian Granger
33
+
34
+ Code moved from IPython and adapted by:
35
+ * Martín Gaitán
36
+
37
+ Parts of this code were taken from Cython.inline.
38
+ """
39
+ #-----------------------------------------------------------------------------
40
+ # Copyright (C) 2010-2011, IPython Development Team.
41
+ #
42
+ # Distributed under the terms of the Modified BSD License.
43
+ #
44
+ # The full license is in the file ipython-COPYING.rst, distributed with this software.
45
+ #-----------------------------------------------------------------------------
46
+
47
+ from __future__ import absolute_import, print_function
48
+
49
+ import io
50
+ import os
51
+ import re
52
+ import sys
53
+ import time
54
+ import copy
55
+ import distutils.log
56
+ import textwrap
57
+
58
+ IO_ENCODING = sys.getfilesystemencoding()
59
+ IS_PY2 = sys.version_info[0] < 3
60
+
61
+ try:
62
+ reload
63
+ except NameError: # Python 3
64
+ from imp import reload
65
+
66
+ try:
67
+ import hashlib
68
+ except ImportError:
69
+ import md5 as hashlib
70
+
71
+ from distutils.core import Distribution, Extension
72
+ from distutils.command.build_ext import build_ext
73
+
74
+ from IPython.core import display
75
+ from IPython.core import magic_arguments
76
+ from IPython.core.magic import Magics, magics_class, cell_magic
77
+ try:
78
+ from IPython.paths import get_ipython_cache_dir
79
+ except ImportError:
80
+ # older IPython version
81
+ from IPython.utils.path import get_ipython_cache_dir
82
+ from IPython.utils.text import dedent
83
+
84
+ from ..Shadow import __version__ as cython_version
85
+ from ..Compiler.Errors import CompileError
86
+ from .Inline import cython_inline, load_dynamic
87
+ from .Dependencies import cythonize
88
+
89
+
90
+ PGO_CONFIG = {
91
+ 'gcc': {
92
+ 'gen': ['-fprofile-generate', '-fprofile-dir={TEMPDIR}'],
93
+ 'use': ['-fprofile-use', '-fprofile-correction', '-fprofile-dir={TEMPDIR}'],
94
+ },
95
+ # blind copy from 'configure' script in CPython 3.7
96
+ 'icc': {
97
+ 'gen': ['-prof-gen'],
98
+ 'use': ['-prof-use'],
99
+ }
100
+ }
101
+ PGO_CONFIG['mingw32'] = PGO_CONFIG['gcc']
102
+
103
+
104
+ if IS_PY2:
105
+ def encode_fs(name):
106
+ return name if isinstance(name, bytes) else name.encode(IO_ENCODING)
107
+ else:
108
+ def encode_fs(name):
109
+ return name
110
+
111
+
112
+ @magics_class
113
+ class CythonMagics(Magics):
114
+
115
+ def __init__(self, shell):
116
+ super(CythonMagics, self).__init__(shell)
117
+ self._reloads = {}
118
+ self._code_cache = {}
119
+ self._pyximport_installed = False
120
+
121
+ def _import_all(self, module):
122
+ mdict = module.__dict__
123
+ if '__all__' in mdict:
124
+ keys = mdict['__all__']
125
+ else:
126
+ keys = [k for k in mdict if not k.startswith('_')]
127
+
128
+ for k in keys:
129
+ try:
130
+ self.shell.push({k: mdict[k]})
131
+ except KeyError:
132
+ msg = "'module' object has no attribute '%s'" % k
133
+ raise AttributeError(msg)
134
+
135
+ @cell_magic
136
+ def cython_inline(self, line, cell):
137
+ """Compile and run a Cython code cell using Cython.inline.
138
+
139
+ This magic simply passes the body of the cell to Cython.inline
140
+ and returns the result. If the variables `a` and `b` are defined
141
+ in the user's namespace, here is a simple example that returns
142
+ their sum::
143
+
144
+ %%cython_inline
145
+ return a+b
146
+
147
+ For most purposes, we recommend the usage of the `%%cython` magic.
148
+ """
149
+ locs = self.shell.user_global_ns
150
+ globs = self.shell.user_ns
151
+ return cython_inline(cell, locals=locs, globals=globs)
152
+
153
+ @cell_magic
154
+ def cython_pyximport(self, line, cell):
155
+ """Compile and import a Cython code cell using pyximport.
156
+
157
+ The contents of the cell are written to a `.pyx` file in the current
158
+ working directory, which is then imported using `pyximport`. This
159
+ magic requires a module name to be passed::
160
+
161
+ %%cython_pyximport modulename
162
+ def f(x):
163
+ return 2.0*x
164
+
165
+ The compiled module is then imported and all of its symbols are
166
+ injected into the user's namespace. For most purposes, we recommend
167
+ the usage of the `%%cython` magic.
168
+ """
169
+ module_name = line.strip()
170
+ if not module_name:
171
+ raise ValueError('module name must be given')
172
+ fname = module_name + '.pyx'
173
+ with io.open(fname, 'w', encoding='utf-8') as f:
174
+ f.write(cell)
175
+ if 'pyximport' not in sys.modules or not self._pyximport_installed:
176
+ import pyximport
177
+ pyximport.install()
178
+ self._pyximport_installed = True
179
+ if module_name in self._reloads:
180
+ module = self._reloads[module_name]
181
+ # Note: reloading extension modules is not actually supported
182
+ # (requires PEP-489 reinitialisation support).
183
+ # Don't know why this should ever have worked as it reads here.
184
+ # All we really need to do is to update the globals below.
185
+ #reload(module)
186
+ else:
187
+ __import__(module_name)
188
+ module = sys.modules[module_name]
189
+ self._reloads[module_name] = module
190
+ self._import_all(module)
191
+
192
+ @magic_arguments.magic_arguments()
193
+ @magic_arguments.argument(
194
+ '-a', '--annotate', action='store_true', default=False,
195
+ help="Produce a colorized HTML version of the source."
196
+ )
197
+ @magic_arguments.argument(
198
+ '-+', '--cplus', action='store_true', default=False,
199
+ help="Output a C++ rather than C file."
200
+ )
201
+ @magic_arguments.argument(
202
+ '-3', dest='language_level', action='store_const', const=3, default=None,
203
+ help="Select Python 3 syntax."
204
+ )
205
+ @magic_arguments.argument(
206
+ '-2', dest='language_level', action='store_const', const=2, default=None,
207
+ help="Select Python 2 syntax."
208
+ )
209
+ @magic_arguments.argument(
210
+ '-f', '--force', action='store_true', default=False,
211
+ help="Force the compilation of a new module, even if the source has been "
212
+ "previously compiled."
213
+ )
214
+ @magic_arguments.argument(
215
+ '-c', '--compile-args', action='append', default=[],
216
+ help="Extra flags to pass to compiler via the `extra_compile_args` "
217
+ "Extension flag (can be specified multiple times)."
218
+ )
219
+ @magic_arguments.argument(
220
+ '--link-args', action='append', default=[],
221
+ help="Extra flags to pass to linker via the `extra_link_args` "
222
+ "Extension flag (can be specified multiple times)."
223
+ )
224
+ @magic_arguments.argument(
225
+ '-l', '--lib', action='append', default=[],
226
+ help="Add a library to link the extension against (can be specified "
227
+ "multiple times)."
228
+ )
229
+ @magic_arguments.argument(
230
+ '-n', '--name',
231
+ help="Specify a name for the Cython module."
232
+ )
233
+ @magic_arguments.argument(
234
+ '-L', dest='library_dirs', metavar='dir', action='append', default=[],
235
+ help="Add a path to the list of library directories (can be specified "
236
+ "multiple times)."
237
+ )
238
+ @magic_arguments.argument(
239
+ '-I', '--include', action='append', default=[],
240
+ help="Add a path to the list of include directories (can be specified "
241
+ "multiple times)."
242
+ )
243
+ @magic_arguments.argument(
244
+ '-S', '--src', action='append', default=[],
245
+ help="Add a path to the list of src files (can be specified "
246
+ "multiple times)."
247
+ )
248
+ @magic_arguments.argument(
249
+ '--pgo', dest='pgo', action='store_true', default=False,
250
+ help=("Enable profile guided optimisation in the C compiler. "
251
+ "Compiles the cell twice and executes it in between to generate a runtime profile.")
252
+ )
253
+ @magic_arguments.argument(
254
+ '--verbose', dest='quiet', action='store_false', default=True,
255
+ help=("Print debug information like generated .c/.cpp file location "
256
+ "and exact gcc/g++ command invoked.")
257
+ )
258
+ @cell_magic
259
+ def cython(self, line, cell):
260
+ """Compile and import everything from a Cython code cell.
261
+
262
+ The contents of the cell are written to a `.pyx` file in the
263
+ directory `IPYTHONDIR/cython` using a filename with the hash of the
264
+ code. This file is then cythonized and compiled. The resulting module
265
+ is imported and all of its symbols are injected into the user's
266
+ namespace. The usage is similar to that of `%%cython_pyximport` but
267
+ you don't have to pass a module name::
268
+
269
+ %%cython
270
+ def f(x):
271
+ return 2.0*x
272
+
273
+ To compile OpenMP codes, pass the required `--compile-args`
274
+ and `--link-args`. For example with gcc::
275
+
276
+ %%cython --compile-args=-fopenmp --link-args=-fopenmp
277
+ ...
278
+
279
+ To enable profile guided optimisation, pass the ``--pgo`` option.
280
+ Note that the cell itself needs to take care of establishing a suitable
281
+ profile when executed. This can be done by implementing the functions to
282
+ optimise, and then calling them directly in the same cell on some realistic
283
+ training data like this::
284
+
285
+ %%cython --pgo
286
+ def critical_function(data):
287
+ for item in data:
288
+ ...
289
+
290
+ # execute function several times to build profile
291
+ from somewhere import some_typical_data
292
+ for _ in range(100):
293
+ critical_function(some_typical_data)
294
+
295
+ In Python 3.5 and later, you can distinguish between the profile and
296
+ non-profile runs as follows::
297
+
298
+ if "_pgo_" in __name__:
299
+ ... # execute critical code here
300
+ """
301
+ args = magic_arguments.parse_argstring(self.cython, line)
302
+ code = cell if cell.endswith('\n') else cell + '\n'
303
+ lib_dir = os.path.join(get_ipython_cache_dir(), 'cython')
304
+ key = (code, line, sys.version_info, sys.executable, cython_version)
305
+
306
+ if not os.path.exists(lib_dir):
307
+ os.makedirs(lib_dir)
308
+
309
+ if args.pgo:
310
+ key += ('pgo',)
311
+ if args.force:
312
+ # Force a new module name by adding the current time to the
313
+ # key which is hashed to determine the module name.
314
+ key += (time.time(),)
315
+
316
+ if args.name:
317
+ module_name = str(args.name) # no-op in Py3
318
+ else:
319
+ module_name = "_cython_magic_" + hashlib.md5(str(key).encode('utf-8')).hexdigest()
320
+ html_file = os.path.join(lib_dir, module_name + '.html')
321
+ module_path = os.path.join(lib_dir, module_name + self.so_ext)
322
+
323
+ have_module = os.path.isfile(module_path)
324
+ need_cythonize = args.pgo or not have_module
325
+
326
+ if args.annotate:
327
+ if not os.path.isfile(html_file):
328
+ need_cythonize = True
329
+
330
+ extension = None
331
+ if need_cythonize:
332
+ extensions = self._cythonize(module_name, code, lib_dir, args, quiet=args.quiet)
333
+ if extensions is None:
334
+ # Compilation failed and printed error message
335
+ return None
336
+ assert len(extensions) == 1
337
+ extension = extensions[0]
338
+ self._code_cache[key] = module_name
339
+
340
+ if args.pgo:
341
+ self._profile_pgo_wrapper(extension, lib_dir)
342
+
343
+ try:
344
+ self._build_extension(extension, lib_dir, pgo_step_name='use' if args.pgo else None,
345
+ quiet=args.quiet)
346
+ except distutils.errors.CompileError:
347
+ # Build failed and printed error message
348
+ return None
349
+
350
+ module = load_dynamic(module_name, module_path)
351
+ self._import_all(module)
352
+
353
+ if args.annotate:
354
+ try:
355
+ with io.open(html_file, encoding='utf-8') as f:
356
+ annotated_html = f.read()
357
+ except IOError as e:
358
+ # File could not be opened. Most likely the user has a version
359
+ # of Cython before 0.15.1 (when `cythonize` learned the
360
+ # `force` keyword argument) and has already compiled this
361
+ # exact source without annotation.
362
+ print('Cython completed successfully but the annotated '
363
+ 'source could not be read.', file=sys.stderr)
364
+ print(e, file=sys.stderr)
365
+ else:
366
+ return display.HTML(self.clean_annotated_html(annotated_html))
367
+
368
+ def _profile_pgo_wrapper(self, extension, lib_dir):
369
+ """
370
+ Generate a .c file for a separate extension module that calls the
371
+ module init function of the original module. This makes sure that the
372
+ PGO profiler sees the correct .o file of the final module, but it still
373
+ allows us to import the module under a different name for profiling,
374
+ before recompiling it into the PGO optimised module. Overwriting and
375
+ reimporting the same shared library is not portable.
376
+ """
377
+ extension = copy.copy(extension) # shallow copy, do not modify sources in place!
378
+ module_name = extension.name
379
+ pgo_module_name = '_pgo_' + module_name
380
+ pgo_wrapper_c_file = os.path.join(lib_dir, pgo_module_name + '.c')
381
+ with io.open(pgo_wrapper_c_file, 'w', encoding='utf-8') as f:
382
+ f.write(textwrap.dedent(u"""
383
+ #include "Python.h"
384
+ #if PY_MAJOR_VERSION < 3
385
+ extern PyMODINIT_FUNC init%(module_name)s(void);
386
+ PyMODINIT_FUNC init%(pgo_module_name)s(void); /*proto*/
387
+ PyMODINIT_FUNC init%(pgo_module_name)s(void) {
388
+ PyObject *sys_modules;
389
+ init%(module_name)s(); if (PyErr_Occurred()) return;
390
+ sys_modules = PyImport_GetModuleDict(); /* borrowed, no exception, "never" fails */
391
+ if (sys_modules) {
392
+ PyObject *module = PyDict_GetItemString(sys_modules, "%(module_name)s"); if (!module) return;
393
+ PyDict_SetItemString(sys_modules, "%(pgo_module_name)s", module);
394
+ Py_DECREF(module);
395
+ }
396
+ }
397
+ #else
398
+ extern PyMODINIT_FUNC PyInit_%(module_name)s(void);
399
+ PyMODINIT_FUNC PyInit_%(pgo_module_name)s(void); /*proto*/
400
+ PyMODINIT_FUNC PyInit_%(pgo_module_name)s(void) {
401
+ return PyInit_%(module_name)s();
402
+ }
403
+ #endif
404
+ """ % {'module_name': module_name, 'pgo_module_name': pgo_module_name}))
405
+
406
+ extension.sources = extension.sources + [pgo_wrapper_c_file] # do not modify in place!
407
+ extension.name = pgo_module_name
408
+
409
+ self._build_extension(extension, lib_dir, pgo_step_name='gen')
410
+
411
+ # import and execute module code to generate profile
412
+ so_module_path = os.path.join(lib_dir, pgo_module_name + self.so_ext)
413
+ load_dynamic(pgo_module_name, so_module_path)
414
+
415
+ def _cythonize(self, module_name, code, lib_dir, args, quiet=True):
416
+ pyx_file = os.path.join(lib_dir, module_name + '.pyx')
417
+ pyx_file = encode_fs(pyx_file)
418
+
419
+ c_include_dirs = args.include
420
+ c_src_files = list(map(str, args.src))
421
+ if 'numpy' in code:
422
+ import numpy
423
+ c_include_dirs.append(numpy.get_include())
424
+ with io.open(pyx_file, 'w', encoding='utf-8') as f:
425
+ f.write(code)
426
+ extension = Extension(
427
+ name=module_name,
428
+ sources=[pyx_file] + c_src_files,
429
+ include_dirs=c_include_dirs,
430
+ library_dirs=args.library_dirs,
431
+ extra_compile_args=args.compile_args,
432
+ extra_link_args=args.link_args,
433
+ libraries=args.lib,
434
+ language='c++' if args.cplus else 'c',
435
+ )
436
+ try:
437
+ opts = dict(
438
+ quiet=quiet,
439
+ annotate=args.annotate,
440
+ force=True,
441
+ )
442
+ if args.language_level is not None:
443
+ assert args.language_level in (2, 3)
444
+ opts['language_level'] = args.language_level
445
+ elif sys.version_info[0] >= 3:
446
+ opts['language_level'] = 3
447
+ return cythonize([extension], **opts)
448
+ except CompileError:
449
+ return None
450
+
451
+ def _build_extension(self, extension, lib_dir, temp_dir=None, pgo_step_name=None, quiet=True):
452
+ build_extension = self._get_build_extension(
453
+ extension, lib_dir=lib_dir, temp_dir=temp_dir, pgo_step_name=pgo_step_name)
454
+ old_threshold = None
455
+ try:
456
+ if not quiet:
457
+ old_threshold = distutils.log.set_threshold(distutils.log.DEBUG)
458
+ build_extension.run()
459
+ finally:
460
+ if not quiet and old_threshold is not None:
461
+ distutils.log.set_threshold(old_threshold)
462
+
463
+ def _add_pgo_flags(self, build_extension, step_name, temp_dir):
464
+ compiler_type = build_extension.compiler.compiler_type
465
+ if compiler_type == 'unix':
466
+ compiler_cmd = build_extension.compiler.compiler_so
467
+ # TODO: we could try to call "[cmd] --version" for better insights
468
+ if not compiler_cmd:
469
+ pass
470
+ elif 'clang' in compiler_cmd or 'clang' in compiler_cmd[0]:
471
+ compiler_type = 'clang'
472
+ elif 'icc' in compiler_cmd or 'icc' in compiler_cmd[0]:
473
+ compiler_type = 'icc'
474
+ elif 'gcc' in compiler_cmd or 'gcc' in compiler_cmd[0]:
475
+ compiler_type = 'gcc'
476
+ elif 'g++' in compiler_cmd or 'g++' in compiler_cmd[0]:
477
+ compiler_type = 'gcc'
478
+ config = PGO_CONFIG.get(compiler_type)
479
+ orig_flags = []
480
+ if config and step_name in config:
481
+ flags = [f.format(TEMPDIR=temp_dir) for f in config[step_name]]
482
+ for extension in build_extension.extensions:
483
+ orig_flags.append((extension.extra_compile_args, extension.extra_link_args))
484
+ extension.extra_compile_args = extension.extra_compile_args + flags
485
+ extension.extra_link_args = extension.extra_link_args + flags
486
+ else:
487
+ print("No PGO %s configuration known for C compiler type '%s'" % (step_name, compiler_type),
488
+ file=sys.stderr)
489
+ return orig_flags
490
+
491
+ @property
492
+ def so_ext(self):
493
+ """The extension suffix for compiled modules."""
494
+ try:
495
+ return self._so_ext
496
+ except AttributeError:
497
+ self._so_ext = self._get_build_extension().get_ext_filename('')
498
+ return self._so_ext
499
+
500
+ def _clear_distutils_mkpath_cache(self):
501
+ """clear distutils mkpath cache
502
+
503
+ prevents distutils from skipping re-creation of dirs that have been removed
504
+ """
505
+ try:
506
+ from distutils.dir_util import _path_created
507
+ except ImportError:
508
+ pass
509
+ else:
510
+ _path_created.clear()
511
+
512
+ def _get_build_extension(self, extension=None, lib_dir=None, temp_dir=None,
513
+ pgo_step_name=None, _build_ext=build_ext):
514
+ self._clear_distutils_mkpath_cache()
515
+ dist = Distribution()
516
+ config_files = dist.find_config_files()
517
+ try:
518
+ config_files.remove('setup.cfg')
519
+ except ValueError:
520
+ pass
521
+ dist.parse_config_files(config_files)
522
+
523
+ if not temp_dir:
524
+ temp_dir = lib_dir
525
+ add_pgo_flags = self._add_pgo_flags
526
+
527
+ if pgo_step_name:
528
+ base_build_ext = _build_ext
529
+ class _build_ext(_build_ext):
530
+ def build_extensions(self):
531
+ add_pgo_flags(self, pgo_step_name, temp_dir)
532
+ base_build_ext.build_extensions(self)
533
+
534
+ build_extension = _build_ext(dist)
535
+ build_extension.finalize_options()
536
+ if temp_dir:
537
+ temp_dir = encode_fs(temp_dir)
538
+ build_extension.build_temp = temp_dir
539
+ if lib_dir:
540
+ lib_dir = encode_fs(lib_dir)
541
+ build_extension.build_lib = lib_dir
542
+ if extension is not None:
543
+ build_extension.extensions = [extension]
544
+ return build_extension
545
+
546
+ @staticmethod
547
+ def clean_annotated_html(html):
548
+ """Clean up the annotated HTML source.
549
+
550
+ Strips the link to the generated C or C++ file, which we do not
551
+ present to the user.
552
+ """
553
+ r = re.compile('<p>Raw output: <a href="(.*)">(.*)</a>')
554
+ html = '\n'.join(l for l in html.splitlines() if not r.match(l))
555
+ return html
556
+
557
+ __doc__ = __doc__.format(
558
+ # rST doesn't see the -+ flag as part of an option list, so we
559
+ # hide it from the module-level docstring.
560
+ CYTHON_DOC=dedent(CythonMagics.cython.__doc__\
561
+ .replace('-+, --cplus', '--cplus ')),
562
+ CYTHON_INLINE_DOC=dedent(CythonMagics.cython_inline.__doc__),
563
+ CYTHON_PYXIMPORT_DOC=dedent(CythonMagics.cython_pyximport.__doc__),
564
+ )
venv/Lib/site-packages/Cython/Build/Tests/TestCyCache.py ADDED
@@ -0,0 +1,106 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import difflib
2
+ import glob
3
+ import gzip
4
+ import os
5
+ import tempfile
6
+
7
+ import Cython.Build.Dependencies
8
+ import Cython.Utils
9
+ from Cython.TestUtils import CythonTest
10
+
11
+
12
+ class TestCyCache(CythonTest):
13
+
14
+ def setUp(self):
15
+ CythonTest.setUp(self)
16
+ self.temp_dir = tempfile.mkdtemp(
17
+ prefix='cycache-test',
18
+ dir='TEST_TMP' if os.path.isdir('TEST_TMP') else None)
19
+ self.src_dir = tempfile.mkdtemp(prefix='src', dir=self.temp_dir)
20
+ self.cache_dir = tempfile.mkdtemp(prefix='cache', dir=self.temp_dir)
21
+
22
+ def cache_files(self, file_glob):
23
+ return glob.glob(os.path.join(self.cache_dir, file_glob))
24
+
25
+ def fresh_cythonize(self, *args, **kwargs):
26
+ Cython.Utils.clear_function_caches()
27
+ Cython.Build.Dependencies._dep_tree = None # discard method caches
28
+ Cython.Build.Dependencies.cythonize(*args, **kwargs)
29
+
30
+ def test_cycache_switch(self):
31
+ content1 = 'value = 1\n'
32
+ content2 = 'value = 2\n'
33
+ a_pyx = os.path.join(self.src_dir, 'a.pyx')
34
+ a_c = a_pyx[:-4] + '.c'
35
+
36
+ open(a_pyx, 'w').write(content1)
37
+ self.fresh_cythonize(a_pyx, cache=self.cache_dir)
38
+ self.fresh_cythonize(a_pyx, cache=self.cache_dir)
39
+ self.assertEqual(1, len(self.cache_files('a.c*')))
40
+ a_contents1 = open(a_c).read()
41
+ os.unlink(a_c)
42
+
43
+ open(a_pyx, 'w').write(content2)
44
+ self.fresh_cythonize(a_pyx, cache=self.cache_dir)
45
+ a_contents2 = open(a_c).read()
46
+ os.unlink(a_c)
47
+
48
+ self.assertNotEqual(a_contents1, a_contents2, 'C file not changed!')
49
+ self.assertEqual(2, len(self.cache_files('a.c*')))
50
+
51
+ open(a_pyx, 'w').write(content1)
52
+ self.fresh_cythonize(a_pyx, cache=self.cache_dir)
53
+ self.assertEqual(2, len(self.cache_files('a.c*')))
54
+ a_contents = open(a_c).read()
55
+ self.assertEqual(
56
+ a_contents, a_contents1,
57
+ msg='\n'.join(list(difflib.unified_diff(
58
+ a_contents.split('\n'), a_contents1.split('\n')))[:10]))
59
+
60
+ def test_cycache_uses_cache(self):
61
+ a_pyx = os.path.join(self.src_dir, 'a.pyx')
62
+ a_c = a_pyx[:-4] + '.c'
63
+ open(a_pyx, 'w').write('pass')
64
+ self.fresh_cythonize(a_pyx, cache=self.cache_dir)
65
+ a_cache = os.path.join(self.cache_dir, os.listdir(self.cache_dir)[0])
66
+ gzip.GzipFile(a_cache, 'wb').write('fake stuff'.encode('ascii'))
67
+ os.unlink(a_c)
68
+ self.fresh_cythonize(a_pyx, cache=self.cache_dir)
69
+ a_contents = open(a_c).read()
70
+ self.assertEqual(a_contents, 'fake stuff',
71
+ 'Unexpected contents: %s...' % a_contents[:100])
72
+
73
+ def test_multi_file_output(self):
74
+ a_pyx = os.path.join(self.src_dir, 'a.pyx')
75
+ a_c = a_pyx[:-4] + '.c'
76
+ a_h = a_pyx[:-4] + '.h'
77
+ a_api_h = a_pyx[:-4] + '_api.h'
78
+ open(a_pyx, 'w').write('cdef public api int foo(int x): return x\n')
79
+ self.fresh_cythonize(a_pyx, cache=self.cache_dir)
80
+ expected = [a_c, a_h, a_api_h]
81
+ for output in expected:
82
+ self.assertTrue(os.path.exists(output), output)
83
+ os.unlink(output)
84
+ self.fresh_cythonize(a_pyx, cache=self.cache_dir)
85
+ for output in expected:
86
+ self.assertTrue(os.path.exists(output), output)
87
+
88
+ def test_options_invalidation(self):
89
+ hash_pyx = os.path.join(self.src_dir, 'options.pyx')
90
+ hash_c = hash_pyx[:-len('.pyx')] + '.c'
91
+
92
+ open(hash_pyx, 'w').write('pass')
93
+ self.fresh_cythonize(hash_pyx, cache=self.cache_dir, cplus=False)
94
+ self.assertEqual(1, len(self.cache_files('options.c*')))
95
+
96
+ os.unlink(hash_c)
97
+ self.fresh_cythonize(hash_pyx, cache=self.cache_dir, cplus=True)
98
+ self.assertEqual(2, len(self.cache_files('options.c*')))
99
+
100
+ os.unlink(hash_c)
101
+ self.fresh_cythonize(hash_pyx, cache=self.cache_dir, cplus=False, show_version=False)
102
+ self.assertEqual(2, len(self.cache_files('options.c*')))
103
+
104
+ os.unlink(hash_c)
105
+ self.fresh_cythonize(hash_pyx, cache=self.cache_dir, cplus=False, show_version=True)
106
+ self.assertEqual(2, len(self.cache_files('options.c*')))
venv/Lib/site-packages/Cython/Build/Tests/TestInline.py ADDED
@@ -0,0 +1,96 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os, tempfile
2
+ from Cython.Shadow import inline
3
+ from Cython.Build.Inline import safe_type
4
+ from Cython.TestUtils import CythonTest
5
+
6
+ try:
7
+ import numpy
8
+ has_numpy = True
9
+ except:
10
+ has_numpy = False
11
+
12
+ test_kwds = dict(force=True, quiet=True)
13
+
14
+ global_value = 100
15
+
16
+ class TestInline(CythonTest):
17
+ def setUp(self):
18
+ CythonTest.setUp(self)
19
+ self.test_kwds = dict(test_kwds)
20
+ if os.path.isdir('TEST_TMP'):
21
+ lib_dir = os.path.join('TEST_TMP','inline')
22
+ else:
23
+ lib_dir = tempfile.mkdtemp(prefix='cython_inline_')
24
+ self.test_kwds['lib_dir'] = lib_dir
25
+
26
+ def test_simple(self):
27
+ self.assertEqual(inline("return 1+2", **self.test_kwds), 3)
28
+
29
+ def test_types(self):
30
+ self.assertEqual(inline("""
31
+ cimport cython
32
+ return cython.typeof(a), cython.typeof(b)
33
+ """, a=1.0, b=[], **self.test_kwds), ('double', 'list object'))
34
+
35
+ def test_locals(self):
36
+ a = 1
37
+ b = 2
38
+ self.assertEqual(inline("return a+b", **self.test_kwds), 3)
39
+
40
+ def test_globals(self):
41
+ self.assertEqual(inline("return global_value + 1", **self.test_kwds), global_value + 1)
42
+
43
+ def test_no_return(self):
44
+ self.assertEqual(inline("""
45
+ a = 1
46
+ cdef double b = 2
47
+ cdef c = []
48
+ """, **self.test_kwds), dict(a=1, b=2.0, c=[]))
49
+
50
+ def test_def_node(self):
51
+ foo = inline("def foo(x): return x * x", **self.test_kwds)['foo']
52
+ self.assertEqual(foo(7), 49)
53
+
54
+ def test_class_ref(self):
55
+ class Type(object):
56
+ pass
57
+ tp = inline("Type")['Type']
58
+ self.assertEqual(tp, Type)
59
+
60
+ def test_pure(self):
61
+ import cython as cy
62
+ b = inline("""
63
+ b = cy.declare(float, a)
64
+ c = cy.declare(cy.pointer(cy.float), &b)
65
+ return b
66
+ """, a=3, **self.test_kwds)
67
+ self.assertEqual(type(b), float)
68
+
69
+ def test_compiler_directives(self):
70
+ self.assertEqual(
71
+ inline('return sum(x)',
72
+ x=[1, 2, 3],
73
+ cython_compiler_directives={'boundscheck': False}),
74
+ 6
75
+ )
76
+
77
+ def test_lang_version(self):
78
+ # GH-3419. Caching for inline code didn't always respect compiler directives.
79
+ inline_divcode = "def f(int a, int b): return a/b"
80
+ self.assertEqual(
81
+ inline(inline_divcode, language_level=2)['f'](5,2),
82
+ 2
83
+ )
84
+ self.assertEqual(
85
+ inline(inline_divcode, language_level=3)['f'](5,2),
86
+ 2.5
87
+ )
88
+
89
+ if has_numpy:
90
+
91
+ def test_numpy(self):
92
+ import numpy
93
+ a = numpy.ndarray((10, 20))
94
+ a[0,0] = 10
95
+ self.assertEqual(safe_type(a), 'numpy.ndarray[numpy.float64_t, ndim=2]')
96
+ self.assertEqual(inline("return a[0,0]", a=a, **self.test_kwds), 10.0)
venv/Lib/site-packages/Cython/Build/Tests/TestIpythonMagic.py ADDED
@@ -0,0 +1,205 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # -*- coding: utf-8 -*-
2
+ # tag: ipython
3
+
4
+ """Tests for the Cython magics extension."""
5
+
6
+ from __future__ import absolute_import
7
+
8
+ import os
9
+ import sys
10
+ from contextlib import contextmanager
11
+ from Cython.Build import IpythonMagic
12
+ from Cython.TestUtils import CythonTest
13
+
14
+ try:
15
+ import IPython.testing.globalipapp
16
+ except ImportError:
17
+ # Disable tests and fake helpers for initialisation below.
18
+ def skip_if_not_installed(_):
19
+ return None
20
+ else:
21
+ def skip_if_not_installed(c):
22
+ return c
23
+
24
+ try:
25
+ # disable IPython history thread before it gets started to avoid having to clean it up
26
+ from IPython.core.history import HistoryManager
27
+ HistoryManager.enabled = False
28
+ except ImportError:
29
+ pass
30
+
31
+ code = u"""\
32
+ def f(x):
33
+ return 2*x
34
+ """
35
+
36
+ cython3_code = u"""\
37
+ def f(int x):
38
+ return 2 / x
39
+
40
+ def call(x):
41
+ return f(*(x,))
42
+ """
43
+
44
+ pgo_cython3_code = cython3_code + u"""\
45
+ def main():
46
+ for _ in range(100): call(5)
47
+ main()
48
+ """
49
+
50
+
51
+ if sys.platform == 'win32':
52
+ # not using IPython's decorators here because they depend on "nose"
53
+ try:
54
+ from unittest import skip as skip_win32
55
+ except ImportError:
56
+ # poor dev's silent @unittest.skip()
57
+ def skip_win32(dummy):
58
+ def _skip_win32(func):
59
+ return None
60
+ return _skip_win32
61
+ else:
62
+ def skip_win32(dummy):
63
+ def _skip_win32(func):
64
+ def wrapper(*args, **kwargs):
65
+ func(*args, **kwargs)
66
+ return wrapper
67
+ return _skip_win32
68
+
69
+
70
+ @skip_if_not_installed
71
+ class TestIPythonMagic(CythonTest):
72
+
73
+ @classmethod
74
+ def setUpClass(cls):
75
+ CythonTest.setUpClass()
76
+ cls._ip = IPython.testing.globalipapp.get_ipython()
77
+
78
+ def setUp(self):
79
+ CythonTest.setUp(self)
80
+ self._ip.extension_manager.load_extension('cython')
81
+
82
+ def test_cython_inline(self):
83
+ ip = self._ip
84
+ ip.ex('a=10; b=20')
85
+ result = ip.run_cell_magic('cython_inline', '', 'return a+b')
86
+ self.assertEqual(result, 30)
87
+
88
+ @skip_win32('Skip on Windows')
89
+ def test_cython_pyximport(self):
90
+ ip = self._ip
91
+ module_name = '_test_cython_pyximport'
92
+ ip.run_cell_magic('cython_pyximport', module_name, code)
93
+ ip.ex('g = f(10)')
94
+ self.assertEqual(ip.user_ns['g'], 20.0)
95
+ ip.run_cell_magic('cython_pyximport', module_name, code)
96
+ ip.ex('h = f(-10)')
97
+ self.assertEqual(ip.user_ns['h'], -20.0)
98
+ try:
99
+ os.remove(module_name + '.pyx')
100
+ except OSError:
101
+ pass
102
+
103
+ def test_cython(self):
104
+ ip = self._ip
105
+ ip.run_cell_magic('cython', '', code)
106
+ ip.ex('g = f(10)')
107
+ self.assertEqual(ip.user_ns['g'], 20.0)
108
+
109
+ def test_cython_name(self):
110
+ # The Cython module named 'mymodule' defines the function f.
111
+ ip = self._ip
112
+ ip.run_cell_magic('cython', '--name=mymodule', code)
113
+ # This module can now be imported in the interactive namespace.
114
+ ip.ex('import mymodule; g = mymodule.f(10)')
115
+ self.assertEqual(ip.user_ns['g'], 20.0)
116
+
117
+ def test_cython_language_level(self):
118
+ # The Cython cell defines the functions f() and call().
119
+ ip = self._ip
120
+ ip.run_cell_magic('cython', '', cython3_code)
121
+ ip.ex('g = f(10); h = call(10)')
122
+ if sys.version_info[0] < 3:
123
+ self.assertEqual(ip.user_ns['g'], 2 // 10)
124
+ self.assertEqual(ip.user_ns['h'], 2 // 10)
125
+ else:
126
+ self.assertEqual(ip.user_ns['g'], 2.0 / 10.0)
127
+ self.assertEqual(ip.user_ns['h'], 2.0 / 10.0)
128
+
129
+ def test_cython3(self):
130
+ # The Cython cell defines the functions f() and call().
131
+ ip = self._ip
132
+ ip.run_cell_magic('cython', '-3', cython3_code)
133
+ ip.ex('g = f(10); h = call(10)')
134
+ self.assertEqual(ip.user_ns['g'], 2.0 / 10.0)
135
+ self.assertEqual(ip.user_ns['h'], 2.0 / 10.0)
136
+
137
+ def test_cython2(self):
138
+ # The Cython cell defines the functions f() and call().
139
+ ip = self._ip
140
+ ip.run_cell_magic('cython', '-2', cython3_code)
141
+ ip.ex('g = f(10); h = call(10)')
142
+ self.assertEqual(ip.user_ns['g'], 2 // 10)
143
+ self.assertEqual(ip.user_ns['h'], 2 // 10)
144
+
145
+ @skip_win32('Skip on Windows')
146
+ def test_cython3_pgo(self):
147
+ # The Cython cell defines the functions f() and call().
148
+ ip = self._ip
149
+ ip.run_cell_magic('cython', '-3 --pgo', pgo_cython3_code)
150
+ ip.ex('g = f(10); h = call(10); main()')
151
+ self.assertEqual(ip.user_ns['g'], 2.0 / 10.0)
152
+ self.assertEqual(ip.user_ns['h'], 2.0 / 10.0)
153
+
154
+ @skip_win32('Skip on Windows')
155
+ def test_extlibs(self):
156
+ ip = self._ip
157
+ code = u"""
158
+ from libc.math cimport sin
159
+ x = sin(0.0)
160
+ """
161
+ ip.user_ns['x'] = 1
162
+ ip.run_cell_magic('cython', '-l m', code)
163
+ self.assertEqual(ip.user_ns['x'], 0)
164
+
165
+
166
+ def test_cython_verbose(self):
167
+ ip = self._ip
168
+ ip.run_cell_magic('cython', '--verbose', code)
169
+ ip.ex('g = f(10)')
170
+ self.assertEqual(ip.user_ns['g'], 20.0)
171
+
172
+ def test_cython_verbose_thresholds(self):
173
+ @contextmanager
174
+ def mock_distutils():
175
+ class MockLog:
176
+ DEBUG = 1
177
+ INFO = 2
178
+ thresholds = [INFO]
179
+
180
+ def set_threshold(self, val):
181
+ self.thresholds.append(val)
182
+ return self.thresholds[-2]
183
+
184
+
185
+ new_log = MockLog()
186
+ old_log = IpythonMagic.distutils.log
187
+ try:
188
+ IpythonMagic.distutils.log = new_log
189
+ yield new_log
190
+ finally:
191
+ IpythonMagic.distutils.log = old_log
192
+
193
+ ip = self._ip
194
+ with mock_distutils() as verbose_log:
195
+ ip.run_cell_magic('cython', '--verbose', code)
196
+ ip.ex('g = f(10)')
197
+ self.assertEqual(ip.user_ns['g'], 20.0)
198
+ self.assertEqual([verbose_log.INFO, verbose_log.DEBUG, verbose_log.INFO],
199
+ verbose_log.thresholds)
200
+
201
+ with mock_distutils() as normal_log:
202
+ ip.run_cell_magic('cython', '', code)
203
+ ip.ex('g = f(10)')
204
+ self.assertEqual(ip.user_ns['g'], 20.0)
205
+ self.assertEqual([normal_log.INFO], normal_log.thresholds)
venv/Lib/site-packages/Cython/Build/Tests/TestStripLiterals.py ADDED
@@ -0,0 +1,57 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from Cython.Build.Dependencies import strip_string_literals
2
+
3
+ from Cython.TestUtils import CythonTest
4
+
5
+ class TestStripLiterals(CythonTest):
6
+
7
+ def t(self, before, expected):
8
+ actual, literals = strip_string_literals(before, prefix="_L")
9
+ self.assertEqual(expected, actual)
10
+ for key, value in literals.items():
11
+ actual = actual.replace(key, value)
12
+ self.assertEqual(before, actual)
13
+
14
+ def test_empty(self):
15
+ self.t("", "")
16
+
17
+ def test_single_quote(self):
18
+ self.t("'x'", "'_L1_'")
19
+
20
+ def test_double_quote(self):
21
+ self.t('"x"', '"_L1_"')
22
+
23
+ def test_nested_quotes(self):
24
+ self.t(""" '"' "'" """, """ '_L1_' "_L2_" """)
25
+
26
+ def test_triple_quote(self):
27
+ self.t(" '''a\n''' ", " '''_L1_''' ")
28
+
29
+ def test_backslash(self):
30
+ self.t(r"'a\'b'", "'_L1_'")
31
+ self.t(r"'a\\'", "'_L1_'")
32
+ self.t(r"'a\\\'b'", "'_L1_'")
33
+
34
+ def test_unicode(self):
35
+ self.t("u'abc'", "u'_L1_'")
36
+
37
+ def test_raw(self):
38
+ self.t(r"r'abc\\'", "r'_L1_'")
39
+
40
+ def test_raw_unicode(self):
41
+ self.t(r"ru'abc\\'", "ru'_L1_'")
42
+
43
+ def test_comment(self):
44
+ self.t("abc # foo", "abc #_L1_")
45
+
46
+ def test_comment_and_quote(self):
47
+ self.t("abc # 'x'", "abc #_L1_")
48
+ self.t("'abc#'", "'_L1_'")
49
+
50
+ def test_include(self):
51
+ self.t("include 'a.pxi' # something here",
52
+ "include '_L1_' #_L2_")
53
+
54
+ def test_extern(self):
55
+ self.t("cdef extern from 'a.h': # comment",
56
+ "cdef extern from '_L1_': #_L2_")
57
+
venv/Lib/site-packages/Cython/Build/Tests/__init__.py ADDED
@@ -0,0 +1 @@
 
 
1
+ # empty file
venv/Lib/site-packages/Cython/Build/Tests/__pycache__/TestCyCache.cpython-311.pyc ADDED
Binary file (9.13 kB). View file
 
venv/Lib/site-packages/Cython/Build/Tests/__pycache__/TestInline.cpython-311.pyc ADDED
Binary file (6.51 kB). View file
 
venv/Lib/site-packages/Cython/Build/Tests/__pycache__/TestIpythonMagic.cpython-311.pyc ADDED
Binary file (12.2 kB). View file
 
venv/Lib/site-packages/Cython/Build/Tests/__pycache__/TestStripLiterals.cpython-311.pyc ADDED
Binary file (4.55 kB). View file
 
venv/Lib/site-packages/Cython/Build/Tests/__pycache__/__init__.cpython-311.pyc ADDED
Binary file (206 Bytes). View file
 
venv/Lib/site-packages/Cython/Build/__init__.py ADDED
@@ -0,0 +1,2 @@
 
 
 
1
+ from .Dependencies import cythonize
2
+ from .Distutils import build_ext
venv/Lib/site-packages/Cython/Build/__pycache__/BuildExecutable.cpython-311.pyc ADDED
Binary file (8.68 kB). View file
 
venv/Lib/site-packages/Cython/Build/__pycache__/Cythonize.cpython-311.pyc ADDED
Binary file (12.4 kB). View file
 
venv/Lib/site-packages/Cython/Build/__pycache__/Dependencies.cpython-311.pyc ADDED
Binary file (68.3 kB). View file
 
venv/Lib/site-packages/Cython/Build/__pycache__/Distutils.cpython-311.pyc ADDED
Binary file (275 Bytes). View file
 
venv/Lib/site-packages/Cython/Build/__pycache__/Inline.cpython-311.pyc ADDED
Binary file (20.3 kB). View file
 
venv/Lib/site-packages/Cython/Build/__pycache__/IpythonMagic.cpython-311.pyc ADDED
Binary file (26.9 kB). View file
 
venv/Lib/site-packages/Cython/Build/__pycache__/__init__.cpython-311.pyc ADDED
Binary file (319 Bytes). View file
 
venv/Lib/site-packages/Cython/CodeWriter.py ADDED
@@ -0,0 +1,819 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ Serializes a Cython code tree to Cython code. This is primarily useful for
3
+ debugging and testing purposes.
4
+
5
+ The output is in a strict format, no whitespace or comments from the input
6
+ is preserved (and it could not be as it is not present in the code tree).
7
+ """
8
+
9
+ from __future__ import absolute_import, print_function
10
+
11
+ from .Compiler.Visitor import TreeVisitor
12
+ from .Compiler.ExprNodes import *
13
+
14
+
15
+ class LinesResult(object):
16
+ def __init__(self):
17
+ self.lines = []
18
+ self.s = u""
19
+
20
+ def put(self, s):
21
+ self.s += s
22
+
23
+ def newline(self):
24
+ self.lines.append(self.s)
25
+ self.s = u""
26
+
27
+ def putline(self, s):
28
+ self.put(s)
29
+ self.newline()
30
+
31
+ class DeclarationWriter(TreeVisitor):
32
+
33
+ indent_string = u" "
34
+
35
+ def __init__(self, result=None):
36
+ super(DeclarationWriter, self).__init__()
37
+ if result is None:
38
+ result = LinesResult()
39
+ self.result = result
40
+ self.numindents = 0
41
+ self.tempnames = {}
42
+ self.tempblockindex = 0
43
+
44
+ def write(self, tree):
45
+ self.visit(tree)
46
+ return self.result
47
+
48
+ def indent(self):
49
+ self.numindents += 1
50
+
51
+ def dedent(self):
52
+ self.numindents -= 1
53
+
54
+ def startline(self, s=u""):
55
+ self.result.put(self.indent_string * self.numindents + s)
56
+
57
+ def put(self, s):
58
+ self.result.put(s)
59
+
60
+ def putline(self, s):
61
+ self.result.putline(self.indent_string * self.numindents + s)
62
+
63
+ def endline(self, s=u""):
64
+ self.result.putline(s)
65
+
66
+ def line(self, s):
67
+ self.startline(s)
68
+ self.endline()
69
+
70
+ def comma_separated_list(self, items, output_rhs=False):
71
+ if len(items) > 0:
72
+ for item in items[:-1]:
73
+ self.visit(item)
74
+ if output_rhs and item.default is not None:
75
+ self.put(u" = ")
76
+ self.visit(item.default)
77
+ self.put(u", ")
78
+ self.visit(items[-1])
79
+
80
+ def visit_Node(self, node):
81
+ raise AssertionError("Node not handled by serializer: %r" % node)
82
+
83
+ def visit_ModuleNode(self, node):
84
+ self.visitchildren(node)
85
+
86
+ def visit_StatListNode(self, node):
87
+ self.visitchildren(node)
88
+
89
+ def visit_CDefExternNode(self, node):
90
+ if node.include_file is None:
91
+ file = u'*'
92
+ else:
93
+ file = u'"%s"' % node.include_file
94
+ self.putline(u"cdef extern from %s:" % file)
95
+ self.indent()
96
+ self.visit(node.body)
97
+ self.dedent()
98
+
99
+ def visit_CPtrDeclaratorNode(self, node):
100
+ self.put('*')
101
+ self.visit(node.base)
102
+
103
+ def visit_CReferenceDeclaratorNode(self, node):
104
+ self.put('&')
105
+ self.visit(node.base)
106
+
107
+ def visit_CArrayDeclaratorNode(self, node):
108
+ self.visit(node.base)
109
+ self.put(u'[')
110
+ if node.dimension is not None:
111
+ self.visit(node.dimension)
112
+ self.put(u']')
113
+
114
+ def visit_CArrayDeclaratorNode(self, node):
115
+ self.visit(node.base)
116
+ self.put(u'[')
117
+ if node.dimension is not None:
118
+ self.visit(node.dimension)
119
+ self.put(u']')
120
+
121
+ def visit_CFuncDeclaratorNode(self, node):
122
+ # TODO: except, gil, etc.
123
+ self.visit(node.base)
124
+ self.put(u'(')
125
+ self.comma_separated_list(node.args)
126
+ self.endline(u')')
127
+
128
+ def visit_CNameDeclaratorNode(self, node):
129
+ self.put(node.name)
130
+
131
+ def visit_CSimpleBaseTypeNode(self, node):
132
+ # See Parsing.p_sign_and_longness
133
+ if node.is_basic_c_type:
134
+ self.put(("unsigned ", "", "signed ")[node.signed])
135
+ if node.longness < 0:
136
+ self.put("short " * -node.longness)
137
+ elif node.longness > 0:
138
+ self.put("long " * node.longness)
139
+ self.put(node.name)
140
+
141
+ def visit_CComplexBaseTypeNode(self, node):
142
+ self.put(u'(')
143
+ self.visit(node.base_type)
144
+ self.visit(node.declarator)
145
+ self.put(u')')
146
+
147
+ def visit_CNestedBaseTypeNode(self, node):
148
+ self.visit(node.base_type)
149
+ self.put(u'.')
150
+ self.put(node.name)
151
+
152
+ def visit_TemplatedTypeNode(self, node):
153
+ self.visit(node.base_type_node)
154
+ self.put(u'[')
155
+ self.comma_separated_list(node.positional_args + node.keyword_args.key_value_pairs)
156
+ self.put(u']')
157
+
158
+ def visit_CVarDefNode(self, node):
159
+ self.startline(u"cdef ")
160
+ self.visit(node.base_type)
161
+ self.put(u" ")
162
+ self.comma_separated_list(node.declarators, output_rhs=True)
163
+ self.endline()
164
+
165
+ def visit_container_node(self, node, decl, extras, attributes):
166
+ # TODO: visibility
167
+ self.startline(decl)
168
+ if node.name:
169
+ self.put(u' ')
170
+ self.put(node.name)
171
+ if node.cname is not None:
172
+ self.put(u' "%s"' % node.cname)
173
+ if extras:
174
+ self.put(extras)
175
+ self.endline(':')
176
+ self.indent()
177
+ if not attributes:
178
+ self.putline('pass')
179
+ else:
180
+ for attribute in attributes:
181
+ self.visit(attribute)
182
+ self.dedent()
183
+
184
+ def visit_CStructOrUnionDefNode(self, node):
185
+ if node.typedef_flag:
186
+ decl = u'ctypedef '
187
+ else:
188
+ decl = u'cdef '
189
+ if node.visibility == 'public':
190
+ decl += u'public '
191
+ if node.packed:
192
+ decl += u'packed '
193
+ decl += node.kind
194
+ self.visit_container_node(node, decl, None, node.attributes)
195
+
196
+ def visit_CppClassNode(self, node):
197
+ extras = ""
198
+ if node.templates:
199
+ extras = u"[%s]" % ", ".join(node.templates)
200
+ if node.base_classes:
201
+ extras += "(%s)" % ", ".join(node.base_classes)
202
+ self.visit_container_node(node, u"cdef cppclass", extras, node.attributes)
203
+
204
+ def visit_CEnumDefNode(self, node):
205
+ self.visit_container_node(node, u"cdef enum", None, node.items)
206
+
207
+ def visit_CEnumDefItemNode(self, node):
208
+ self.startline(node.name)
209
+ if node.cname:
210
+ self.put(u' "%s"' % node.cname)
211
+ if node.value:
212
+ self.put(u" = ")
213
+ self.visit(node.value)
214
+ self.endline()
215
+
216
+ def visit_CClassDefNode(self, node):
217
+ assert not node.module_name
218
+ if node.decorators:
219
+ for decorator in node.decorators:
220
+ self.visit(decorator)
221
+ self.startline(u"cdef class ")
222
+ self.put(node.class_name)
223
+ if node.base_class_name:
224
+ self.put(u"(")
225
+ if node.base_class_module:
226
+ self.put(node.base_class_module)
227
+ self.put(u".")
228
+ self.put(node.base_class_name)
229
+ self.put(u")")
230
+ self.endline(u":")
231
+ self.indent()
232
+ self.visit(node.body)
233
+ self.dedent()
234
+
235
+ def visit_CTypeDefNode(self, node):
236
+ self.startline(u"ctypedef ")
237
+ self.visit(node.base_type)
238
+ self.put(u" ")
239
+ self.visit(node.declarator)
240
+ self.endline()
241
+
242
+ def visit_FuncDefNode(self, node):
243
+ self.startline(u"def %s(" % node.name)
244
+ self.comma_separated_list(node.args)
245
+ self.endline(u"):")
246
+ self.indent()
247
+ self.visit(node.body)
248
+ self.dedent()
249
+
250
+ def visit_CArgDeclNode(self, node):
251
+ if node.base_type.name is not None:
252
+ self.visit(node.base_type)
253
+ self.put(u" ")
254
+ self.visit(node.declarator)
255
+ if node.default is not None:
256
+ self.put(u" = ")
257
+ self.visit(node.default)
258
+
259
+ def visit_CImportStatNode(self, node):
260
+ self.startline(u"cimport ")
261
+ self.put(node.module_name)
262
+ if node.as_name:
263
+ self.put(u" as ")
264
+ self.put(node.as_name)
265
+ self.endline()
266
+
267
+ def visit_FromCImportStatNode(self, node):
268
+ self.startline(u"from ")
269
+ self.put(node.module_name)
270
+ self.put(u" cimport ")
271
+ first = True
272
+ for pos, name, as_name, kind in node.imported_names:
273
+ assert kind is None
274
+ if first:
275
+ first = False
276
+ else:
277
+ self.put(u", ")
278
+ self.put(name)
279
+ if as_name:
280
+ self.put(u" as ")
281
+ self.put(as_name)
282
+ self.endline()
283
+
284
+ def visit_NameNode(self, node):
285
+ self.put(node.name)
286
+
287
+ def visit_IntNode(self, node):
288
+ self.put(node.value)
289
+
290
+ def visit_NoneNode(self, node):
291
+ self.put(u"None")
292
+
293
+ def visit_NotNode(self, node):
294
+ self.put(u"(not ")
295
+ self.visit(node.operand)
296
+ self.put(u")")
297
+
298
+ def visit_DecoratorNode(self, node):
299
+ self.startline("@")
300
+ self.visit(node.decorator)
301
+ self.endline()
302
+
303
+ def visit_BinopNode(self, node):
304
+ self.visit(node.operand1)
305
+ self.put(u" %s " % node.operator)
306
+ self.visit(node.operand2)
307
+
308
+ def visit_AttributeNode(self, node):
309
+ self.visit(node.obj)
310
+ self.put(u".%s" % node.attribute)
311
+
312
+ def visit_BoolNode(self, node):
313
+ self.put(str(node.value))
314
+
315
+ # FIXME: represent string nodes correctly
316
+ def visit_StringNode(self, node):
317
+ value = node.value
318
+ if value.encoding is not None:
319
+ value = value.encode(value.encoding)
320
+ self.put(repr(value))
321
+
322
+ def visit_PassStatNode(self, node):
323
+ self.startline(u"pass")
324
+ self.endline()
325
+
326
+ class CodeWriter(DeclarationWriter):
327
+
328
+ def visit_SingleAssignmentNode(self, node):
329
+ self.startline()
330
+ self.visit(node.lhs)
331
+ self.put(u" = ")
332
+ self.visit(node.rhs)
333
+ self.endline()
334
+
335
+ def visit_CascadedAssignmentNode(self, node):
336
+ self.startline()
337
+ for lhs in node.lhs_list:
338
+ self.visit(lhs)
339
+ self.put(u" = ")
340
+ self.visit(node.rhs)
341
+ self.endline()
342
+
343
+ def visit_PrintStatNode(self, node):
344
+ self.startline(u"print ")
345
+ self.comma_separated_list(node.arg_tuple.args)
346
+ if not node.append_newline:
347
+ self.put(u",")
348
+ self.endline()
349
+
350
+ def visit_ForInStatNode(self, node):
351
+ self.startline(u"for ")
352
+ self.visit(node.target)
353
+ self.put(u" in ")
354
+ self.visit(node.iterator.sequence)
355
+ self.endline(u":")
356
+ self.indent()
357
+ self.visit(node.body)
358
+ self.dedent()
359
+ if node.else_clause is not None:
360
+ self.line(u"else:")
361
+ self.indent()
362
+ self.visit(node.else_clause)
363
+ self.dedent()
364
+
365
+ def visit_IfStatNode(self, node):
366
+ # The IfClauseNode is handled directly without a separate match
367
+ # for clariy.
368
+ self.startline(u"if ")
369
+ self.visit(node.if_clauses[0].condition)
370
+ self.endline(":")
371
+ self.indent()
372
+ self.visit(node.if_clauses[0].body)
373
+ self.dedent()
374
+ for clause in node.if_clauses[1:]:
375
+ self.startline("elif ")
376
+ self.visit(clause.condition)
377
+ self.endline(":")
378
+ self.indent()
379
+ self.visit(clause.body)
380
+ self.dedent()
381
+ if node.else_clause is not None:
382
+ self.line("else:")
383
+ self.indent()
384
+ self.visit(node.else_clause)
385
+ self.dedent()
386
+
387
+ def visit_SequenceNode(self, node):
388
+ self.comma_separated_list(node.args) # Might need to discover whether we need () around tuples...hmm...
389
+
390
+ def visit_SimpleCallNode(self, node):
391
+ self.visit(node.function)
392
+ self.put(u"(")
393
+ self.comma_separated_list(node.args)
394
+ self.put(")")
395
+
396
+ def visit_GeneralCallNode(self, node):
397
+ self.visit(node.function)
398
+ self.put(u"(")
399
+ posarg = node.positional_args
400
+ if isinstance(posarg, AsTupleNode):
401
+ self.visit(posarg.arg)
402
+ else:
403
+ self.comma_separated_list(posarg.args) # TupleNode.args
404
+ if node.keyword_args:
405
+ if isinstance(node.keyword_args, DictNode):
406
+ for i, (name, value) in enumerate(node.keyword_args.key_value_pairs):
407
+ if i > 0:
408
+ self.put(', ')
409
+ self.visit(name)
410
+ self.put('=')
411
+ self.visit(value)
412
+ else:
413
+ raise Exception("Not implemented yet")
414
+ self.put(u")")
415
+
416
+ def visit_ExprStatNode(self, node):
417
+ self.startline()
418
+ self.visit(node.expr)
419
+ self.endline()
420
+
421
+ def visit_InPlaceAssignmentNode(self, node):
422
+ self.startline()
423
+ self.visit(node.lhs)
424
+ self.put(u" %s= " % node.operator)
425
+ self.visit(node.rhs)
426
+ self.endline()
427
+
428
+ def visit_WithStatNode(self, node):
429
+ self.startline()
430
+ self.put(u"with ")
431
+ self.visit(node.manager)
432
+ if node.target is not None:
433
+ self.put(u" as ")
434
+ self.visit(node.target)
435
+ self.endline(u":")
436
+ self.indent()
437
+ self.visit(node.body)
438
+ self.dedent()
439
+
440
+ def visit_TryFinallyStatNode(self, node):
441
+ self.line(u"try:")
442
+ self.indent()
443
+ self.visit(node.body)
444
+ self.dedent()
445
+ self.line(u"finally:")
446
+ self.indent()
447
+ self.visit(node.finally_clause)
448
+ self.dedent()
449
+
450
+ def visit_TryExceptStatNode(self, node):
451
+ self.line(u"try:")
452
+ self.indent()
453
+ self.visit(node.body)
454
+ self.dedent()
455
+ for x in node.except_clauses:
456
+ self.visit(x)
457
+ if node.else_clause is not None:
458
+ self.visit(node.else_clause)
459
+
460
+ def visit_ExceptClauseNode(self, node):
461
+ self.startline(u"except")
462
+ if node.pattern is not None:
463
+ self.put(u" ")
464
+ self.visit(node.pattern)
465
+ if node.target is not None:
466
+ self.put(u", ")
467
+ self.visit(node.target)
468
+ self.endline(":")
469
+ self.indent()
470
+ self.visit(node.body)
471
+ self.dedent()
472
+
473
+ def visit_ReturnStatNode(self, node):
474
+ self.startline("return ")
475
+ self.visit(node.value)
476
+ self.endline()
477
+
478
+ def visit_ReraiseStatNode(self, node):
479
+ self.line("raise")
480
+
481
+ def visit_ImportNode(self, node):
482
+ self.put(u"(import %s)" % node.module_name.value)
483
+
484
+ def visit_TempsBlockNode(self, node):
485
+ """
486
+ Temporaries are output like $1_1', where the first number is
487
+ an index of the TempsBlockNode and the second number is an index
488
+ of the temporary which that block allocates.
489
+ """
490
+ idx = 0
491
+ for handle in node.temps:
492
+ self.tempnames[handle] = "$%d_%d" % (self.tempblockindex, idx)
493
+ idx += 1
494
+ self.tempblockindex += 1
495
+ self.visit(node.body)
496
+
497
+ def visit_TempRefNode(self, node):
498
+ self.put(self.tempnames[node.handle])
499
+
500
+
501
+ class PxdWriter(DeclarationWriter):
502
+ def __call__(self, node):
503
+ print(u'\n'.join(self.write(node).lines))
504
+ return node
505
+
506
+ def visit_CFuncDefNode(self, node):
507
+ if 'inline' in node.modifiers:
508
+ return
509
+ if node.overridable:
510
+ self.startline(u'cpdef ')
511
+ else:
512
+ self.startline(u'cdef ')
513
+ if node.visibility != 'private':
514
+ self.put(node.visibility)
515
+ self.put(u' ')
516
+ if node.api:
517
+ self.put(u'api ')
518
+ self.visit(node.declarator)
519
+
520
+ def visit_StatNode(self, node):
521
+ pass
522
+
523
+
524
+ class ExpressionWriter(TreeVisitor):
525
+
526
+ def __init__(self, result=None):
527
+ super(ExpressionWriter, self).__init__()
528
+ if result is None:
529
+ result = u""
530
+ self.result = result
531
+ self.precedence = [0]
532
+
533
+ def write(self, tree):
534
+ self.visit(tree)
535
+ return self.result
536
+
537
+ def put(self, s):
538
+ self.result += s
539
+
540
+ def remove(self, s):
541
+ if self.result.endswith(s):
542
+ self.result = self.result[:-len(s)]
543
+
544
+ def comma_separated_list(self, items):
545
+ if len(items) > 0:
546
+ for item in items[:-1]:
547
+ self.visit(item)
548
+ self.put(u", ")
549
+ self.visit(items[-1])
550
+
551
+ def visit_Node(self, node):
552
+ raise AssertionError("Node not handled by serializer: %r" % node)
553
+
554
+ def visit_NameNode(self, node):
555
+ self.put(node.name)
556
+
557
+ def visit_NoneNode(self, node):
558
+ self.put(u"None")
559
+
560
+ def visit_EllipsisNode(self, node):
561
+ self.put(u"...")
562
+
563
+ def visit_BoolNode(self, node):
564
+ self.put(str(node.value))
565
+
566
+ def visit_ConstNode(self, node):
567
+ self.put(str(node.value))
568
+
569
+ def visit_ImagNode(self, node):
570
+ self.put(node.value)
571
+ self.put(u"j")
572
+
573
+ def emit_string(self, node, prefix=u""):
574
+ repr_val = repr(node.value)
575
+ if repr_val[0] in 'ub':
576
+ repr_val = repr_val[1:]
577
+ self.put(u"%s%s" % (prefix, repr_val))
578
+
579
+ def visit_BytesNode(self, node):
580
+ self.emit_string(node, u"b")
581
+
582
+ def visit_StringNode(self, node):
583
+ self.emit_string(node)
584
+
585
+ def visit_UnicodeNode(self, node):
586
+ self.emit_string(node, u"u")
587
+
588
+ def emit_sequence(self, node, parens=(u"", u"")):
589
+ open_paren, close_paren = parens
590
+ items = node.subexpr_nodes()
591
+ self.put(open_paren)
592
+ self.comma_separated_list(items)
593
+ self.put(close_paren)
594
+
595
+ def visit_ListNode(self, node):
596
+ self.emit_sequence(node, u"[]")
597
+
598
+ def visit_TupleNode(self, node):
599
+ self.emit_sequence(node, u"()")
600
+
601
+ def visit_SetNode(self, node):
602
+ if len(node.subexpr_nodes()) > 0:
603
+ self.emit_sequence(node, u"{}")
604
+ else:
605
+ self.put(u"set()")
606
+
607
+ def visit_DictNode(self, node):
608
+ self.emit_sequence(node, u"{}")
609
+
610
+ def visit_DictItemNode(self, node):
611
+ self.visit(node.key)
612
+ self.put(u": ")
613
+ self.visit(node.value)
614
+
615
+ unop_precedence = {
616
+ 'not': 3, '!': 3,
617
+ '+': 11, '-': 11, '~': 11,
618
+ }
619
+ binop_precedence = {
620
+ 'or': 1,
621
+ 'and': 2,
622
+ # unary: 'not': 3, '!': 3,
623
+ 'in': 4, 'not_in': 4, 'is': 4, 'is_not': 4, '<': 4, '<=': 4, '>': 4, '>=': 4, '!=': 4, '==': 4,
624
+ '|': 5,
625
+ '^': 6,
626
+ '&': 7,
627
+ '<<': 8, '>>': 8,
628
+ '+': 9, '-': 9,
629
+ '*': 10, '@': 10, '/': 10, '//': 10, '%': 10,
630
+ # unary: '+': 11, '-': 11, '~': 11
631
+ '**': 12,
632
+ }
633
+
634
+ def operator_enter(self, new_prec):
635
+ old_prec = self.precedence[-1]
636
+ if old_prec > new_prec:
637
+ self.put(u"(")
638
+ self.precedence.append(new_prec)
639
+
640
+ def operator_exit(self):
641
+ old_prec, new_prec = self.precedence[-2:]
642
+ if old_prec > new_prec:
643
+ self.put(u")")
644
+ self.precedence.pop()
645
+
646
+ def visit_NotNode(self, node):
647
+ op = 'not'
648
+ prec = self.unop_precedence[op]
649
+ self.operator_enter(prec)
650
+ self.put(u"not ")
651
+ self.visit(node.operand)
652
+ self.operator_exit()
653
+
654
+ def visit_UnopNode(self, node):
655
+ op = node.operator
656
+ prec = self.unop_precedence[op]
657
+ self.operator_enter(prec)
658
+ self.put(u"%s" % node.operator)
659
+ self.visit(node.operand)
660
+ self.operator_exit()
661
+
662
+ def visit_BinopNode(self, node):
663
+ op = node.operator
664
+ prec = self.binop_precedence.get(op, 0)
665
+ self.operator_enter(prec)
666
+ self.visit(node.operand1)
667
+ self.put(u" %s " % op.replace('_', ' '))
668
+ self.visit(node.operand2)
669
+ self.operator_exit()
670
+
671
+ def visit_BoolBinopNode(self, node):
672
+ self.visit_BinopNode(node)
673
+
674
+ def visit_PrimaryCmpNode(self, node):
675
+ self.visit_BinopNode(node)
676
+
677
+ def visit_IndexNode(self, node):
678
+ self.visit(node.base)
679
+ self.put(u"[")
680
+ if isinstance(node.index, TupleNode):
681
+ if node.index.subexpr_nodes():
682
+ self.emit_sequence(node.index)
683
+ else:
684
+ self.put(u"()")
685
+ else:
686
+ self.visit(node.index)
687
+ self.put(u"]")
688
+
689
+ def visit_SliceIndexNode(self, node):
690
+ self.visit(node.base)
691
+ self.put(u"[")
692
+ if node.start:
693
+ self.visit(node.start)
694
+ self.put(u":")
695
+ if node.stop:
696
+ self.visit(node.stop)
697
+ if node.slice:
698
+ self.put(u":")
699
+ self.visit(node.slice)
700
+ self.put(u"]")
701
+
702
+ def visit_SliceNode(self, node):
703
+ if not node.start.is_none:
704
+ self.visit(node.start)
705
+ self.put(u":")
706
+ if not node.stop.is_none:
707
+ self.visit(node.stop)
708
+ if not node.step.is_none:
709
+ self.put(u":")
710
+ self.visit(node.step)
711
+
712
+ def visit_CondExprNode(self, node):
713
+ self.visit(node.true_val)
714
+ self.put(u" if ")
715
+ self.visit(node.test)
716
+ self.put(u" else ")
717
+ self.visit(node.false_val)
718
+
719
+ def visit_AttributeNode(self, node):
720
+ self.visit(node.obj)
721
+ self.put(u".%s" % node.attribute)
722
+
723
+ def visit_SimpleCallNode(self, node):
724
+ self.visit(node.function)
725
+ self.put(u"(")
726
+ self.comma_separated_list(node.args)
727
+ self.put(")")
728
+
729
+ def emit_pos_args(self, node):
730
+ if node is None:
731
+ return
732
+ if isinstance(node, AddNode):
733
+ self.emit_pos_args(node.operand1)
734
+ self.emit_pos_args(node.operand2)
735
+ elif isinstance(node, TupleNode):
736
+ for expr in node.subexpr_nodes():
737
+ self.visit(expr)
738
+ self.put(u", ")
739
+ elif isinstance(node, AsTupleNode):
740
+ self.put("*")
741
+ self.visit(node.arg)
742
+ self.put(u", ")
743
+ else:
744
+ self.visit(node)
745
+ self.put(u", ")
746
+
747
+ def emit_kwd_args(self, node):
748
+ if node is None:
749
+ return
750
+ if isinstance(node, MergedDictNode):
751
+ for expr in node.subexpr_nodes():
752
+ self.emit_kwd_args(expr)
753
+ elif isinstance(node, DictNode):
754
+ for expr in node.subexpr_nodes():
755
+ self.put(u"%s=" % expr.key.value)
756
+ self.visit(expr.value)
757
+ self.put(u", ")
758
+ else:
759
+ self.put(u"**")
760
+ self.visit(node)
761
+ self.put(u", ")
762
+
763
+ def visit_GeneralCallNode(self, node):
764
+ self.visit(node.function)
765
+ self.put(u"(")
766
+ self.emit_pos_args(node.positional_args)
767
+ self.emit_kwd_args(node.keyword_args)
768
+ self.remove(u", ")
769
+ self.put(")")
770
+
771
+ def emit_comprehension(self, body, target,
772
+ sequence, condition,
773
+ parens=(u"", u"")):
774
+ open_paren, close_paren = parens
775
+ self.put(open_paren)
776
+ self.visit(body)
777
+ self.put(u" for ")
778
+ self.visit(target)
779
+ self.put(u" in ")
780
+ self.visit(sequence)
781
+ if condition:
782
+ self.put(u" if ")
783
+ self.visit(condition)
784
+ self.put(close_paren)
785
+
786
+ def visit_ComprehensionAppendNode(self, node):
787
+ self.visit(node.expr)
788
+
789
+ def visit_DictComprehensionAppendNode(self, node):
790
+ self.visit(node.key_expr)
791
+ self.put(u": ")
792
+ self.visit(node.value_expr)
793
+
794
+ def visit_ComprehensionNode(self, node):
795
+ tpmap = {'list': u"[]", 'dict': u"{}", 'set': u"{}"}
796
+ parens = tpmap[node.type.py_type_name()]
797
+ body = node.loop.body
798
+ target = node.loop.target
799
+ sequence = node.loop.iterator.sequence
800
+ condition = None
801
+ if hasattr(body, 'if_clauses'):
802
+ # type(body) is Nodes.IfStatNode
803
+ condition = body.if_clauses[0].condition
804
+ body = body.if_clauses[0].body
805
+ self.emit_comprehension(body, target, sequence, condition, parens)
806
+
807
+ def visit_GeneratorExpressionNode(self, node):
808
+ body = node.loop.body
809
+ target = node.loop.target
810
+ sequence = node.loop.iterator.sequence
811
+ condition = None
812
+ if hasattr(body, 'if_clauses'):
813
+ # type(body) is Nodes.IfStatNode
814
+ condition = body.if_clauses[0].condition
815
+ body = body.if_clauses[0].body.expr.arg
816
+ elif hasattr(body, 'expr'):
817
+ # type(body) is Nodes.ExprStatNode
818
+ body = body.expr.arg
819
+ self.emit_comprehension(body, target, sequence, condition, u"()")
venv/Lib/site-packages/Cython/Compiler/AnalysedTreeTransforms.py ADDED
@@ -0,0 +1,99 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from __future__ import absolute_import
2
+
3
+ from .Visitor import ScopeTrackingTransform
4
+ from .Nodes import StatListNode, SingleAssignmentNode, CFuncDefNode, DefNode
5
+ from .ExprNodes import DictNode, DictItemNode, NameNode, UnicodeNode
6
+ from .PyrexTypes import py_object_type
7
+ from .StringEncoding import EncodedString
8
+ from . import Symtab
9
+
10
+ class AutoTestDictTransform(ScopeTrackingTransform):
11
+ # Handles autotestdict directive
12
+
13
+ blacklist = ['__cinit__', '__dealloc__', '__richcmp__',
14
+ '__nonzero__', '__bool__',
15
+ '__len__', '__contains__']
16
+
17
+ def visit_ModuleNode(self, node):
18
+ if node.is_pxd:
19
+ return node
20
+ self.scope_type = 'module'
21
+ self.scope_node = node
22
+
23
+ if not self.current_directives['autotestdict']:
24
+ return node
25
+ self.all_docstrings = self.current_directives['autotestdict.all']
26
+ self.cdef_docstrings = self.all_docstrings or self.current_directives['autotestdict.cdef']
27
+
28
+ assert isinstance(node.body, StatListNode)
29
+
30
+ # First see if __test__ is already created
31
+ if u'__test__' in node.scope.entries:
32
+ # Do nothing
33
+ return node
34
+
35
+ pos = node.pos
36
+
37
+ self.tests = []
38
+ self.testspos = node.pos
39
+
40
+ test_dict_entry = node.scope.declare_var(EncodedString(u'__test__'),
41
+ py_object_type,
42
+ pos,
43
+ visibility='public')
44
+ create_test_dict_assignment = SingleAssignmentNode(pos,
45
+ lhs=NameNode(pos, name=EncodedString(u'__test__'),
46
+ entry=test_dict_entry),
47
+ rhs=DictNode(pos, key_value_pairs=self.tests))
48
+ self.visitchildren(node)
49
+ node.body.stats.append(create_test_dict_assignment)
50
+ return node
51
+
52
+ def add_test(self, testpos, path, doctest):
53
+ pos = self.testspos
54
+ keystr = u'%s (line %d)' % (path, testpos[1])
55
+ key = UnicodeNode(pos, value=EncodedString(keystr))
56
+ value = UnicodeNode(pos, value=doctest)
57
+ self.tests.append(DictItemNode(pos, key=key, value=value))
58
+
59
+ def visit_ExprNode(self, node):
60
+ # expressions cannot contain functions and lambda expressions
61
+ # do not have a docstring
62
+ return node
63
+
64
+ def visit_FuncDefNode(self, node):
65
+ if not node.doc or (isinstance(node, DefNode) and node.fused_py_func):
66
+ return node
67
+ if not self.cdef_docstrings:
68
+ if isinstance(node, CFuncDefNode) and not node.py_func:
69
+ return node
70
+ if not self.all_docstrings and '>>>' not in node.doc:
71
+ return node
72
+
73
+ pos = self.testspos
74
+ if self.scope_type == 'module':
75
+ path = node.entry.name
76
+ elif self.scope_type in ('pyclass', 'cclass'):
77
+ if isinstance(node, CFuncDefNode):
78
+ if node.py_func is not None:
79
+ name = node.py_func.name
80
+ else:
81
+ name = node.entry.name
82
+ else:
83
+ name = node.name
84
+ if self.scope_type == 'cclass' and name in self.blacklist:
85
+ return node
86
+ if self.scope_type == 'pyclass':
87
+ class_name = self.scope_node.name
88
+ else:
89
+ class_name = self.scope_node.class_name
90
+ if isinstance(node.entry.scope, Symtab.PropertyScope):
91
+ property_method_name = node.entry.scope.name
92
+ path = "%s.%s.%s" % (class_name, node.entry.scope.name,
93
+ node.entry.name)
94
+ else:
95
+ path = "%s.%s" % (class_name, node.entry.name)
96
+ else:
97
+ assert False
98
+ self.add_test(node.pos, path, node.doc)
99
+ return node
venv/Lib/site-packages/Cython/Compiler/Annotate.py ADDED
@@ -0,0 +1,317 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Note: Work in progress
2
+
3
+ from __future__ import absolute_import
4
+
5
+ import os
6
+ import os.path
7
+ import re
8
+ import codecs
9
+ import textwrap
10
+ from datetime import datetime
11
+ from functools import partial
12
+ from collections import defaultdict
13
+ from xml.sax.saxutils import escape as html_escape
14
+ try:
15
+ from StringIO import StringIO
16
+ except ImportError:
17
+ from io import StringIO # does not support writing 'str' in Py2
18
+
19
+ from . import Version
20
+ from .Code import CCodeWriter
21
+ from .. import Utils
22
+
23
+
24
+ class AnnotationCCodeWriter(CCodeWriter):
25
+
26
+ def __init__(self, create_from=None, buffer=None, copy_formatting=True):
27
+ CCodeWriter.__init__(self, create_from, buffer, copy_formatting=copy_formatting)
28
+ if create_from is None:
29
+ self.annotation_buffer = StringIO()
30
+ self.last_annotated_pos = None
31
+ # annotations[filename][line] -> [(column, AnnotationItem)*]
32
+ self.annotations = defaultdict(partial(defaultdict, list))
33
+ # code[filename][line] -> str
34
+ self.code = defaultdict(partial(defaultdict, str))
35
+ # scopes[filename][line] -> set(scopes)
36
+ self.scopes = defaultdict(partial(defaultdict, set))
37
+ else:
38
+ # When creating an insertion point, keep references to the same database
39
+ self.annotation_buffer = create_from.annotation_buffer
40
+ self.annotations = create_from.annotations
41
+ self.code = create_from.code
42
+ self.scopes = create_from.scopes
43
+ self.last_annotated_pos = create_from.last_annotated_pos
44
+
45
+ def create_new(self, create_from, buffer, copy_formatting):
46
+ return AnnotationCCodeWriter(create_from, buffer, copy_formatting)
47
+
48
+ def write(self, s):
49
+ CCodeWriter.write(self, s)
50
+ self.annotation_buffer.write(s)
51
+
52
+ def mark_pos(self, pos, trace=True):
53
+ if pos is not None:
54
+ CCodeWriter.mark_pos(self, pos, trace)
55
+ if self.funcstate and self.funcstate.scope:
56
+ # lambdas and genexprs can result in multiple scopes per line => keep them in a set
57
+ self.scopes[pos[0].filename][pos[1]].add(self.funcstate.scope)
58
+ if self.last_annotated_pos:
59
+ source_desc, line, _ = self.last_annotated_pos
60
+ pos_code = self.code[source_desc.filename]
61
+ pos_code[line] += self.annotation_buffer.getvalue()
62
+ self.annotation_buffer = StringIO()
63
+ self.last_annotated_pos = pos
64
+
65
+ def annotate(self, pos, item):
66
+ self.annotations[pos[0].filename][pos[1]].append((pos[2], item))
67
+
68
+ def _css(self):
69
+ """css template will later allow to choose a colormap"""
70
+ css = [self._css_template]
71
+ for i in range(255):
72
+ color = u"FFFF%02x" % int(255/(1+i/10.0))
73
+ css.append('.cython.score-%d {background-color: #%s;}' % (i, color))
74
+ try:
75
+ from pygments.formatters import HtmlFormatter
76
+ except ImportError:
77
+ pass
78
+ else:
79
+ css.append(HtmlFormatter().get_style_defs('.cython'))
80
+ return '\n'.join(css)
81
+
82
+ _css_template = textwrap.dedent("""
83
+ body.cython { font-family: courier; font-size: 12; }
84
+
85
+ .cython.tag { }
86
+ .cython.line { margin: 0em }
87
+ .cython.code { font-size: 9; color: #444444; display: none; margin: 0px 0px 0px 8px; border-left: 8px none; }
88
+
89
+ .cython.line .run { background-color: #B0FFB0; }
90
+ .cython.line .mis { background-color: #FFB0B0; }
91
+ .cython.code.run { border-left: 8px solid #B0FFB0; }
92
+ .cython.code.mis { border-left: 8px solid #FFB0B0; }
93
+
94
+ .cython.code .py_c_api { color: red; }
95
+ .cython.code .py_macro_api { color: #FF7000; }
96
+ .cython.code .pyx_c_api { color: #FF3000; }
97
+ .cython.code .pyx_macro_api { color: #FF7000; }
98
+ .cython.code .refnanny { color: #FFA000; }
99
+ .cython.code .trace { color: #FFA000; }
100
+ .cython.code .error_goto { color: #FFA000; }
101
+
102
+ .cython.code .coerce { color: #008000; border: 1px dotted #008000 }
103
+ .cython.code .py_attr { color: #FF0000; font-weight: bold; }
104
+ .cython.code .c_attr { color: #0000FF; }
105
+ .cython.code .py_call { color: #FF0000; font-weight: bold; }
106
+ .cython.code .c_call { color: #0000FF; }
107
+ """)
108
+
109
+ # on-click toggle function to show/hide C source code
110
+ _onclick_attr = ' onclick="{0}"'.format((
111
+ "(function(s){"
112
+ " s.display = s.display === 'block' ? 'none' : 'block'"
113
+ "})(this.nextElementSibling.style)"
114
+ ).replace(' ', '') # poor dev's JS minification
115
+ )
116
+
117
+ def save_annotation(self, source_filename, target_filename, coverage_xml=None):
118
+ with Utils.open_source_file(source_filename) as f:
119
+ code = f.read()
120
+ generated_code = self.code.get(source_filename, {})
121
+ c_file = Utils.decode_filename(os.path.basename(target_filename))
122
+ html_filename = os.path.splitext(target_filename)[0] + ".html"
123
+
124
+ with codecs.open(html_filename, "w", encoding="UTF-8") as out_buffer:
125
+ out_buffer.write(self._save_annotation(code, generated_code, c_file, source_filename, coverage_xml))
126
+
127
+ def _save_annotation_header(self, c_file, source_filename, coverage_timestamp=None):
128
+ coverage_info = ''
129
+ if coverage_timestamp:
130
+ coverage_info = u' with coverage data from {timestamp}'.format(
131
+ timestamp=datetime.fromtimestamp(int(coverage_timestamp) // 1000))
132
+
133
+ outlist = [
134
+ textwrap.dedent(u'''\
135
+ <!DOCTYPE html>
136
+ <!-- Generated by Cython {watermark} -->
137
+ <html>
138
+ <head>
139
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
140
+ <title>Cython: {filename}</title>
141
+ <style type="text/css">
142
+ {css}
143
+ </style>
144
+ </head>
145
+ <body class="cython">
146
+ <p><span style="border-bottom: solid 1px grey;">Generated by Cython {watermark}</span>{more_info}</p>
147
+ <p>
148
+ <span style="background-color: #FFFF00">Yellow lines</span> hint at Python interaction.<br />
149
+ Click on a line that starts with a "<code>+</code>" to see the C code that Cython generated for it.
150
+ </p>
151
+ ''').format(css=self._css(), watermark=Version.watermark,
152
+ filename=os.path.basename(source_filename) if source_filename else '',
153
+ more_info=coverage_info)
154
+ ]
155
+ if c_file:
156
+ outlist.append(u'<p>Raw output: <a href="%s">%s</a></p>\n' % (c_file, c_file))
157
+ return outlist
158
+
159
+ def _save_annotation_footer(self):
160
+ return (u'</body></html>\n',)
161
+
162
+ def _save_annotation(self, code, generated_code, c_file=None, source_filename=None, coverage_xml=None):
163
+ """
164
+ lines : original cython source code split by lines
165
+ generated_code : generated c code keyed by line number in original file
166
+ target filename : name of the file in which to store the generated html
167
+ c_file : filename in which the c_code has been written
168
+ """
169
+ if coverage_xml is not None and source_filename:
170
+ coverage_timestamp = coverage_xml.get('timestamp', '').strip()
171
+ covered_lines = self._get_line_coverage(coverage_xml, source_filename)
172
+ else:
173
+ coverage_timestamp = covered_lines = None
174
+ annotation_items = dict(self.annotations[source_filename])
175
+ scopes = dict(self.scopes[source_filename])
176
+
177
+ outlist = []
178
+ outlist.extend(self._save_annotation_header(c_file, source_filename, coverage_timestamp))
179
+ outlist.extend(self._save_annotation_body(code, generated_code, annotation_items, scopes, covered_lines))
180
+ outlist.extend(self._save_annotation_footer())
181
+ return ''.join(outlist)
182
+
183
+ def _get_line_coverage(self, coverage_xml, source_filename):
184
+ coverage_data = None
185
+ for entry in coverage_xml.iterfind('.//class'):
186
+ if not entry.get('filename'):
187
+ continue
188
+ if (entry.get('filename') == source_filename or
189
+ os.path.abspath(entry.get('filename')) == source_filename):
190
+ coverage_data = entry
191
+ break
192
+ elif source_filename.endswith(entry.get('filename')):
193
+ coverage_data = entry # but we might still find a better match...
194
+ if coverage_data is None:
195
+ return None
196
+ return dict(
197
+ (int(line.get('number')), int(line.get('hits')))
198
+ for line in coverage_data.iterfind('lines/line')
199
+ )
200
+
201
+ def _htmlify_code(self, code):
202
+ try:
203
+ from pygments import highlight
204
+ from pygments.lexers import CythonLexer
205
+ from pygments.formatters import HtmlFormatter
206
+ except ImportError:
207
+ # no Pygments, just escape the code
208
+ return html_escape(code)
209
+
210
+ html_code = highlight(
211
+ code, CythonLexer(stripnl=False, stripall=False),
212
+ HtmlFormatter(nowrap=True))
213
+ return html_code
214
+
215
+ def _save_annotation_body(self, cython_code, generated_code, annotation_items, scopes, covered_lines=None):
216
+ outlist = [u'<div class="cython">']
217
+ pos_comment_marker = u'/* \N{HORIZONTAL ELLIPSIS} */\n'
218
+ new_calls_map = dict(
219
+ (name, 0) for name in
220
+ 'refnanny trace py_macro_api py_c_api pyx_macro_api pyx_c_api error_goto'.split()
221
+ ).copy
222
+
223
+ self.mark_pos(None)
224
+
225
+ def annotate(match):
226
+ group_name = match.lastgroup
227
+ calls[group_name] += 1
228
+ return u"<span class='%s'>%s</span>" % (
229
+ group_name, match.group(group_name))
230
+
231
+ lines = self._htmlify_code(cython_code).splitlines()
232
+ lineno_width = len(str(len(lines)))
233
+ if not covered_lines:
234
+ covered_lines = None
235
+
236
+ for k, line in enumerate(lines, 1):
237
+ try:
238
+ c_code = generated_code[k]
239
+ except KeyError:
240
+ c_code = ''
241
+ else:
242
+ c_code = _replace_pos_comment(pos_comment_marker, c_code)
243
+ if c_code.startswith(pos_comment_marker):
244
+ c_code = c_code[len(pos_comment_marker):]
245
+ c_code = html_escape(c_code)
246
+
247
+ calls = new_calls_map()
248
+ c_code = _parse_code(annotate, c_code)
249
+ score = (5 * calls['py_c_api'] + 2 * calls['pyx_c_api'] +
250
+ calls['py_macro_api'] + calls['pyx_macro_api'])
251
+
252
+ if c_code:
253
+ onclick = self._onclick_attr
254
+ expandsymbol = '+'
255
+ else:
256
+ onclick = ''
257
+ expandsymbol = '&#xA0;'
258
+
259
+ covered = ''
260
+ if covered_lines is not None and k in covered_lines:
261
+ hits = covered_lines[k]
262
+ if hits is not None:
263
+ covered = 'run' if hits else 'mis'
264
+
265
+ outlist.append(
266
+ u'<pre class="cython line score-{score}"{onclick}>'
267
+ # generate line number with expand symbol in front,
268
+ # and the right number of digit
269
+ u'{expandsymbol}<span class="{covered}">{line:0{lineno_width}d}</span>: {code}</pre>\n'.format(
270
+ score=score,
271
+ expandsymbol=expandsymbol,
272
+ covered=covered,
273
+ lineno_width=lineno_width,
274
+ line=k,
275
+ code=line.rstrip(),
276
+ onclick=onclick,
277
+ ))
278
+ if c_code:
279
+ outlist.append(u"<pre class='cython code score-{score} {covered}'>{code}</pre>".format(
280
+ score=score, covered=covered, code=c_code))
281
+ outlist.append(u"</div>")
282
+ return outlist
283
+
284
+
285
+ _parse_code = re.compile((
286
+ br'(?P<refnanny>__Pyx_X?(?:GOT|GIVE)REF|__Pyx_RefNanny[A-Za-z]+)|'
287
+ br'(?P<trace>__Pyx_Trace[A-Za-z]+)|'
288
+ br'(?:'
289
+ br'(?P<pyx_macro_api>__Pyx_[A-Z][A-Z_]+)|'
290
+ br'(?P<pyx_c_api>(?:__Pyx_[A-Z][a-z_][A-Za-z_]*)|__pyx_convert_[A-Za-z_]*)|'
291
+ br'(?P<py_macro_api>Py[A-Z][a-z]+_[A-Z][A-Z_]+)|'
292
+ br'(?P<py_c_api>Py[A-Z][a-z]+_[A-Z][a-z][A-Za-z_]*)'
293
+ br')(?=\()|' # look-ahead to exclude subsequent '(' from replacement
294
+ br'(?P<error_goto>(?:(?<=;) *if [^;]* +)?__PYX_ERR\([^)]+\))'
295
+ ).decode('ascii')).sub
296
+
297
+
298
+ _replace_pos_comment = re.compile(
299
+ # this matches what Cython generates as code line marker comment
300
+ br'^\s*/\*(?:(?:[^*]|\*[^/])*\n)+\s*\*/\s*\n'.decode('ascii'),
301
+ re.M
302
+ ).sub
303
+
304
+
305
+ class AnnotationItem(object):
306
+
307
+ def __init__(self, style, text, tag="", size=0):
308
+ self.style = style
309
+ self.text = text
310
+ self.tag = tag
311
+ self.size = size
312
+
313
+ def start(self):
314
+ return u"<span class='cython tag %s' title='%s'>%s" % (self.style, self.text, self.tag)
315
+
316
+ def end(self):
317
+ return self.size, u"</span>"
venv/Lib/site-packages/Cython/Compiler/AutoDocTransforms.py ADDED
@@ -0,0 +1,214 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from __future__ import absolute_import, print_function
2
+
3
+ from .Visitor import CythonTransform
4
+ from .StringEncoding import EncodedString
5
+ from . import Options
6
+ from . import PyrexTypes, ExprNodes
7
+ from ..CodeWriter import ExpressionWriter
8
+
9
+
10
+ class AnnotationWriter(ExpressionWriter):
11
+
12
+ def visit_Node(self, node):
13
+ self.put(u"<???>")
14
+
15
+ def visit_LambdaNode(self, node):
16
+ # XXX Should we do better?
17
+ self.put("<lambda>")
18
+
19
+
20
+ class EmbedSignature(CythonTransform):
21
+
22
+ def __init__(self, context):
23
+ super(EmbedSignature, self).__init__(context)
24
+ self.class_name = None
25
+ self.class_node = None
26
+
27
+ def _fmt_expr(self, node):
28
+ writer = AnnotationWriter()
29
+ result = writer.write(node)
30
+ # print(type(node).__name__, '-->', result)
31
+ return result
32
+
33
+ def _fmt_arg(self, arg):
34
+ if arg.type is PyrexTypes.py_object_type or arg.is_self_arg:
35
+ doc = arg.name
36
+ else:
37
+ doc = arg.type.declaration_code(arg.name, for_display=1)
38
+
39
+ if arg.annotation:
40
+ annotation = self._fmt_expr(arg.annotation)
41
+ doc = doc + (': %s' % annotation)
42
+ if arg.default:
43
+ default = self._fmt_expr(arg.default)
44
+ doc = doc + (' = %s' % default)
45
+ elif arg.default:
46
+ default = self._fmt_expr(arg.default)
47
+ doc = doc + ('=%s' % default)
48
+ return doc
49
+
50
+ def _fmt_star_arg(self, arg):
51
+ arg_doc = arg.name
52
+ if arg.annotation:
53
+ annotation = self._fmt_expr(arg.annotation)
54
+ arg_doc = arg_doc + (': %s' % annotation)
55
+ return arg_doc
56
+
57
+ def _fmt_arglist(self, args,
58
+ npargs=0, pargs=None,
59
+ nkargs=0, kargs=None,
60
+ hide_self=False):
61
+ arglist = []
62
+ for arg in args:
63
+ if not hide_self or not arg.entry.is_self_arg:
64
+ arg_doc = self._fmt_arg(arg)
65
+ arglist.append(arg_doc)
66
+ if pargs:
67
+ arg_doc = self._fmt_star_arg(pargs)
68
+ arglist.insert(npargs, '*%s' % arg_doc)
69
+ elif nkargs:
70
+ arglist.insert(npargs, '*')
71
+ if kargs:
72
+ arg_doc = self._fmt_star_arg(kargs)
73
+ arglist.append('**%s' % arg_doc)
74
+ return arglist
75
+
76
+ def _fmt_ret_type(self, ret):
77
+ if ret is PyrexTypes.py_object_type:
78
+ return None
79
+ else:
80
+ return ret.declaration_code("", for_display=1)
81
+
82
+ def _fmt_signature(self, cls_name, func_name, args,
83
+ npargs=0, pargs=None,
84
+ nkargs=0, kargs=None,
85
+ return_expr=None,
86
+ return_type=None, hide_self=False):
87
+ arglist = self._fmt_arglist(args,
88
+ npargs, pargs,
89
+ nkargs, kargs,
90
+ hide_self=hide_self)
91
+ arglist_doc = ', '.join(arglist)
92
+ func_doc = '%s(%s)' % (func_name, arglist_doc)
93
+ if cls_name:
94
+ func_doc = '%s.%s' % (cls_name, func_doc)
95
+ ret_doc = None
96
+ if return_expr:
97
+ ret_doc = self._fmt_expr(return_expr)
98
+ elif return_type:
99
+ ret_doc = self._fmt_ret_type(return_type)
100
+ if ret_doc:
101
+ func_doc = '%s -> %s' % (func_doc, ret_doc)
102
+ return func_doc
103
+
104
+ def _embed_signature(self, signature, node_doc):
105
+ if node_doc:
106
+ return "%s\n%s" % (signature, node_doc)
107
+ else:
108
+ return signature
109
+
110
+ def __call__(self, node):
111
+ if not Options.docstrings:
112
+ return node
113
+ else:
114
+ return super(EmbedSignature, self).__call__(node)
115
+
116
+ def visit_ClassDefNode(self, node):
117
+ oldname = self.class_name
118
+ oldclass = self.class_node
119
+ self.class_node = node
120
+ try:
121
+ # PyClassDefNode
122
+ self.class_name = node.name
123
+ except AttributeError:
124
+ # CClassDefNode
125
+ self.class_name = node.class_name
126
+ self.visitchildren(node)
127
+ self.class_name = oldname
128
+ self.class_node = oldclass
129
+ return node
130
+
131
+ def visit_LambdaNode(self, node):
132
+ # lambda expressions so not have signature or inner functions
133
+ return node
134
+
135
+ def visit_DefNode(self, node):
136
+ if not self.current_directives['embedsignature']:
137
+ return node
138
+
139
+ is_constructor = False
140
+ hide_self = False
141
+ if node.entry.is_special:
142
+ is_constructor = self.class_node and node.name == '__init__'
143
+ if not is_constructor:
144
+ return node
145
+ class_name, func_name = None, self.class_name
146
+ hide_self = True
147
+ else:
148
+ class_name, func_name = self.class_name, node.name
149
+
150
+ nkargs = getattr(node, 'num_kwonly_args', 0)
151
+ npargs = len(node.args) - nkargs
152
+ signature = self._fmt_signature(
153
+ class_name, func_name, node.args,
154
+ npargs, node.star_arg,
155
+ nkargs, node.starstar_arg,
156
+ return_expr=node.return_type_annotation,
157
+ return_type=None, hide_self=hide_self)
158
+ if signature:
159
+ if is_constructor:
160
+ doc_holder = self.class_node.entry.type.scope
161
+ else:
162
+ doc_holder = node.entry
163
+
164
+ if doc_holder.doc is not None:
165
+ old_doc = doc_holder.doc
166
+ elif not is_constructor and getattr(node, 'py_func', None) is not None:
167
+ old_doc = node.py_func.entry.doc
168
+ else:
169
+ old_doc = None
170
+ new_doc = self._embed_signature(signature, old_doc)
171
+ doc_holder.doc = EncodedString(new_doc)
172
+ if not is_constructor and getattr(node, 'py_func', None) is not None:
173
+ node.py_func.entry.doc = EncodedString(new_doc)
174
+ return node
175
+
176
+ def visit_CFuncDefNode(self, node):
177
+ if not self.current_directives['embedsignature']:
178
+ return node
179
+ if not node.overridable: # not cpdef FOO(...):
180
+ return node
181
+
182
+ signature = self._fmt_signature(
183
+ self.class_name, node.declarator.base.name,
184
+ node.declarator.args,
185
+ return_type=node.return_type)
186
+ if signature:
187
+ if node.entry.doc is not None:
188
+ old_doc = node.entry.doc
189
+ elif getattr(node, 'py_func', None) is not None:
190
+ old_doc = node.py_func.entry.doc
191
+ else:
192
+ old_doc = None
193
+ new_doc = self._embed_signature(signature, old_doc)
194
+ node.entry.doc = EncodedString(new_doc)
195
+ if hasattr(node, 'py_func') and node.py_func is not None:
196
+ node.py_func.entry.doc = EncodedString(new_doc)
197
+ return node
198
+
199
+ def visit_PropertyNode(self, node):
200
+ if not self.current_directives['embedsignature']:
201
+ return node
202
+
203
+ entry = node.entry
204
+ if entry.visibility == 'public':
205
+ # property synthesised from a cdef public attribute
206
+ type_name = entry.type.declaration_code("", for_display=1)
207
+ if not entry.type.is_pyobject:
208
+ type_name = "'%s'" % type_name
209
+ elif entry.type.is_extension_type:
210
+ type_name = entry.type.module_name + '.' + type_name
211
+ signature = '%s: %s' % (entry.name, type_name)
212
+ new_doc = self._embed_signature(signature, entry.doc)
213
+ entry.doc = EncodedString(new_doc)
214
+ return node
venv/Lib/site-packages/Cython/Compiler/Buffer.py ADDED
@@ -0,0 +1,740 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from __future__ import absolute_import
2
+
3
+ from .Visitor import CythonTransform
4
+ from .ModuleNode import ModuleNode
5
+ from .Errors import CompileError
6
+ from .UtilityCode import CythonUtilityCode
7
+ from .Code import UtilityCode, TempitaUtilityCode
8
+
9
+ from . import Options
10
+ from . import Interpreter
11
+ from . import PyrexTypes
12
+ from . import Naming
13
+ from . import Symtab
14
+
15
+ def dedent(text, reindent=0):
16
+ from textwrap import dedent
17
+ text = dedent(text)
18
+ if reindent > 0:
19
+ indent = " " * reindent
20
+ text = '\n'.join([indent + x for x in text.split('\n')])
21
+ return text
22
+
23
+ class IntroduceBufferAuxiliaryVars(CythonTransform):
24
+
25
+ #
26
+ # Entry point
27
+ #
28
+
29
+ buffers_exists = False
30
+ using_memoryview = False
31
+
32
+ def __call__(self, node):
33
+ assert isinstance(node, ModuleNode)
34
+ self.max_ndim = 0
35
+ result = super(IntroduceBufferAuxiliaryVars, self).__call__(node)
36
+ if self.buffers_exists:
37
+ use_bufstruct_declare_code(node.scope)
38
+ use_py2_buffer_functions(node.scope)
39
+
40
+ return result
41
+
42
+
43
+ #
44
+ # Basic operations for transforms
45
+ #
46
+ def handle_scope(self, node, scope):
47
+ # For all buffers, insert extra variables in the scope.
48
+ # The variables are also accessible from the buffer_info
49
+ # on the buffer entry
50
+ scope_items = scope.entries.items()
51
+ bufvars = [entry for name, entry in scope_items if entry.type.is_buffer]
52
+ if len(bufvars) > 0:
53
+ bufvars.sort(key=lambda entry: entry.name)
54
+ self.buffers_exists = True
55
+
56
+ memviewslicevars = [entry for name, entry in scope_items if entry.type.is_memoryviewslice]
57
+ if len(memviewslicevars) > 0:
58
+ self.buffers_exists = True
59
+
60
+
61
+ for (name, entry) in scope_items:
62
+ if name == 'memoryview' and isinstance(entry.utility_code_definition, CythonUtilityCode):
63
+ self.using_memoryview = True
64
+ break
65
+ del scope_items
66
+
67
+ if isinstance(node, ModuleNode) and len(bufvars) > 0:
68
+ # for now...note that pos is wrong
69
+ raise CompileError(node.pos, "Buffer vars not allowed in module scope")
70
+ for entry in bufvars:
71
+ if entry.type.dtype.is_ptr:
72
+ raise CompileError(node.pos, "Buffers with pointer types not yet supported.")
73
+
74
+ name = entry.name
75
+ buftype = entry.type
76
+ if buftype.ndim > Options.buffer_max_dims:
77
+ raise CompileError(node.pos,
78
+ "Buffer ndims exceeds Options.buffer_max_dims = %d" % Options.buffer_max_dims)
79
+ if buftype.ndim > self.max_ndim:
80
+ self.max_ndim = buftype.ndim
81
+
82
+ # Declare auxiliary vars
83
+ def decvar(type, prefix):
84
+ cname = scope.mangle(prefix, name)
85
+ aux_var = scope.declare_var(name=None, cname=cname,
86
+ type=type, pos=node.pos)
87
+ if entry.is_arg:
88
+ aux_var.used = True # otherwise, NameNode will mark whether it is used
89
+
90
+ return aux_var
91
+
92
+ auxvars = ((PyrexTypes.c_pyx_buffer_nd_type, Naming.pybuffernd_prefix),
93
+ (PyrexTypes.c_pyx_buffer_type, Naming.pybufferstruct_prefix))
94
+ pybuffernd, rcbuffer = [decvar(type, prefix) for (type, prefix) in auxvars]
95
+
96
+ entry.buffer_aux = Symtab.BufferAux(pybuffernd, rcbuffer)
97
+
98
+ scope.buffer_entries = bufvars
99
+ self.scope = scope
100
+
101
+ def visit_ModuleNode(self, node):
102
+ self.handle_scope(node, node.scope)
103
+ self.visitchildren(node)
104
+ return node
105
+
106
+ def visit_FuncDefNode(self, node):
107
+ self.handle_scope(node, node.local_scope)
108
+ self.visitchildren(node)
109
+ return node
110
+
111
+ #
112
+ # Analysis
113
+ #
114
+ buffer_options = ("dtype", "ndim", "mode", "negative_indices", "cast") # ordered!
115
+ buffer_defaults = {"ndim": 1, "mode": "full", "negative_indices": True, "cast": False}
116
+ buffer_positional_options_count = 1 # anything beyond this needs keyword argument
117
+
118
+ ERR_BUF_OPTION_UNKNOWN = '"%s" is not a buffer option'
119
+ ERR_BUF_TOO_MANY = 'Too many buffer options'
120
+ ERR_BUF_DUP = '"%s" buffer option already supplied'
121
+ ERR_BUF_MISSING = '"%s" missing'
122
+ ERR_BUF_MODE = 'Only allowed buffer modes are: "c", "fortran", "full", "strided" (as a compile-time string)'
123
+ ERR_BUF_NDIM = 'ndim must be a non-negative integer'
124
+ ERR_BUF_DTYPE = 'dtype must be "object", numeric type or a struct'
125
+ ERR_BUF_BOOL = '"%s" must be a boolean'
126
+
127
+ def analyse_buffer_options(globalpos, env, posargs, dictargs, defaults=None, need_complete=True):
128
+ """
129
+ Must be called during type analysis, as analyse is called
130
+ on the dtype argument.
131
+
132
+ posargs and dictargs should consist of a list and a dict
133
+ of tuples (value, pos). Defaults should be a dict of values.
134
+
135
+ Returns a dict containing all the options a buffer can have and
136
+ its value (with the positions stripped).
137
+ """
138
+ if defaults is None:
139
+ defaults = buffer_defaults
140
+
141
+ posargs, dictargs = Interpreter.interpret_compiletime_options(
142
+ posargs, dictargs, type_env=env, type_args=(0, 'dtype'))
143
+
144
+ if len(posargs) > buffer_positional_options_count:
145
+ raise CompileError(posargs[-1][1], ERR_BUF_TOO_MANY)
146
+
147
+ options = {}
148
+ for name, (value, pos) in dictargs.items():
149
+ if not name in buffer_options:
150
+ raise CompileError(pos, ERR_BUF_OPTION_UNKNOWN % name)
151
+ options[name] = value
152
+
153
+ for name, (value, pos) in zip(buffer_options, posargs):
154
+ if not name in buffer_options:
155
+ raise CompileError(pos, ERR_BUF_OPTION_UNKNOWN % name)
156
+ if name in options:
157
+ raise CompileError(pos, ERR_BUF_DUP % name)
158
+ options[name] = value
159
+
160
+ # Check that they are all there and copy defaults
161
+ for name in buffer_options:
162
+ if not name in options:
163
+ try:
164
+ options[name] = defaults[name]
165
+ except KeyError:
166
+ if need_complete:
167
+ raise CompileError(globalpos, ERR_BUF_MISSING % name)
168
+
169
+ dtype = options.get("dtype")
170
+ if dtype and dtype.is_extension_type:
171
+ raise CompileError(globalpos, ERR_BUF_DTYPE)
172
+
173
+ ndim = options.get("ndim")
174
+ if ndim and (not isinstance(ndim, int) or ndim < 0):
175
+ raise CompileError(globalpos, ERR_BUF_NDIM)
176
+
177
+ mode = options.get("mode")
178
+ if mode and not (mode in ('full', 'strided', 'c', 'fortran')):
179
+ raise CompileError(globalpos, ERR_BUF_MODE)
180
+
181
+ def assert_bool(name):
182
+ x = options.get(name)
183
+ if not isinstance(x, bool):
184
+ raise CompileError(globalpos, ERR_BUF_BOOL % name)
185
+
186
+ assert_bool('negative_indices')
187
+ assert_bool('cast')
188
+
189
+ return options
190
+
191
+
192
+ #
193
+ # Code generation
194
+ #
195
+
196
+ class BufferEntry(object):
197
+ def __init__(self, entry):
198
+ self.entry = entry
199
+ self.type = entry.type
200
+ self.cname = entry.buffer_aux.buflocal_nd_var.cname
201
+ self.buf_ptr = "%s.rcbuffer->pybuffer.buf" % self.cname
202
+ self.buf_ptr_type = entry.type.buffer_ptr_type
203
+ self.init_attributes()
204
+
205
+ def init_attributes(self):
206
+ self.shape = self.get_buf_shapevars()
207
+ self.strides = self.get_buf_stridevars()
208
+ self.suboffsets = self.get_buf_suboffsetvars()
209
+
210
+ def get_buf_suboffsetvars(self):
211
+ return self._for_all_ndim("%s.diminfo[%d].suboffsets")
212
+
213
+ def get_buf_stridevars(self):
214
+ return self._for_all_ndim("%s.diminfo[%d].strides")
215
+
216
+ def get_buf_shapevars(self):
217
+ return self._for_all_ndim("%s.diminfo[%d].shape")
218
+
219
+ def _for_all_ndim(self, s):
220
+ return [s % (self.cname, i) for i in range(self.type.ndim)]
221
+
222
+ def generate_buffer_lookup_code(self, code, index_cnames):
223
+ # Create buffer lookup and return it
224
+ # This is done via utility macros/inline functions, which vary
225
+ # according to the access mode used.
226
+ params = []
227
+ nd = self.type.ndim
228
+ mode = self.type.mode
229
+ if mode == 'full':
230
+ for i, s, o in zip(index_cnames,
231
+ self.get_buf_stridevars(),
232
+ self.get_buf_suboffsetvars()):
233
+ params.append(i)
234
+ params.append(s)
235
+ params.append(o)
236
+ funcname = "__Pyx_BufPtrFull%dd" % nd
237
+ funcgen = buf_lookup_full_code
238
+ else:
239
+ if mode == 'strided':
240
+ funcname = "__Pyx_BufPtrStrided%dd" % nd
241
+ funcgen = buf_lookup_strided_code
242
+ elif mode == 'c':
243
+ funcname = "__Pyx_BufPtrCContig%dd" % nd
244
+ funcgen = buf_lookup_c_code
245
+ elif mode == 'fortran':
246
+ funcname = "__Pyx_BufPtrFortranContig%dd" % nd
247
+ funcgen = buf_lookup_fortran_code
248
+ else:
249
+ assert False
250
+ for i, s in zip(index_cnames, self.get_buf_stridevars()):
251
+ params.append(i)
252
+ params.append(s)
253
+
254
+ # Make sure the utility code is available
255
+ if funcname not in code.globalstate.utility_codes:
256
+ code.globalstate.utility_codes.add(funcname)
257
+ protocode = code.globalstate['utility_code_proto']
258
+ defcode = code.globalstate['utility_code_def']
259
+ funcgen(protocode, defcode, name=funcname, nd=nd)
260
+
261
+ buf_ptr_type_code = self.buf_ptr_type.empty_declaration_code()
262
+ ptrcode = "%s(%s, %s, %s)" % (funcname, buf_ptr_type_code, self.buf_ptr,
263
+ ", ".join(params))
264
+ return ptrcode
265
+
266
+
267
+ def get_flags(buffer_aux, buffer_type):
268
+ flags = 'PyBUF_FORMAT'
269
+ mode = buffer_type.mode
270
+ if mode == 'full':
271
+ flags += '| PyBUF_INDIRECT'
272
+ elif mode == 'strided':
273
+ flags += '| PyBUF_STRIDES'
274
+ elif mode == 'c':
275
+ flags += '| PyBUF_C_CONTIGUOUS'
276
+ elif mode == 'fortran':
277
+ flags += '| PyBUF_F_CONTIGUOUS'
278
+ else:
279
+ assert False
280
+ if buffer_aux.writable_needed: flags += "| PyBUF_WRITABLE"
281
+ return flags
282
+
283
+ def used_buffer_aux_vars(entry):
284
+ buffer_aux = entry.buffer_aux
285
+ buffer_aux.buflocal_nd_var.used = True
286
+ buffer_aux.rcbuf_var.used = True
287
+
288
+ def put_unpack_buffer_aux_into_scope(buf_entry, code):
289
+ # Generate code to copy the needed struct info into local
290
+ # variables.
291
+ buffer_aux, mode = buf_entry.buffer_aux, buf_entry.type.mode
292
+ pybuffernd_struct = buffer_aux.buflocal_nd_var.cname
293
+
294
+ fldnames = ['strides', 'shape']
295
+ if mode == 'full':
296
+ fldnames.append('suboffsets')
297
+
298
+ ln = []
299
+ for i in range(buf_entry.type.ndim):
300
+ for fldname in fldnames:
301
+ ln.append("%s.diminfo[%d].%s = %s.rcbuffer->pybuffer.%s[%d];" % \
302
+ (pybuffernd_struct, i, fldname,
303
+ pybuffernd_struct, fldname, i))
304
+ code.putln(' '.join(ln))
305
+
306
+ def put_init_vars(entry, code):
307
+ bufaux = entry.buffer_aux
308
+ pybuffernd_struct = bufaux.buflocal_nd_var.cname
309
+ pybuffer_struct = bufaux.rcbuf_var.cname
310
+ # init pybuffer_struct
311
+ code.putln("%s.pybuffer.buf = NULL;" % pybuffer_struct)
312
+ code.putln("%s.refcount = 0;" % pybuffer_struct)
313
+ # init the buffer object
314
+ # code.put_init_var_to_py_none(entry)
315
+ # init the pybuffernd_struct
316
+ code.putln("%s.data = NULL;" % pybuffernd_struct)
317
+ code.putln("%s.rcbuffer = &%s;" % (pybuffernd_struct, pybuffer_struct))
318
+
319
+
320
+ def put_acquire_arg_buffer(entry, code, pos):
321
+ buffer_aux = entry.buffer_aux
322
+ getbuffer = get_getbuffer_call(code, entry.cname, buffer_aux, entry.type)
323
+
324
+ # Acquire any new buffer
325
+ code.putln("{")
326
+ code.putln("__Pyx_BufFmt_StackElem __pyx_stack[%d];" % entry.type.dtype.struct_nesting_depth())
327
+ code.putln(code.error_goto_if("%s == -1" % getbuffer, pos))
328
+ code.putln("}")
329
+ # An exception raised in arg parsing cannot be caught, so no
330
+ # need to care about the buffer then.
331
+ put_unpack_buffer_aux_into_scope(entry, code)
332
+
333
+
334
+ def put_release_buffer_code(code, entry):
335
+ code.globalstate.use_utility_code(acquire_utility_code)
336
+ code.putln("__Pyx_SafeReleaseBuffer(&%s.rcbuffer->pybuffer);" % entry.buffer_aux.buflocal_nd_var.cname)
337
+
338
+
339
+ def get_getbuffer_call(code, obj_cname, buffer_aux, buffer_type):
340
+ ndim = buffer_type.ndim
341
+ cast = int(buffer_type.cast)
342
+ flags = get_flags(buffer_aux, buffer_type)
343
+ pybuffernd_struct = buffer_aux.buflocal_nd_var.cname
344
+
345
+ dtype_typeinfo = get_type_information_cname(code, buffer_type.dtype)
346
+
347
+ code.globalstate.use_utility_code(acquire_utility_code)
348
+ return ("__Pyx_GetBufferAndValidate(&%(pybuffernd_struct)s.rcbuffer->pybuffer, "
349
+ "(PyObject*)%(obj_cname)s, &%(dtype_typeinfo)s, %(flags)s, %(ndim)d, "
350
+ "%(cast)d, __pyx_stack)" % locals())
351
+
352
+
353
+ def put_assign_to_buffer(lhs_cname, rhs_cname, buf_entry,
354
+ is_initialized, pos, code):
355
+ """
356
+ Generate code for reassigning a buffer variables. This only deals with getting
357
+ the buffer auxiliary structure and variables set up correctly, the assignment
358
+ itself and refcounting is the responsibility of the caller.
359
+
360
+ However, the assignment operation may throw an exception so that the reassignment
361
+ never happens.
362
+
363
+ Depending on the circumstances there are two possible outcomes:
364
+ - Old buffer released, new acquired, rhs assigned to lhs
365
+ - Old buffer released, new acquired which fails, reaqcuire old lhs buffer
366
+ (which may or may not succeed).
367
+ """
368
+
369
+ buffer_aux, buffer_type = buf_entry.buffer_aux, buf_entry.type
370
+ pybuffernd_struct = buffer_aux.buflocal_nd_var.cname
371
+ flags = get_flags(buffer_aux, buffer_type)
372
+
373
+ code.putln("{") # Set up necessary stack for getbuffer
374
+ code.putln("__Pyx_BufFmt_StackElem __pyx_stack[%d];" % buffer_type.dtype.struct_nesting_depth())
375
+
376
+ getbuffer = get_getbuffer_call(code, "%s", buffer_aux, buffer_type) # fill in object below
377
+
378
+ if is_initialized:
379
+ # Release any existing buffer
380
+ code.putln('__Pyx_SafeReleaseBuffer(&%s.rcbuffer->pybuffer);' % pybuffernd_struct)
381
+ # Acquire
382
+ retcode_cname = code.funcstate.allocate_temp(PyrexTypes.c_int_type, manage_ref=False)
383
+ code.putln("%s = %s;" % (retcode_cname, getbuffer % rhs_cname))
384
+ code.putln('if (%s) {' % (code.unlikely("%s < 0" % retcode_cname)))
385
+ # If acquisition failed, attempt to reacquire the old buffer
386
+ # before raising the exception. A failure of reacquisition
387
+ # will cause the reacquisition exception to be reported, one
388
+ # can consider working around this later.
389
+ exc_temps = tuple(code.funcstate.allocate_temp(PyrexTypes.py_object_type, manage_ref=False)
390
+ for _ in range(3))
391
+ code.putln('PyErr_Fetch(&%s, &%s, &%s);' % exc_temps)
392
+ code.putln('if (%s) {' % code.unlikely("%s == -1" % (getbuffer % lhs_cname)))
393
+ code.putln('Py_XDECREF(%s); Py_XDECREF(%s); Py_XDECREF(%s);' % exc_temps) # Do not refnanny these!
394
+ code.globalstate.use_utility_code(raise_buffer_fallback_code)
395
+ code.putln('__Pyx_RaiseBufferFallbackError();')
396
+ code.putln('} else {')
397
+ code.putln('PyErr_Restore(%s, %s, %s);' % exc_temps)
398
+ code.putln('}')
399
+ code.putln('%s = %s = %s = 0;' % exc_temps)
400
+ for t in exc_temps:
401
+ code.funcstate.release_temp(t)
402
+ code.putln('}')
403
+ # Unpack indices
404
+ put_unpack_buffer_aux_into_scope(buf_entry, code)
405
+ code.putln(code.error_goto_if_neg(retcode_cname, pos))
406
+ code.funcstate.release_temp(retcode_cname)
407
+ else:
408
+ # Our entry had no previous value, so set to None when acquisition fails.
409
+ # In this case, auxiliary vars should be set up right in initialization to a zero-buffer,
410
+ # so it suffices to set the buf field to NULL.
411
+ code.putln('if (%s) {' % code.unlikely("%s == -1" % (getbuffer % rhs_cname)))
412
+ code.putln('%s = %s; __Pyx_INCREF(Py_None); %s.rcbuffer->pybuffer.buf = NULL;' %
413
+ (lhs_cname,
414
+ PyrexTypes.typecast(buffer_type, PyrexTypes.py_object_type, "Py_None"),
415
+ pybuffernd_struct))
416
+ code.putln(code.error_goto(pos))
417
+ code.put('} else {')
418
+ # Unpack indices
419
+ put_unpack_buffer_aux_into_scope(buf_entry, code)
420
+ code.putln('}')
421
+
422
+ code.putln("}") # Release stack
423
+
424
+
425
+ def put_buffer_lookup_code(entry, index_signeds, index_cnames, directives,
426
+ pos, code, negative_indices, in_nogil_context):
427
+ """
428
+ Generates code to process indices and calculate an offset into
429
+ a buffer. Returns a C string which gives a pointer which can be
430
+ read from or written to at will (it is an expression so caller should
431
+ store it in a temporary if it is used more than once).
432
+
433
+ As the bounds checking can have any number of combinations of unsigned
434
+ arguments, smart optimizations etc. we insert it directly in the function
435
+ body. The lookup however is delegated to a inline function that is instantiated
436
+ once per ndim (lookup with suboffsets tend to get quite complicated).
437
+
438
+ entry is a BufferEntry
439
+ """
440
+ negative_indices = directives['wraparound'] and negative_indices
441
+
442
+ if directives['boundscheck']:
443
+ # Check bounds and fix negative indices.
444
+ # We allocate a temporary which is initialized to -1, meaning OK (!).
445
+ # If an error occurs, the temp is set to the index dimension the
446
+ # error is occurring at.
447
+ failed_dim_temp = code.funcstate.allocate_temp(PyrexTypes.c_int_type, manage_ref=False)
448
+ code.putln("%s = -1;" % failed_dim_temp)
449
+ for dim, (signed, cname, shape) in enumerate(zip(index_signeds, index_cnames, entry.get_buf_shapevars())):
450
+ if signed != 0:
451
+ # not unsigned, deal with negative index
452
+ code.putln("if (%s < 0) {" % cname)
453
+ if negative_indices:
454
+ code.putln("%s += %s;" % (cname, shape))
455
+ code.putln("if (%s) %s = %d;" % (
456
+ code.unlikely("%s < 0" % cname),
457
+ failed_dim_temp, dim))
458
+ else:
459
+ code.putln("%s = %d;" % (failed_dim_temp, dim))
460
+ code.put("} else ")
461
+ # check bounds in positive direction
462
+ if signed != 0:
463
+ cast = ""
464
+ else:
465
+ cast = "(size_t)"
466
+ code.putln("if (%s) %s = %d;" % (
467
+ code.unlikely("%s >= %s%s" % (cname, cast, shape)),
468
+ failed_dim_temp, dim))
469
+
470
+ if in_nogil_context:
471
+ code.globalstate.use_utility_code(raise_indexerror_nogil)
472
+ func = '__Pyx_RaiseBufferIndexErrorNogil'
473
+ else:
474
+ code.globalstate.use_utility_code(raise_indexerror_code)
475
+ func = '__Pyx_RaiseBufferIndexError'
476
+
477
+ code.putln("if (%s) {" % code.unlikely("%s != -1" % failed_dim_temp))
478
+ code.putln('%s(%s);' % (func, failed_dim_temp))
479
+ code.putln(code.error_goto(pos))
480
+ code.putln('}')
481
+ code.funcstate.release_temp(failed_dim_temp)
482
+ elif negative_indices:
483
+ # Only fix negative indices.
484
+ for signed, cname, shape in zip(index_signeds, index_cnames, entry.get_buf_shapevars()):
485
+ if signed != 0:
486
+ code.putln("if (%s < 0) %s += %s;" % (cname, cname, shape))
487
+
488
+ return entry.generate_buffer_lookup_code(code, index_cnames)
489
+
490
+
491
+ def use_bufstruct_declare_code(env):
492
+ env.use_utility_code(buffer_struct_declare_code)
493
+
494
+
495
+ def buf_lookup_full_code(proto, defin, name, nd):
496
+ """
497
+ Generates a buffer lookup function for the right number
498
+ of dimensions. The function gives back a void* at the right location.
499
+ """
500
+ # _i_ndex, _s_tride, sub_o_ffset
501
+ macroargs = ", ".join(["i%d, s%d, o%d" % (i, i, i) for i in range(nd)])
502
+ proto.putln("#define %s(type, buf, %s) (type)(%s_imp(buf, %s))" % (name, macroargs, name, macroargs))
503
+
504
+ funcargs = ", ".join(["Py_ssize_t i%d, Py_ssize_t s%d, Py_ssize_t o%d" % (i, i, i) for i in range(nd)])
505
+ proto.putln("static CYTHON_INLINE void* %s_imp(void* buf, %s);" % (name, funcargs))
506
+ defin.putln(dedent("""
507
+ static CYTHON_INLINE void* %s_imp(void* buf, %s) {
508
+ char* ptr = (char*)buf;
509
+ """) % (name, funcargs) + "".join([dedent("""\
510
+ ptr += s%d * i%d;
511
+ if (o%d >= 0) ptr = *((char**)ptr) + o%d;
512
+ """) % (i, i, i, i) for i in range(nd)]
513
+ ) + "\nreturn ptr;\n}")
514
+
515
+
516
+ def buf_lookup_strided_code(proto, defin, name, nd):
517
+ """
518
+ Generates a buffer lookup function for the right number
519
+ of dimensions. The function gives back a void* at the right location.
520
+ """
521
+ # _i_ndex, _s_tride
522
+ args = ", ".join(["i%d, s%d" % (i, i) for i in range(nd)])
523
+ offset = " + ".join(["i%d * s%d" % (i, i) for i in range(nd)])
524
+ proto.putln("#define %s(type, buf, %s) (type)((char*)buf + %s)" % (name, args, offset))
525
+
526
+
527
+ def buf_lookup_c_code(proto, defin, name, nd):
528
+ """
529
+ Similar to strided lookup, but can assume that the last dimension
530
+ doesn't need a multiplication as long as.
531
+ Still we keep the same signature for now.
532
+ """
533
+ if nd == 1:
534
+ proto.putln("#define %s(type, buf, i0, s0) ((type)buf + i0)" % name)
535
+ else:
536
+ args = ", ".join(["i%d, s%d" % (i, i) for i in range(nd)])
537
+ offset = " + ".join(["i%d * s%d" % (i, i) for i in range(nd - 1)])
538
+ proto.putln("#define %s(type, buf, %s) ((type)((char*)buf + %s) + i%d)" % (name, args, offset, nd - 1))
539
+
540
+
541
+ def buf_lookup_fortran_code(proto, defin, name, nd):
542
+ """
543
+ Like C lookup, but the first index is optimized instead.
544
+ """
545
+ if nd == 1:
546
+ proto.putln("#define %s(type, buf, i0, s0) ((type)buf + i0)" % name)
547
+ else:
548
+ args = ", ".join(["i%d, s%d" % (i, i) for i in range(nd)])
549
+ offset = " + ".join(["i%d * s%d" % (i, i) for i in range(1, nd)])
550
+ proto.putln("#define %s(type, buf, %s) ((type)((char*)buf + %s) + i%d)" % (name, args, offset, 0))
551
+
552
+
553
+ def use_py2_buffer_functions(env):
554
+ env.use_utility_code(GetAndReleaseBufferUtilityCode())
555
+
556
+
557
+ class GetAndReleaseBufferUtilityCode(object):
558
+ # Emulation of PyObject_GetBuffer and PyBuffer_Release for Python 2.
559
+ # For >= 2.6 we do double mode -- use the new buffer interface on objects
560
+ # which has the right tp_flags set, but emulation otherwise.
561
+
562
+ requires = None
563
+ is_cython_utility = False
564
+
565
+ def __init__(self):
566
+ pass
567
+
568
+ def __eq__(self, other):
569
+ return isinstance(other, GetAndReleaseBufferUtilityCode)
570
+
571
+ def __hash__(self):
572
+ return 24342342
573
+
574
+ def get_tree(self, **kwargs): pass
575
+
576
+ def put_code(self, output):
577
+ code = output['utility_code_def']
578
+ proto_code = output['utility_code_proto']
579
+ env = output.module_node.scope
580
+ cython_scope = env.context.cython_scope
581
+
582
+ # Search all types for __getbuffer__ overloads
583
+ types = []
584
+ visited_scopes = set()
585
+ def find_buffer_types(scope):
586
+ if scope in visited_scopes:
587
+ return
588
+ visited_scopes.add(scope)
589
+ for m in scope.cimported_modules:
590
+ find_buffer_types(m)
591
+ for e in scope.type_entries:
592
+ if isinstance(e.utility_code_definition, CythonUtilityCode):
593
+ continue
594
+ t = e.type
595
+ if t.is_extension_type:
596
+ if scope is cython_scope and not e.used:
597
+ continue
598
+ release = get = None
599
+ for x in t.scope.pyfunc_entries:
600
+ if x.name == u"__getbuffer__": get = x.func_cname
601
+ elif x.name == u"__releasebuffer__": release = x.func_cname
602
+ if get:
603
+ types.append((t.typeptr_cname, get, release))
604
+
605
+ find_buffer_types(env)
606
+
607
+ util_code = TempitaUtilityCode.load(
608
+ "GetAndReleaseBuffer", from_file="Buffer.c",
609
+ context=dict(types=types))
610
+
611
+ proto = util_code.format_code(util_code.proto)
612
+ impl = util_code.format_code(
613
+ util_code.inject_string_constants(util_code.impl, output)[1])
614
+
615
+ proto_code.putln(proto)
616
+ code.putln(impl)
617
+
618
+
619
+ def mangle_dtype_name(dtype):
620
+ # Use prefixes to separate user defined types from builtins
621
+ # (consider "typedef float unsigned_int")
622
+ if dtype.is_pyobject:
623
+ return "object"
624
+ elif dtype.is_ptr:
625
+ return "ptr"
626
+ else:
627
+ if dtype.is_typedef or dtype.is_struct_or_union:
628
+ prefix = "nn_"
629
+ else:
630
+ prefix = ""
631
+ return prefix + dtype.specialization_name()
632
+
633
+ def get_type_information_cname(code, dtype, maxdepth=None):
634
+ """
635
+ Output the run-time type information (__Pyx_TypeInfo) for given dtype,
636
+ and return the name of the type info struct.
637
+
638
+ Structs with two floats of the same size are encoded as complex numbers.
639
+ One can separate between complex numbers declared as struct or with native
640
+ encoding by inspecting to see if the fields field of the type is
641
+ filled in.
642
+ """
643
+ namesuffix = mangle_dtype_name(dtype)
644
+ name = "__Pyx_TypeInfo_%s" % namesuffix
645
+ structinfo_name = "__Pyx_StructFields_%s" % namesuffix
646
+
647
+ if dtype.is_error: return "<error>"
648
+
649
+ # It's critical that walking the type info doesn't use more stack
650
+ # depth than dtype.struct_nesting_depth() returns, so use an assertion for this
651
+ if maxdepth is None: maxdepth = dtype.struct_nesting_depth()
652
+ if maxdepth <= 0:
653
+ assert False
654
+
655
+ if name not in code.globalstate.utility_codes:
656
+ code.globalstate.utility_codes.add(name)
657
+ typecode = code.globalstate['typeinfo']
658
+
659
+ arraysizes = []
660
+ if dtype.is_array:
661
+ while dtype.is_array:
662
+ arraysizes.append(dtype.size)
663
+ dtype = dtype.base_type
664
+
665
+ complex_possible = dtype.is_struct_or_union and dtype.can_be_complex()
666
+
667
+ declcode = dtype.empty_declaration_code()
668
+ if dtype.is_simple_buffer_dtype():
669
+ structinfo_name = "NULL"
670
+ elif dtype.is_struct:
671
+ struct_scope = dtype.scope
672
+ if dtype.is_const:
673
+ struct_scope = struct_scope.const_base_type_scope
674
+ # Must pre-call all used types in order not to recurse during utility code writing.
675
+ fields = struct_scope.var_entries
676
+ assert len(fields) > 0
677
+ types = [get_type_information_cname(code, f.type, maxdepth - 1)
678
+ for f in fields]
679
+ typecode.putln("static __Pyx_StructField %s[] = {" % structinfo_name, safe=True)
680
+ for f, typeinfo in zip(fields, types):
681
+ typecode.putln(' {&%s, "%s", offsetof(%s, %s)},' %
682
+ (typeinfo, f.name, dtype.empty_declaration_code(), f.cname), safe=True)
683
+ typecode.putln(' {NULL, NULL, 0}', safe=True)
684
+ typecode.putln("};", safe=True)
685
+ else:
686
+ assert False
687
+
688
+ rep = str(dtype)
689
+
690
+ flags = "0"
691
+ is_unsigned = "0"
692
+ if dtype is PyrexTypes.c_char_type:
693
+ is_unsigned = "IS_UNSIGNED(%s)" % declcode
694
+ typegroup = "'H'"
695
+ elif dtype.is_int:
696
+ is_unsigned = "IS_UNSIGNED(%s)" % declcode
697
+ typegroup = "%s ? 'U' : 'I'" % is_unsigned
698
+ elif complex_possible or dtype.is_complex:
699
+ typegroup = "'C'"
700
+ elif dtype.is_float:
701
+ typegroup = "'R'"
702
+ elif dtype.is_struct:
703
+ typegroup = "'S'"
704
+ if dtype.packed:
705
+ flags = "__PYX_BUF_FLAGS_PACKED_STRUCT"
706
+ elif dtype.is_pyobject:
707
+ typegroup = "'O'"
708
+ else:
709
+ assert False, dtype
710
+
711
+ typeinfo = ('static __Pyx_TypeInfo %s = '
712
+ '{ "%s", %s, sizeof(%s), { %s }, %s, %s, %s, %s };')
713
+ tup = (name, rep, structinfo_name, declcode,
714
+ ', '.join([str(x) for x in arraysizes]) or '0', len(arraysizes),
715
+ typegroup, is_unsigned, flags)
716
+ typecode.putln(typeinfo % tup, safe=True)
717
+
718
+ return name
719
+
720
+ def load_buffer_utility(util_code_name, context=None, **kwargs):
721
+ if context is None:
722
+ return UtilityCode.load(util_code_name, "Buffer.c", **kwargs)
723
+ else:
724
+ return TempitaUtilityCode.load(util_code_name, "Buffer.c", context=context, **kwargs)
725
+
726
+ context = dict(max_dims=Options.buffer_max_dims)
727
+ buffer_struct_declare_code = load_buffer_utility("BufferStructDeclare", context=context)
728
+ buffer_formats_declare_code = load_buffer_utility("BufferFormatStructs")
729
+
730
+ # Utility function to set the right exception
731
+ # The caller should immediately goto_error
732
+ raise_indexerror_code = load_buffer_utility("BufferIndexError")
733
+ raise_indexerror_nogil = load_buffer_utility("BufferIndexErrorNogil")
734
+ raise_buffer_fallback_code = load_buffer_utility("BufferFallbackError")
735
+
736
+ acquire_utility_code = load_buffer_utility("BufferGetAndValidate", context=context)
737
+ buffer_format_check_code = load_buffer_utility("BufferFormatCheck", context=context)
738
+
739
+ # See utility code BufferFormatFromTypeInfo
740
+ _typeinfo_to_format_code = load_buffer_utility("TypeInfoToFormat")
venv/Lib/site-packages/Cython/Compiler/Builtin.py ADDED
@@ -0,0 +1,445 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #
2
+ # Builtin Definitions
3
+ #
4
+
5
+ from __future__ import absolute_import
6
+
7
+ from .Symtab import BuiltinScope, StructOrUnionScope
8
+ from .Code import UtilityCode
9
+ from .TypeSlots import Signature
10
+ from . import PyrexTypes
11
+ from . import Options
12
+
13
+
14
+ # C-level implementations of builtin types, functions and methods
15
+
16
+ iter_next_utility_code = UtilityCode.load("IterNext", "ObjectHandling.c")
17
+ getattr_utility_code = UtilityCode.load("GetAttr", "ObjectHandling.c")
18
+ getattr3_utility_code = UtilityCode.load("GetAttr3", "Builtins.c")
19
+ pyexec_utility_code = UtilityCode.load("PyExec", "Builtins.c")
20
+ pyexec_globals_utility_code = UtilityCode.load("PyExecGlobals", "Builtins.c")
21
+ globals_utility_code = UtilityCode.load("Globals", "Builtins.c")
22
+
23
+ builtin_utility_code = {
24
+ 'StopAsyncIteration': UtilityCode.load_cached("StopAsyncIteration", "Coroutine.c"),
25
+ }
26
+
27
+
28
+ # mapping from builtins to their C-level equivalents
29
+
30
+ class _BuiltinOverride(object):
31
+ def __init__(self, py_name, args, ret_type, cname, py_equiv="*",
32
+ utility_code=None, sig=None, func_type=None,
33
+ is_strict_signature=False, builtin_return_type=None):
34
+ self.py_name, self.cname, self.py_equiv = py_name, cname, py_equiv
35
+ self.args, self.ret_type = args, ret_type
36
+ self.func_type, self.sig = func_type, sig
37
+ self.builtin_return_type = builtin_return_type
38
+ self.is_strict_signature = is_strict_signature
39
+ self.utility_code = utility_code
40
+
41
+ def build_func_type(self, sig=None, self_arg=None):
42
+ if sig is None:
43
+ sig = Signature(self.args, self.ret_type)
44
+ sig.exception_check = False # not needed for the current builtins
45
+ func_type = sig.function_type(self_arg)
46
+ if self.is_strict_signature:
47
+ func_type.is_strict_signature = True
48
+ if self.builtin_return_type:
49
+ func_type.return_type = builtin_types[self.builtin_return_type]
50
+ return func_type
51
+
52
+
53
+ class BuiltinAttribute(object):
54
+ def __init__(self, py_name, cname=None, field_type=None, field_type_name=None):
55
+ self.py_name = py_name
56
+ self.cname = cname or py_name
57
+ self.field_type_name = field_type_name # can't do the lookup before the type is declared!
58
+ self.field_type = field_type
59
+
60
+ def declare_in_type(self, self_type):
61
+ if self.field_type_name is not None:
62
+ # lazy type lookup
63
+ field_type = builtin_scope.lookup(self.field_type_name).type
64
+ else:
65
+ field_type = self.field_type or PyrexTypes.py_object_type
66
+ entry = self_type.scope.declare(self.py_name, self.cname, field_type, None, 'private')
67
+ entry.is_variable = True
68
+
69
+
70
+ class BuiltinFunction(_BuiltinOverride):
71
+ def declare_in_scope(self, scope):
72
+ func_type, sig = self.func_type, self.sig
73
+ if func_type is None:
74
+ func_type = self.build_func_type(sig)
75
+ scope.declare_builtin_cfunction(self.py_name, func_type, self.cname,
76
+ self.py_equiv, self.utility_code)
77
+
78
+
79
+ class BuiltinMethod(_BuiltinOverride):
80
+ def declare_in_type(self, self_type):
81
+ method_type, sig = self.func_type, self.sig
82
+ if method_type is None:
83
+ # override 'self' type (first argument)
84
+ self_arg = PyrexTypes.CFuncTypeArg("", self_type, None)
85
+ self_arg.not_none = True
86
+ self_arg.accept_builtin_subtypes = True
87
+ method_type = self.build_func_type(sig, self_arg)
88
+ self_type.scope.declare_builtin_cfunction(
89
+ self.py_name, method_type, self.cname, utility_code=self.utility_code)
90
+
91
+
92
+ builtin_function_table = [
93
+ # name, args, return, C API func, py equiv = "*"
94
+ BuiltinFunction('abs', "d", "d", "fabs",
95
+ is_strict_signature = True),
96
+ BuiltinFunction('abs', "f", "f", "fabsf",
97
+ is_strict_signature = True),
98
+ BuiltinFunction('abs', "i", "i", "abs",
99
+ is_strict_signature = True),
100
+ BuiltinFunction('abs', "l", "l", "labs",
101
+ is_strict_signature = True),
102
+ BuiltinFunction('abs', None, None, "__Pyx_abs_longlong",
103
+ utility_code = UtilityCode.load("abs_longlong", "Builtins.c"),
104
+ func_type = PyrexTypes.CFuncType(
105
+ PyrexTypes.c_longlong_type, [
106
+ PyrexTypes.CFuncTypeArg("arg", PyrexTypes.c_longlong_type, None)
107
+ ],
108
+ is_strict_signature = True, nogil=True)),
109
+ ] + list(
110
+ BuiltinFunction('abs', None, None, "/*abs_{0}*/".format(t.specialization_name()),
111
+ func_type = PyrexTypes.CFuncType(
112
+ t,
113
+ [PyrexTypes.CFuncTypeArg("arg", t, None)],
114
+ is_strict_signature = True, nogil=True))
115
+ for t in (PyrexTypes.c_uint_type, PyrexTypes.c_ulong_type, PyrexTypes.c_ulonglong_type)
116
+ ) + list(
117
+ BuiltinFunction('abs', None, None, "__Pyx_c_abs{0}".format(t.funcsuffix),
118
+ func_type = PyrexTypes.CFuncType(
119
+ t.real_type, [
120
+ PyrexTypes.CFuncTypeArg("arg", t, None)
121
+ ],
122
+ is_strict_signature = True, nogil=True))
123
+ for t in (PyrexTypes.c_float_complex_type,
124
+ PyrexTypes.c_double_complex_type,
125
+ PyrexTypes.c_longdouble_complex_type)
126
+ ) + [
127
+ BuiltinFunction('abs', "O", "O", "__Pyx_PyNumber_Absolute",
128
+ utility_code=UtilityCode.load("py_abs", "Builtins.c")),
129
+ #('all', "", "", ""),
130
+ #('any', "", "", ""),
131
+ #('ascii', "", "", ""),
132
+ #('bin', "", "", ""),
133
+ BuiltinFunction('callable', "O", "b", "__Pyx_PyCallable_Check",
134
+ utility_code = UtilityCode.load("CallableCheck", "ObjectHandling.c")),
135
+ #('chr', "", "", ""),
136
+ #('cmp', "", "", "", ""), # int PyObject_Cmp(PyObject *o1, PyObject *o2, int *result)
137
+ #('compile', "", "", ""), # PyObject* Py_CompileString( char *str, char *filename, int start)
138
+ BuiltinFunction('delattr', "OO", "r", "PyObject_DelAttr"),
139
+ BuiltinFunction('dir', "O", "O", "PyObject_Dir"),
140
+ BuiltinFunction('divmod', "OO", "O", "PyNumber_Divmod"),
141
+ BuiltinFunction('exec', "O", "O", "__Pyx_PyExecGlobals",
142
+ utility_code = pyexec_globals_utility_code),
143
+ BuiltinFunction('exec', "OO", "O", "__Pyx_PyExec2",
144
+ utility_code = pyexec_utility_code),
145
+ BuiltinFunction('exec', "OOO", "O", "__Pyx_PyExec3",
146
+ utility_code = pyexec_utility_code),
147
+ #('eval', "", "", ""),
148
+ #('execfile', "", "", ""),
149
+ #('filter', "", "", ""),
150
+ BuiltinFunction('getattr3', "OOO", "O", "__Pyx_GetAttr3", "getattr",
151
+ utility_code=getattr3_utility_code), # Pyrex legacy
152
+ BuiltinFunction('getattr', "OOO", "O", "__Pyx_GetAttr3",
153
+ utility_code=getattr3_utility_code),
154
+ BuiltinFunction('getattr', "OO", "O", "__Pyx_GetAttr",
155
+ utility_code=getattr_utility_code),
156
+ BuiltinFunction('hasattr', "OO", "b", "__Pyx_HasAttr",
157
+ utility_code = UtilityCode.load("HasAttr", "Builtins.c")),
158
+ BuiltinFunction('hash', "O", "h", "PyObject_Hash"),
159
+ #('hex', "", "", ""),
160
+ #('id', "", "", ""),
161
+ #('input', "", "", ""),
162
+ BuiltinFunction('intern', "O", "O", "__Pyx_Intern",
163
+ utility_code = UtilityCode.load("Intern", "Builtins.c")),
164
+ BuiltinFunction('isinstance', "OO", "b", "PyObject_IsInstance"),
165
+ BuiltinFunction('issubclass', "OO", "b", "PyObject_IsSubclass"),
166
+ BuiltinFunction('iter', "OO", "O", "PyCallIter_New"),
167
+ BuiltinFunction('iter', "O", "O", "PyObject_GetIter"),
168
+ BuiltinFunction('len', "O", "z", "PyObject_Length"),
169
+ BuiltinFunction('locals', "", "O", "__pyx_locals"),
170
+ #('map', "", "", ""),
171
+ #('max', "", "", ""),
172
+ #('min', "", "", ""),
173
+ BuiltinFunction('next', "O", "O", "__Pyx_PyIter_Next",
174
+ utility_code = iter_next_utility_code), # not available in Py2 => implemented here
175
+ BuiltinFunction('next', "OO", "O", "__Pyx_PyIter_Next2",
176
+ utility_code = iter_next_utility_code), # not available in Py2 => implemented here
177
+ #('oct', "", "", ""),
178
+ #('open', "ss", "O", "PyFile_FromString"), # not in Py3
179
+ ] + [
180
+ BuiltinFunction('ord', None, None, "__Pyx_long_cast",
181
+ func_type=PyrexTypes.CFuncType(
182
+ PyrexTypes.c_long_type, [PyrexTypes.CFuncTypeArg("c", c_type, None)],
183
+ is_strict_signature=True))
184
+ for c_type in [PyrexTypes.c_py_ucs4_type, PyrexTypes.c_py_unicode_type]
185
+ ] + [
186
+ BuiltinFunction('ord', None, None, "__Pyx_uchar_cast",
187
+ func_type=PyrexTypes.CFuncType(
188
+ PyrexTypes.c_uchar_type, [PyrexTypes.CFuncTypeArg("c", c_type, None)],
189
+ is_strict_signature=True))
190
+ for c_type in [PyrexTypes.c_char_type, PyrexTypes.c_schar_type, PyrexTypes.c_uchar_type]
191
+ ] + [
192
+ BuiltinFunction('ord', None, None, "__Pyx_PyObject_Ord",
193
+ utility_code=UtilityCode.load_cached("object_ord", "Builtins.c"),
194
+ func_type=PyrexTypes.CFuncType(
195
+ PyrexTypes.c_long_type, [
196
+ PyrexTypes.CFuncTypeArg("c", PyrexTypes.py_object_type, None)
197
+ ],
198
+ exception_value="(long)(Py_UCS4)-1")),
199
+ BuiltinFunction('pow', "OOO", "O", "PyNumber_Power"),
200
+ BuiltinFunction('pow', "OO", "O", "__Pyx_PyNumber_Power2",
201
+ utility_code = UtilityCode.load("pow2", "Builtins.c")),
202
+ #('range', "", "", ""),
203
+ #('raw_input', "", "", ""),
204
+ #('reduce', "", "", ""),
205
+ BuiltinFunction('reload', "O", "O", "PyImport_ReloadModule"),
206
+ BuiltinFunction('repr', "O", "O", "PyObject_Repr"), # , builtin_return_type='str'), # add in Cython 3.1
207
+ #('round', "", "", ""),
208
+ BuiltinFunction('setattr', "OOO", "r", "PyObject_SetAttr"),
209
+ #('sum', "", "", ""),
210
+ #('sorted', "", "", ""),
211
+ #('type', "O", "O", "PyObject_Type"),
212
+ #('unichr', "", "", ""),
213
+ #('unicode', "", "", ""),
214
+ #('vars', "", "", ""),
215
+ #('zip', "", "", ""),
216
+ # Can't do these easily until we have builtin type entries.
217
+ #('typecheck', "OO", "i", "PyObject_TypeCheck", False),
218
+ #('issubtype', "OO", "i", "PyType_IsSubtype", False),
219
+
220
+ # Put in namespace append optimization.
221
+ BuiltinFunction('__Pyx_PyObject_Append', "OO", "O", "__Pyx_PyObject_Append"),
222
+
223
+ # This is conditionally looked up based on a compiler directive.
224
+ BuiltinFunction('__Pyx_Globals', "", "O", "__Pyx_Globals",
225
+ utility_code=globals_utility_code),
226
+ ]
227
+
228
+
229
+ # Builtin types
230
+ # bool
231
+ # buffer
232
+ # classmethod
233
+ # dict
234
+ # enumerate
235
+ # file
236
+ # float
237
+ # int
238
+ # list
239
+ # long
240
+ # object
241
+ # property
242
+ # slice
243
+ # staticmethod
244
+ # super
245
+ # str
246
+ # tuple
247
+ # type
248
+ # xrange
249
+
250
+ builtin_types_table = [
251
+
252
+ ("type", "PyType_Type", []),
253
+
254
+ # This conflicts with the C++ bool type, and unfortunately
255
+ # C++ is too liberal about PyObject* <-> bool conversions,
256
+ # resulting in unintuitive runtime behavior and segfaults.
257
+ # ("bool", "PyBool_Type", []),
258
+
259
+ ("int", "PyInt_Type", []),
260
+ ("long", "PyLong_Type", []),
261
+ ("float", "PyFloat_Type", []),
262
+
263
+ ("complex", "PyComplex_Type", [BuiltinAttribute('cval', field_type_name = 'Py_complex'),
264
+ BuiltinAttribute('real', 'cval.real', field_type = PyrexTypes.c_double_type),
265
+ BuiltinAttribute('imag', 'cval.imag', field_type = PyrexTypes.c_double_type),
266
+ ]),
267
+
268
+ ("basestring", "PyBaseString_Type", [
269
+ BuiltinMethod("join", "TO", "T", "__Pyx_PyBaseString_Join",
270
+ utility_code=UtilityCode.load("StringJoin", "StringTools.c")),
271
+ ]),
272
+ ("bytearray", "PyByteArray_Type", [
273
+ ]),
274
+ ("bytes", "PyBytes_Type", [BuiltinMethod("join", "TO", "O", "__Pyx_PyBytes_Join",
275
+ utility_code=UtilityCode.load("StringJoin", "StringTools.c")),
276
+ ]),
277
+ ("str", "PyString_Type", [BuiltinMethod("join", "TO", "O", "__Pyx_PyString_Join",
278
+ builtin_return_type='basestring',
279
+ utility_code=UtilityCode.load("StringJoin", "StringTools.c")),
280
+ ]),
281
+ ("unicode", "PyUnicode_Type", [BuiltinMethod("__contains__", "TO", "b", "PyUnicode_Contains"),
282
+ BuiltinMethod("join", "TO", "T", "PyUnicode_Join"),
283
+ ]),
284
+
285
+ ("tuple", "PyTuple_Type", []),
286
+
287
+ ("list", "PyList_Type", [BuiltinMethod("insert", "TzO", "r", "PyList_Insert"),
288
+ BuiltinMethod("reverse", "T", "r", "PyList_Reverse"),
289
+ BuiltinMethod("append", "TO", "r", "__Pyx_PyList_Append",
290
+ utility_code=UtilityCode.load("ListAppend", "Optimize.c")),
291
+ BuiltinMethod("extend", "TO", "r", "__Pyx_PyList_Extend",
292
+ utility_code=UtilityCode.load("ListExtend", "Optimize.c")),
293
+ ]),
294
+
295
+ ("dict", "PyDict_Type", [BuiltinMethod("__contains__", "TO", "b", "PyDict_Contains"),
296
+ BuiltinMethod("has_key", "TO", "b", "PyDict_Contains"),
297
+ BuiltinMethod("items", "T", "O", "__Pyx_PyDict_Items",
298
+ utility_code=UtilityCode.load("py_dict_items", "Builtins.c")),
299
+ BuiltinMethod("keys", "T", "O", "__Pyx_PyDict_Keys",
300
+ utility_code=UtilityCode.load("py_dict_keys", "Builtins.c")),
301
+ BuiltinMethod("values", "T", "O", "__Pyx_PyDict_Values",
302
+ utility_code=UtilityCode.load("py_dict_values", "Builtins.c")),
303
+ BuiltinMethod("iteritems", "T", "O", "__Pyx_PyDict_IterItems",
304
+ utility_code=UtilityCode.load("py_dict_iteritems", "Builtins.c")),
305
+ BuiltinMethod("iterkeys", "T", "O", "__Pyx_PyDict_IterKeys",
306
+ utility_code=UtilityCode.load("py_dict_iterkeys", "Builtins.c")),
307
+ BuiltinMethod("itervalues", "T", "O", "__Pyx_PyDict_IterValues",
308
+ utility_code=UtilityCode.load("py_dict_itervalues", "Builtins.c")),
309
+ BuiltinMethod("viewitems", "T", "O", "__Pyx_PyDict_ViewItems",
310
+ utility_code=UtilityCode.load("py_dict_viewitems", "Builtins.c")),
311
+ BuiltinMethod("viewkeys", "T", "O", "__Pyx_PyDict_ViewKeys",
312
+ utility_code=UtilityCode.load("py_dict_viewkeys", "Builtins.c")),
313
+ BuiltinMethod("viewvalues", "T", "O", "__Pyx_PyDict_ViewValues",
314
+ utility_code=UtilityCode.load("py_dict_viewvalues", "Builtins.c")),
315
+ BuiltinMethod("clear", "T", "r", "__Pyx_PyDict_Clear",
316
+ utility_code=UtilityCode.load("py_dict_clear", "Optimize.c")),
317
+ BuiltinMethod("copy", "T", "T", "PyDict_Copy")]),
318
+
319
+ ("slice", "PySlice_Type", [BuiltinAttribute('start'),
320
+ BuiltinAttribute('stop'),
321
+ BuiltinAttribute('step'),
322
+ ]),
323
+ # ("file", "PyFile_Type", []), # not in Py3
324
+
325
+ ("set", "PySet_Type", [BuiltinMethod("clear", "T", "r", "PySet_Clear"),
326
+ # discard() and remove() have a special treatment for unhashable values
327
+ BuiltinMethod("discard", "TO", "r", "__Pyx_PySet_Discard",
328
+ utility_code=UtilityCode.load("py_set_discard", "Optimize.c")),
329
+ BuiltinMethod("remove", "TO", "r", "__Pyx_PySet_Remove",
330
+ utility_code=UtilityCode.load("py_set_remove", "Optimize.c")),
331
+ # update is actually variadic (see Github issue #1645)
332
+ # BuiltinMethod("update", "TO", "r", "__Pyx_PySet_Update",
333
+ # utility_code=UtilityCode.load_cached("PySet_Update", "Builtins.c")),
334
+ BuiltinMethod("add", "TO", "r", "PySet_Add"),
335
+ BuiltinMethod("pop", "T", "O", "PySet_Pop")]),
336
+ ("frozenset", "PyFrozenSet_Type", []),
337
+ ("Exception", "((PyTypeObject*)PyExc_Exception)[0]", []),
338
+ ("StopAsyncIteration", "((PyTypeObject*)__Pyx_PyExc_StopAsyncIteration)[0]", []),
339
+ ]
340
+
341
+
342
+ types_that_construct_their_instance = set([
343
+ # some builtin types do not always return an instance of
344
+ # themselves - these do:
345
+ 'type', 'bool', 'long', 'float', 'complex',
346
+ 'bytes', 'unicode', 'bytearray',
347
+ 'tuple', 'list', 'dict', 'set', 'frozenset'
348
+ # 'str', # only in Py3.x
349
+ # 'file', # only in Py2.x
350
+ ])
351
+
352
+
353
+ builtin_structs_table = [
354
+ ('Py_buffer', 'Py_buffer',
355
+ [("buf", PyrexTypes.c_void_ptr_type),
356
+ ("obj", PyrexTypes.py_object_type),
357
+ ("len", PyrexTypes.c_py_ssize_t_type),
358
+ ("itemsize", PyrexTypes.c_py_ssize_t_type),
359
+ ("readonly", PyrexTypes.c_bint_type),
360
+ ("ndim", PyrexTypes.c_int_type),
361
+ ("format", PyrexTypes.c_char_ptr_type),
362
+ ("shape", PyrexTypes.c_py_ssize_t_ptr_type),
363
+ ("strides", PyrexTypes.c_py_ssize_t_ptr_type),
364
+ ("suboffsets", PyrexTypes.c_py_ssize_t_ptr_type),
365
+ ("smalltable", PyrexTypes.CArrayType(PyrexTypes.c_py_ssize_t_type, 2)),
366
+ ("internal", PyrexTypes.c_void_ptr_type),
367
+ ]),
368
+ ('Py_complex', 'Py_complex',
369
+ [('real', PyrexTypes.c_double_type),
370
+ ('imag', PyrexTypes.c_double_type),
371
+ ])
372
+ ]
373
+
374
+ # set up builtin scope
375
+
376
+ builtin_scope = BuiltinScope()
377
+
378
+ def init_builtin_funcs():
379
+ for bf in builtin_function_table:
380
+ bf.declare_in_scope(builtin_scope)
381
+
382
+ builtin_types = {}
383
+
384
+ def init_builtin_types():
385
+ global builtin_types
386
+ for name, cname, methods in builtin_types_table:
387
+ utility = builtin_utility_code.get(name)
388
+ if name == 'frozenset':
389
+ objstruct_cname = 'PySetObject'
390
+ elif name == 'bytearray':
391
+ objstruct_cname = 'PyByteArrayObject'
392
+ elif name == 'bool':
393
+ objstruct_cname = None
394
+ elif name == 'Exception':
395
+ objstruct_cname = "PyBaseExceptionObject"
396
+ elif name == 'StopAsyncIteration':
397
+ objstruct_cname = "PyBaseExceptionObject"
398
+ else:
399
+ objstruct_cname = 'Py%sObject' % name.capitalize()
400
+ the_type = builtin_scope.declare_builtin_type(name, cname, utility, objstruct_cname)
401
+ builtin_types[name] = the_type
402
+ for method in methods:
403
+ method.declare_in_type(the_type)
404
+
405
+ def init_builtin_structs():
406
+ for name, cname, attribute_types in builtin_structs_table:
407
+ scope = StructOrUnionScope(name)
408
+ for attribute_name, attribute_type in attribute_types:
409
+ scope.declare_var(attribute_name, attribute_type, None,
410
+ attribute_name, allow_pyobject=True)
411
+ builtin_scope.declare_struct_or_union(
412
+ name, "struct", scope, 1, None, cname = cname)
413
+
414
+
415
+ def init_builtins():
416
+ init_builtin_structs()
417
+ init_builtin_types()
418
+ init_builtin_funcs()
419
+
420
+ entry = builtin_scope.declare_var(
421
+ '__debug__', PyrexTypes.c_const_type(PyrexTypes.c_bint_type),
422
+ pos=None, cname='__pyx_assertions_enabled()', is_cdef=True)
423
+ entry.utility_code = UtilityCode.load_cached("AssertionsEnabled", "Exceptions.c")
424
+
425
+ global list_type, tuple_type, dict_type, set_type, frozenset_type
426
+ global bytes_type, str_type, unicode_type, basestring_type, slice_type
427
+ global float_type, bool_type, type_type, complex_type, bytearray_type
428
+ type_type = builtin_scope.lookup('type').type
429
+ list_type = builtin_scope.lookup('list').type
430
+ tuple_type = builtin_scope.lookup('tuple').type
431
+ dict_type = builtin_scope.lookup('dict').type
432
+ set_type = builtin_scope.lookup('set').type
433
+ frozenset_type = builtin_scope.lookup('frozenset').type
434
+ slice_type = builtin_scope.lookup('slice').type
435
+ bytes_type = builtin_scope.lookup('bytes').type
436
+ str_type = builtin_scope.lookup('str').type
437
+ unicode_type = builtin_scope.lookup('unicode').type
438
+ basestring_type = builtin_scope.lookup('basestring').type
439
+ bytearray_type = builtin_scope.lookup('bytearray').type
440
+ float_type = builtin_scope.lookup('float').type
441
+ bool_type = builtin_scope.lookup('bool').type
442
+ complex_type = builtin_scope.lookup('complex').type
443
+
444
+
445
+ init_builtins()
venv/Lib/site-packages/Cython/Compiler/CmdLine.py ADDED
@@ -0,0 +1,240 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #
2
+ # Cython - Command Line Parsing
3
+ #
4
+
5
+ from __future__ import absolute_import
6
+
7
+ import os
8
+ import sys
9
+ from . import Options
10
+
11
+ usage = """\
12
+ Cython (http://cython.org) is a compiler for code written in the
13
+ Cython language. Cython is based on Pyrex by Greg Ewing.
14
+
15
+ Usage: cython [options] sourcefile.{pyx,py} ...
16
+
17
+ Options:
18
+ -V, --version Display version number of cython compiler
19
+ -l, --create-listing Write error messages to a listing file
20
+ -I, --include-dir <directory> Search for include files in named directory
21
+ (multiple include directories are allowed).
22
+ -o, --output-file <filename> Specify name of generated C file
23
+ -t, --timestamps Only compile newer source files
24
+ -f, --force Compile all source files (overrides implied -t)
25
+ -v, --verbose Be verbose, print file names on multiple compilation
26
+ -p, --embed-positions If specified, the positions in Cython files of each
27
+ function definition is embedded in its docstring.
28
+ --cleanup <level> Release interned objects on python exit, for memory debugging.
29
+ Level indicates aggressiveness, default 0 releases nothing.
30
+ -w, --working <directory> Sets the working directory for Cython (the directory modules
31
+ are searched from)
32
+ --gdb Output debug information for cygdb
33
+ --gdb-outdir <directory> Specify gdb debug information output directory. Implies --gdb.
34
+
35
+ -D, --no-docstrings Strip docstrings from the compiled module.
36
+ -a, --annotate Produce a colorized HTML version of the source.
37
+ --annotate-coverage <cov.xml> Annotate and include coverage information from cov.xml.
38
+ --line-directives Produce #line directives pointing to the .pyx source
39
+ --cplus Output a C++ rather than C file.
40
+ --embed[=<method_name>] Generate a main() function that embeds the Python interpreter.
41
+ -2 Compile based on Python-2 syntax and code semantics.
42
+ -3 Compile based on Python-3 syntax and code semantics.
43
+ --3str Compile based on Python-3 syntax and code semantics without
44
+ assuming unicode by default for string literals under Python 2.
45
+ --lenient Change some compile time errors to runtime errors to
46
+ improve Python compatibility
47
+ --capi-reexport-cincludes Add cincluded headers to any auto-generated header files.
48
+ --fast-fail Abort the compilation on the first error
49
+ --warning-errors, -Werror Make all warnings into errors
50
+ --warning-extra, -Wextra Enable extra warnings
51
+ -X, --directive <name>=<value>[,<name=value,...] Overrides a compiler directive
52
+ -E, --compile-time-env name=value[,<name=value,...] Provides compile time env like DEF would do.
53
+ --module-name Fully qualified module name. If not given, it is deduced from the
54
+ import path if source file is in a package, or equals the
55
+ filename otherwise.
56
+ -M, --depfile Produce depfiles for the sources
57
+ """
58
+
59
+
60
+ # The following experimental options are supported only on MacOSX:
61
+ # -C, --compile Compile generated .c file to .o file
62
+ # --link Link .o file to produce extension module (implies -C)
63
+ # -+, --cplus Use C++ compiler for compiling and linking
64
+ # Additional .o files to link may be supplied when using -X."""
65
+
66
+ def bad_usage():
67
+ sys.stderr.write(usage)
68
+ sys.exit(1)
69
+
70
+ def parse_command_line(args):
71
+ from .Main import CompilationOptions, default_options
72
+
73
+ pending_arg = []
74
+
75
+ def pop_arg():
76
+ if not args or pending_arg:
77
+ bad_usage()
78
+ if '=' in args[0] and args[0].startswith('--'): # allow "--long-option=xyz"
79
+ name, value = args.pop(0).split('=', 1)
80
+ pending_arg.append(value)
81
+ return name
82
+ return args.pop(0)
83
+
84
+ def pop_value(default=None):
85
+ if pending_arg:
86
+ return pending_arg.pop()
87
+ elif default is not None:
88
+ return default
89
+ elif not args:
90
+ bad_usage()
91
+ return args.pop(0)
92
+
93
+ def get_param(option):
94
+ tail = option[2:]
95
+ if tail:
96
+ return tail
97
+ else:
98
+ return pop_arg()
99
+
100
+ options = CompilationOptions(default_options)
101
+ sources = []
102
+ while args:
103
+ if args[0].startswith("-"):
104
+ option = pop_arg()
105
+ if option in ("-V", "--version"):
106
+ options.show_version = 1
107
+ elif option in ("-l", "--create-listing"):
108
+ options.use_listing_file = 1
109
+ elif option in ("-+", "--cplus"):
110
+ options.cplus = 1
111
+ elif option == "--embed":
112
+ Options.embed = pop_value("main")
113
+ elif option.startswith("-I"):
114
+ options.include_path.append(get_param(option))
115
+ elif option == "--include-dir":
116
+ options.include_path.append(pop_value())
117
+ elif option in ("-w", "--working"):
118
+ options.working_path = pop_value()
119
+ elif option in ("-o", "--output-file"):
120
+ options.output_file = pop_value()
121
+ elif option in ("-t", "--timestamps"):
122
+ options.timestamps = 1
123
+ elif option in ("-f", "--force"):
124
+ options.timestamps = 0
125
+ elif option in ("-v", "--verbose"):
126
+ options.verbose += 1
127
+ elif option in ("-p", "--embed-positions"):
128
+ Options.embed_pos_in_docstring = 1
129
+ elif option in ("-z", "--pre-import"):
130
+ Options.pre_import = pop_value()
131
+ elif option == "--cleanup":
132
+ Options.generate_cleanup_code = int(pop_value())
133
+ elif option in ("-D", "--no-docstrings"):
134
+ Options.docstrings = False
135
+ elif option in ("-a", "--annotate"):
136
+ Options.annotate = True
137
+ elif option == "--annotate-coverage":
138
+ Options.annotate = True
139
+ Options.annotate_coverage_xml = pop_value()
140
+ elif option == "--convert-range":
141
+ Options.convert_range = True
142
+ elif option == "--line-directives":
143
+ options.emit_linenums = True
144
+ elif option == "--no-c-in-traceback":
145
+ options.c_line_in_traceback = False
146
+ elif option == "--gdb":
147
+ options.gdb_debug = True
148
+ options.output_dir = os.curdir
149
+ elif option == "--gdb-outdir":
150
+ options.gdb_debug = True
151
+ options.output_dir = pop_value()
152
+ elif option == "--lenient":
153
+ Options.error_on_unknown_names = False
154
+ Options.error_on_uninitialized = False
155
+ elif option == '-2':
156
+ options.language_level = 2
157
+ elif option == '-3':
158
+ options.language_level = 3
159
+ elif option == '--3str':
160
+ options.language_level = '3str'
161
+ elif option == "--capi-reexport-cincludes":
162
+ options.capi_reexport_cincludes = True
163
+ elif option == "--fast-fail":
164
+ Options.fast_fail = True
165
+ elif option == "--cimport-from-pyx":
166
+ Options.cimport_from_pyx = True
167
+ elif option in ('-Werror', '--warning-errors'):
168
+ Options.warning_errors = True
169
+ elif option in ('-Wextra', '--warning-extra'):
170
+ options.compiler_directives.update(Options.extra_warnings)
171
+ elif option == "--old-style-globals":
172
+ Options.old_style_globals = True
173
+ elif option == "--directive" or option.startswith('-X'):
174
+ if option.startswith('-X') and option[2:].strip():
175
+ x_args = option[2:]
176
+ else:
177
+ x_args = pop_value()
178
+ try:
179
+ options.compiler_directives = Options.parse_directive_list(
180
+ x_args, relaxed_bool=True,
181
+ current_settings=options.compiler_directives)
182
+ except ValueError as e:
183
+ sys.stderr.write("Error in compiler directive: %s\n" % e.args[0])
184
+ sys.exit(1)
185
+ elif option == "--compile-time-env" or option.startswith('-E'):
186
+ if option.startswith('-E') and option[2:].strip():
187
+ x_args = option[2:]
188
+ else:
189
+ x_args = pop_value()
190
+ try:
191
+ options.compile_time_env = Options.parse_compile_time_env(
192
+ x_args, current_settings=options.compile_time_env)
193
+ except ValueError as e:
194
+ sys.stderr.write("Error in compile-time-env: %s\n" % e.args[0])
195
+ sys.exit(1)
196
+ elif option == "--module-name":
197
+ options.module_name = pop_value()
198
+ elif option in ('-M', '--depfile'):
199
+ options.depfile = True
200
+ elif option.startswith('--debug'):
201
+ option = option[2:].replace('-', '_')
202
+ from . import DebugFlags
203
+ if option in dir(DebugFlags):
204
+ setattr(DebugFlags, option, True)
205
+ else:
206
+ sys.stderr.write("Unknown debug flag: %s\n" % option)
207
+ bad_usage()
208
+ elif option in ('-h', '--help'):
209
+ sys.stdout.write(usage)
210
+ sys.exit(0)
211
+ else:
212
+ sys.stderr.write(usage)
213
+ sys.stderr.write("Unknown compiler flag: %s\n" % option)
214
+ sys.exit(1)
215
+ else:
216
+ sources.append(pop_arg())
217
+
218
+ if pending_arg:
219
+ bad_usage()
220
+
221
+ if options.use_listing_file and len(sources) > 1:
222
+ sys.stderr.write(
223
+ "cython: Only one source file allowed when using -o\n")
224
+ sys.exit(1)
225
+ if len(sources) == 0 and not options.show_version:
226
+ bad_usage()
227
+ if Options.embed and len(sources) > 1:
228
+ sys.stderr.write(
229
+ "cython: Only one source file allowed when using --embed\n")
230
+ sys.exit(1)
231
+ if options.module_name:
232
+ if options.timestamps:
233
+ sys.stderr.write(
234
+ "cython: Cannot use --module-name with --timestamps\n")
235
+ sys.exit(1)
236
+ if len(sources) > 1:
237
+ sys.stderr.write(
238
+ "cython: Only one source file allowed when using --module-name\n")
239
+ sys.exit(1)
240
+ return options, sources
venv/Lib/site-packages/Cython/Compiler/Code.pxd ADDED
@@ -0,0 +1,124 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+
2
+ from __future__ import absolute_import
3
+
4
+ cimport cython
5
+ from ..StringIOTree cimport StringIOTree
6
+
7
+
8
+ cdef class UtilityCodeBase(object):
9
+ cpdef format_code(self, code_string, replace_empty_lines=*)
10
+
11
+
12
+ cdef class UtilityCode(UtilityCodeBase):
13
+ cdef public object name
14
+ cdef public object proto
15
+ cdef public object impl
16
+ cdef public object init
17
+ cdef public object cleanup
18
+ cdef public object proto_block
19
+ cdef public object requires
20
+ cdef public dict _cache
21
+ cdef public list specialize_list
22
+ cdef public object file
23
+
24
+ cpdef none_or_sub(self, s, context)
25
+
26
+
27
+ cdef class FunctionState:
28
+ cdef public set names_taken
29
+ cdef public object owner
30
+ cdef public object scope
31
+
32
+ cdef public object error_label
33
+ cdef public size_t label_counter
34
+ cdef public set labels_used
35
+ cdef public object return_label
36
+ cdef public object continue_label
37
+ cdef public object break_label
38
+ cdef public list yield_labels
39
+
40
+ cdef public object return_from_error_cleanup_label # not used in __init__ ?
41
+
42
+ cdef public object exc_vars
43
+ cdef public object current_except
44
+ cdef public bint in_try_finally
45
+ cdef public bint can_trace
46
+ cdef public bint gil_owned
47
+
48
+ cdef public list temps_allocated
49
+ cdef public dict temps_free
50
+ cdef public dict temps_used_type
51
+ cdef public set zombie_temps
52
+ cdef public size_t temp_counter
53
+ cdef public list collect_temps_stack
54
+
55
+ cdef public object closure_temps
56
+ cdef public bint should_declare_error_indicator
57
+ cdef public bint uses_error_indicator
58
+
59
+ @cython.locals(n=size_t)
60
+ cpdef new_label(self, name=*)
61
+ cpdef tuple get_loop_labels(self)
62
+ cpdef set_loop_labels(self, labels)
63
+ cpdef tuple get_all_labels(self)
64
+ cpdef set_all_labels(self, labels)
65
+ cpdef start_collecting_temps(self)
66
+ cpdef stop_collecting_temps(self)
67
+
68
+ cpdef list temps_in_use(self)
69
+
70
+ cdef class IntConst:
71
+ cdef public object cname
72
+ cdef public object value
73
+ cdef public bint is_long
74
+
75
+ cdef class PyObjectConst:
76
+ cdef public object cname
77
+ cdef public object type
78
+
79
+ cdef class StringConst:
80
+ cdef public object cname
81
+ cdef public object text
82
+ cdef public object escaped_value
83
+ cdef public dict py_strings
84
+ cdef public list py_versions
85
+
86
+ @cython.locals(intern=bint, is_str=bint, is_unicode=bint)
87
+ cpdef get_py_string_const(self, encoding, identifier=*, is_str=*, py3str_cstring=*)
88
+
89
+ ## cdef class PyStringConst:
90
+ ## cdef public object cname
91
+ ## cdef public object encoding
92
+ ## cdef public bint is_str
93
+ ## cdef public bint is_unicode
94
+ ## cdef public bint intern
95
+
96
+ #class GlobalState(object):
97
+
98
+ #def funccontext_property(name):
99
+
100
+ cdef class CCodeWriter(object):
101
+ cdef readonly StringIOTree buffer
102
+ cdef readonly list pyclass_stack
103
+ cdef readonly object globalstate
104
+ cdef readonly object funcstate
105
+ cdef object code_config
106
+ cdef object last_pos
107
+ cdef object last_marked_pos
108
+ cdef Py_ssize_t level
109
+ cdef public Py_ssize_t call_level # debug-only, see Nodes.py
110
+ cdef bint bol
111
+
112
+ cpdef write(self, s)
113
+ cpdef put(self, code)
114
+ cpdef put_safe(self, code)
115
+ cpdef putln(self, code=*, bint safe=*)
116
+ @cython.final
117
+ cdef increase_indent(self)
118
+ @cython.final
119
+ cdef decrease_indent(self)
120
+
121
+
122
+ cdef class PyrexCodeWriter:
123
+ cdef public object f
124
+ cdef public Py_ssize_t level
venv/Lib/site-packages/Cython/Compiler/Code.py ADDED
@@ -0,0 +1,2597 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # cython: language_level = 2
2
+ # cython: auto_pickle=False
3
+ #
4
+ # Code output module
5
+ #
6
+
7
+ from __future__ import absolute_import
8
+
9
+ import cython
10
+ cython.declare(os=object, re=object, operator=object, textwrap=object,
11
+ Template=object, Naming=object, Options=object, StringEncoding=object,
12
+ Utils=object, SourceDescriptor=object, StringIOTree=object,
13
+ DebugFlags=object, basestring=object, defaultdict=object,
14
+ closing=object, partial=object)
15
+
16
+ import os
17
+ import re
18
+ import shutil
19
+ import sys
20
+ import operator
21
+ import textwrap
22
+ from string import Template
23
+ from functools import partial
24
+ from contextlib import closing
25
+ from collections import defaultdict
26
+
27
+ try:
28
+ import hashlib
29
+ except ImportError:
30
+ import md5 as hashlib
31
+
32
+ from . import Naming
33
+ from . import Options
34
+ from . import DebugFlags
35
+ from . import StringEncoding
36
+ from . import Version
37
+ from .. import Utils
38
+ from .Scanning import SourceDescriptor
39
+ from ..StringIOTree import StringIOTree
40
+
41
+ try:
42
+ from __builtin__ import basestring
43
+ except ImportError:
44
+ from builtins import str as basestring
45
+
46
+ KEYWORDS_MUST_BE_BYTES = sys.version_info < (2, 7)
47
+
48
+
49
+ non_portable_builtins_map = {
50
+ # builtins that have different names in different Python versions
51
+ 'bytes' : ('PY_MAJOR_VERSION < 3', 'str'),
52
+ 'unicode' : ('PY_MAJOR_VERSION >= 3', 'str'),
53
+ 'basestring' : ('PY_MAJOR_VERSION >= 3', 'str'),
54
+ 'xrange' : ('PY_MAJOR_VERSION >= 3', 'range'),
55
+ 'raw_input' : ('PY_MAJOR_VERSION >= 3', 'input'),
56
+ }
57
+
58
+ ctypedef_builtins_map = {
59
+ # types of builtins in "ctypedef class" statements which we don't
60
+ # import either because the names conflict with C types or because
61
+ # the type simply is not exposed.
62
+ 'py_int' : '&PyInt_Type',
63
+ 'py_long' : '&PyLong_Type',
64
+ 'py_float' : '&PyFloat_Type',
65
+ 'wrapper_descriptor' : '&PyWrapperDescr_Type',
66
+ }
67
+
68
+ basicsize_builtins_map = {
69
+ # builtins whose type has a different tp_basicsize than sizeof(...)
70
+ 'PyTypeObject': 'PyHeapTypeObject',
71
+ }
72
+
73
+ uncachable_builtins = [
74
+ # Global/builtin names that cannot be cached because they may or may not
75
+ # be available at import time, for various reasons:
76
+ ## - Py3.7+
77
+ 'breakpoint', # might deserve an implementation in Cython
78
+ ## - Py3.4+
79
+ '__loader__',
80
+ '__spec__',
81
+ ## - Py3+
82
+ 'BlockingIOError',
83
+ 'BrokenPipeError',
84
+ 'ChildProcessError',
85
+ 'ConnectionAbortedError',
86
+ 'ConnectionError',
87
+ 'ConnectionRefusedError',
88
+ 'ConnectionResetError',
89
+ 'FileExistsError',
90
+ 'FileNotFoundError',
91
+ 'InterruptedError',
92
+ 'IsADirectoryError',
93
+ 'ModuleNotFoundError',
94
+ 'NotADirectoryError',
95
+ 'PermissionError',
96
+ 'ProcessLookupError',
97
+ 'RecursionError',
98
+ 'ResourceWarning',
99
+ #'StopAsyncIteration', # backported
100
+ 'TimeoutError',
101
+ '__build_class__',
102
+ 'ascii', # might deserve an implementation in Cython
103
+ #'exec', # implemented in Cython
104
+ ## - Py2.7+
105
+ 'memoryview',
106
+ ## - platform specific
107
+ 'WindowsError',
108
+ ## - others
109
+ '_', # e.g. used by gettext
110
+ ]
111
+
112
+ special_py_methods = set([
113
+ '__cinit__', '__dealloc__', '__richcmp__', '__next__',
114
+ '__await__', '__aiter__', '__anext__',
115
+ '__getreadbuffer__', '__getwritebuffer__', '__getsegcount__',
116
+ '__getcharbuffer__', '__getbuffer__', '__releasebuffer__'
117
+ ])
118
+
119
+ modifier_output_mapper = {
120
+ 'inline': 'CYTHON_INLINE'
121
+ }.get
122
+
123
+
124
+ class IncludeCode(object):
125
+ """
126
+ An include file and/or verbatim C code to be included in the
127
+ generated sources.
128
+ """
129
+ # attributes:
130
+ #
131
+ # pieces {order: unicode}: pieces of C code to be generated.
132
+ # For the included file, the key "order" is zero.
133
+ # For verbatim include code, the "order" is the "order"
134
+ # attribute of the original IncludeCode where this piece
135
+ # of C code was first added. This is needed to prevent
136
+ # duplication if the same include code is found through
137
+ # multiple cimports.
138
+ # location int: where to put this include in the C sources, one
139
+ # of the constants INITIAL, EARLY, LATE
140
+ # order int: sorting order (automatically set by increasing counter)
141
+
142
+ # Constants for location. If the same include occurs with different
143
+ # locations, the earliest one takes precedense.
144
+ INITIAL = 0
145
+ EARLY = 1
146
+ LATE = 2
147
+
148
+ counter = 1 # Counter for "order"
149
+
150
+ def __init__(self, include=None, verbatim=None, late=True, initial=False):
151
+ self.order = self.counter
152
+ type(self).counter += 1
153
+ self.pieces = {}
154
+
155
+ if include:
156
+ if include[0] == '<' and include[-1] == '>':
157
+ self.pieces[0] = u'#include {0}'.format(include)
158
+ late = False # system include is never late
159
+ else:
160
+ self.pieces[0] = u'#include "{0}"'.format(include)
161
+
162
+ if verbatim:
163
+ self.pieces[self.order] = verbatim
164
+
165
+ if initial:
166
+ self.location = self.INITIAL
167
+ elif late:
168
+ self.location = self.LATE
169
+ else:
170
+ self.location = self.EARLY
171
+
172
+ def dict_update(self, d, key):
173
+ """
174
+ Insert `self` in dict `d` with key `key`. If that key already
175
+ exists, update the attributes of the existing value with `self`.
176
+ """
177
+ if key in d:
178
+ other = d[key]
179
+ other.location = min(self.location, other.location)
180
+ other.pieces.update(self.pieces)
181
+ else:
182
+ d[key] = self
183
+
184
+ def sortkey(self):
185
+ return self.order
186
+
187
+ def mainpiece(self):
188
+ """
189
+ Return the main piece of C code, corresponding to the include
190
+ file. If there was no include file, return None.
191
+ """
192
+ return self.pieces.get(0)
193
+
194
+ def write(self, code):
195
+ # Write values of self.pieces dict, sorted by the keys
196
+ for k in sorted(self.pieces):
197
+ code.putln(self.pieces[k])
198
+
199
+
200
+ def get_utility_dir():
201
+ # make this a function and not global variables:
202
+ # http://trac.cython.org/cython_trac/ticket/475
203
+ Cython_dir = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
204
+ return os.path.join(Cython_dir, "Utility")
205
+
206
+
207
+ class UtilityCodeBase(object):
208
+ """
209
+ Support for loading utility code from a file.
210
+
211
+ Code sections in the file can be specified as follows:
212
+
213
+ ##### MyUtility.proto #####
214
+
215
+ [proto declarations]
216
+
217
+ ##### MyUtility.init #####
218
+
219
+ [code run at module initialization]
220
+
221
+ ##### MyUtility #####
222
+ #@requires: MyOtherUtility
223
+ #@substitute: naming
224
+
225
+ [definitions]
226
+
227
+ for prototypes and implementation respectively. For non-python or
228
+ -cython files backslashes should be used instead. 5 to 30 comment
229
+ characters may be used on either side.
230
+
231
+ If the @cname decorator is not used and this is a CythonUtilityCode,
232
+ one should pass in the 'name' keyword argument to be used for name
233
+ mangling of such entries.
234
+ """
235
+
236
+ is_cython_utility = False
237
+ _utility_cache = {}
238
+
239
+ @classmethod
240
+ def _add_utility(cls, utility, type, lines, begin_lineno, tags=None):
241
+ if utility is None:
242
+ return
243
+
244
+ code = '\n'.join(lines)
245
+ if tags and 'substitute' in tags and tags['substitute'] == set(['naming']):
246
+ del tags['substitute']
247
+ try:
248
+ code = Template(code).substitute(vars(Naming))
249
+ except (KeyError, ValueError) as e:
250
+ raise RuntimeError("Error parsing templated utility code of type '%s' at line %d: %s" % (
251
+ type, begin_lineno, e))
252
+
253
+ # remember correct line numbers at least until after templating
254
+ code = '\n' * begin_lineno + code
255
+
256
+ if type == 'proto':
257
+ utility[0] = code
258
+ elif type == 'impl':
259
+ utility[1] = code
260
+ else:
261
+ all_tags = utility[2]
262
+ if KEYWORDS_MUST_BE_BYTES:
263
+ type = type.encode('ASCII')
264
+ all_tags[type] = code
265
+
266
+ if tags:
267
+ all_tags = utility[2]
268
+ for name, values in tags.items():
269
+ if KEYWORDS_MUST_BE_BYTES:
270
+ name = name.encode('ASCII')
271
+ all_tags.setdefault(name, set()).update(values)
272
+
273
+ @classmethod
274
+ def load_utilities_from_file(cls, path):
275
+ utilities = cls._utility_cache.get(path)
276
+ if utilities:
277
+ return utilities
278
+
279
+ filename = os.path.join(get_utility_dir(), path)
280
+ _, ext = os.path.splitext(path)
281
+ if ext in ('.pyx', '.py', '.pxd', '.pxi'):
282
+ comment = '#'
283
+ strip_comments = partial(re.compile(r'^\s*#(?!\s*cython\s*:).*').sub, '')
284
+ rstrip = StringEncoding._unicode.rstrip
285
+ else:
286
+ comment = '/'
287
+ strip_comments = partial(re.compile(r'^\s*//.*|/\*[^*]*\*/').sub, '')
288
+ rstrip = partial(re.compile(r'\s+(\\?)$').sub, r'\1')
289
+ match_special = re.compile(
290
+ (r'^%(C)s{5,30}\s*(?P<name>(?:\w|\.)+)\s*%(C)s{5,30}|'
291
+ r'^%(C)s+@(?P<tag>\w+)\s*:\s*(?P<value>(?:\w|[.:])+)') %
292
+ {'C': comment}).match
293
+ match_type = re.compile(r'(.+)[.](proto(?:[.]\S+)?|impl|init|cleanup)$').match
294
+
295
+ with closing(Utils.open_source_file(filename, encoding='UTF-8')) as f:
296
+ all_lines = f.readlines()
297
+
298
+ utilities = defaultdict(lambda: [None, None, {}])
299
+ lines = []
300
+ tags = defaultdict(set)
301
+ utility = type = None
302
+ begin_lineno = 0
303
+
304
+ for lineno, line in enumerate(all_lines):
305
+ m = match_special(line)
306
+ if m:
307
+ if m.group('name'):
308
+ cls._add_utility(utility, type, lines, begin_lineno, tags)
309
+
310
+ begin_lineno = lineno + 1
311
+ del lines[:]
312
+ tags.clear()
313
+
314
+ name = m.group('name')
315
+ mtype = match_type(name)
316
+ if mtype:
317
+ name, type = mtype.groups()
318
+ else:
319
+ type = 'impl'
320
+ utility = utilities[name]
321
+ else:
322
+ tags[m.group('tag')].add(m.group('value'))
323
+ lines.append('') # keep line number correct
324
+ else:
325
+ lines.append(rstrip(strip_comments(line)))
326
+
327
+ if utility is None:
328
+ raise ValueError("Empty utility code file")
329
+
330
+ # Don't forget to add the last utility code
331
+ cls._add_utility(utility, type, lines, begin_lineno, tags)
332
+
333
+ utilities = dict(utilities) # un-defaultdict-ify
334
+ cls._utility_cache[path] = utilities
335
+ return utilities
336
+
337
+ @classmethod
338
+ def load(cls, util_code_name, from_file=None, **kwargs):
339
+ """
340
+ Load utility code from a file specified by from_file (relative to
341
+ Cython/Utility) and name util_code_name. If from_file is not given,
342
+ load it from the file util_code_name.*. There should be only one
343
+ file matched by this pattern.
344
+ """
345
+ if '::' in util_code_name:
346
+ from_file, util_code_name = util_code_name.rsplit('::', 1)
347
+ if not from_file:
348
+ utility_dir = get_utility_dir()
349
+ prefix = util_code_name + '.'
350
+ try:
351
+ listing = os.listdir(utility_dir)
352
+ except OSError:
353
+ # XXX the code below assumes as 'zipimport.zipimporter' instance
354
+ # XXX should be easy to generalize, but too lazy right now to write it
355
+ import zipfile
356
+ global __loader__
357
+ loader = __loader__
358
+ archive = loader.archive
359
+ with closing(zipfile.ZipFile(archive)) as fileobj:
360
+ listing = [os.path.basename(name)
361
+ for name in fileobj.namelist()
362
+ if os.path.join(archive, name).startswith(utility_dir)]
363
+ files = [filename for filename in listing
364
+ if filename.startswith(prefix)]
365
+ if not files:
366
+ raise ValueError("No match found for utility code " + util_code_name)
367
+ if len(files) > 1:
368
+ raise ValueError("More than one filename match found for utility code " + util_code_name)
369
+ from_file = files[0]
370
+
371
+ utilities = cls.load_utilities_from_file(from_file)
372
+ proto, impl, tags = utilities[util_code_name]
373
+
374
+ if tags:
375
+ orig_kwargs = kwargs.copy()
376
+ for name, values in tags.items():
377
+ if name in kwargs:
378
+ continue
379
+ # only pass lists when we have to: most argument expect one value or None
380
+ if name == 'requires':
381
+ if orig_kwargs:
382
+ values = [cls.load(dep, from_file, **orig_kwargs)
383
+ for dep in sorted(values)]
384
+ else:
385
+ # dependencies are rarely unique, so use load_cached() when we can
386
+ values = [cls.load_cached(dep, from_file)
387
+ for dep in sorted(values)]
388
+ elif not values:
389
+ values = None
390
+ elif len(values) == 1:
391
+ values = list(values)[0]
392
+ kwargs[name] = values
393
+
394
+ if proto is not None:
395
+ kwargs['proto'] = proto
396
+ if impl is not None:
397
+ kwargs['impl'] = impl
398
+
399
+ if 'name' not in kwargs:
400
+ kwargs['name'] = util_code_name
401
+
402
+ if 'file' not in kwargs and from_file:
403
+ kwargs['file'] = from_file
404
+ return cls(**kwargs)
405
+
406
+ @classmethod
407
+ def load_cached(cls, utility_code_name, from_file=None, __cache={}):
408
+ """
409
+ Calls .load(), but using a per-type cache based on utility name and file name.
410
+ """
411
+ key = (cls, from_file, utility_code_name)
412
+ try:
413
+ return __cache[key]
414
+ except KeyError:
415
+ pass
416
+ code = __cache[key] = cls.load(utility_code_name, from_file)
417
+ return code
418
+
419
+ @classmethod
420
+ def load_as_string(cls, util_code_name, from_file=None, **kwargs):
421
+ """
422
+ Load a utility code as a string. Returns (proto, implementation)
423
+ """
424
+ util = cls.load(util_code_name, from_file, **kwargs)
425
+ proto, impl = util.proto, util.impl
426
+ return util.format_code(proto), util.format_code(impl)
427
+
428
+ def format_code(self, code_string, replace_empty_lines=re.compile(r'\n\n+').sub):
429
+ """
430
+ Format a code section for output.
431
+ """
432
+ if code_string:
433
+ code_string = replace_empty_lines('\n', code_string.strip()) + '\n\n'
434
+ return code_string
435
+
436
+ def __str__(self):
437
+ return "<%s(%s)>" % (type(self).__name__, self.name)
438
+
439
+ def get_tree(self, **kwargs):
440
+ pass
441
+
442
+ def __deepcopy__(self, memodict=None):
443
+ # No need to deep-copy utility code since it's essentially immutable.
444
+ return self
445
+
446
+
447
+ class UtilityCode(UtilityCodeBase):
448
+ """
449
+ Stores utility code to add during code generation.
450
+
451
+ See GlobalState.put_utility_code.
452
+
453
+ hashes/equals by instance
454
+
455
+ proto C prototypes
456
+ impl implementation code
457
+ init code to call on module initialization
458
+ requires utility code dependencies
459
+ proto_block the place in the resulting file where the prototype should
460
+ end up
461
+ name name of the utility code (or None)
462
+ file filename of the utility code file this utility was loaded
463
+ from (or None)
464
+ """
465
+
466
+ def __init__(self, proto=None, impl=None, init=None, cleanup=None, requires=None,
467
+ proto_block='utility_code_proto', name=None, file=None):
468
+ # proto_block: Which code block to dump prototype in. See GlobalState.
469
+ self.proto = proto
470
+ self.impl = impl
471
+ self.init = init
472
+ self.cleanup = cleanup
473
+ self.requires = requires
474
+ self._cache = {}
475
+ self.specialize_list = []
476
+ self.proto_block = proto_block
477
+ self.name = name
478
+ self.file = file
479
+
480
+ def __hash__(self):
481
+ return hash((self.proto, self.impl))
482
+
483
+ def __eq__(self, other):
484
+ if self is other:
485
+ return True
486
+ self_type, other_type = type(self), type(other)
487
+ if self_type is not other_type and not (isinstance(other, self_type) or isinstance(self, other_type)):
488
+ return False
489
+
490
+ self_proto = getattr(self, 'proto', None)
491
+ other_proto = getattr(other, 'proto', None)
492
+ return (self_proto, self.impl) == (other_proto, other.impl)
493
+
494
+ def none_or_sub(self, s, context):
495
+ """
496
+ Format a string in this utility code with context. If None, do nothing.
497
+ """
498
+ if s is None:
499
+ return None
500
+ return s % context
501
+
502
+ def specialize(self, pyrex_type=None, **data):
503
+ # Dicts aren't hashable...
504
+ name = self.name
505
+ if pyrex_type is not None:
506
+ data['type'] = pyrex_type.empty_declaration_code()
507
+ data['type_name'] = pyrex_type.specialization_name()
508
+ name = "%s[%s]" % (name, data['type_name'])
509
+ key = tuple(sorted(data.items()))
510
+ try:
511
+ return self._cache[key]
512
+ except KeyError:
513
+ if self.requires is None:
514
+ requires = None
515
+ else:
516
+ requires = [r.specialize(data) for r in self.requires]
517
+
518
+ s = self._cache[key] = UtilityCode(
519
+ self.none_or_sub(self.proto, data),
520
+ self.none_or_sub(self.impl, data),
521
+ self.none_or_sub(self.init, data),
522
+ self.none_or_sub(self.cleanup, data),
523
+ requires,
524
+ self.proto_block,
525
+ name,
526
+ )
527
+
528
+ self.specialize_list.append(s)
529
+ return s
530
+
531
+ def inject_string_constants(self, impl, output):
532
+ """Replace 'PYIDENT("xyz")' by a constant Python identifier cname.
533
+ """
534
+ if 'PYIDENT(' not in impl and 'PYUNICODE(' not in impl:
535
+ return False, impl
536
+
537
+ replacements = {}
538
+ def externalise(matchobj):
539
+ key = matchobj.groups()
540
+ try:
541
+ cname = replacements[key]
542
+ except KeyError:
543
+ str_type, name = key
544
+ cname = replacements[key] = output.get_py_string_const(
545
+ StringEncoding.EncodedString(name), identifier=str_type == 'IDENT').cname
546
+ return cname
547
+
548
+ impl = re.sub(r'PY(IDENT|UNICODE)\("([^"]+)"\)', externalise, impl)
549
+ assert 'PYIDENT(' not in impl and 'PYUNICODE(' not in impl
550
+ return True, impl
551
+
552
+ def inject_unbound_methods(self, impl, output):
553
+ """Replace 'UNBOUND_METHOD(type, "name")' by a constant Python identifier cname.
554
+ """
555
+ if 'CALL_UNBOUND_METHOD(' not in impl:
556
+ return False, impl
557
+
558
+ def externalise(matchobj):
559
+ type_cname, method_name, obj_cname, args = matchobj.groups()
560
+ args = [arg.strip() for arg in args[1:].split(',')] if args else []
561
+ assert len(args) < 3, "CALL_UNBOUND_METHOD() does not support %d call arguments" % len(args)
562
+ return output.cached_unbound_method_call_code(obj_cname, type_cname, method_name, args)
563
+
564
+ impl = re.sub(
565
+ r'CALL_UNBOUND_METHOD\('
566
+ r'([a-zA-Z_]+),' # type cname
567
+ r'\s*"([^"]+)",' # method name
568
+ r'\s*([^),]+)' # object cname
569
+ r'((?:,\s*[^),]+)*)' # args*
570
+ r'\)', externalise, impl)
571
+ assert 'CALL_UNBOUND_METHOD(' not in impl
572
+
573
+ return True, impl
574
+
575
+ def wrap_c_strings(self, impl):
576
+ """Replace CSTRING('''xyz''') by a C compatible string
577
+ """
578
+ if 'CSTRING(' not in impl:
579
+ return impl
580
+
581
+ def split_string(matchobj):
582
+ content = matchobj.group(1).replace('"', '\042')
583
+ return ''.join(
584
+ '"%s\\n"\n' % line if not line.endswith('\\') or line.endswith('\\\\') else '"%s"\n' % line[:-1]
585
+ for line in content.splitlines())
586
+
587
+ impl = re.sub(r'CSTRING\(\s*"""([^"]*(?:"[^"]+)*)"""\s*\)', split_string, impl)
588
+ assert 'CSTRING(' not in impl
589
+ return impl
590
+
591
+ def put_code(self, output):
592
+ if self.requires:
593
+ for dependency in self.requires:
594
+ output.use_utility_code(dependency)
595
+ if self.proto:
596
+ writer = output[self.proto_block]
597
+ writer.putln("/* %s.proto */" % self.name)
598
+ writer.put_or_include(
599
+ self.format_code(self.proto), '%s_proto' % self.name)
600
+ if self.impl:
601
+ impl = self.format_code(self.wrap_c_strings(self.impl))
602
+ is_specialised1, impl = self.inject_string_constants(impl, output)
603
+ is_specialised2, impl = self.inject_unbound_methods(impl, output)
604
+ writer = output['utility_code_def']
605
+ writer.putln("/* %s */" % self.name)
606
+ if not (is_specialised1 or is_specialised2):
607
+ # no module specific adaptations => can be reused
608
+ writer.put_or_include(impl, '%s_impl' % self.name)
609
+ else:
610
+ writer.put(impl)
611
+ if self.init:
612
+ writer = output['init_globals']
613
+ writer.putln("/* %s.init */" % self.name)
614
+ if isinstance(self.init, basestring):
615
+ writer.put(self.format_code(self.init))
616
+ else:
617
+ self.init(writer, output.module_pos)
618
+ writer.putln(writer.error_goto_if_PyErr(output.module_pos))
619
+ writer.putln()
620
+ if self.cleanup and Options.generate_cleanup_code:
621
+ writer = output['cleanup_globals']
622
+ writer.putln("/* %s.cleanup */" % self.name)
623
+ if isinstance(self.cleanup, basestring):
624
+ writer.put_or_include(
625
+ self.format_code(self.cleanup),
626
+ '%s_cleanup' % self.name)
627
+ else:
628
+ self.cleanup(writer, output.module_pos)
629
+
630
+
631
+ def sub_tempita(s, context, file=None, name=None):
632
+ "Run tempita on string s with given context."
633
+ if not s:
634
+ return None
635
+
636
+ if file:
637
+ context['__name'] = "%s:%s" % (file, name)
638
+ elif name:
639
+ context['__name'] = name
640
+
641
+ from ..Tempita import sub
642
+ return sub(s, **context)
643
+
644
+
645
+ class TempitaUtilityCode(UtilityCode):
646
+ def __init__(self, name=None, proto=None, impl=None, init=None, file=None, context=None, **kwargs):
647
+ if context is None:
648
+ context = {}
649
+ proto = sub_tempita(proto, context, file, name)
650
+ impl = sub_tempita(impl, context, file, name)
651
+ init = sub_tempita(init, context, file, name)
652
+ super(TempitaUtilityCode, self).__init__(
653
+ proto, impl, init=init, name=name, file=file, **kwargs)
654
+
655
+ @classmethod
656
+ def load_cached(cls, utility_code_name, from_file=None, context=None, __cache={}):
657
+ context_key = tuple(sorted(context.items())) if context else None
658
+ assert hash(context_key) is not None # raise TypeError if not hashable
659
+ key = (cls, from_file, utility_code_name, context_key)
660
+ try:
661
+ return __cache[key]
662
+ except KeyError:
663
+ pass
664
+ code = __cache[key] = cls.load(utility_code_name, from_file, context=context)
665
+ return code
666
+
667
+ def none_or_sub(self, s, context):
668
+ """
669
+ Format a string in this utility code with context. If None, do nothing.
670
+ """
671
+ if s is None:
672
+ return None
673
+ return sub_tempita(s, context, self.file, self.name)
674
+
675
+
676
+ class LazyUtilityCode(UtilityCodeBase):
677
+ """
678
+ Utility code that calls a callback with the root code writer when
679
+ available. Useful when you only have 'env' but not 'code'.
680
+ """
681
+ __name__ = '<lazy>'
682
+ requires = None
683
+
684
+ def __init__(self, callback):
685
+ self.callback = callback
686
+
687
+ def put_code(self, globalstate):
688
+ utility = self.callback(globalstate.rootwriter)
689
+ globalstate.use_utility_code(utility)
690
+
691
+
692
+ class FunctionState(object):
693
+ # return_label string function return point label
694
+ # error_label string error catch point label
695
+ # continue_label string loop continue point label
696
+ # break_label string loop break point label
697
+ # return_from_error_cleanup_label string
698
+ # label_counter integer counter for naming labels
699
+ # in_try_finally boolean inside try of try...finally
700
+ # exc_vars (string * 3) exception variables for reraise, or None
701
+ # can_trace boolean line tracing is supported in the current context
702
+ # scope Scope the scope object of the current function
703
+
704
+ # Not used for now, perhaps later
705
+ def __init__(self, owner, names_taken=set(), scope=None):
706
+ self.names_taken = names_taken
707
+ self.owner = owner
708
+ self.scope = scope
709
+
710
+ self.error_label = None
711
+ self.label_counter = 0
712
+ self.labels_used = set()
713
+ self.return_label = self.new_label()
714
+ self.new_error_label()
715
+ self.continue_label = None
716
+ self.break_label = None
717
+ self.yield_labels = []
718
+
719
+ self.in_try_finally = 0
720
+ self.exc_vars = None
721
+ self.current_except = None
722
+ self.can_trace = False
723
+ self.gil_owned = True
724
+
725
+ self.temps_allocated = [] # of (name, type, manage_ref, static)
726
+ self.temps_free = {} # (type, manage_ref) -> list of free vars with same type/managed status
727
+ self.temps_used_type = {} # name -> (type, manage_ref)
728
+ self.zombie_temps = set() # temps that must not be reused after release
729
+ self.temp_counter = 0
730
+ self.closure_temps = None
731
+
732
+ # This is used to collect temporaries, useful to find out which temps
733
+ # need to be privatized in parallel sections
734
+ self.collect_temps_stack = []
735
+
736
+ # This is used for the error indicator, which needs to be local to the
737
+ # function. It used to be global, which relies on the GIL being held.
738
+ # However, exceptions may need to be propagated through 'nogil'
739
+ # sections, in which case we introduce a race condition.
740
+ self.should_declare_error_indicator = False
741
+ self.uses_error_indicator = False
742
+
743
+ # safety checks
744
+
745
+ def validate_exit(self):
746
+ # validate that all allocated temps have been freed
747
+ if self.temps_allocated:
748
+ leftovers = self.temps_in_use()
749
+ if leftovers:
750
+ msg = "TEMPGUARD: Temps left over at end of '%s': %s" % (self.scope.name, ', '.join([
751
+ '%s [%s]' % (name, ctype)
752
+ for name, ctype, is_pytemp in sorted(leftovers)]),
753
+ )
754
+ #print(msg)
755
+ raise RuntimeError(msg)
756
+
757
+ # labels
758
+
759
+ def new_label(self, name=None):
760
+ n = self.label_counter
761
+ self.label_counter = n + 1
762
+ label = "%s%d" % (Naming.label_prefix, n)
763
+ if name is not None:
764
+ label += '_' + name
765
+ return label
766
+
767
+ def new_yield_label(self, expr_type='yield'):
768
+ label = self.new_label('resume_from_%s' % expr_type)
769
+ num_and_label = (len(self.yield_labels) + 1, label)
770
+ self.yield_labels.append(num_and_label)
771
+ return num_and_label
772
+
773
+ def new_error_label(self):
774
+ old_err_lbl = self.error_label
775
+ self.error_label = self.new_label('error')
776
+ return old_err_lbl
777
+
778
+ def get_loop_labels(self):
779
+ return (
780
+ self.continue_label,
781
+ self.break_label)
782
+
783
+ def set_loop_labels(self, labels):
784
+ (self.continue_label,
785
+ self.break_label) = labels
786
+
787
+ def new_loop_labels(self):
788
+ old_labels = self.get_loop_labels()
789
+ self.set_loop_labels(
790
+ (self.new_label("continue"),
791
+ self.new_label("break")))
792
+ return old_labels
793
+
794
+ def get_all_labels(self):
795
+ return (
796
+ self.continue_label,
797
+ self.break_label,
798
+ self.return_label,
799
+ self.error_label)
800
+
801
+ def set_all_labels(self, labels):
802
+ (self.continue_label,
803
+ self.break_label,
804
+ self.return_label,
805
+ self.error_label) = labels
806
+
807
+ def all_new_labels(self):
808
+ old_labels = self.get_all_labels()
809
+ new_labels = []
810
+ for old_label, name in zip(old_labels, ['continue', 'break', 'return', 'error']):
811
+ if old_label:
812
+ new_labels.append(self.new_label(name))
813
+ else:
814
+ new_labels.append(old_label)
815
+ self.set_all_labels(new_labels)
816
+ return old_labels
817
+
818
+ def use_label(self, lbl):
819
+ self.labels_used.add(lbl)
820
+
821
+ def label_used(self, lbl):
822
+ return lbl in self.labels_used
823
+
824
+ # temp handling
825
+
826
+ def allocate_temp(self, type, manage_ref, static=False, reusable=True):
827
+ """
828
+ Allocates a temporary (which may create a new one or get a previously
829
+ allocated and released one of the same type). Type is simply registered
830
+ and handed back, but will usually be a PyrexType.
831
+
832
+ If type.is_pyobject, manage_ref comes into play. If manage_ref is set to
833
+ True, the temp will be decref-ed on return statements and in exception
834
+ handling clauses. Otherwise the caller has to deal with any reference
835
+ counting of the variable.
836
+
837
+ If not type.is_pyobject, then manage_ref will be ignored, but it
838
+ still has to be passed. It is recommended to pass False by convention
839
+ if it is known that type will never be a Python object.
840
+
841
+ static=True marks the temporary declaration with "static".
842
+ This is only used when allocating backing store for a module-level
843
+ C array literals.
844
+
845
+ if reusable=False, the temp will not be reused after release.
846
+
847
+ A C string referring to the variable is returned.
848
+ """
849
+ if type.is_const and not type.is_reference:
850
+ type = type.const_base_type
851
+ elif type.is_reference and not type.is_fake_reference:
852
+ type = type.ref_base_type
853
+ elif type.is_cfunction:
854
+ from . import PyrexTypes
855
+ type = PyrexTypes.c_ptr_type(type) # A function itself isn't an l-value
856
+ if not type.is_pyobject and not type.is_memoryviewslice:
857
+ # Make manage_ref canonical, so that manage_ref will always mean
858
+ # a decref is needed.
859
+ manage_ref = False
860
+
861
+ freelist = self.temps_free.get((type, manage_ref))
862
+ if reusable and freelist is not None and freelist[0]:
863
+ result = freelist[0].pop()
864
+ freelist[1].remove(result)
865
+ else:
866
+ while True:
867
+ self.temp_counter += 1
868
+ result = "%s%d" % (Naming.codewriter_temp_prefix, self.temp_counter)
869
+ if result not in self.names_taken: break
870
+ self.temps_allocated.append((result, type, manage_ref, static))
871
+ if not reusable:
872
+ self.zombie_temps.add(result)
873
+ self.temps_used_type[result] = (type, manage_ref)
874
+ if DebugFlags.debug_temp_code_comments:
875
+ self.owner.putln("/* %s allocated (%s)%s */" % (result, type, "" if reusable else " - zombie"))
876
+
877
+ if self.collect_temps_stack:
878
+ self.collect_temps_stack[-1].add((result, type))
879
+
880
+ return result
881
+
882
+ def release_temp(self, name):
883
+ """
884
+ Releases a temporary so that it can be reused by other code needing
885
+ a temp of the same type.
886
+ """
887
+ type, manage_ref = self.temps_used_type[name]
888
+ freelist = self.temps_free.get((type, manage_ref))
889
+ if freelist is None:
890
+ freelist = ([], set()) # keep order in list and make lookups in set fast
891
+ self.temps_free[(type, manage_ref)] = freelist
892
+ if name in freelist[1]:
893
+ raise RuntimeError("Temp %s freed twice!" % name)
894
+ if name not in self.zombie_temps:
895
+ freelist[0].append(name)
896
+ freelist[1].add(name)
897
+ if DebugFlags.debug_temp_code_comments:
898
+ self.owner.putln("/* %s released %s*/" % (
899
+ name, " - zombie" if name in self.zombie_temps else ""))
900
+
901
+ def temps_in_use(self):
902
+ """Return a list of (cname,type,manage_ref) tuples of temp names and their type
903
+ that are currently in use.
904
+ """
905
+ used = []
906
+ for name, type, manage_ref, static in self.temps_allocated:
907
+ freelist = self.temps_free.get((type, manage_ref))
908
+ if freelist is None or name not in freelist[1]:
909
+ used.append((name, type, manage_ref and type.is_pyobject))
910
+ return used
911
+
912
+ def temps_holding_reference(self):
913
+ """Return a list of (cname,type) tuples of temp names and their type
914
+ that are currently in use. This includes only temps of a
915
+ Python object type which owns its reference.
916
+ """
917
+ return [(name, type)
918
+ for name, type, manage_ref in self.temps_in_use()
919
+ if manage_ref and type.is_pyobject]
920
+
921
+ def all_managed_temps(self):
922
+ """Return a list of (cname, type) tuples of refcount-managed Python objects.
923
+ """
924
+ return [(cname, type)
925
+ for cname, type, manage_ref, static in self.temps_allocated
926
+ if manage_ref]
927
+
928
+ def all_free_managed_temps(self):
929
+ """Return a list of (cname, type) tuples of refcount-managed Python
930
+ objects that are not currently in use. This is used by
931
+ try-except and try-finally blocks to clean up temps in the
932
+ error case.
933
+ """
934
+ return sorted([ # Enforce deterministic order.
935
+ (cname, type)
936
+ for (type, manage_ref), freelist in self.temps_free.items() if manage_ref
937
+ for cname in freelist[0]
938
+ ])
939
+
940
+ def start_collecting_temps(self):
941
+ """
942
+ Useful to find out which temps were used in a code block
943
+ """
944
+ self.collect_temps_stack.append(set())
945
+
946
+ def stop_collecting_temps(self):
947
+ return self.collect_temps_stack.pop()
948
+
949
+ def init_closure_temps(self, scope):
950
+ self.closure_temps = ClosureTempAllocator(scope)
951
+
952
+
953
+ class NumConst(object):
954
+ """Global info about a Python number constant held by GlobalState.
955
+
956
+ cname string
957
+ value string
958
+ py_type string int, long, float
959
+ value_code string evaluation code if different from value
960
+ """
961
+
962
+ def __init__(self, cname, value, py_type, value_code=None):
963
+ self.cname = cname
964
+ self.value = value
965
+ self.py_type = py_type
966
+ self.value_code = value_code or value
967
+
968
+
969
+ class PyObjectConst(object):
970
+ """Global info about a generic constant held by GlobalState.
971
+ """
972
+ # cname string
973
+ # type PyrexType
974
+
975
+ def __init__(self, cname, type):
976
+ self.cname = cname
977
+ self.type = type
978
+
979
+
980
+ cython.declare(possible_unicode_identifier=object, possible_bytes_identifier=object,
981
+ replace_identifier=object, find_alphanums=object)
982
+ possible_unicode_identifier = re.compile(br"(?![0-9])\w+$".decode('ascii'), re.U).match
983
+ possible_bytes_identifier = re.compile(r"(?![0-9])\w+$".encode('ASCII')).match
984
+ replace_identifier = re.compile(r'[^a-zA-Z0-9_]+').sub
985
+ find_alphanums = re.compile('([a-zA-Z0-9]+)').findall
986
+
987
+ class StringConst(object):
988
+ """Global info about a C string constant held by GlobalState.
989
+ """
990
+ # cname string
991
+ # text EncodedString or BytesLiteral
992
+ # py_strings {(identifier, encoding) : PyStringConst}
993
+
994
+ def __init__(self, cname, text, byte_string):
995
+ self.cname = cname
996
+ self.text = text
997
+ self.escaped_value = StringEncoding.escape_byte_string(byte_string)
998
+ self.py_strings = None
999
+ self.py_versions = []
1000
+
1001
+ def add_py_version(self, version):
1002
+ if not version:
1003
+ self.py_versions = [2, 3]
1004
+ elif version not in self.py_versions:
1005
+ self.py_versions.append(version)
1006
+
1007
+ def get_py_string_const(self, encoding, identifier=None,
1008
+ is_str=False, py3str_cstring=None):
1009
+ py_strings = self.py_strings
1010
+ text = self.text
1011
+
1012
+ is_str = bool(identifier or is_str)
1013
+ is_unicode = encoding is None and not is_str
1014
+
1015
+ if encoding is None:
1016
+ # unicode string
1017
+ encoding_key = None
1018
+ else:
1019
+ # bytes or str
1020
+ encoding = encoding.lower()
1021
+ if encoding in ('utf8', 'utf-8', 'ascii', 'usascii', 'us-ascii'):
1022
+ encoding = None
1023
+ encoding_key = None
1024
+ else:
1025
+ encoding_key = ''.join(find_alphanums(encoding))
1026
+
1027
+ key = (is_str, is_unicode, encoding_key, py3str_cstring)
1028
+ if py_strings is not None:
1029
+ try:
1030
+ return py_strings[key]
1031
+ except KeyError:
1032
+ pass
1033
+ else:
1034
+ self.py_strings = {}
1035
+
1036
+ if identifier:
1037
+ intern = True
1038
+ elif identifier is None:
1039
+ if isinstance(text, bytes):
1040
+ intern = bool(possible_bytes_identifier(text))
1041
+ else:
1042
+ intern = bool(possible_unicode_identifier(text))
1043
+ else:
1044
+ intern = False
1045
+ if intern:
1046
+ prefix = Naming.interned_prefixes['str']
1047
+ else:
1048
+ prefix = Naming.py_const_prefix
1049
+
1050
+ if encoding_key:
1051
+ encoding_prefix = '_%s' % encoding_key
1052
+ else:
1053
+ encoding_prefix = ''
1054
+
1055
+ pystring_cname = "%s%s%s_%s" % (
1056
+ prefix,
1057
+ (is_str and 's') or (is_unicode and 'u') or 'b',
1058
+ encoding_prefix,
1059
+ self.cname[len(Naming.const_prefix):])
1060
+
1061
+ py_string = PyStringConst(
1062
+ pystring_cname, encoding, is_unicode, is_str, py3str_cstring, intern)
1063
+ self.py_strings[key] = py_string
1064
+ return py_string
1065
+
1066
+ class PyStringConst(object):
1067
+ """Global info about a Python string constant held by GlobalState.
1068
+ """
1069
+ # cname string
1070
+ # py3str_cstring string
1071
+ # encoding string
1072
+ # intern boolean
1073
+ # is_unicode boolean
1074
+ # is_str boolean
1075
+
1076
+ def __init__(self, cname, encoding, is_unicode, is_str=False,
1077
+ py3str_cstring=None, intern=False):
1078
+ self.cname = cname
1079
+ self.py3str_cstring = py3str_cstring
1080
+ self.encoding = encoding
1081
+ self.is_str = is_str
1082
+ self.is_unicode = is_unicode
1083
+ self.intern = intern
1084
+
1085
+ def __lt__(self, other):
1086
+ return self.cname < other.cname
1087
+
1088
+
1089
+ class GlobalState(object):
1090
+ # filename_table {string : int} for finding filename table indexes
1091
+ # filename_list [string] filenames in filename table order
1092
+ # input_file_contents dict contents (=list of lines) of any file that was used as input
1093
+ # to create this output C code. This is
1094
+ # used to annotate the comments.
1095
+ #
1096
+ # utility_codes set IDs of used utility code (to avoid reinsertion)
1097
+ #
1098
+ # declared_cnames {string:Entry} used in a transition phase to merge pxd-declared
1099
+ # constants etc. into the pyx-declared ones (i.e,
1100
+ # check if constants are already added).
1101
+ # In time, hopefully the literals etc. will be
1102
+ # supplied directly instead.
1103
+ #
1104
+ # const_cnames_used dict global counter for unique constant identifiers
1105
+ #
1106
+
1107
+ # parts {string:CCodeWriter}
1108
+
1109
+
1110
+ # interned_strings
1111
+ # consts
1112
+ # interned_nums
1113
+
1114
+ # directives set Temporary variable used to track
1115
+ # the current set of directives in the code generation
1116
+ # process.
1117
+
1118
+ directives = {}
1119
+
1120
+ code_layout = [
1121
+ 'h_code',
1122
+ 'filename_table',
1123
+ 'utility_code_proto_before_types',
1124
+ 'numeric_typedefs', # Let these detailed individual parts stay!,
1125
+ 'complex_type_declarations', # as the proper solution is to make a full DAG...
1126
+ 'type_declarations', # More coarse-grained blocks would simply hide
1127
+ 'utility_code_proto', # the ugliness, not fix it
1128
+ 'module_declarations',
1129
+ 'typeinfo',
1130
+ 'before_global_var',
1131
+ 'global_var',
1132
+ 'string_decls',
1133
+ 'decls',
1134
+ 'late_includes',
1135
+ 'all_the_rest',
1136
+ 'pystring_table',
1137
+ 'cached_builtins',
1138
+ 'cached_constants',
1139
+ 'init_globals',
1140
+ 'init_module',
1141
+ 'cleanup_globals',
1142
+ 'cleanup_module',
1143
+ 'main_method',
1144
+ 'utility_code_def',
1145
+ 'end'
1146
+ ]
1147
+
1148
+
1149
+ def __init__(self, writer, module_node, code_config, common_utility_include_dir=None):
1150
+ self.filename_table = {}
1151
+ self.filename_list = []
1152
+ self.input_file_contents = {}
1153
+ self.utility_codes = set()
1154
+ self.declared_cnames = {}
1155
+ self.in_utility_code_generation = False
1156
+ self.code_config = code_config
1157
+ self.common_utility_include_dir = common_utility_include_dir
1158
+ self.parts = {}
1159
+ self.module_node = module_node # because some utility code generation needs it
1160
+ # (generating backwards-compatible Get/ReleaseBuffer
1161
+
1162
+ self.const_cnames_used = {}
1163
+ self.string_const_index = {}
1164
+ self.dedup_const_index = {}
1165
+ self.pyunicode_ptr_const_index = {}
1166
+ self.num_const_index = {}
1167
+ self.py_constants = []
1168
+ self.cached_cmethods = {}
1169
+ self.initialised_constants = set()
1170
+
1171
+ writer.set_global_state(self)
1172
+ self.rootwriter = writer
1173
+
1174
+ def initialize_main_c_code(self):
1175
+ rootwriter = self.rootwriter
1176
+ for part in self.code_layout:
1177
+ self.parts[part] = rootwriter.insertion_point()
1178
+
1179
+ if not Options.cache_builtins:
1180
+ del self.parts['cached_builtins']
1181
+ else:
1182
+ w = self.parts['cached_builtins']
1183
+ w.enter_cfunc_scope()
1184
+ w.putln("static CYTHON_SMALL_CODE int __Pyx_InitCachedBuiltins(void) {")
1185
+
1186
+ w = self.parts['cached_constants']
1187
+ w.enter_cfunc_scope()
1188
+ w.putln("")
1189
+ w.putln("static CYTHON_SMALL_CODE int __Pyx_InitCachedConstants(void) {")
1190
+ w.put_declare_refcount_context()
1191
+ w.put_setup_refcount_context("__Pyx_InitCachedConstants")
1192
+
1193
+ w = self.parts['init_globals']
1194
+ w.enter_cfunc_scope()
1195
+ w.putln("")
1196
+ w.putln("static CYTHON_SMALL_CODE int __Pyx_InitGlobals(void) {")
1197
+
1198
+ if not Options.generate_cleanup_code:
1199
+ del self.parts['cleanup_globals']
1200
+ else:
1201
+ w = self.parts['cleanup_globals']
1202
+ w.enter_cfunc_scope()
1203
+ w.putln("")
1204
+ w.putln("static CYTHON_SMALL_CODE void __Pyx_CleanupGlobals(void) {")
1205
+
1206
+ code = self.parts['utility_code_proto']
1207
+ code.putln("")
1208
+ code.putln("/* --- Runtime support code (head) --- */")
1209
+
1210
+ code = self.parts['utility_code_def']
1211
+ if self.code_config.emit_linenums:
1212
+ code.write('\n#line 1 "cython_utility"\n')
1213
+ code.putln("")
1214
+ code.putln("/* --- Runtime support code --- */")
1215
+
1216
+ def finalize_main_c_code(self):
1217
+ self.close_global_decls()
1218
+
1219
+ #
1220
+ # utility_code_def
1221
+ #
1222
+ code = self.parts['utility_code_def']
1223
+ util = TempitaUtilityCode.load_cached("TypeConversions", "TypeConversion.c")
1224
+ code.put(util.format_code(util.impl))
1225
+ code.putln("")
1226
+
1227
+ def __getitem__(self, key):
1228
+ return self.parts[key]
1229
+
1230
+ #
1231
+ # Global constants, interned objects, etc.
1232
+ #
1233
+ def close_global_decls(self):
1234
+ # This is called when it is known that no more global declarations will
1235
+ # declared.
1236
+ self.generate_const_declarations()
1237
+ if Options.cache_builtins:
1238
+ w = self.parts['cached_builtins']
1239
+ w.putln("return 0;")
1240
+ if w.label_used(w.error_label):
1241
+ w.put_label(w.error_label)
1242
+ w.putln("return -1;")
1243
+ w.putln("}")
1244
+ w.exit_cfunc_scope()
1245
+
1246
+ w = self.parts['cached_constants']
1247
+ w.put_finish_refcount_context()
1248
+ w.putln("return 0;")
1249
+ if w.label_used(w.error_label):
1250
+ w.put_label(w.error_label)
1251
+ w.put_finish_refcount_context()
1252
+ w.putln("return -1;")
1253
+ w.putln("}")
1254
+ w.exit_cfunc_scope()
1255
+
1256
+ w = self.parts['init_globals']
1257
+ w.putln("return 0;")
1258
+ if w.label_used(w.error_label):
1259
+ w.put_label(w.error_label)
1260
+ w.putln("return -1;")
1261
+ w.putln("}")
1262
+ w.exit_cfunc_scope()
1263
+
1264
+ if Options.generate_cleanup_code:
1265
+ w = self.parts['cleanup_globals']
1266
+ w.putln("}")
1267
+ w.exit_cfunc_scope()
1268
+
1269
+ if Options.generate_cleanup_code:
1270
+ w = self.parts['cleanup_module']
1271
+ w.putln("}")
1272
+ w.exit_cfunc_scope()
1273
+
1274
+ def put_pyobject_decl(self, entry):
1275
+ self['global_var'].putln("static PyObject *%s;" % entry.cname)
1276
+
1277
+ # constant handling at code generation time
1278
+
1279
+ def get_cached_constants_writer(self, target=None):
1280
+ if target is not None:
1281
+ if target in self.initialised_constants:
1282
+ # Return None on second/later calls to prevent duplicate creation code.
1283
+ return None
1284
+ self.initialised_constants.add(target)
1285
+ return self.parts['cached_constants']
1286
+
1287
+ def get_int_const(self, str_value, longness=False):
1288
+ py_type = longness and 'long' or 'int'
1289
+ try:
1290
+ c = self.num_const_index[(str_value, py_type)]
1291
+ except KeyError:
1292
+ c = self.new_num_const(str_value, py_type)
1293
+ return c
1294
+
1295
+ def get_float_const(self, str_value, value_code):
1296
+ try:
1297
+ c = self.num_const_index[(str_value, 'float')]
1298
+ except KeyError:
1299
+ c = self.new_num_const(str_value, 'float', value_code)
1300
+ return c
1301
+
1302
+ def get_py_const(self, type, prefix='', cleanup_level=None, dedup_key=None):
1303
+ if dedup_key is not None:
1304
+ const = self.dedup_const_index.get(dedup_key)
1305
+ if const is not None:
1306
+ return const
1307
+ # create a new Python object constant
1308
+ const = self.new_py_const(type, prefix)
1309
+ if cleanup_level is not None \
1310
+ and cleanup_level <= Options.generate_cleanup_code:
1311
+ cleanup_writer = self.parts['cleanup_globals']
1312
+ cleanup_writer.putln('Py_CLEAR(%s);' % const.cname)
1313
+ if dedup_key is not None:
1314
+ self.dedup_const_index[dedup_key] = const
1315
+ return const
1316
+
1317
+ def get_string_const(self, text, py_version=None):
1318
+ # return a C string constant, creating a new one if necessary
1319
+ if text.is_unicode:
1320
+ byte_string = text.utf8encode()
1321
+ else:
1322
+ byte_string = text.byteencode()
1323
+ try:
1324
+ c = self.string_const_index[byte_string]
1325
+ except KeyError:
1326
+ c = self.new_string_const(text, byte_string)
1327
+ c.add_py_version(py_version)
1328
+ return c
1329
+
1330
+ def get_pyunicode_ptr_const(self, text):
1331
+ # return a Py_UNICODE[] constant, creating a new one if necessary
1332
+ assert text.is_unicode
1333
+ try:
1334
+ c = self.pyunicode_ptr_const_index[text]
1335
+ except KeyError:
1336
+ c = self.pyunicode_ptr_const_index[text] = self.new_const_cname()
1337
+ return c
1338
+
1339
+ def get_py_string_const(self, text, identifier=None,
1340
+ is_str=False, unicode_value=None):
1341
+ # return a Python string constant, creating a new one if necessary
1342
+ py3str_cstring = None
1343
+ if is_str and unicode_value is not None \
1344
+ and unicode_value.utf8encode() != text.byteencode():
1345
+ py3str_cstring = self.get_string_const(unicode_value, py_version=3)
1346
+ c_string = self.get_string_const(text, py_version=2)
1347
+ else:
1348
+ c_string = self.get_string_const(text)
1349
+ py_string = c_string.get_py_string_const(
1350
+ text.encoding, identifier, is_str, py3str_cstring)
1351
+ return py_string
1352
+
1353
+ def get_interned_identifier(self, text):
1354
+ return self.get_py_string_const(text, identifier=True)
1355
+
1356
+ def new_string_const(self, text, byte_string):
1357
+ cname = self.new_string_const_cname(byte_string)
1358
+ c = StringConst(cname, text, byte_string)
1359
+ self.string_const_index[byte_string] = c
1360
+ return c
1361
+
1362
+ def new_num_const(self, value, py_type, value_code=None):
1363
+ cname = self.new_num_const_cname(value, py_type)
1364
+ c = NumConst(cname, value, py_type, value_code)
1365
+ self.num_const_index[(value, py_type)] = c
1366
+ return c
1367
+
1368
+ def new_py_const(self, type, prefix=''):
1369
+ cname = self.new_const_cname(prefix)
1370
+ c = PyObjectConst(cname, type)
1371
+ self.py_constants.append(c)
1372
+ return c
1373
+
1374
+ def new_string_const_cname(self, bytes_value):
1375
+ # Create a new globally-unique nice name for a C string constant.
1376
+ value = bytes_value.decode('ASCII', 'ignore')
1377
+ return self.new_const_cname(value=value)
1378
+
1379
+ def new_num_const_cname(self, value, py_type):
1380
+ if py_type == 'long':
1381
+ value += 'L'
1382
+ py_type = 'int'
1383
+ prefix = Naming.interned_prefixes[py_type]
1384
+ cname = "%s%s" % (prefix, value)
1385
+ cname = cname.replace('+', '_').replace('-', 'neg_').replace('.', '_')
1386
+ return cname
1387
+
1388
+ def new_const_cname(self, prefix='', value=''):
1389
+ value = replace_identifier('_', value)[:32].strip('_')
1390
+ used = self.const_cnames_used
1391
+ name_suffix = value
1392
+ while name_suffix in used:
1393
+ counter = used[value] = used[value] + 1
1394
+ name_suffix = '%s_%d' % (value, counter)
1395
+ used[name_suffix] = 1
1396
+ if prefix:
1397
+ prefix = Naming.interned_prefixes[prefix]
1398
+ else:
1399
+ prefix = Naming.const_prefix
1400
+ return "%s%s" % (prefix, name_suffix)
1401
+
1402
+ def get_cached_unbound_method(self, type_cname, method_name):
1403
+ key = (type_cname, method_name)
1404
+ try:
1405
+ cname = self.cached_cmethods[key]
1406
+ except KeyError:
1407
+ cname = self.cached_cmethods[key] = self.new_const_cname(
1408
+ 'umethod', '%s_%s' % (type_cname, method_name))
1409
+ return cname
1410
+
1411
+ def cached_unbound_method_call_code(self, obj_cname, type_cname, method_name, arg_cnames):
1412
+ # admittedly, not the best place to put this method, but it is reused by UtilityCode and ExprNodes ...
1413
+ utility_code_name = "CallUnboundCMethod%d" % len(arg_cnames)
1414
+ self.use_utility_code(UtilityCode.load_cached(utility_code_name, "ObjectHandling.c"))
1415
+ cache_cname = self.get_cached_unbound_method(type_cname, method_name)
1416
+ args = [obj_cname] + arg_cnames
1417
+ return "__Pyx_%s(&%s, %s)" % (
1418
+ utility_code_name,
1419
+ cache_cname,
1420
+ ', '.join(args),
1421
+ )
1422
+
1423
+ def add_cached_builtin_decl(self, entry):
1424
+ if entry.is_builtin and entry.is_const:
1425
+ if self.should_declare(entry.cname, entry):
1426
+ self.put_pyobject_decl(entry)
1427
+ w = self.parts['cached_builtins']
1428
+ condition = None
1429
+ if entry.name in non_portable_builtins_map:
1430
+ condition, replacement = non_portable_builtins_map[entry.name]
1431
+ w.putln('#if %s' % condition)
1432
+ self.put_cached_builtin_init(
1433
+ entry.pos, StringEncoding.EncodedString(replacement),
1434
+ entry.cname)
1435
+ w.putln('#else')
1436
+ self.put_cached_builtin_init(
1437
+ entry.pos, StringEncoding.EncodedString(entry.name),
1438
+ entry.cname)
1439
+ if condition:
1440
+ w.putln('#endif')
1441
+
1442
+ def put_cached_builtin_init(self, pos, name, cname):
1443
+ w = self.parts['cached_builtins']
1444
+ interned_cname = self.get_interned_identifier(name).cname
1445
+ self.use_utility_code(
1446
+ UtilityCode.load_cached("GetBuiltinName", "ObjectHandling.c"))
1447
+ w.putln('%s = __Pyx_GetBuiltinName(%s); if (!%s) %s' % (
1448
+ cname,
1449
+ interned_cname,
1450
+ cname,
1451
+ w.error_goto(pos)))
1452
+
1453
+ def generate_const_declarations(self):
1454
+ self.generate_cached_methods_decls()
1455
+ self.generate_string_constants()
1456
+ self.generate_num_constants()
1457
+ self.generate_object_constant_decls()
1458
+
1459
+ def generate_object_constant_decls(self):
1460
+ consts = [(len(c.cname), c.cname, c)
1461
+ for c in self.py_constants]
1462
+ consts.sort()
1463
+ decls_writer = self.parts['decls']
1464
+ for _, cname, c in consts:
1465
+ decls_writer.putln(
1466
+ "static %s;" % c.type.declaration_code(cname))
1467
+
1468
+ def generate_cached_methods_decls(self):
1469
+ if not self.cached_cmethods:
1470
+ return
1471
+
1472
+ decl = self.parts['decls']
1473
+ init = self.parts['init_globals']
1474
+ cnames = []
1475
+ for (type_cname, method_name), cname in sorted(self.cached_cmethods.items()):
1476
+ cnames.append(cname)
1477
+ method_name_cname = self.get_interned_identifier(StringEncoding.EncodedString(method_name)).cname
1478
+ decl.putln('static __Pyx_CachedCFunction %s = {0, &%s, 0, 0, 0};' % (
1479
+ cname, method_name_cname))
1480
+ # split type reference storage as it might not be static
1481
+ init.putln('%s.type = (PyObject*)&%s;' % (
1482
+ cname, type_cname))
1483
+
1484
+ if Options.generate_cleanup_code:
1485
+ cleanup = self.parts['cleanup_globals']
1486
+ for cname in cnames:
1487
+ cleanup.putln("Py_CLEAR(%s.method);" % cname)
1488
+
1489
+ def generate_string_constants(self):
1490
+ c_consts = [(len(c.cname), c.cname, c) for c in self.string_const_index.values()]
1491
+ c_consts.sort()
1492
+ py_strings = []
1493
+
1494
+ decls_writer = self.parts['string_decls']
1495
+ for _, cname, c in c_consts:
1496
+ conditional = False
1497
+ if c.py_versions and (2 not in c.py_versions or 3 not in c.py_versions):
1498
+ conditional = True
1499
+ decls_writer.putln("#if PY_MAJOR_VERSION %s 3" % (
1500
+ (2 in c.py_versions) and '<' or '>='))
1501
+ decls_writer.putln('static const char %s[] = "%s";' % (
1502
+ cname, StringEncoding.split_string_literal(c.escaped_value)))
1503
+ if conditional:
1504
+ decls_writer.putln("#endif")
1505
+ if c.py_strings is not None:
1506
+ for py_string in c.py_strings.values():
1507
+ py_strings.append((c.cname, len(py_string.cname), py_string))
1508
+
1509
+ for c, cname in sorted(self.pyunicode_ptr_const_index.items()):
1510
+ utf16_array, utf32_array = StringEncoding.encode_pyunicode_string(c)
1511
+ if utf16_array:
1512
+ # Narrow and wide representations differ
1513
+ decls_writer.putln("#ifdef Py_UNICODE_WIDE")
1514
+ decls_writer.putln("static Py_UNICODE %s[] = { %s };" % (cname, utf32_array))
1515
+ if utf16_array:
1516
+ decls_writer.putln("#else")
1517
+ decls_writer.putln("static Py_UNICODE %s[] = { %s };" % (cname, utf16_array))
1518
+ decls_writer.putln("#endif")
1519
+
1520
+ if py_strings:
1521
+ self.use_utility_code(UtilityCode.load_cached("InitStrings", "StringTools.c"))
1522
+ py_strings.sort()
1523
+ w = self.parts['pystring_table']
1524
+ w.putln("")
1525
+ w.putln("static __Pyx_StringTabEntry %s[] = {" % Naming.stringtab_cname)
1526
+ for c_cname, _, py_string in py_strings:
1527
+ if not py_string.is_str or not py_string.encoding or \
1528
+ py_string.encoding in ('ASCII', 'USASCII', 'US-ASCII',
1529
+ 'UTF8', 'UTF-8'):
1530
+ encoding = '0'
1531
+ else:
1532
+ encoding = '"%s"' % py_string.encoding.lower()
1533
+
1534
+ decls_writer.putln(
1535
+ "static PyObject *%s;" % py_string.cname)
1536
+ if py_string.py3str_cstring:
1537
+ w.putln("#if PY_MAJOR_VERSION >= 3")
1538
+ w.putln("{&%s, %s, sizeof(%s), %s, %d, %d, %d}," % (
1539
+ py_string.cname,
1540
+ py_string.py3str_cstring.cname,
1541
+ py_string.py3str_cstring.cname,
1542
+ '0', 1, 0,
1543
+ py_string.intern
1544
+ ))
1545
+ w.putln("#else")
1546
+ w.putln("{&%s, %s, sizeof(%s), %s, %d, %d, %d}," % (
1547
+ py_string.cname,
1548
+ c_cname,
1549
+ c_cname,
1550
+ encoding,
1551
+ py_string.is_unicode,
1552
+ py_string.is_str,
1553
+ py_string.intern
1554
+ ))
1555
+ if py_string.py3str_cstring:
1556
+ w.putln("#endif")
1557
+ w.putln("{0, 0, 0, 0, 0, 0, 0}")
1558
+ w.putln("};")
1559
+
1560
+ init_globals = self.parts['init_globals']
1561
+ init_globals.putln(
1562
+ "if (__Pyx_InitStrings(%s) < 0) %s" % (
1563
+ Naming.stringtab_cname,
1564
+ init_globals.error_goto(self.module_pos)))
1565
+
1566
+ def generate_num_constants(self):
1567
+ consts = [(c.py_type, c.value[0] == '-', len(c.value), c.value, c.value_code, c)
1568
+ for c in self.num_const_index.values()]
1569
+ consts.sort()
1570
+ decls_writer = self.parts['decls']
1571
+ init_globals = self.parts['init_globals']
1572
+ for py_type, _, _, value, value_code, c in consts:
1573
+ cname = c.cname
1574
+ decls_writer.putln("static PyObject *%s;" % cname)
1575
+ if py_type == 'float':
1576
+ function = 'PyFloat_FromDouble(%s)'
1577
+ elif py_type == 'long':
1578
+ function = 'PyLong_FromString((char *)"%s", 0, 0)'
1579
+ elif Utils.long_literal(value):
1580
+ function = 'PyInt_FromString((char *)"%s", 0, 0)'
1581
+ elif len(value.lstrip('-')) > 4:
1582
+ function = "PyInt_FromLong(%sL)"
1583
+ else:
1584
+ function = "PyInt_FromLong(%s)"
1585
+ init_globals.putln('%s = %s; %s' % (
1586
+ cname, function % value_code,
1587
+ init_globals.error_goto_if_null(cname, self.module_pos)))
1588
+
1589
+ # The functions below are there in a transition phase only
1590
+ # and will be deprecated. They are called from Nodes.BlockNode.
1591
+ # The copy&paste duplication is intentional in order to be able
1592
+ # to see quickly how BlockNode worked, until this is replaced.
1593
+
1594
+ def should_declare(self, cname, entry):
1595
+ if cname in self.declared_cnames:
1596
+ other = self.declared_cnames[cname]
1597
+ assert str(entry.type) == str(other.type)
1598
+ assert entry.init == other.init
1599
+ return False
1600
+ else:
1601
+ self.declared_cnames[cname] = entry
1602
+ return True
1603
+
1604
+ #
1605
+ # File name state
1606
+ #
1607
+
1608
+ def lookup_filename(self, source_desc):
1609
+ entry = source_desc.get_filenametable_entry()
1610
+ try:
1611
+ index = self.filename_table[entry]
1612
+ except KeyError:
1613
+ index = len(self.filename_list)
1614
+ self.filename_list.append(source_desc)
1615
+ self.filename_table[entry] = index
1616
+ return index
1617
+
1618
+ def commented_file_contents(self, source_desc):
1619
+ try:
1620
+ return self.input_file_contents[source_desc]
1621
+ except KeyError:
1622
+ pass
1623
+ source_file = source_desc.get_lines(encoding='ASCII',
1624
+ error_handling='ignore')
1625
+ try:
1626
+ F = [u' * ' + line.rstrip().replace(
1627
+ u'*/', u'*[inserted by cython to avoid comment closer]/'
1628
+ ).replace(
1629
+ u'/*', u'/[inserted by cython to avoid comment start]*'
1630
+ )
1631
+ for line in source_file]
1632
+ finally:
1633
+ if hasattr(source_file, 'close'):
1634
+ source_file.close()
1635
+ if not F: F.append(u'')
1636
+ self.input_file_contents[source_desc] = F
1637
+ return F
1638
+
1639
+ #
1640
+ # Utility code state
1641
+ #
1642
+
1643
+ def use_utility_code(self, utility_code):
1644
+ """
1645
+ Adds code to the C file. utility_code should
1646
+ a) implement __eq__/__hash__ for the purpose of knowing whether the same
1647
+ code has already been included
1648
+ b) implement put_code, which takes a globalstate instance
1649
+
1650
+ See UtilityCode.
1651
+ """
1652
+ if utility_code and utility_code not in self.utility_codes:
1653
+ self.utility_codes.add(utility_code)
1654
+ utility_code.put_code(self)
1655
+
1656
+ def use_entry_utility_code(self, entry):
1657
+ if entry is None:
1658
+ return
1659
+ if entry.utility_code:
1660
+ self.use_utility_code(entry.utility_code)
1661
+ if entry.utility_code_definition:
1662
+ self.use_utility_code(entry.utility_code_definition)
1663
+
1664
+
1665
+ def funccontext_property(func):
1666
+ name = func.__name__
1667
+ attribute_of = operator.attrgetter(name)
1668
+ def get(self):
1669
+ return attribute_of(self.funcstate)
1670
+ def set(self, value):
1671
+ setattr(self.funcstate, name, value)
1672
+ return property(get, set)
1673
+
1674
+
1675
+ class CCodeConfig(object):
1676
+ # emit_linenums boolean write #line pragmas?
1677
+ # emit_code_comments boolean copy the original code into C comments?
1678
+ # c_line_in_traceback boolean append the c file and line number to the traceback for exceptions?
1679
+
1680
+ def __init__(self, emit_linenums=True, emit_code_comments=True, c_line_in_traceback=True):
1681
+ self.emit_code_comments = emit_code_comments
1682
+ self.emit_linenums = emit_linenums
1683
+ self.c_line_in_traceback = c_line_in_traceback
1684
+
1685
+
1686
+ class CCodeWriter(object):
1687
+ """
1688
+ Utility class to output C code.
1689
+
1690
+ When creating an insertion point one must care about the state that is
1691
+ kept:
1692
+ - formatting state (level, bol) is cloned and used in insertion points
1693
+ as well
1694
+ - labels, temps, exc_vars: One must construct a scope in which these can
1695
+ exist by calling enter_cfunc_scope/exit_cfunc_scope (these are for
1696
+ sanity checking and forward compatibility). Created insertion points
1697
+ looses this scope and cannot access it.
1698
+ - marker: Not copied to insertion point
1699
+ - filename_table, filename_list, input_file_contents: All codewriters
1700
+ coming from the same root share the same instances simultaneously.
1701
+ """
1702
+
1703
+ # f file output file
1704
+ # buffer StringIOTree
1705
+
1706
+ # level int indentation level
1707
+ # bol bool beginning of line?
1708
+ # marker string comment to emit before next line
1709
+ # funcstate FunctionState contains state local to a C function used for code
1710
+ # generation (labels and temps state etc.)
1711
+ # globalstate GlobalState contains state global for a C file (input file info,
1712
+ # utility code, declared constants etc.)
1713
+ # pyclass_stack list used during recursive code generation to pass information
1714
+ # about the current class one is in
1715
+ # code_config CCodeConfig configuration options for the C code writer
1716
+
1717
+ @cython.locals(create_from='CCodeWriter')
1718
+ def __init__(self, create_from=None, buffer=None, copy_formatting=False):
1719
+ if buffer is None: buffer = StringIOTree()
1720
+ self.buffer = buffer
1721
+ self.last_pos = None
1722
+ self.last_marked_pos = None
1723
+ self.pyclass_stack = []
1724
+
1725
+ self.funcstate = None
1726
+ self.globalstate = None
1727
+ self.code_config = None
1728
+ self.level = 0
1729
+ self.call_level = 0
1730
+ self.bol = 1
1731
+
1732
+ if create_from is not None:
1733
+ # Use same global state
1734
+ self.set_global_state(create_from.globalstate)
1735
+ self.funcstate = create_from.funcstate
1736
+ # Clone formatting state
1737
+ if copy_formatting:
1738
+ self.level = create_from.level
1739
+ self.bol = create_from.bol
1740
+ self.call_level = create_from.call_level
1741
+ self.last_pos = create_from.last_pos
1742
+ self.last_marked_pos = create_from.last_marked_pos
1743
+
1744
+ def create_new(self, create_from, buffer, copy_formatting):
1745
+ # polymorphic constructor -- very slightly more versatile
1746
+ # than using __class__
1747
+ result = CCodeWriter(create_from, buffer, copy_formatting)
1748
+ return result
1749
+
1750
+ def set_global_state(self, global_state):
1751
+ assert self.globalstate is None # prevent overwriting once it's set
1752
+ self.globalstate = global_state
1753
+ self.code_config = global_state.code_config
1754
+
1755
+ def copyto(self, f):
1756
+ self.buffer.copyto(f)
1757
+
1758
+ def getvalue(self):
1759
+ return self.buffer.getvalue()
1760
+
1761
+ def write(self, s):
1762
+ # also put invalid markers (lineno 0), to indicate that those lines
1763
+ # have no Cython source code correspondence
1764
+ cython_lineno = self.last_marked_pos[1] if self.last_marked_pos else 0
1765
+ self.buffer.markers.extend([cython_lineno] * s.count('\n'))
1766
+ self.buffer.write(s)
1767
+
1768
+ def insertion_point(self):
1769
+ other = self.create_new(create_from=self, buffer=self.buffer.insertion_point(), copy_formatting=True)
1770
+ return other
1771
+
1772
+ def new_writer(self):
1773
+ """
1774
+ Creates a new CCodeWriter connected to the same global state, which
1775
+ can later be inserted using insert.
1776
+ """
1777
+ return CCodeWriter(create_from=self)
1778
+
1779
+ def insert(self, writer):
1780
+ """
1781
+ Inserts the contents of another code writer (created with
1782
+ the same global state) in the current location.
1783
+
1784
+ It is ok to write to the inserted writer also after insertion.
1785
+ """
1786
+ assert writer.globalstate is self.globalstate
1787
+ self.buffer.insert(writer.buffer)
1788
+
1789
+ # Properties delegated to function scope
1790
+ @funccontext_property
1791
+ def label_counter(self): pass
1792
+ @funccontext_property
1793
+ def return_label(self): pass
1794
+ @funccontext_property
1795
+ def error_label(self): pass
1796
+ @funccontext_property
1797
+ def labels_used(self): pass
1798
+ @funccontext_property
1799
+ def continue_label(self): pass
1800
+ @funccontext_property
1801
+ def break_label(self): pass
1802
+ @funccontext_property
1803
+ def return_from_error_cleanup_label(self): pass
1804
+ @funccontext_property
1805
+ def yield_labels(self): pass
1806
+
1807
+ # Functions delegated to function scope
1808
+ def new_label(self, name=None): return self.funcstate.new_label(name)
1809
+ def new_error_label(self): return self.funcstate.new_error_label()
1810
+ def new_yield_label(self, *args): return self.funcstate.new_yield_label(*args)
1811
+ def get_loop_labels(self): return self.funcstate.get_loop_labels()
1812
+ def set_loop_labels(self, labels): return self.funcstate.set_loop_labels(labels)
1813
+ def new_loop_labels(self): return self.funcstate.new_loop_labels()
1814
+ def get_all_labels(self): return self.funcstate.get_all_labels()
1815
+ def set_all_labels(self, labels): return self.funcstate.set_all_labels(labels)
1816
+ def all_new_labels(self): return self.funcstate.all_new_labels()
1817
+ def use_label(self, lbl): return self.funcstate.use_label(lbl)
1818
+ def label_used(self, lbl): return self.funcstate.label_used(lbl)
1819
+
1820
+
1821
+ def enter_cfunc_scope(self, scope=None):
1822
+ self.funcstate = FunctionState(self, scope=scope)
1823
+
1824
+ def exit_cfunc_scope(self):
1825
+ self.funcstate = None
1826
+
1827
+ # constant handling
1828
+
1829
+ def get_py_int(self, str_value, longness):
1830
+ return self.globalstate.get_int_const(str_value, longness).cname
1831
+
1832
+ def get_py_float(self, str_value, value_code):
1833
+ return self.globalstate.get_float_const(str_value, value_code).cname
1834
+
1835
+ def get_py_const(self, type, prefix='', cleanup_level=None, dedup_key=None):
1836
+ return self.globalstate.get_py_const(type, prefix, cleanup_level, dedup_key).cname
1837
+
1838
+ def get_string_const(self, text):
1839
+ return self.globalstate.get_string_const(text).cname
1840
+
1841
+ def get_pyunicode_ptr_const(self, text):
1842
+ return self.globalstate.get_pyunicode_ptr_const(text)
1843
+
1844
+ def get_py_string_const(self, text, identifier=None,
1845
+ is_str=False, unicode_value=None):
1846
+ return self.globalstate.get_py_string_const(
1847
+ text, identifier, is_str, unicode_value).cname
1848
+
1849
+ def get_argument_default_const(self, type):
1850
+ return self.globalstate.get_py_const(type).cname
1851
+
1852
+ def intern(self, text):
1853
+ return self.get_py_string_const(text)
1854
+
1855
+ def intern_identifier(self, text):
1856
+ return self.get_py_string_const(text, identifier=True)
1857
+
1858
+ def get_cached_constants_writer(self, target=None):
1859
+ return self.globalstate.get_cached_constants_writer(target)
1860
+
1861
+ # code generation
1862
+
1863
+ def putln(self, code="", safe=False):
1864
+ if self.last_pos and self.bol:
1865
+ self.emit_marker()
1866
+ if self.code_config.emit_linenums and self.last_marked_pos:
1867
+ source_desc, line, _ = self.last_marked_pos
1868
+ self.write('\n#line %s "%s"\n' % (line, source_desc.get_escaped_description()))
1869
+ if code:
1870
+ if safe:
1871
+ self.put_safe(code)
1872
+ else:
1873
+ self.put(code)
1874
+ self.write("\n")
1875
+ self.bol = 1
1876
+
1877
+ def mark_pos(self, pos, trace=True):
1878
+ if pos is None:
1879
+ return
1880
+ if self.last_marked_pos and self.last_marked_pos[:2] == pos[:2]:
1881
+ return
1882
+ self.last_pos = (pos, trace)
1883
+
1884
+ def emit_marker(self):
1885
+ pos, trace = self.last_pos
1886
+ self.last_marked_pos = pos
1887
+ self.last_pos = None
1888
+ self.write("\n")
1889
+ if self.code_config.emit_code_comments:
1890
+ self.indent()
1891
+ self.write("/* %s */\n" % self._build_marker(pos))
1892
+ if trace and self.funcstate and self.funcstate.can_trace and self.globalstate.directives['linetrace']:
1893
+ self.indent()
1894
+ self.write('__Pyx_TraceLine(%d,%d,%s)\n' % (
1895
+ pos[1], not self.funcstate.gil_owned, self.error_goto(pos)))
1896
+
1897
+ def _build_marker(self, pos):
1898
+ source_desc, line, col = pos
1899
+ assert isinstance(source_desc, SourceDescriptor)
1900
+ contents = self.globalstate.commented_file_contents(source_desc)
1901
+ lines = contents[max(0, line-3):line] # line numbers start at 1
1902
+ lines[-1] += u' # <<<<<<<<<<<<<<'
1903
+ lines += contents[line:line+2]
1904
+ return u'"%s":%d\n%s\n' % (source_desc.get_escaped_description(), line, u'\n'.join(lines))
1905
+
1906
+ def put_safe(self, code):
1907
+ # put code, but ignore {}
1908
+ self.write(code)
1909
+ self.bol = 0
1910
+
1911
+ def put_or_include(self, code, name):
1912
+ include_dir = self.globalstate.common_utility_include_dir
1913
+ if include_dir and len(code) > 1024:
1914
+ include_file = "%s_%s.h" % (
1915
+ name, hashlib.md5(code.encode('utf8')).hexdigest())
1916
+ path = os.path.join(include_dir, include_file)
1917
+ if not os.path.exists(path):
1918
+ tmp_path = '%s.tmp%s' % (path, os.getpid())
1919
+ with closing(Utils.open_new_file(tmp_path)) as f:
1920
+ f.write(code)
1921
+ shutil.move(tmp_path, path)
1922
+ code = '#include "%s"\n' % path
1923
+ self.put(code)
1924
+
1925
+ def put(self, code):
1926
+ fix_indent = False
1927
+ if "{" in code:
1928
+ dl = code.count("{")
1929
+ else:
1930
+ dl = 0
1931
+ if "}" in code:
1932
+ dl -= code.count("}")
1933
+ if dl < 0:
1934
+ self.level += dl
1935
+ elif dl == 0 and code[0] == "}":
1936
+ # special cases like "} else {" need a temporary dedent
1937
+ fix_indent = True
1938
+ self.level -= 1
1939
+ if self.bol:
1940
+ self.indent()
1941
+ self.write(code)
1942
+ self.bol = 0
1943
+ if dl > 0:
1944
+ self.level += dl
1945
+ elif fix_indent:
1946
+ self.level += 1
1947
+
1948
+ def putln_tempita(self, code, **context):
1949
+ from ..Tempita import sub
1950
+ self.putln(sub(code, **context))
1951
+
1952
+ def put_tempita(self, code, **context):
1953
+ from ..Tempita import sub
1954
+ self.put(sub(code, **context))
1955
+
1956
+ def increase_indent(self):
1957
+ self.level += 1
1958
+
1959
+ def decrease_indent(self):
1960
+ self.level -= 1
1961
+
1962
+ def begin_block(self):
1963
+ self.putln("{")
1964
+ self.increase_indent()
1965
+
1966
+ def end_block(self):
1967
+ self.decrease_indent()
1968
+ self.putln("}")
1969
+
1970
+ def indent(self):
1971
+ self.write(" " * self.level)
1972
+
1973
+ def get_py_version_hex(self, pyversion):
1974
+ return "0x%02X%02X%02X%02X" % (tuple(pyversion) + (0,0,0,0))[:4]
1975
+
1976
+ def put_label(self, lbl):
1977
+ if lbl in self.funcstate.labels_used:
1978
+ self.putln("%s:;" % lbl)
1979
+
1980
+ def put_goto(self, lbl):
1981
+ self.funcstate.use_label(lbl)
1982
+ self.putln("goto %s;" % lbl)
1983
+
1984
+ def put_var_declaration(self, entry, storage_class="",
1985
+ dll_linkage=None, definition=True):
1986
+ #print "Code.put_var_declaration:", entry.name, "definition =", definition ###
1987
+ if entry.visibility == 'private' and not (definition or entry.defined_in_pxd):
1988
+ #print "...private and not definition, skipping", entry.cname ###
1989
+ return
1990
+ if entry.visibility == "private" and not entry.used:
1991
+ #print "...private and not used, skipping", entry.cname ###
1992
+ return
1993
+ if storage_class:
1994
+ self.put("%s " % storage_class)
1995
+ if not entry.cf_used:
1996
+ self.put('CYTHON_UNUSED ')
1997
+ self.put(entry.type.declaration_code(
1998
+ entry.cname, dll_linkage=dll_linkage))
1999
+ if entry.init is not None:
2000
+ self.put_safe(" = %s" % entry.type.literal_code(entry.init))
2001
+ elif entry.type.is_pyobject:
2002
+ self.put(" = NULL")
2003
+ self.putln(";")
2004
+
2005
+ def put_temp_declarations(self, func_context):
2006
+ for name, type, manage_ref, static in func_context.temps_allocated:
2007
+ decl = type.declaration_code(name)
2008
+ if type.is_pyobject:
2009
+ self.putln("%s = NULL;" % decl)
2010
+ elif type.is_memoryviewslice:
2011
+ from . import MemoryView
2012
+ self.putln("%s = %s;" % (decl, MemoryView.memslice_entry_init))
2013
+ else:
2014
+ self.putln("%s%s;" % (static and "static " or "", decl))
2015
+
2016
+ if func_context.should_declare_error_indicator:
2017
+ if self.funcstate.uses_error_indicator:
2018
+ unused = ''
2019
+ else:
2020
+ unused = 'CYTHON_UNUSED '
2021
+ # Initialize these variables to silence compiler warnings
2022
+ self.putln("%sint %s = 0;" % (unused, Naming.lineno_cname))
2023
+ self.putln("%sconst char *%s = NULL;" % (unused, Naming.filename_cname))
2024
+ self.putln("%sint %s = 0;" % (unused, Naming.clineno_cname))
2025
+
2026
+ def put_generated_by(self):
2027
+ self.putln("/* Generated by Cython %s */" % Version.watermark)
2028
+ self.putln("")
2029
+
2030
+ def put_h_guard(self, guard):
2031
+ self.putln("#ifndef %s" % guard)
2032
+ self.putln("#define %s" % guard)
2033
+
2034
+ def unlikely(self, cond):
2035
+ if Options.gcc_branch_hints:
2036
+ return 'unlikely(%s)' % cond
2037
+ else:
2038
+ return cond
2039
+
2040
+ def build_function_modifiers(self, modifiers, mapper=modifier_output_mapper):
2041
+ if not modifiers:
2042
+ return ''
2043
+ return '%s ' % ' '.join([mapper(m,m) for m in modifiers])
2044
+
2045
+ # Python objects and reference counting
2046
+
2047
+ def entry_as_pyobject(self, entry):
2048
+ type = entry.type
2049
+ if (not entry.is_self_arg and not entry.type.is_complete()
2050
+ or entry.type.is_extension_type):
2051
+ return "(PyObject *)" + entry.cname
2052
+ else:
2053
+ return entry.cname
2054
+
2055
+ def as_pyobject(self, cname, type):
2056
+ from .PyrexTypes import py_object_type, typecast
2057
+ return typecast(py_object_type, type, cname)
2058
+
2059
+ def put_gotref(self, cname):
2060
+ self.putln("__Pyx_GOTREF(%s);" % cname)
2061
+
2062
+ def put_giveref(self, cname):
2063
+ self.putln("__Pyx_GIVEREF(%s);" % cname)
2064
+
2065
+ def put_xgiveref(self, cname):
2066
+ self.putln("__Pyx_XGIVEREF(%s);" % cname)
2067
+
2068
+ def put_xgotref(self, cname):
2069
+ self.putln("__Pyx_XGOTREF(%s);" % cname)
2070
+
2071
+ def put_incref(self, cname, type, nanny=True):
2072
+ if nanny:
2073
+ self.putln("__Pyx_INCREF(%s);" % self.as_pyobject(cname, type))
2074
+ else:
2075
+ self.putln("Py_INCREF(%s);" % self.as_pyobject(cname, type))
2076
+
2077
+ def put_decref(self, cname, type, nanny=True):
2078
+ self._put_decref(cname, type, nanny, null_check=False, clear=False)
2079
+
2080
+ def put_var_gotref(self, entry):
2081
+ if entry.type.is_pyobject:
2082
+ self.putln("__Pyx_GOTREF(%s);" % self.entry_as_pyobject(entry))
2083
+
2084
+ def put_var_giveref(self, entry):
2085
+ if entry.type.is_pyobject:
2086
+ self.putln("__Pyx_GIVEREF(%s);" % self.entry_as_pyobject(entry))
2087
+
2088
+ def put_var_xgotref(self, entry):
2089
+ if entry.type.is_pyobject:
2090
+ self.putln("__Pyx_XGOTREF(%s);" % self.entry_as_pyobject(entry))
2091
+
2092
+ def put_var_xgiveref(self, entry):
2093
+ if entry.type.is_pyobject:
2094
+ self.putln("__Pyx_XGIVEREF(%s);" % self.entry_as_pyobject(entry))
2095
+
2096
+ def put_var_incref(self, entry, nanny=True):
2097
+ if entry.type.is_pyobject:
2098
+ if nanny:
2099
+ self.putln("__Pyx_INCREF(%s);" % self.entry_as_pyobject(entry))
2100
+ else:
2101
+ self.putln("Py_INCREF(%s);" % self.entry_as_pyobject(entry))
2102
+
2103
+ def put_var_xincref(self, entry):
2104
+ if entry.type.is_pyobject:
2105
+ self.putln("__Pyx_XINCREF(%s);" % self.entry_as_pyobject(entry))
2106
+
2107
+ def put_decref_clear(self, cname, type, nanny=True, clear_before_decref=False):
2108
+ self._put_decref(cname, type, nanny, null_check=False,
2109
+ clear=True, clear_before_decref=clear_before_decref)
2110
+
2111
+ def put_xdecref(self, cname, type, nanny=True, have_gil=True):
2112
+ self._put_decref(cname, type, nanny, null_check=True,
2113
+ have_gil=have_gil, clear=False)
2114
+
2115
+ def put_xdecref_clear(self, cname, type, nanny=True, clear_before_decref=False):
2116
+ self._put_decref(cname, type, nanny, null_check=True,
2117
+ clear=True, clear_before_decref=clear_before_decref)
2118
+
2119
+ def _put_decref(self, cname, type, nanny=True, null_check=False,
2120
+ have_gil=True, clear=False, clear_before_decref=False):
2121
+ if type.is_memoryviewslice:
2122
+ self.put_xdecref_memoryviewslice(cname, have_gil=have_gil)
2123
+ return
2124
+
2125
+ prefix = '__Pyx' if nanny else 'Py'
2126
+ X = 'X' if null_check else ''
2127
+
2128
+ if clear:
2129
+ if clear_before_decref:
2130
+ if not nanny:
2131
+ X = '' # CPython doesn't have a Py_XCLEAR()
2132
+ self.putln("%s_%sCLEAR(%s);" % (prefix, X, cname))
2133
+ else:
2134
+ self.putln("%s_%sDECREF(%s); %s = 0;" % (
2135
+ prefix, X, self.as_pyobject(cname, type), cname))
2136
+ else:
2137
+ self.putln("%s_%sDECREF(%s);" % (
2138
+ prefix, X, self.as_pyobject(cname, type)))
2139
+
2140
+ def put_decref_set(self, cname, rhs_cname):
2141
+ self.putln("__Pyx_DECREF_SET(%s, %s);" % (cname, rhs_cname))
2142
+
2143
+ def put_xdecref_set(self, cname, rhs_cname):
2144
+ self.putln("__Pyx_XDECREF_SET(%s, %s);" % (cname, rhs_cname))
2145
+
2146
+ def put_var_decref(self, entry):
2147
+ if entry.type.is_pyobject:
2148
+ self.putln("__Pyx_XDECREF(%s);" % self.entry_as_pyobject(entry))
2149
+
2150
+ def put_var_xdecref(self, entry, nanny=True):
2151
+ if entry.type.is_pyobject:
2152
+ if nanny:
2153
+ self.putln("__Pyx_XDECREF(%s);" % self.entry_as_pyobject(entry))
2154
+ else:
2155
+ self.putln("Py_XDECREF(%s);" % self.entry_as_pyobject(entry))
2156
+
2157
+ def put_var_decref_clear(self, entry):
2158
+ self._put_var_decref_clear(entry, null_check=False)
2159
+
2160
+ def put_var_xdecref_clear(self, entry):
2161
+ self._put_var_decref_clear(entry, null_check=True)
2162
+
2163
+ def _put_var_decref_clear(self, entry, null_check):
2164
+ if entry.type.is_pyobject:
2165
+ if entry.in_closure:
2166
+ # reset before DECREF to make sure closure state is
2167
+ # consistent during call to DECREF()
2168
+ self.putln("__Pyx_%sCLEAR(%s);" % (
2169
+ null_check and 'X' or '',
2170
+ entry.cname))
2171
+ else:
2172
+ self.putln("__Pyx_%sDECREF(%s); %s = 0;" % (
2173
+ null_check and 'X' or '',
2174
+ self.entry_as_pyobject(entry),
2175
+ entry.cname))
2176
+
2177
+ def put_var_decrefs(self, entries, used_only = 0):
2178
+ for entry in entries:
2179
+ if not used_only or entry.used:
2180
+ if entry.xdecref_cleanup:
2181
+ self.put_var_xdecref(entry)
2182
+ else:
2183
+ self.put_var_decref(entry)
2184
+
2185
+ def put_var_xdecrefs(self, entries):
2186
+ for entry in entries:
2187
+ self.put_var_xdecref(entry)
2188
+
2189
+ def put_var_xdecrefs_clear(self, entries):
2190
+ for entry in entries:
2191
+ self.put_var_xdecref_clear(entry)
2192
+
2193
+ def put_incref_memoryviewslice(self, slice_cname, have_gil=False):
2194
+ from . import MemoryView
2195
+ self.globalstate.use_utility_code(MemoryView.memviewslice_init_code)
2196
+ self.putln("__PYX_INC_MEMVIEW(&%s, %d);" % (slice_cname, int(have_gil)))
2197
+
2198
+ def put_xdecref_memoryviewslice(self, slice_cname, have_gil=False):
2199
+ from . import MemoryView
2200
+ self.globalstate.use_utility_code(MemoryView.memviewslice_init_code)
2201
+ self.putln("__PYX_XDEC_MEMVIEW(&%s, %d);" % (slice_cname, int(have_gil)))
2202
+
2203
+ def put_xgiveref_memoryviewslice(self, slice_cname):
2204
+ self.put_xgiveref("%s.memview" % slice_cname)
2205
+
2206
+ def put_init_to_py_none(self, cname, type, nanny=True):
2207
+ from .PyrexTypes import py_object_type, typecast
2208
+ py_none = typecast(type, py_object_type, "Py_None")
2209
+ if nanny:
2210
+ self.putln("%s = %s; __Pyx_INCREF(Py_None);" % (cname, py_none))
2211
+ else:
2212
+ self.putln("%s = %s; Py_INCREF(Py_None);" % (cname, py_none))
2213
+
2214
+ def put_init_var_to_py_none(self, entry, template = "%s", nanny=True):
2215
+ code = template % entry.cname
2216
+ #if entry.type.is_extension_type:
2217
+ # code = "((PyObject*)%s)" % code
2218
+ self.put_init_to_py_none(code, entry.type, nanny)
2219
+ if entry.in_closure:
2220
+ self.put_giveref('Py_None')
2221
+
2222
+ def put_pymethoddef(self, entry, term, allow_skip=True, wrapper_code_writer=None):
2223
+ if entry.is_special or entry.name == '__getattribute__':
2224
+ if entry.name not in special_py_methods:
2225
+ if entry.name == '__getattr__' and not self.globalstate.directives['fast_getattr']:
2226
+ pass
2227
+ # Python's typeobject.c will automatically fill in our slot
2228
+ # in add_operators() (called by PyType_Ready) with a value
2229
+ # that's better than ours.
2230
+ elif allow_skip:
2231
+ return
2232
+
2233
+ method_flags = entry.signature.method_flags()
2234
+ if not method_flags:
2235
+ return
2236
+ from . import TypeSlots
2237
+ if entry.is_special or TypeSlots.is_reverse_number_slot(entry.name):
2238
+ method_flags += [TypeSlots.method_coexist]
2239
+ func_ptr = wrapper_code_writer.put_pymethoddef_wrapper(entry) if wrapper_code_writer else entry.func_cname
2240
+ # Add required casts, but try not to shadow real warnings.
2241
+ cast = '__Pyx_PyCFunctionFast' if 'METH_FASTCALL' in method_flags else 'PyCFunction'
2242
+ if 'METH_KEYWORDS' in method_flags:
2243
+ cast += 'WithKeywords'
2244
+ if cast != 'PyCFunction':
2245
+ func_ptr = '(void*)(%s)%s' % (cast, func_ptr)
2246
+ self.putln(
2247
+ '{"%s", (PyCFunction)%s, %s, %s}%s' % (
2248
+ entry.name,
2249
+ func_ptr,
2250
+ "|".join(method_flags),
2251
+ entry.doc_cname if entry.doc else '0',
2252
+ term))
2253
+
2254
+ def put_pymethoddef_wrapper(self, entry):
2255
+ func_cname = entry.func_cname
2256
+ if entry.is_special:
2257
+ method_flags = entry.signature.method_flags()
2258
+ if method_flags and 'METH_NOARGS' in method_flags:
2259
+ # Special NOARGS methods really take no arguments besides 'self', but PyCFunction expects one.
2260
+ func_cname = Naming.method_wrapper_prefix + func_cname
2261
+ self.putln("static PyObject *%s(PyObject *self, CYTHON_UNUSED PyObject *arg) {return %s(self);}" % (
2262
+ func_cname, entry.func_cname))
2263
+ return func_cname
2264
+
2265
+ # GIL methods
2266
+
2267
+ def put_ensure_gil(self, declare_gilstate=True, variable=None):
2268
+ """
2269
+ Acquire the GIL. The generated code is safe even when no PyThreadState
2270
+ has been allocated for this thread (for threads not initialized by
2271
+ using the Python API). Additionally, the code generated by this method
2272
+ may be called recursively.
2273
+ """
2274
+ self.globalstate.use_utility_code(
2275
+ UtilityCode.load_cached("ForceInitThreads", "ModuleSetupCode.c"))
2276
+ if self.globalstate.directives['fast_gil']:
2277
+ self.globalstate.use_utility_code(UtilityCode.load_cached("FastGil", "ModuleSetupCode.c"))
2278
+ else:
2279
+ self.globalstate.use_utility_code(UtilityCode.load_cached("NoFastGil", "ModuleSetupCode.c"))
2280
+ self.putln("#ifdef WITH_THREAD")
2281
+ if not variable:
2282
+ variable = '__pyx_gilstate_save'
2283
+ if declare_gilstate:
2284
+ self.put("PyGILState_STATE ")
2285
+ self.putln("%s = __Pyx_PyGILState_Ensure();" % variable)
2286
+ self.putln("#endif")
2287
+
2288
+ def put_release_ensured_gil(self, variable=None):
2289
+ """
2290
+ Releases the GIL, corresponds to `put_ensure_gil`.
2291
+ """
2292
+ if self.globalstate.directives['fast_gil']:
2293
+ self.globalstate.use_utility_code(UtilityCode.load_cached("FastGil", "ModuleSetupCode.c"))
2294
+ else:
2295
+ self.globalstate.use_utility_code(UtilityCode.load_cached("NoFastGil", "ModuleSetupCode.c"))
2296
+ if not variable:
2297
+ variable = '__pyx_gilstate_save'
2298
+ self.putln("#ifdef WITH_THREAD")
2299
+ self.putln("__Pyx_PyGILState_Release(%s);" % variable)
2300
+ self.putln("#endif")
2301
+
2302
+ def put_acquire_gil(self, variable=None):
2303
+ """
2304
+ Acquire the GIL. The thread's thread state must have been initialized
2305
+ by a previous `put_release_gil`
2306
+ """
2307
+ if self.globalstate.directives['fast_gil']:
2308
+ self.globalstate.use_utility_code(UtilityCode.load_cached("FastGil", "ModuleSetupCode.c"))
2309
+ else:
2310
+ self.globalstate.use_utility_code(UtilityCode.load_cached("NoFastGil", "ModuleSetupCode.c"))
2311
+ self.putln("#ifdef WITH_THREAD")
2312
+ self.putln("__Pyx_FastGIL_Forget();")
2313
+ if variable:
2314
+ self.putln('_save = %s;' % variable)
2315
+ self.putln("Py_BLOCK_THREADS")
2316
+ self.putln("#endif")
2317
+
2318
+ def put_release_gil(self, variable=None):
2319
+ "Release the GIL, corresponds to `put_acquire_gil`."
2320
+ if self.globalstate.directives['fast_gil']:
2321
+ self.globalstate.use_utility_code(UtilityCode.load_cached("FastGil", "ModuleSetupCode.c"))
2322
+ else:
2323
+ self.globalstate.use_utility_code(UtilityCode.load_cached("NoFastGil", "ModuleSetupCode.c"))
2324
+ self.putln("#ifdef WITH_THREAD")
2325
+ self.putln("PyThreadState *_save;")
2326
+ self.putln("Py_UNBLOCK_THREADS")
2327
+ if variable:
2328
+ self.putln('%s = _save;' % variable)
2329
+ self.putln("__Pyx_FastGIL_Remember();")
2330
+ self.putln("#endif")
2331
+
2332
+ def declare_gilstate(self):
2333
+ self.putln("#ifdef WITH_THREAD")
2334
+ self.putln("PyGILState_STATE __pyx_gilstate_save;")
2335
+ self.putln("#endif")
2336
+
2337
+ # error handling
2338
+
2339
+ def put_error_if_neg(self, pos, value):
2340
+ # TODO this path is almost _never_ taken, yet this macro makes is slower!
2341
+ # return self.putln("if (unlikely(%s < 0)) %s" % (value, self.error_goto(pos)))
2342
+ return self.putln("if (%s < 0) %s" % (value, self.error_goto(pos)))
2343
+
2344
+ def put_error_if_unbound(self, pos, entry, in_nogil_context=False):
2345
+ from . import ExprNodes
2346
+ if entry.from_closure:
2347
+ func = '__Pyx_RaiseClosureNameError'
2348
+ self.globalstate.use_utility_code(
2349
+ ExprNodes.raise_closure_name_error_utility_code)
2350
+ elif entry.type.is_memoryviewslice and in_nogil_context:
2351
+ func = '__Pyx_RaiseUnboundMemoryviewSliceNogil'
2352
+ self.globalstate.use_utility_code(
2353
+ ExprNodes.raise_unbound_memoryview_utility_code_nogil)
2354
+ else:
2355
+ func = '__Pyx_RaiseUnboundLocalError'
2356
+ self.globalstate.use_utility_code(
2357
+ ExprNodes.raise_unbound_local_error_utility_code)
2358
+
2359
+ self.putln('if (unlikely(!%s)) { %s("%s"); %s }' % (
2360
+ entry.type.check_for_null_code(entry.cname),
2361
+ func,
2362
+ entry.name,
2363
+ self.error_goto(pos)))
2364
+
2365
+ def set_error_info(self, pos, used=False):
2366
+ self.funcstate.should_declare_error_indicator = True
2367
+ if used:
2368
+ self.funcstate.uses_error_indicator = True
2369
+ return "__PYX_MARK_ERR_POS(%s, %s)" % (
2370
+ self.lookup_filename(pos[0]),
2371
+ pos[1])
2372
+
2373
+ def error_goto(self, pos, used=True):
2374
+ lbl = self.funcstate.error_label
2375
+ self.funcstate.use_label(lbl)
2376
+ if pos is None:
2377
+ return 'goto %s;' % lbl
2378
+ self.funcstate.should_declare_error_indicator = True
2379
+ if used:
2380
+ self.funcstate.uses_error_indicator = True
2381
+ return "__PYX_ERR(%s, %s, %s)" % (
2382
+ self.lookup_filename(pos[0]),
2383
+ pos[1],
2384
+ lbl)
2385
+
2386
+ def error_goto_if(self, cond, pos):
2387
+ return "if (%s) %s" % (self.unlikely(cond), self.error_goto(pos))
2388
+
2389
+ def error_goto_if_null(self, cname, pos):
2390
+ return self.error_goto_if("!%s" % cname, pos)
2391
+
2392
+ def error_goto_if_neg(self, cname, pos):
2393
+ return self.error_goto_if("%s < 0" % cname, pos)
2394
+
2395
+ def error_goto_if_PyErr(self, pos):
2396
+ return self.error_goto_if("PyErr_Occurred()", pos)
2397
+
2398
+ def lookup_filename(self, filename):
2399
+ return self.globalstate.lookup_filename(filename)
2400
+
2401
+ def put_declare_refcount_context(self):
2402
+ self.putln('__Pyx_RefNannyDeclarations')
2403
+
2404
+ def put_setup_refcount_context(self, name, acquire_gil=False):
2405
+ if acquire_gil:
2406
+ self.globalstate.use_utility_code(
2407
+ UtilityCode.load_cached("ForceInitThreads", "ModuleSetupCode.c"))
2408
+ self.putln('__Pyx_RefNannySetupContext("%s", %d);' % (name, acquire_gil and 1 or 0))
2409
+
2410
+ def put_finish_refcount_context(self):
2411
+ self.putln("__Pyx_RefNannyFinishContext();")
2412
+
2413
+ def put_add_traceback(self, qualified_name, include_cline=True):
2414
+ """
2415
+ Build a Python traceback for propagating exceptions.
2416
+
2417
+ qualified_name should be the qualified name of the function.
2418
+ """
2419
+ format_tuple = (
2420
+ qualified_name,
2421
+ Naming.clineno_cname if include_cline else 0,
2422
+ Naming.lineno_cname,
2423
+ Naming.filename_cname,
2424
+ )
2425
+ self.funcstate.uses_error_indicator = True
2426
+ self.putln('__Pyx_AddTraceback("%s", %s, %s, %s);' % format_tuple)
2427
+
2428
+ def put_unraisable(self, qualified_name, nogil=False):
2429
+ """
2430
+ Generate code to print a Python warning for an unraisable exception.
2431
+
2432
+ qualified_name should be the qualified name of the function.
2433
+ """
2434
+ format_tuple = (
2435
+ qualified_name,
2436
+ Naming.clineno_cname,
2437
+ Naming.lineno_cname,
2438
+ Naming.filename_cname,
2439
+ self.globalstate.directives['unraisable_tracebacks'],
2440
+ nogil,
2441
+ )
2442
+ self.funcstate.uses_error_indicator = True
2443
+ self.putln('__Pyx_WriteUnraisable("%s", %s, %s, %s, %d, %d);' % format_tuple)
2444
+ self.globalstate.use_utility_code(
2445
+ UtilityCode.load_cached("WriteUnraisableException", "Exceptions.c"))
2446
+
2447
+ def put_trace_declarations(self):
2448
+ self.putln('__Pyx_TraceDeclarations')
2449
+
2450
+ def put_trace_frame_init(self, codeobj=None):
2451
+ if codeobj:
2452
+ self.putln('__Pyx_TraceFrameInit(%s)' % codeobj)
2453
+
2454
+ def put_trace_call(self, name, pos, nogil=False):
2455
+ self.putln('__Pyx_TraceCall("%s", %s[%s], %s, %d, %s);' % (
2456
+ name, Naming.filetable_cname, self.lookup_filename(pos[0]), pos[1], nogil, self.error_goto(pos)))
2457
+
2458
+ def put_trace_exception(self):
2459
+ self.putln("__Pyx_TraceException();")
2460
+
2461
+ def put_trace_return(self, retvalue_cname, nogil=False):
2462
+ self.putln("__Pyx_TraceReturn(%s, %d);" % (retvalue_cname, nogil))
2463
+
2464
+ def putln_openmp(self, string):
2465
+ self.putln("#ifdef _OPENMP")
2466
+ self.putln(string)
2467
+ self.putln("#endif /* _OPENMP */")
2468
+
2469
+ def undef_builtin_expect(self, cond):
2470
+ """
2471
+ Redefine the macros likely() and unlikely to no-ops, depending on
2472
+ condition 'cond'
2473
+ """
2474
+ self.putln("#if %s" % cond)
2475
+ self.putln(" #undef likely")
2476
+ self.putln(" #undef unlikely")
2477
+ self.putln(" #define likely(x) (x)")
2478
+ self.putln(" #define unlikely(x) (x)")
2479
+ self.putln("#endif")
2480
+
2481
+ def redef_builtin_expect(self, cond):
2482
+ self.putln("#if %s" % cond)
2483
+ self.putln(" #undef likely")
2484
+ self.putln(" #undef unlikely")
2485
+ self.putln(" #define likely(x) __builtin_expect(!!(x), 1)")
2486
+ self.putln(" #define unlikely(x) __builtin_expect(!!(x), 0)")
2487
+ self.putln("#endif")
2488
+
2489
+
2490
+ class PyrexCodeWriter(object):
2491
+ # f file output file
2492
+ # level int indentation level
2493
+
2494
+ def __init__(self, outfile_name):
2495
+ self.f = Utils.open_new_file(outfile_name)
2496
+ self.level = 0
2497
+
2498
+ def putln(self, code):
2499
+ self.f.write("%s%s\n" % (" " * self.level, code))
2500
+
2501
+ def indent(self):
2502
+ self.level += 1
2503
+
2504
+ def dedent(self):
2505
+ self.level -= 1
2506
+
2507
+ class PyxCodeWriter(object):
2508
+ """
2509
+ Can be used for writing out some Cython code. To use the indenter
2510
+ functionality, the Cython.Compiler.Importer module will have to be used
2511
+ to load the code to support python 2.4
2512
+ """
2513
+
2514
+ def __init__(self, buffer=None, indent_level=0, context=None, encoding='ascii'):
2515
+ self.buffer = buffer or StringIOTree()
2516
+ self.level = indent_level
2517
+ self.context = context
2518
+ self.encoding = encoding
2519
+
2520
+ def indent(self, levels=1):
2521
+ self.level += levels
2522
+ return True
2523
+
2524
+ def dedent(self, levels=1):
2525
+ self.level -= levels
2526
+
2527
+ def indenter(self, line):
2528
+ """
2529
+ Instead of
2530
+
2531
+ with pyx_code.indenter("for i in range(10):"):
2532
+ pyx_code.putln("print i")
2533
+
2534
+ write
2535
+
2536
+ if pyx_code.indenter("for i in range(10);"):
2537
+ pyx_code.putln("print i")
2538
+ pyx_code.dedent()
2539
+ """
2540
+ self.putln(line)
2541
+ self.indent()
2542
+ return True
2543
+
2544
+ def getvalue(self):
2545
+ result = self.buffer.getvalue()
2546
+ if isinstance(result, bytes):
2547
+ result = result.decode(self.encoding)
2548
+ return result
2549
+
2550
+ def putln(self, line, context=None):
2551
+ context = context or self.context
2552
+ if context:
2553
+ line = sub_tempita(line, context)
2554
+ self._putln(line)
2555
+
2556
+ def _putln(self, line):
2557
+ self.buffer.write("%s%s\n" % (self.level * " ", line))
2558
+
2559
+ def put_chunk(self, chunk, context=None):
2560
+ context = context or self.context
2561
+ if context:
2562
+ chunk = sub_tempita(chunk, context)
2563
+
2564
+ chunk = textwrap.dedent(chunk)
2565
+ for line in chunk.splitlines():
2566
+ self._putln(line)
2567
+
2568
+ def insertion_point(self):
2569
+ return PyxCodeWriter(self.buffer.insertion_point(), self.level,
2570
+ self.context)
2571
+
2572
+ def named_insertion_point(self, name):
2573
+ setattr(self, name, self.insertion_point())
2574
+
2575
+
2576
+ class ClosureTempAllocator(object):
2577
+ def __init__(self, klass):
2578
+ self.klass = klass
2579
+ self.temps_allocated = {}
2580
+ self.temps_free = {}
2581
+ self.temps_count = 0
2582
+
2583
+ def reset(self):
2584
+ for type, cnames in self.temps_allocated.items():
2585
+ self.temps_free[type] = list(cnames)
2586
+
2587
+ def allocate_temp(self, type):
2588
+ if type not in self.temps_allocated:
2589
+ self.temps_allocated[type] = []
2590
+ self.temps_free[type] = []
2591
+ elif self.temps_free[type]:
2592
+ return self.temps_free[type].pop(0)
2593
+ cname = '%s%d' % (Naming.codewriter_temp_prefix, self.temps_count)
2594
+ self.klass.declare_var(pos=None, name=cname, cname=cname, type=type, is_cdef=True)
2595
+ self.temps_allocated[type].append(cname)
2596
+ self.temps_count += 1
2597
+ return cname
venv/Lib/site-packages/Cython/Compiler/CodeGeneration.py ADDED
@@ -0,0 +1,35 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from __future__ import absolute_import
2
+
3
+ from .Visitor import VisitorTransform
4
+ from .Nodes import StatListNode
5
+
6
+
7
+ class ExtractPxdCode(VisitorTransform):
8
+ """
9
+ Finds nodes in a pxd file that should generate code, and
10
+ returns them in a StatListNode.
11
+
12
+ The result is a tuple (StatListNode, ModuleScope), i.e.
13
+ everything that is needed from the pxd after it is processed.
14
+
15
+ A purer approach would be to separately compile the pxd code,
16
+ but the result would have to be slightly more sophisticated
17
+ than pure strings (functions + wanted interned strings +
18
+ wanted utility code + wanted cached objects) so for now this
19
+ approach is taken.
20
+ """
21
+
22
+ def __call__(self, root):
23
+ self.funcs = []
24
+ self.visitchildren(root)
25
+ return (StatListNode(root.pos, stats=self.funcs), root.scope)
26
+
27
+ def visit_FuncDefNode(self, node):
28
+ self.funcs.append(node)
29
+ # Do not visit children, nested funcdefnodes will
30
+ # also be moved by this action...
31
+ return node
32
+
33
+ def visit_Node(self, node):
34
+ self.visitchildren(node)
35
+ return node
venv/Lib/site-packages/Cython/Compiler/CythonScope.py ADDED
@@ -0,0 +1,164 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from __future__ import absolute_import
2
+
3
+ from .Symtab import ModuleScope
4
+ from .PyrexTypes import *
5
+ from .UtilityCode import CythonUtilityCode
6
+ from .Errors import error
7
+ from .Scanning import StringSourceDescriptor
8
+ from . import MemoryView
9
+
10
+
11
+ class CythonScope(ModuleScope):
12
+ is_cython_builtin = 1
13
+ _cythonscope_initialized = False
14
+
15
+ def __init__(self, context):
16
+ ModuleScope.__init__(self, u'cython', None, None)
17
+ self.pxd_file_loaded = True
18
+ self.populate_cython_scope()
19
+ # The Main.Context object
20
+ self.context = context
21
+
22
+ for fused_type in (cy_integral_type, cy_floating_type, cy_numeric_type):
23
+ entry = self.declare_typedef(fused_type.name,
24
+ fused_type,
25
+ None,
26
+ cname='<error>')
27
+ entry.in_cinclude = True
28
+
29
+ def is_cpp(self):
30
+ # Allow C++ utility code in C++ contexts.
31
+ return self.context.cpp
32
+
33
+ def lookup_type(self, name):
34
+ # This function should go away when types are all first-level objects.
35
+ type = parse_basic_type(name)
36
+ if type:
37
+ return type
38
+
39
+ return super(CythonScope, self).lookup_type(name)
40
+
41
+ def lookup(self, name):
42
+ entry = super(CythonScope, self).lookup(name)
43
+
44
+ if entry is None and not self._cythonscope_initialized:
45
+ self.load_cythonscope()
46
+ entry = super(CythonScope, self).lookup(name)
47
+
48
+ return entry
49
+
50
+ def find_module(self, module_name, pos):
51
+ error("cython.%s is not available" % module_name, pos)
52
+
53
+ def find_submodule(self, module_name):
54
+ entry = self.entries.get(module_name, None)
55
+ if not entry:
56
+ self.load_cythonscope()
57
+ entry = self.entries.get(module_name, None)
58
+
59
+ if entry and entry.as_module:
60
+ return entry.as_module
61
+ else:
62
+ # TODO: fix find_submodule control flow so that we're not
63
+ # expected to create a submodule here (to protect CythonScope's
64
+ # possible immutability). Hack ourselves out of the situation
65
+ # for now.
66
+ raise error((StringSourceDescriptor(u"cython", u""), 0, 0),
67
+ "cython.%s is not available" % module_name)
68
+
69
+ def lookup_qualified_name(self, qname):
70
+ # ExprNode.as_cython_attribute generates qnames and we untangle it here...
71
+ name_path = qname.split(u'.')
72
+ scope = self
73
+ while len(name_path) > 1:
74
+ scope = scope.lookup_here(name_path[0])
75
+ if scope:
76
+ scope = scope.as_module
77
+ del name_path[0]
78
+ if scope is None:
79
+ return None
80
+ else:
81
+ return scope.lookup_here(name_path[0])
82
+
83
+ def populate_cython_scope(self):
84
+ # These are used to optimize isinstance in FinalOptimizePhase
85
+ type_object = self.declare_typedef(
86
+ 'PyTypeObject',
87
+ base_type = c_void_type,
88
+ pos = None,
89
+ cname = 'PyTypeObject')
90
+ type_object.is_void = True
91
+ type_object_type = type_object.type
92
+
93
+ self.declare_cfunction(
94
+ 'PyObject_TypeCheck',
95
+ CFuncType(c_bint_type, [CFuncTypeArg("o", py_object_type, None),
96
+ CFuncTypeArg("t", c_ptr_type(type_object_type), None)]),
97
+ pos = None,
98
+ defining = 1,
99
+ cname = 'PyObject_TypeCheck')
100
+
101
+ def load_cythonscope(self):
102
+ """
103
+ Creates some entries for testing purposes and entries for
104
+ cython.array() and for cython.view.*.
105
+ """
106
+ if self._cythonscope_initialized:
107
+ return
108
+
109
+ self._cythonscope_initialized = True
110
+ cython_testscope_utility_code.declare_in_scope(
111
+ self, cython_scope=self)
112
+ cython_test_extclass_utility_code.declare_in_scope(
113
+ self, cython_scope=self)
114
+
115
+ #
116
+ # The view sub-scope
117
+ #
118
+ self.viewscope = viewscope = ModuleScope(u'view', self, None)
119
+ self.declare_module('view', viewscope, None).as_module = viewscope
120
+ viewscope.is_cython_builtin = True
121
+ viewscope.pxd_file_loaded = True
122
+
123
+ cythonview_testscope_utility_code.declare_in_scope(
124
+ viewscope, cython_scope=self)
125
+
126
+ view_utility_scope = MemoryView.view_utility_code.declare_in_scope(
127
+ self.viewscope, cython_scope=self,
128
+ whitelist=MemoryView.view_utility_whitelist)
129
+
130
+ # self.entries["array"] = view_utility_scope.entries.pop("array")
131
+
132
+
133
+ def create_cython_scope(context):
134
+ # One could in fact probably make it a singleton,
135
+ # but not sure yet whether any code mutates it (which would kill reusing
136
+ # it across different contexts)
137
+ return CythonScope(context)
138
+
139
+ # Load test utilities for the cython scope
140
+
141
+ def load_testscope_utility(cy_util_name, **kwargs):
142
+ return CythonUtilityCode.load(cy_util_name, "TestCythonScope.pyx", **kwargs)
143
+
144
+
145
+ undecorated_methods_protos = UtilityCode(proto=u"""
146
+ /* These methods are undecorated and have therefore no prototype */
147
+ static PyObject *__pyx_TestClass_cdef_method(
148
+ struct __pyx_TestClass_obj *self, int value);
149
+ static PyObject *__pyx_TestClass_cpdef_method(
150
+ struct __pyx_TestClass_obj *self, int value, int skip_dispatch);
151
+ static PyObject *__pyx_TestClass_def_method(
152
+ PyObject *self, PyObject *value);
153
+ """)
154
+
155
+ cython_testscope_utility_code = load_testscope_utility("TestScope")
156
+
157
+ test_cython_utility_dep = load_testscope_utility("TestDep")
158
+
159
+ cython_test_extclass_utility_code = \
160
+ load_testscope_utility("TestClass", name="TestClass",
161
+ requires=[undecorated_methods_protos,
162
+ test_cython_utility_dep])
163
+
164
+ cythonview_testscope_utility_code = load_testscope_utility("View.TestScope")
venv/Lib/site-packages/Cython/Compiler/DebugFlags.py ADDED
@@ -0,0 +1,21 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Can be enabled at the command line with --debug-xxx.
2
+
3
+ debug_disposal_code = 0
4
+ debug_temp_alloc = 0
5
+ debug_coercion = 0
6
+
7
+ # Write comments into the C code that show where temporary variables
8
+ # are allocated and released.
9
+ debug_temp_code_comments = 0
10
+
11
+ # Write a call trace of the code generation phase into the C code.
12
+ debug_trace_code_generation = 0
13
+
14
+ # Do not replace exceptions with user-friendly error messages.
15
+ debug_no_exception_intercept = 0
16
+
17
+ # Print a message each time a new stage in the pipeline is entered.
18
+ debug_verbose_pipeline = 0
19
+
20
+ # Raise an exception when an error is encountered.
21
+ debug_exception_on_error = 0
venv/Lib/site-packages/Cython/Compiler/Errors.py ADDED
@@ -0,0 +1,265 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #
2
+ # Errors
3
+ #
4
+
5
+ from __future__ import absolute_import
6
+
7
+ try:
8
+ from __builtin__ import basestring as any_string_type
9
+ except ImportError:
10
+ any_string_type = (bytes, str)
11
+
12
+ import sys
13
+ from contextlib import contextmanager
14
+
15
+ from ..Utils import open_new_file
16
+ from . import DebugFlags
17
+ from . import Options
18
+
19
+
20
+ class PyrexError(Exception):
21
+ pass
22
+
23
+
24
+ class PyrexWarning(Exception):
25
+ pass
26
+
27
+
28
+ def context(position):
29
+ source = position[0]
30
+ assert not (isinstance(source, any_string_type)), (
31
+ "Please replace filename strings with Scanning.FileSourceDescriptor instances %r" % source)
32
+ try:
33
+ F = source.get_lines()
34
+ except UnicodeDecodeError:
35
+ # file has an encoding problem
36
+ s = u"[unprintable code]\n"
37
+ else:
38
+ s = u''.join(F[max(0, position[1]-6):position[1]])
39
+ s = u'...\n%s%s^\n' % (s, u' '*(position[2]-1))
40
+ s = u'%s\n%s%s\n' % (u'-'*60, s, u'-'*60)
41
+ return s
42
+
43
+ def format_position(position):
44
+ if position:
45
+ return u"%s:%d:%d: " % (position[0].get_error_description(),
46
+ position[1], position[2])
47
+ return u''
48
+
49
+ def format_error(message, position):
50
+ if position:
51
+ pos_str = format_position(position)
52
+ cont = context(position)
53
+ message = u'\nError compiling Cython file:\n%s\n%s%s' % (cont, pos_str, message or u'')
54
+ return message
55
+
56
+ class CompileError(PyrexError):
57
+
58
+ def __init__(self, position = None, message = u""):
59
+ self.position = position
60
+ self.message_only = message
61
+ self.formatted_message = format_error(message, position)
62
+ self.reported = False
63
+ # Deprecated and withdrawn in 2.6:
64
+ # self.message = message
65
+ Exception.__init__(self, self.formatted_message)
66
+ # Python Exception subclass pickling is broken,
67
+ # see http://bugs.python.org/issue1692335
68
+ self.args = (position, message)
69
+
70
+ def __str__(self):
71
+ return self.formatted_message
72
+
73
+ class CompileWarning(PyrexWarning):
74
+
75
+ def __init__(self, position = None, message = ""):
76
+ self.position = position
77
+ # Deprecated and withdrawn in 2.6:
78
+ # self.message = message
79
+ Exception.__init__(self, format_position(position) + message)
80
+
81
+ class InternalError(Exception):
82
+ # If this is ever raised, there is a bug in the compiler.
83
+
84
+ def __init__(self, message):
85
+ self.message_only = message
86
+ Exception.__init__(self, u"Internal compiler error: %s"
87
+ % message)
88
+
89
+ class AbortError(Exception):
90
+ # Throw this to stop the compilation immediately.
91
+
92
+ def __init__(self, message):
93
+ self.message_only = message
94
+ Exception.__init__(self, u"Abort error: %s" % message)
95
+
96
+ class CompilerCrash(CompileError):
97
+ # raised when an unexpected exception occurs in a transform
98
+ def __init__(self, pos, context, message, cause, stacktrace=None):
99
+ if message:
100
+ message = u'\n' + message
101
+ else:
102
+ message = u'\n'
103
+ self.message_only = message
104
+ if context:
105
+ message = u"Compiler crash in %s%s" % (context, message)
106
+ if stacktrace:
107
+ import traceback
108
+ message += (
109
+ u'\n\nCompiler crash traceback from this point on:\n' +
110
+ u''.join(traceback.format_tb(stacktrace)))
111
+ if cause:
112
+ if not stacktrace:
113
+ message += u'\n'
114
+ message += u'%s: %s' % (cause.__class__.__name__, cause)
115
+ CompileError.__init__(self, pos, message)
116
+ # Python Exception subclass pickling is broken,
117
+ # see http://bugs.python.org/issue1692335
118
+ self.args = (pos, context, message, cause, stacktrace)
119
+
120
+ class NoElementTreeInstalledException(PyrexError):
121
+ """raised when the user enabled options.gdb_debug but no ElementTree
122
+ implementation was found
123
+ """
124
+
125
+ listing_file = None
126
+ num_errors = 0
127
+ echo_file = None
128
+
129
+ def open_listing_file(path, echo_to_stderr = 1):
130
+ # Begin a new error listing. If path is None, no file
131
+ # is opened, the error counter is just reset.
132
+ global listing_file, num_errors, echo_file
133
+ if path is not None:
134
+ listing_file = open_new_file(path)
135
+ else:
136
+ listing_file = None
137
+ if echo_to_stderr:
138
+ echo_file = sys.stderr
139
+ else:
140
+ echo_file = None
141
+ num_errors = 0
142
+
143
+ def close_listing_file():
144
+ global listing_file
145
+ if listing_file:
146
+ listing_file.close()
147
+ listing_file = None
148
+
149
+ def report_error(err, use_stack=True):
150
+ if error_stack and use_stack:
151
+ error_stack[-1].append(err)
152
+ else:
153
+ global num_errors
154
+ # See Main.py for why dual reporting occurs. Quick fix for now.
155
+ if err.reported: return
156
+ err.reported = True
157
+ try: line = u"%s\n" % err
158
+ except UnicodeEncodeError:
159
+ # Python <= 2.5 does this for non-ASCII Unicode exceptions
160
+ line = format_error(getattr(err, 'message_only', "[unprintable exception message]"),
161
+ getattr(err, 'position', None)) + u'\n'
162
+ if listing_file:
163
+ try: listing_file.write(line)
164
+ except UnicodeEncodeError:
165
+ listing_file.write(line.encode('ASCII', 'replace'))
166
+ if echo_file:
167
+ try: echo_file.write(line)
168
+ except UnicodeEncodeError:
169
+ echo_file.write(line.encode('ASCII', 'replace'))
170
+ num_errors += 1
171
+ if Options.fast_fail:
172
+ raise AbortError("fatal errors")
173
+
174
+
175
+ def error(position, message):
176
+ #print("Errors.error:", repr(position), repr(message)) ###
177
+ if position is None:
178
+ raise InternalError(message)
179
+ err = CompileError(position, message)
180
+ if DebugFlags.debug_exception_on_error: raise Exception(err) # debug
181
+ report_error(err)
182
+ return err
183
+
184
+
185
+ LEVEL = 1 # warn about all errors level 1 or higher
186
+
187
+
188
+ def message(position, message, level=1):
189
+ if level < LEVEL:
190
+ return
191
+ warn = CompileWarning(position, message)
192
+ line = "note: %s\n" % warn
193
+ if listing_file:
194
+ listing_file.write(line)
195
+ if echo_file:
196
+ echo_file.write(line)
197
+ return warn
198
+
199
+
200
+ def warning(position, message, level=0):
201
+ if level < LEVEL:
202
+ return
203
+ if Options.warning_errors and position:
204
+ return error(position, message)
205
+ warn = CompileWarning(position, message)
206
+ line = "warning: %s\n" % warn
207
+ if listing_file:
208
+ listing_file.write(line)
209
+ if echo_file:
210
+ echo_file.write(line)
211
+ return warn
212
+
213
+
214
+ _warn_once_seen = {}
215
+ def warn_once(position, message, level=0):
216
+ if level < LEVEL or message in _warn_once_seen:
217
+ return
218
+ warn = CompileWarning(position, message)
219
+ line = "warning: %s\n" % warn
220
+ if listing_file:
221
+ listing_file.write(line)
222
+ if echo_file:
223
+ echo_file.write(line)
224
+ _warn_once_seen[message] = True
225
+ return warn
226
+
227
+
228
+ # These functions can be used to momentarily suppress errors.
229
+
230
+ error_stack = []
231
+
232
+
233
+ def hold_errors():
234
+ error_stack.append([])
235
+
236
+
237
+ def release_errors(ignore=False):
238
+ held_errors = error_stack.pop()
239
+ if not ignore:
240
+ for err in held_errors:
241
+ report_error(err)
242
+
243
+
244
+ def held_errors():
245
+ return error_stack[-1]
246
+
247
+
248
+ # same as context manager:
249
+
250
+ @contextmanager
251
+ def local_errors(ignore=False):
252
+ errors = []
253
+ error_stack.append(errors)
254
+ try:
255
+ yield errors
256
+ finally:
257
+ release_errors(ignore=ignore)
258
+
259
+
260
+ # this module needs a redesign to support parallel cythonisation, but
261
+ # for now, the following works at least in sequential compiler runs
262
+
263
+ def reset():
264
+ _warn_once_seen.clear()
265
+ del error_stack[:]
venv/Lib/site-packages/Cython/Compiler/ExprNodes.py ADDED
The diff for this file is too large to render. See raw diff
 
venv/Lib/site-packages/Cython/Compiler/FlowControl.pxd ADDED
@@ -0,0 +1,111 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from __future__ import absolute_import
2
+
3
+ cimport cython
4
+
5
+ from .Visitor cimport CythonTransform, TreeVisitor
6
+
7
+ cdef class ControlBlock:
8
+ cdef public set children
9
+ cdef public set parents
10
+ cdef public set positions
11
+ cdef public list stats
12
+ cdef public dict gen
13
+ cdef public set bounded
14
+
15
+ # Big integer bitsets
16
+ cdef public object i_input
17
+ cdef public object i_output
18
+ cdef public object i_gen
19
+ cdef public object i_kill
20
+ cdef public object i_state
21
+
22
+ cpdef bint empty(self)
23
+ cpdef detach(self)
24
+ cpdef add_child(self, block)
25
+
26
+ cdef class ExitBlock(ControlBlock):
27
+ cpdef bint empty(self)
28
+
29
+ cdef class NameAssignment:
30
+ cdef public bint is_arg
31
+ cdef public bint is_deletion
32
+ cdef public object lhs
33
+ cdef public object rhs
34
+ cdef public object entry
35
+ cdef public object pos
36
+ cdef public set refs
37
+ cdef public object bit
38
+ cdef public object inferred_type
39
+
40
+ cdef class AssignmentList:
41
+ cdef public object bit
42
+ cdef public object mask
43
+ cdef public list stats
44
+
45
+ cdef class AssignmentCollector(TreeVisitor):
46
+ cdef list assignments
47
+
48
+ @cython.final
49
+ cdef class ControlFlow:
50
+ cdef public set blocks
51
+ cdef public set entries
52
+ cdef public list loops
53
+ cdef public list exceptions
54
+
55
+ cdef public ControlBlock entry_point
56
+ cdef public ExitBlock exit_point
57
+ cdef public ControlBlock block
58
+
59
+ cdef public dict assmts
60
+
61
+ cpdef newblock(self, ControlBlock parent=*)
62
+ cpdef nextblock(self, ControlBlock parent=*)
63
+ cpdef bint is_tracked(self, entry)
64
+ cpdef bint is_statically_assigned(self, entry)
65
+ cpdef mark_position(self, node)
66
+ cpdef mark_assignment(self, lhs, rhs, entry)
67
+ cpdef mark_argument(self, lhs, rhs, entry)
68
+ cpdef mark_deletion(self, node, entry)
69
+ cpdef mark_reference(self, node, entry)
70
+
71
+ @cython.locals(block=ControlBlock, parent=ControlBlock, unreachable=set)
72
+ cpdef normalize(self)
73
+
74
+ @cython.locals(bit=object, assmts=AssignmentList,
75
+ block=ControlBlock)
76
+ cpdef initialize(self)
77
+
78
+ @cython.locals(assmts=AssignmentList, assmt=NameAssignment)
79
+ cpdef set map_one(self, istate, entry)
80
+
81
+ @cython.locals(block=ControlBlock, parent=ControlBlock)
82
+ cdef reaching_definitions(self)
83
+
84
+ cdef class Uninitialized:
85
+ pass
86
+
87
+ cdef class Unknown:
88
+ pass
89
+
90
+
91
+ cdef class MessageCollection:
92
+ cdef set messages
93
+
94
+
95
+ @cython.locals(dirty=bint, block=ControlBlock, parent=ControlBlock,
96
+ assmt=NameAssignment)
97
+ cdef check_definitions(ControlFlow flow, dict compiler_directives)
98
+
99
+ @cython.final
100
+ cdef class ControlFlowAnalysis(CythonTransform):
101
+ cdef object gv_ctx
102
+ cdef object constant_folder
103
+ cdef set reductions
104
+ cdef list env_stack
105
+ cdef list stack
106
+ cdef object env
107
+ cdef ControlFlow flow
108
+ cdef bint in_inplace_assignment
109
+
110
+ cpdef mark_assignment(self, lhs, rhs=*)
111
+ cpdef mark_position(self, node)
venv/Lib/site-packages/Cython/Compiler/FlowControl.py ADDED
@@ -0,0 +1,1325 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from __future__ import absolute_import
2
+
3
+ import cython
4
+ cython.declare(PyrexTypes=object, ExprNodes=object, Nodes=object,
5
+ Builtin=object, InternalError=object, error=object, warning=object,
6
+ py_object_type=object, unspecified_type=object,
7
+ object_expr=object, fake_rhs_expr=object, TypedExprNode=object)
8
+
9
+ from . import Builtin
10
+ from . import ExprNodes
11
+ from . import Nodes
12
+ from . import Options
13
+ from .PyrexTypes import py_object_type, unspecified_type
14
+ from . import PyrexTypes
15
+
16
+ from .Visitor import TreeVisitor, CythonTransform
17
+ from .Errors import error, warning, InternalError
18
+ from .Optimize import ConstantFolding
19
+
20
+
21
+ class TypedExprNode(ExprNodes.ExprNode):
22
+ # Used for declaring assignments of a specified type without a known entry.
23
+ def __init__(self, type, may_be_none=None, pos=None):
24
+ super(TypedExprNode, self).__init__(pos)
25
+ self.type = type
26
+ self._may_be_none = may_be_none
27
+
28
+ def may_be_none(self):
29
+ return self._may_be_none != False
30
+
31
+ object_expr = TypedExprNode(py_object_type, may_be_none=True)
32
+ # Fake rhs to silence "unused variable" warning
33
+ fake_rhs_expr = TypedExprNode(unspecified_type)
34
+
35
+
36
+ class ControlBlock(object):
37
+ """Control flow graph node. Sequence of assignments and name references.
38
+
39
+ children set of children nodes
40
+ parents set of parent nodes
41
+ positions set of position markers
42
+
43
+ stats list of block statements
44
+ gen dict of assignments generated by this block
45
+ bounded set of entries that are definitely bounded in this block
46
+
47
+ Example:
48
+
49
+ a = 1
50
+ b = a + c # 'c' is already bounded or exception here
51
+
52
+ stats = [Assignment(a), NameReference(a), NameReference(c),
53
+ Assignment(b)]
54
+ gen = {Entry(a): Assignment(a), Entry(b): Assignment(b)}
55
+ bounded = set([Entry(a), Entry(c)])
56
+
57
+ """
58
+
59
+ def __init__(self):
60
+ self.children = set()
61
+ self.parents = set()
62
+ self.positions = set()
63
+
64
+ self.stats = []
65
+ self.gen = {}
66
+ self.bounded = set()
67
+
68
+ self.i_input = 0
69
+ self.i_output = 0
70
+ self.i_gen = 0
71
+ self.i_kill = 0
72
+ self.i_state = 0
73
+
74
+ def empty(self):
75
+ return (not self.stats and not self.positions)
76
+
77
+ def detach(self):
78
+ """Detach block from parents and children."""
79
+ for child in self.children:
80
+ child.parents.remove(self)
81
+ for parent in self.parents:
82
+ parent.children.remove(self)
83
+ self.parents.clear()
84
+ self.children.clear()
85
+
86
+ def add_child(self, block):
87
+ self.children.add(block)
88
+ block.parents.add(self)
89
+
90
+
91
+ class ExitBlock(ControlBlock):
92
+ """Non-empty exit point block."""
93
+
94
+ def empty(self):
95
+ return False
96
+
97
+
98
+ class AssignmentList(object):
99
+ def __init__(self):
100
+ self.stats = []
101
+
102
+
103
+ class ControlFlow(object):
104
+ """Control-flow graph.
105
+
106
+ entry_point ControlBlock entry point for this graph
107
+ exit_point ControlBlock normal exit point
108
+ block ControlBlock current block
109
+ blocks set children nodes
110
+ entries set tracked entries
111
+ loops list stack for loop descriptors
112
+ exceptions list stack for exception descriptors
113
+ """
114
+
115
+ def __init__(self):
116
+ self.blocks = set()
117
+ self.entries = set()
118
+ self.loops = []
119
+ self.exceptions = []
120
+
121
+ self.entry_point = ControlBlock()
122
+ self.exit_point = ExitBlock()
123
+ self.blocks.add(self.exit_point)
124
+ self.block = self.entry_point
125
+
126
+ def newblock(self, parent=None):
127
+ """Create floating block linked to `parent` if given.
128
+
129
+ NOTE: Block is NOT added to self.blocks
130
+ """
131
+ block = ControlBlock()
132
+ self.blocks.add(block)
133
+ if parent:
134
+ parent.add_child(block)
135
+ return block
136
+
137
+ def nextblock(self, parent=None):
138
+ """Create block children block linked to current or `parent` if given.
139
+
140
+ NOTE: Block is added to self.blocks
141
+ """
142
+ block = ControlBlock()
143
+ self.blocks.add(block)
144
+ if parent:
145
+ parent.add_child(block)
146
+ elif self.block:
147
+ self.block.add_child(block)
148
+ self.block = block
149
+ return self.block
150
+
151
+ def is_tracked(self, entry):
152
+ if entry.is_anonymous:
153
+ return False
154
+ return (entry.is_local or entry.is_pyclass_attr or entry.is_arg or
155
+ entry.from_closure or entry.in_closure or
156
+ entry.error_on_uninitialized)
157
+
158
+ def is_statically_assigned(self, entry):
159
+ if (entry.is_local and entry.is_variable and
160
+ (entry.type.is_struct_or_union or
161
+ entry.type.is_complex or
162
+ entry.type.is_array or
163
+ entry.type.is_cpp_class)):
164
+ # stack allocated structured variable => never uninitialised
165
+ return True
166
+ return False
167
+
168
+ def mark_position(self, node):
169
+ """Mark position, will be used to draw graph nodes."""
170
+ if self.block:
171
+ self.block.positions.add(node.pos[:2])
172
+
173
+ def mark_assignment(self, lhs, rhs, entry):
174
+ if self.block and self.is_tracked(entry):
175
+ assignment = NameAssignment(lhs, rhs, entry)
176
+ self.block.stats.append(assignment)
177
+ self.block.gen[entry] = assignment
178
+ self.entries.add(entry)
179
+
180
+ def mark_argument(self, lhs, rhs, entry):
181
+ if self.block and self.is_tracked(entry):
182
+ assignment = Argument(lhs, rhs, entry)
183
+ self.block.stats.append(assignment)
184
+ self.block.gen[entry] = assignment
185
+ self.entries.add(entry)
186
+
187
+ def mark_deletion(self, node, entry):
188
+ if self.block and self.is_tracked(entry):
189
+ assignment = NameDeletion(node, entry)
190
+ self.block.stats.append(assignment)
191
+ self.block.gen[entry] = Uninitialized
192
+ self.entries.add(entry)
193
+
194
+ def mark_reference(self, node, entry):
195
+ if self.block and self.is_tracked(entry):
196
+ self.block.stats.append(NameReference(node, entry))
197
+ ## XXX: We don't track expression evaluation order so we can't use
198
+ ## XXX: successful reference as initialization sign.
199
+ ## # Local variable is definitely bound after this reference
200
+ ## if not node.allow_null:
201
+ ## self.block.bounded.add(entry)
202
+ self.entries.add(entry)
203
+
204
+ def normalize(self):
205
+ """Delete unreachable and orphan blocks."""
206
+ queue = set([self.entry_point])
207
+ visited = set()
208
+ while queue:
209
+ root = queue.pop()
210
+ visited.add(root)
211
+ for child in root.children:
212
+ if child not in visited:
213
+ queue.add(child)
214
+ unreachable = self.blocks - visited
215
+ for block in unreachable:
216
+ block.detach()
217
+ visited.remove(self.entry_point)
218
+ for block in visited:
219
+ if block.empty():
220
+ for parent in block.parents: # Re-parent
221
+ for child in block.children:
222
+ parent.add_child(child)
223
+ block.detach()
224
+ unreachable.add(block)
225
+ self.blocks -= unreachable
226
+
227
+ def initialize(self):
228
+ """Set initial state, map assignments to bits."""
229
+ self.assmts = {}
230
+
231
+ bit = 1
232
+ for entry in self.entries:
233
+ assmts = AssignmentList()
234
+ assmts.mask = assmts.bit = bit
235
+ self.assmts[entry] = assmts
236
+ bit <<= 1
237
+
238
+ for block in self.blocks:
239
+ for stat in block.stats:
240
+ if isinstance(stat, NameAssignment):
241
+ stat.bit = bit
242
+ assmts = self.assmts[stat.entry]
243
+ assmts.stats.append(stat)
244
+ assmts.mask |= bit
245
+ bit <<= 1
246
+
247
+ for block in self.blocks:
248
+ for entry, stat in block.gen.items():
249
+ assmts = self.assmts[entry]
250
+ if stat is Uninitialized:
251
+ block.i_gen |= assmts.bit
252
+ else:
253
+ block.i_gen |= stat.bit
254
+ block.i_kill |= assmts.mask
255
+ block.i_output = block.i_gen
256
+ for entry in block.bounded:
257
+ block.i_kill |= self.assmts[entry].bit
258
+
259
+ for assmts in self.assmts.values():
260
+ self.entry_point.i_gen |= assmts.bit
261
+ self.entry_point.i_output = self.entry_point.i_gen
262
+
263
+ def map_one(self, istate, entry):
264
+ ret = set()
265
+ assmts = self.assmts[entry]
266
+ if istate & assmts.bit:
267
+ if self.is_statically_assigned(entry):
268
+ ret.add(StaticAssignment(entry))
269
+ elif entry.from_closure:
270
+ ret.add(Unknown)
271
+ else:
272
+ ret.add(Uninitialized)
273
+ for assmt in assmts.stats:
274
+ if istate & assmt.bit:
275
+ ret.add(assmt)
276
+ return ret
277
+
278
+ def reaching_definitions(self):
279
+ """Per-block reaching definitions analysis."""
280
+ dirty = True
281
+ while dirty:
282
+ dirty = False
283
+ for block in self.blocks:
284
+ i_input = 0
285
+ for parent in block.parents:
286
+ i_input |= parent.i_output
287
+ i_output = (i_input & ~block.i_kill) | block.i_gen
288
+ if i_output != block.i_output:
289
+ dirty = True
290
+ block.i_input = i_input
291
+ block.i_output = i_output
292
+
293
+
294
+ class LoopDescr(object):
295
+ def __init__(self, next_block, loop_block):
296
+ self.next_block = next_block
297
+ self.loop_block = loop_block
298
+ self.exceptions = []
299
+
300
+
301
+ class ExceptionDescr(object):
302
+ """Exception handling helper.
303
+
304
+ entry_point ControlBlock Exception handling entry point
305
+ finally_enter ControlBlock Normal finally clause entry point
306
+ finally_exit ControlBlock Normal finally clause exit point
307
+ """
308
+
309
+ def __init__(self, entry_point, finally_enter=None, finally_exit=None):
310
+ self.entry_point = entry_point
311
+ self.finally_enter = finally_enter
312
+ self.finally_exit = finally_exit
313
+
314
+
315
+ class NameAssignment(object):
316
+ def __init__(self, lhs, rhs, entry):
317
+ if lhs.cf_state is None:
318
+ lhs.cf_state = set()
319
+ self.lhs = lhs
320
+ self.rhs = rhs
321
+ self.entry = entry
322
+ self.pos = lhs.pos
323
+ self.refs = set()
324
+ self.is_arg = False
325
+ self.is_deletion = False
326
+ self.inferred_type = None
327
+
328
+ def __repr__(self):
329
+ return '%s(entry=%r)' % (self.__class__.__name__, self.entry)
330
+
331
+ def infer_type(self):
332
+ self.inferred_type = self.rhs.infer_type(self.entry.scope)
333
+ return self.inferred_type
334
+
335
+ def type_dependencies(self):
336
+ return self.rhs.type_dependencies(self.entry.scope)
337
+
338
+ @property
339
+ def type(self):
340
+ if not self.entry.type.is_unspecified:
341
+ return self.entry.type
342
+ return self.inferred_type
343
+
344
+
345
+ class StaticAssignment(NameAssignment):
346
+ """Initialised at declaration time, e.g. stack allocation."""
347
+ def __init__(self, entry):
348
+ if not entry.type.is_pyobject:
349
+ may_be_none = False
350
+ else:
351
+ may_be_none = None # unknown
352
+ lhs = TypedExprNode(
353
+ entry.type, may_be_none=may_be_none, pos=entry.pos)
354
+ super(StaticAssignment, self).__init__(lhs, lhs, entry)
355
+
356
+ def infer_type(self):
357
+ return self.entry.type
358
+
359
+ def type_dependencies(self):
360
+ return ()
361
+
362
+
363
+ class Argument(NameAssignment):
364
+ def __init__(self, lhs, rhs, entry):
365
+ NameAssignment.__init__(self, lhs, rhs, entry)
366
+ self.is_arg = True
367
+
368
+
369
+ class NameDeletion(NameAssignment):
370
+ def __init__(self, lhs, entry):
371
+ NameAssignment.__init__(self, lhs, lhs, entry)
372
+ self.is_deletion = True
373
+
374
+ def infer_type(self):
375
+ inferred_type = self.rhs.infer_type(self.entry.scope)
376
+ if (not inferred_type.is_pyobject and
377
+ inferred_type.can_coerce_to_pyobject(self.entry.scope)):
378
+ return py_object_type
379
+ self.inferred_type = inferred_type
380
+ return inferred_type
381
+
382
+
383
+ class Uninitialized(object):
384
+ """Definitely not initialised yet."""
385
+
386
+
387
+ class Unknown(object):
388
+ """Coming from outer closure, might be initialised or not."""
389
+
390
+
391
+ class NameReference(object):
392
+ def __init__(self, node, entry):
393
+ if node.cf_state is None:
394
+ node.cf_state = set()
395
+ self.node = node
396
+ self.entry = entry
397
+ self.pos = node.pos
398
+
399
+ def __repr__(self):
400
+ return '%s(entry=%r)' % (self.__class__.__name__, self.entry)
401
+
402
+
403
+ class ControlFlowState(list):
404
+ # Keeps track of Node's entry assignments
405
+ #
406
+ # cf_is_null [boolean] It is uninitialized
407
+ # cf_maybe_null [boolean] May be uninitialized
408
+ # is_single [boolean] Has only one assignment at this point
409
+
410
+ cf_maybe_null = False
411
+ cf_is_null = False
412
+ is_single = False
413
+
414
+ def __init__(self, state):
415
+ if Uninitialized in state:
416
+ state.discard(Uninitialized)
417
+ self.cf_maybe_null = True
418
+ if not state:
419
+ self.cf_is_null = True
420
+ elif Unknown in state:
421
+ state.discard(Unknown)
422
+ self.cf_maybe_null = True
423
+ else:
424
+ if len(state) == 1:
425
+ self.is_single = True
426
+ # XXX: Remove fake_rhs_expr
427
+ super(ControlFlowState, self).__init__(
428
+ [i for i in state if i.rhs is not fake_rhs_expr])
429
+
430
+ def one(self):
431
+ return self[0]
432
+
433
+
434
+ class GVContext(object):
435
+ """Graphviz subgraph object."""
436
+
437
+ def __init__(self):
438
+ self.blockids = {}
439
+ self.nextid = 0
440
+ self.children = []
441
+ self.sources = {}
442
+
443
+ def add(self, child):
444
+ self.children.append(child)
445
+
446
+ def nodeid(self, block):
447
+ if block not in self.blockids:
448
+ self.blockids[block] = 'block%d' % self.nextid
449
+ self.nextid += 1
450
+ return self.blockids[block]
451
+
452
+ def extract_sources(self, block):
453
+ if not block.positions:
454
+ return ''
455
+ start = min(block.positions)
456
+ stop = max(block.positions)
457
+ srcdescr = start[0]
458
+ if not srcdescr in self.sources:
459
+ self.sources[srcdescr] = list(srcdescr.get_lines())
460
+ lines = self.sources[srcdescr]
461
+ return '\\n'.join([l.strip() for l in lines[start[1] - 1:stop[1]]])
462
+
463
+ def render(self, fp, name, annotate_defs=False):
464
+ """Render graphviz dot graph"""
465
+ fp.write('digraph %s {\n' % name)
466
+ fp.write(' node [shape=box];\n')
467
+ for child in self.children:
468
+ child.render(fp, self, annotate_defs)
469
+ fp.write('}\n')
470
+
471
+ def escape(self, text):
472
+ return text.replace('"', '\\"').replace('\n', '\\n')
473
+
474
+
475
+ class GV(object):
476
+ """Graphviz DOT renderer."""
477
+
478
+ def __init__(self, name, flow):
479
+ self.name = name
480
+ self.flow = flow
481
+
482
+ def render(self, fp, ctx, annotate_defs=False):
483
+ fp.write(' subgraph %s {\n' % self.name)
484
+ for block in self.flow.blocks:
485
+ label = ctx.extract_sources(block)
486
+ if annotate_defs:
487
+ for stat in block.stats:
488
+ if isinstance(stat, NameAssignment):
489
+ label += '\n %s [%s %s]' % (
490
+ stat.entry.name, 'deletion' if stat.is_deletion else 'definition', stat.pos[1])
491
+ elif isinstance(stat, NameReference):
492
+ if stat.entry:
493
+ label += '\n %s [reference %s]' % (stat.entry.name, stat.pos[1])
494
+ if not label:
495
+ label = 'empty'
496
+ pid = ctx.nodeid(block)
497
+ fp.write(' %s [label="%s"];\n' % (pid, ctx.escape(label)))
498
+ for block in self.flow.blocks:
499
+ pid = ctx.nodeid(block)
500
+ for child in block.children:
501
+ fp.write(' %s -> %s;\n' % (pid, ctx.nodeid(child)))
502
+ fp.write(' }\n')
503
+
504
+
505
+ class MessageCollection(object):
506
+ """Collect error/warnings messages first then sort"""
507
+ def __init__(self):
508
+ self.messages = set()
509
+
510
+ def error(self, pos, message):
511
+ self.messages.add((pos, True, message))
512
+
513
+ def warning(self, pos, message):
514
+ self.messages.add((pos, False, message))
515
+
516
+ def report(self):
517
+ for pos, is_error, message in sorted(self.messages):
518
+ if is_error:
519
+ error(pos, message)
520
+ else:
521
+ warning(pos, message, 2)
522
+
523
+
524
+ def check_definitions(flow, compiler_directives):
525
+ flow.initialize()
526
+ flow.reaching_definitions()
527
+
528
+ # Track down state
529
+ assignments = set()
530
+ # Node to entry map
531
+ references = {}
532
+ assmt_nodes = set()
533
+
534
+ for block in flow.blocks:
535
+ i_state = block.i_input
536
+ for stat in block.stats:
537
+ i_assmts = flow.assmts[stat.entry]
538
+ state = flow.map_one(i_state, stat.entry)
539
+ if isinstance(stat, NameAssignment):
540
+ stat.lhs.cf_state.update(state)
541
+ assmt_nodes.add(stat.lhs)
542
+ i_state = i_state & ~i_assmts.mask
543
+ if stat.is_deletion:
544
+ i_state |= i_assmts.bit
545
+ else:
546
+ i_state |= stat.bit
547
+ assignments.add(stat)
548
+ if stat.rhs is not fake_rhs_expr:
549
+ stat.entry.cf_assignments.append(stat)
550
+ elif isinstance(stat, NameReference):
551
+ references[stat.node] = stat.entry
552
+ stat.entry.cf_references.append(stat)
553
+ stat.node.cf_state.update(state)
554
+ ## if not stat.node.allow_null:
555
+ ## i_state &= ~i_assmts.bit
556
+ ## # after successful read, the state is known to be initialised
557
+ state.discard(Uninitialized)
558
+ state.discard(Unknown)
559
+ for assmt in state:
560
+ assmt.refs.add(stat)
561
+
562
+ # Check variable usage
563
+ warn_maybe_uninitialized = compiler_directives['warn.maybe_uninitialized']
564
+ warn_unused_result = compiler_directives['warn.unused_result']
565
+ warn_unused = compiler_directives['warn.unused']
566
+ warn_unused_arg = compiler_directives['warn.unused_arg']
567
+
568
+ messages = MessageCollection()
569
+
570
+ # assignment hints
571
+ for node in assmt_nodes:
572
+ if Uninitialized in node.cf_state:
573
+ node.cf_maybe_null = True
574
+ if len(node.cf_state) == 1:
575
+ node.cf_is_null = True
576
+ else:
577
+ node.cf_is_null = False
578
+ elif Unknown in node.cf_state:
579
+ node.cf_maybe_null = True
580
+ else:
581
+ node.cf_is_null = False
582
+ node.cf_maybe_null = False
583
+
584
+ # Find uninitialized references and cf-hints
585
+ for node, entry in references.items():
586
+ if Uninitialized in node.cf_state:
587
+ node.cf_maybe_null = True
588
+ if not entry.from_closure and len(node.cf_state) == 1:
589
+ node.cf_is_null = True
590
+ if (node.allow_null or entry.from_closure
591
+ or entry.is_pyclass_attr or entry.type.is_error):
592
+ pass # Can be uninitialized here
593
+ elif node.cf_is_null:
594
+ if entry.error_on_uninitialized or (
595
+ Options.error_on_uninitialized and (
596
+ entry.type.is_pyobject or entry.type.is_unspecified)):
597
+ messages.error(
598
+ node.pos,
599
+ "local variable '%s' referenced before assignment"
600
+ % entry.name)
601
+ else:
602
+ messages.warning(
603
+ node.pos,
604
+ "local variable '%s' referenced before assignment"
605
+ % entry.name)
606
+ elif warn_maybe_uninitialized:
607
+ messages.warning(
608
+ node.pos,
609
+ "local variable '%s' might be referenced before assignment"
610
+ % entry.name)
611
+ elif Unknown in node.cf_state:
612
+ # TODO: better cross-closure analysis to know when inner functions
613
+ # are being called before a variable is being set, and when
614
+ # a variable is known to be set before even defining the
615
+ # inner function, etc.
616
+ node.cf_maybe_null = True
617
+ else:
618
+ node.cf_is_null = False
619
+ node.cf_maybe_null = False
620
+
621
+ # Unused result
622
+ for assmt in assignments:
623
+ if (not assmt.refs and not assmt.entry.is_pyclass_attr
624
+ and not assmt.entry.in_closure):
625
+ if assmt.entry.cf_references and warn_unused_result:
626
+ if assmt.is_arg:
627
+ messages.warning(assmt.pos, "Unused argument value '%s'" %
628
+ assmt.entry.name)
629
+ else:
630
+ messages.warning(assmt.pos, "Unused result in '%s'" %
631
+ assmt.entry.name)
632
+ assmt.lhs.cf_used = False
633
+
634
+ # Unused entries
635
+ for entry in flow.entries:
636
+ if (not entry.cf_references
637
+ and not entry.is_pyclass_attr):
638
+ if entry.name != '_' and not entry.name.startswith('unused'):
639
+ # '_' is often used for unused variables, e.g. in loops
640
+ if entry.is_arg:
641
+ if warn_unused_arg:
642
+ messages.warning(entry.pos, "Unused argument '%s'" %
643
+ entry.name)
644
+ else:
645
+ if warn_unused:
646
+ messages.warning(entry.pos, "Unused entry '%s'" %
647
+ entry.name)
648
+ entry.cf_used = False
649
+
650
+ messages.report()
651
+
652
+ for node in assmt_nodes:
653
+ node.cf_state = ControlFlowState(node.cf_state)
654
+ for node in references:
655
+ node.cf_state = ControlFlowState(node.cf_state)
656
+
657
+
658
+ class AssignmentCollector(TreeVisitor):
659
+ def __init__(self):
660
+ super(AssignmentCollector, self).__init__()
661
+ self.assignments = []
662
+
663
+ def visit_Node(self):
664
+ self._visitchildren(self, None)
665
+
666
+ def visit_SingleAssignmentNode(self, node):
667
+ self.assignments.append((node.lhs, node.rhs))
668
+
669
+ def visit_CascadedAssignmentNode(self, node):
670
+ for lhs in node.lhs_list:
671
+ self.assignments.append((lhs, node.rhs))
672
+
673
+
674
+ class ControlFlowAnalysis(CythonTransform):
675
+
676
+ def visit_ModuleNode(self, node):
677
+ self.gv_ctx = GVContext()
678
+ self.constant_folder = ConstantFolding()
679
+
680
+ # Set of NameNode reductions
681
+ self.reductions = set()
682
+
683
+ self.in_inplace_assignment = False
684
+ self.env_stack = []
685
+ self.env = node.scope
686
+ self.stack = []
687
+ self.flow = ControlFlow()
688
+ self.visitchildren(node)
689
+
690
+ check_definitions(self.flow, self.current_directives)
691
+
692
+ dot_output = self.current_directives['control_flow.dot_output']
693
+ if dot_output:
694
+ annotate_defs = self.current_directives['control_flow.dot_annotate_defs']
695
+ fp = open(dot_output, 'wt')
696
+ try:
697
+ self.gv_ctx.render(fp, 'module', annotate_defs=annotate_defs)
698
+ finally:
699
+ fp.close()
700
+ return node
701
+
702
+ def visit_FuncDefNode(self, node):
703
+ for arg in node.args:
704
+ if arg.default:
705
+ self.visitchildren(arg)
706
+ self.visitchildren(node, ('decorators',))
707
+ self.env_stack.append(self.env)
708
+ self.env = node.local_scope
709
+ self.stack.append(self.flow)
710
+ self.flow = ControlFlow()
711
+
712
+ # Collect all entries
713
+ for entry in node.local_scope.entries.values():
714
+ if self.flow.is_tracked(entry):
715
+ self.flow.entries.add(entry)
716
+
717
+ self.mark_position(node)
718
+ # Function body block
719
+ self.flow.nextblock()
720
+
721
+ for arg in node.args:
722
+ self._visit(arg)
723
+ if node.star_arg:
724
+ self.flow.mark_argument(node.star_arg,
725
+ TypedExprNode(Builtin.tuple_type,
726
+ may_be_none=False),
727
+ node.star_arg.entry)
728
+ if node.starstar_arg:
729
+ self.flow.mark_argument(node.starstar_arg,
730
+ TypedExprNode(Builtin.dict_type,
731
+ may_be_none=False),
732
+ node.starstar_arg.entry)
733
+ self._visit(node.body)
734
+ # Workaround for generators
735
+ if node.is_generator:
736
+ self._visit(node.gbody.body)
737
+
738
+ # Exit point
739
+ if self.flow.block:
740
+ self.flow.block.add_child(self.flow.exit_point)
741
+
742
+ # Cleanup graph
743
+ self.flow.normalize()
744
+ check_definitions(self.flow, self.current_directives)
745
+ self.flow.blocks.add(self.flow.entry_point)
746
+
747
+ self.gv_ctx.add(GV(node.local_scope.name, self.flow))
748
+
749
+ self.flow = self.stack.pop()
750
+ self.env = self.env_stack.pop()
751
+ return node
752
+
753
+ def visit_DefNode(self, node):
754
+ node.used = True
755
+ return self.visit_FuncDefNode(node)
756
+
757
+ def visit_GeneratorBodyDefNode(self, node):
758
+ return node
759
+
760
+ def visit_CTypeDefNode(self, node):
761
+ return node
762
+
763
+ def mark_assignment(self, lhs, rhs=None):
764
+ if not self.flow.block:
765
+ return
766
+ if self.flow.exceptions:
767
+ exc_descr = self.flow.exceptions[-1]
768
+ self.flow.block.add_child(exc_descr.entry_point)
769
+ self.flow.nextblock()
770
+
771
+ if not rhs:
772
+ rhs = object_expr
773
+ if lhs.is_name:
774
+ if lhs.entry is not None:
775
+ entry = lhs.entry
776
+ else:
777
+ entry = self.env.lookup(lhs.name)
778
+ if entry is None: # TODO: This shouldn't happen...
779
+ return
780
+ self.flow.mark_assignment(lhs, rhs, entry)
781
+ elif lhs.is_sequence_constructor:
782
+ for i, arg in enumerate(lhs.args):
783
+ if not rhs or arg.is_starred:
784
+ item_node = None
785
+ else:
786
+ item_node = rhs.inferable_item_node(i)
787
+ self.mark_assignment(arg, item_node)
788
+ else:
789
+ self._visit(lhs)
790
+
791
+ if self.flow.exceptions:
792
+ exc_descr = self.flow.exceptions[-1]
793
+ self.flow.block.add_child(exc_descr.entry_point)
794
+ self.flow.nextblock()
795
+
796
+ def mark_position(self, node):
797
+ """Mark position if DOT output is enabled."""
798
+ if self.current_directives['control_flow.dot_output']:
799
+ self.flow.mark_position(node)
800
+
801
+ def visit_FromImportStatNode(self, node):
802
+ for name, target in node.items:
803
+ if name != "*":
804
+ self.mark_assignment(target)
805
+ self.visitchildren(node)
806
+ return node
807
+
808
+ def visit_AssignmentNode(self, node):
809
+ raise InternalError("Unhandled assignment node")
810
+
811
+ def visit_SingleAssignmentNode(self, node):
812
+ self._visit(node.rhs)
813
+ self.mark_assignment(node.lhs, node.rhs)
814
+ return node
815
+
816
+ def visit_CascadedAssignmentNode(self, node):
817
+ self._visit(node.rhs)
818
+ for lhs in node.lhs_list:
819
+ self.mark_assignment(lhs, node.rhs)
820
+ return node
821
+
822
+ def visit_ParallelAssignmentNode(self, node):
823
+ collector = AssignmentCollector()
824
+ collector.visitchildren(node)
825
+ for lhs, rhs in collector.assignments:
826
+ self._visit(rhs)
827
+ for lhs, rhs in collector.assignments:
828
+ self.mark_assignment(lhs, rhs)
829
+ return node
830
+
831
+ def visit_InPlaceAssignmentNode(self, node):
832
+ self.in_inplace_assignment = True
833
+ self.visitchildren(node)
834
+ self.in_inplace_assignment = False
835
+ self.mark_assignment(node.lhs, self.constant_folder(node.create_binop_node()))
836
+ return node
837
+
838
+ def visit_DelStatNode(self, node):
839
+ for arg in node.args:
840
+ if arg.is_name:
841
+ entry = arg.entry or self.env.lookup(arg.name)
842
+ if entry.in_closure or entry.from_closure:
843
+ error(arg.pos,
844
+ "can not delete variable '%s' "
845
+ "referenced in nested scope" % entry.name)
846
+ if not node.ignore_nonexisting:
847
+ self._visit(arg) # mark reference
848
+ self.flow.mark_deletion(arg, entry)
849
+ else:
850
+ self._visit(arg)
851
+ return node
852
+
853
+ def visit_CArgDeclNode(self, node):
854
+ entry = self.env.lookup(node.name)
855
+ if entry:
856
+ may_be_none = not node.not_none
857
+ self.flow.mark_argument(
858
+ node, TypedExprNode(entry.type, may_be_none), entry)
859
+ return node
860
+
861
+ def visit_NameNode(self, node):
862
+ if self.flow.block:
863
+ entry = node.entry or self.env.lookup(node.name)
864
+ if entry:
865
+ self.flow.mark_reference(node, entry)
866
+
867
+ if entry in self.reductions and not self.in_inplace_assignment:
868
+ error(node.pos,
869
+ "Cannot read reduction variable in loop body")
870
+
871
+ return node
872
+
873
+ def visit_StatListNode(self, node):
874
+ if self.flow.block:
875
+ for stat in node.stats:
876
+ self._visit(stat)
877
+ if not self.flow.block:
878
+ stat.is_terminator = True
879
+ break
880
+ return node
881
+
882
+ def visit_Node(self, node):
883
+ self.visitchildren(node)
884
+ self.mark_position(node)
885
+ return node
886
+
887
+ def visit_SizeofVarNode(self, node):
888
+ return node
889
+
890
+ def visit_TypeidNode(self, node):
891
+ return node
892
+
893
+ def visit_IfStatNode(self, node):
894
+ next_block = self.flow.newblock()
895
+ parent = self.flow.block
896
+ # If clauses
897
+ for clause in node.if_clauses:
898
+ parent = self.flow.nextblock(parent)
899
+ self._visit(clause.condition)
900
+ self.flow.nextblock()
901
+ self._visit(clause.body)
902
+ if self.flow.block:
903
+ self.flow.block.add_child(next_block)
904
+ # Else clause
905
+ if node.else_clause:
906
+ self.flow.nextblock(parent=parent)
907
+ self._visit(node.else_clause)
908
+ if self.flow.block:
909
+ self.flow.block.add_child(next_block)
910
+ else:
911
+ parent.add_child(next_block)
912
+
913
+ if next_block.parents:
914
+ self.flow.block = next_block
915
+ else:
916
+ self.flow.block = None
917
+ return node
918
+
919
+ def visit_WhileStatNode(self, node):
920
+ condition_block = self.flow.nextblock()
921
+ next_block = self.flow.newblock()
922
+ # Condition block
923
+ self.flow.loops.append(LoopDescr(next_block, condition_block))
924
+ if node.condition:
925
+ self._visit(node.condition)
926
+ # Body block
927
+ self.flow.nextblock()
928
+ self._visit(node.body)
929
+ self.flow.loops.pop()
930
+ # Loop it
931
+ if self.flow.block:
932
+ self.flow.block.add_child(condition_block)
933
+ self.flow.block.add_child(next_block)
934
+ # Else clause
935
+ if node.else_clause:
936
+ self.flow.nextblock(parent=condition_block)
937
+ self._visit(node.else_clause)
938
+ if self.flow.block:
939
+ self.flow.block.add_child(next_block)
940
+ else:
941
+ condition_block.add_child(next_block)
942
+
943
+ if next_block.parents:
944
+ self.flow.block = next_block
945
+ else:
946
+ self.flow.block = None
947
+ return node
948
+
949
+ def mark_forloop_target(self, node):
950
+ # TODO: Remove redundancy with range optimization...
951
+ is_special = False
952
+ sequence = node.iterator.sequence
953
+ target = node.target
954
+ if isinstance(sequence, ExprNodes.SimpleCallNode):
955
+ function = sequence.function
956
+ if sequence.self is None and function.is_name:
957
+ entry = self.env.lookup(function.name)
958
+ if not entry or entry.is_builtin:
959
+ if function.name == 'reversed' and len(sequence.args) == 1:
960
+ sequence = sequence.args[0]
961
+ elif function.name == 'enumerate' and len(sequence.args) == 1:
962
+ if target.is_sequence_constructor and len(target.args) == 2:
963
+ iterator = sequence.args[0]
964
+ if iterator.is_name:
965
+ iterator_type = iterator.infer_type(self.env)
966
+ if iterator_type.is_builtin_type:
967
+ # assume that builtin types have a length within Py_ssize_t
968
+ self.mark_assignment(
969
+ target.args[0],
970
+ ExprNodes.IntNode(target.pos, value='PY_SSIZE_T_MAX',
971
+ type=PyrexTypes.c_py_ssize_t_type))
972
+ target = target.args[1]
973
+ sequence = sequence.args[0]
974
+ if isinstance(sequence, ExprNodes.SimpleCallNode):
975
+ function = sequence.function
976
+ if sequence.self is None and function.is_name:
977
+ entry = self.env.lookup(function.name)
978
+ if not entry or entry.is_builtin:
979
+ if function.name in ('range', 'xrange'):
980
+ is_special = True
981
+ for arg in sequence.args[:2]:
982
+ self.mark_assignment(target, arg)
983
+ if len(sequence.args) > 2:
984
+ self.mark_assignment(target, self.constant_folder(
985
+ ExprNodes.binop_node(node.pos,
986
+ '+',
987
+ sequence.args[0],
988
+ sequence.args[2])))
989
+
990
+ if not is_special:
991
+ # A for-loop basically translates to subsequent calls to
992
+ # __getitem__(), so using an IndexNode here allows us to
993
+ # naturally infer the base type of pointers, C arrays,
994
+ # Python strings, etc., while correctly falling back to an
995
+ # object type when the base type cannot be handled.
996
+
997
+ self.mark_assignment(target, node.item)
998
+
999
+ def visit_AsyncForStatNode(self, node):
1000
+ return self.visit_ForInStatNode(node)
1001
+
1002
+ def visit_ForInStatNode(self, node):
1003
+ condition_block = self.flow.nextblock()
1004
+ next_block = self.flow.newblock()
1005
+ # Condition with iterator
1006
+ self.flow.loops.append(LoopDescr(next_block, condition_block))
1007
+ self._visit(node.iterator)
1008
+ # Target assignment
1009
+ self.flow.nextblock()
1010
+
1011
+ if isinstance(node, Nodes.ForInStatNode):
1012
+ self.mark_forloop_target(node)
1013
+ elif isinstance(node, Nodes.AsyncForStatNode):
1014
+ # not entirely correct, but good enough for now
1015
+ self.mark_assignment(node.target, node.item)
1016
+ else: # Parallel
1017
+ self.mark_assignment(node.target)
1018
+
1019
+ # Body block
1020
+ if isinstance(node, Nodes.ParallelRangeNode):
1021
+ # In case of an invalid
1022
+ self._delete_privates(node, exclude=node.target.entry)
1023
+
1024
+ self.flow.nextblock()
1025
+ self._visit(node.body)
1026
+ self.flow.loops.pop()
1027
+
1028
+ # Loop it
1029
+ if self.flow.block:
1030
+ self.flow.block.add_child(condition_block)
1031
+ # Else clause
1032
+ if node.else_clause:
1033
+ self.flow.nextblock(parent=condition_block)
1034
+ self._visit(node.else_clause)
1035
+ if self.flow.block:
1036
+ self.flow.block.add_child(next_block)
1037
+ else:
1038
+ condition_block.add_child(next_block)
1039
+
1040
+ if next_block.parents:
1041
+ self.flow.block = next_block
1042
+ else:
1043
+ self.flow.block = None
1044
+ return node
1045
+
1046
+ def _delete_privates(self, node, exclude=None):
1047
+ for private_node in node.assigned_nodes:
1048
+ if not exclude or private_node.entry is not exclude:
1049
+ self.flow.mark_deletion(private_node, private_node.entry)
1050
+
1051
+ def visit_ParallelRangeNode(self, node):
1052
+ reductions = self.reductions
1053
+
1054
+ # if node.target is None or not a NameNode, an error will have
1055
+ # been previously issued
1056
+ if hasattr(node.target, 'entry'):
1057
+ self.reductions = set(reductions)
1058
+
1059
+ for private_node in node.assigned_nodes:
1060
+ private_node.entry.error_on_uninitialized = True
1061
+ pos, reduction = node.assignments[private_node.entry]
1062
+ if reduction:
1063
+ self.reductions.add(private_node.entry)
1064
+
1065
+ node = self.visit_ForInStatNode(node)
1066
+
1067
+ self.reductions = reductions
1068
+ return node
1069
+
1070
+ def visit_ParallelWithBlockNode(self, node):
1071
+ for private_node in node.assigned_nodes:
1072
+ private_node.entry.error_on_uninitialized = True
1073
+
1074
+ self._delete_privates(node)
1075
+ self.visitchildren(node)
1076
+ self._delete_privates(node)
1077
+
1078
+ return node
1079
+
1080
+ def visit_ForFromStatNode(self, node):
1081
+ condition_block = self.flow.nextblock()
1082
+ next_block = self.flow.newblock()
1083
+ # Condition with iterator
1084
+ self.flow.loops.append(LoopDescr(next_block, condition_block))
1085
+ self._visit(node.bound1)
1086
+ self._visit(node.bound2)
1087
+ if node.step is not None:
1088
+ self._visit(node.step)
1089
+ # Target assignment
1090
+ self.flow.nextblock()
1091
+ self.mark_assignment(node.target, node.bound1)
1092
+ if node.step is not None:
1093
+ self.mark_assignment(node.target, self.constant_folder(
1094
+ ExprNodes.binop_node(node.pos, '+', node.bound1, node.step)))
1095
+ # Body block
1096
+ self.flow.nextblock()
1097
+ self._visit(node.body)
1098
+ self.flow.loops.pop()
1099
+ # Loop it
1100
+ if self.flow.block:
1101
+ self.flow.block.add_child(condition_block)
1102
+ # Else clause
1103
+ if node.else_clause:
1104
+ self.flow.nextblock(parent=condition_block)
1105
+ self._visit(node.else_clause)
1106
+ if self.flow.block:
1107
+ self.flow.block.add_child(next_block)
1108
+ else:
1109
+ condition_block.add_child(next_block)
1110
+
1111
+ if next_block.parents:
1112
+ self.flow.block = next_block
1113
+ else:
1114
+ self.flow.block = None
1115
+ return node
1116
+
1117
+ def visit_LoopNode(self, node):
1118
+ raise InternalError("Generic loops are not supported")
1119
+
1120
+ def visit_WithTargetAssignmentStatNode(self, node):
1121
+ self.mark_assignment(node.lhs, node.with_node.enter_call)
1122
+ return node
1123
+
1124
+ def visit_WithStatNode(self, node):
1125
+ self._visit(node.manager)
1126
+ self._visit(node.enter_call)
1127
+ self._visit(node.body)
1128
+ return node
1129
+
1130
+ def visit_TryExceptStatNode(self, node):
1131
+ # After exception handling
1132
+ next_block = self.flow.newblock()
1133
+ # Body block
1134
+ self.flow.newblock()
1135
+ # Exception entry point
1136
+ entry_point = self.flow.newblock()
1137
+ self.flow.exceptions.append(ExceptionDescr(entry_point))
1138
+ self.flow.nextblock()
1139
+ ## XXX: links to exception handling point should be added by
1140
+ ## XXX: children nodes
1141
+ self.flow.block.add_child(entry_point)
1142
+ self.flow.nextblock()
1143
+ self._visit(node.body)
1144
+ self.flow.exceptions.pop()
1145
+
1146
+ # After exception
1147
+ if self.flow.block:
1148
+ if node.else_clause:
1149
+ self.flow.nextblock()
1150
+ self._visit(node.else_clause)
1151
+ if self.flow.block:
1152
+ self.flow.block.add_child(next_block)
1153
+
1154
+ for clause in node.except_clauses:
1155
+ self.flow.block = entry_point
1156
+ if clause.pattern:
1157
+ for pattern in clause.pattern:
1158
+ self._visit(pattern)
1159
+ else:
1160
+ # TODO: handle * pattern
1161
+ pass
1162
+ entry_point = self.flow.newblock(parent=self.flow.block)
1163
+ self.flow.nextblock()
1164
+ if clause.target:
1165
+ self.mark_assignment(clause.target)
1166
+ self._visit(clause.body)
1167
+ if self.flow.block:
1168
+ self.flow.block.add_child(next_block)
1169
+
1170
+ if self.flow.exceptions:
1171
+ entry_point.add_child(self.flow.exceptions[-1].entry_point)
1172
+
1173
+ if next_block.parents:
1174
+ self.flow.block = next_block
1175
+ else:
1176
+ self.flow.block = None
1177
+ return node
1178
+
1179
+ def visit_TryFinallyStatNode(self, node):
1180
+ body_block = self.flow.nextblock()
1181
+
1182
+ # Exception entry point
1183
+ entry_point = self.flow.newblock()
1184
+ self.flow.block = entry_point
1185
+ self._visit(node.finally_except_clause)
1186
+
1187
+ if self.flow.block and self.flow.exceptions:
1188
+ self.flow.block.add_child(self.flow.exceptions[-1].entry_point)
1189
+
1190
+ # Normal execution
1191
+ finally_enter = self.flow.newblock()
1192
+ self.flow.block = finally_enter
1193
+ self._visit(node.finally_clause)
1194
+ finally_exit = self.flow.block
1195
+
1196
+ descr = ExceptionDescr(entry_point, finally_enter, finally_exit)
1197
+ self.flow.exceptions.append(descr)
1198
+ if self.flow.loops:
1199
+ self.flow.loops[-1].exceptions.append(descr)
1200
+ self.flow.block = body_block
1201
+ body_block.add_child(entry_point)
1202
+ self.flow.nextblock()
1203
+ self._visit(node.body)
1204
+ self.flow.exceptions.pop()
1205
+ if self.flow.loops:
1206
+ self.flow.loops[-1].exceptions.pop()
1207
+
1208
+ if self.flow.block:
1209
+ self.flow.block.add_child(finally_enter)
1210
+ if finally_exit:
1211
+ self.flow.block = self.flow.nextblock(parent=finally_exit)
1212
+ else:
1213
+ self.flow.block = None
1214
+ return node
1215
+
1216
+ def visit_RaiseStatNode(self, node):
1217
+ self.mark_position(node)
1218
+ self.visitchildren(node)
1219
+ if self.flow.exceptions:
1220
+ self.flow.block.add_child(self.flow.exceptions[-1].entry_point)
1221
+ self.flow.block = None
1222
+ return node
1223
+
1224
+ def visit_ReraiseStatNode(self, node):
1225
+ self.mark_position(node)
1226
+ if self.flow.exceptions:
1227
+ self.flow.block.add_child(self.flow.exceptions[-1].entry_point)
1228
+ self.flow.block = None
1229
+ return node
1230
+
1231
+ def visit_ReturnStatNode(self, node):
1232
+ self.mark_position(node)
1233
+ self.visitchildren(node)
1234
+
1235
+ outer_exception_handlers = iter(self.flow.exceptions[::-1])
1236
+ for handler in outer_exception_handlers:
1237
+ if handler.finally_enter:
1238
+ self.flow.block.add_child(handler.finally_enter)
1239
+ if handler.finally_exit:
1240
+ # 'return' goes to function exit, or to the next outer 'finally' clause
1241
+ exit_point = self.flow.exit_point
1242
+ for next_handler in outer_exception_handlers:
1243
+ if next_handler.finally_enter:
1244
+ exit_point = next_handler.finally_enter
1245
+ break
1246
+ handler.finally_exit.add_child(exit_point)
1247
+ break
1248
+ else:
1249
+ if self.flow.block:
1250
+ self.flow.block.add_child(self.flow.exit_point)
1251
+ self.flow.block = None
1252
+ return node
1253
+
1254
+ def visit_BreakStatNode(self, node):
1255
+ if not self.flow.loops:
1256
+ #error(node.pos, "break statement not inside loop")
1257
+ return node
1258
+ loop = self.flow.loops[-1]
1259
+ self.mark_position(node)
1260
+ for exception in loop.exceptions[::-1]:
1261
+ if exception.finally_enter:
1262
+ self.flow.block.add_child(exception.finally_enter)
1263
+ if exception.finally_exit:
1264
+ exception.finally_exit.add_child(loop.next_block)
1265
+ break
1266
+ else:
1267
+ self.flow.block.add_child(loop.next_block)
1268
+ self.flow.block = None
1269
+ return node
1270
+
1271
+ def visit_ContinueStatNode(self, node):
1272
+ if not self.flow.loops:
1273
+ #error(node.pos, "continue statement not inside loop")
1274
+ return node
1275
+ loop = self.flow.loops[-1]
1276
+ self.mark_position(node)
1277
+ for exception in loop.exceptions[::-1]:
1278
+ if exception.finally_enter:
1279
+ self.flow.block.add_child(exception.finally_enter)
1280
+ if exception.finally_exit:
1281
+ exception.finally_exit.add_child(loop.loop_block)
1282
+ break
1283
+ else:
1284
+ self.flow.block.add_child(loop.loop_block)
1285
+ self.flow.block = None
1286
+ return node
1287
+
1288
+ def visit_ComprehensionNode(self, node):
1289
+ if node.expr_scope:
1290
+ self.env_stack.append(self.env)
1291
+ self.env = node.expr_scope
1292
+ # Skip append node here
1293
+ self._visit(node.loop)
1294
+ if node.expr_scope:
1295
+ self.env = self.env_stack.pop()
1296
+ return node
1297
+
1298
+ def visit_ScopedExprNode(self, node):
1299
+ if node.expr_scope:
1300
+ self.env_stack.append(self.env)
1301
+ self.env = node.expr_scope
1302
+ self.visitchildren(node)
1303
+ if node.expr_scope:
1304
+ self.env = self.env_stack.pop()
1305
+ return node
1306
+
1307
+ def visit_PyClassDefNode(self, node):
1308
+ self.visitchildren(node, ('dict', 'metaclass',
1309
+ 'mkw', 'bases', 'class_result'))
1310
+ self.flow.mark_assignment(node.target, node.classobj,
1311
+ self.env.lookup(node.name))
1312
+ self.env_stack.append(self.env)
1313
+ self.env = node.scope
1314
+ self.flow.nextblock()
1315
+ self.visitchildren(node, ('body',))
1316
+ self.flow.nextblock()
1317
+ self.env = self.env_stack.pop()
1318
+ return node
1319
+
1320
+ def visit_AmpersandNode(self, node):
1321
+ if node.operand.is_name:
1322
+ # Fake assignment to silence warning
1323
+ self.mark_assignment(node.operand, fake_rhs_expr)
1324
+ self.visitchildren(node)
1325
+ return node
venv/Lib/site-packages/Cython/Compiler/FusedNode.py ADDED
@@ -0,0 +1,901 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from __future__ import absolute_import
2
+
3
+ import copy
4
+
5
+ from . import (ExprNodes, PyrexTypes, MemoryView,
6
+ ParseTreeTransforms, StringEncoding, Errors)
7
+ from .ExprNodes import CloneNode, ProxyNode, TupleNode
8
+ from .Nodes import FuncDefNode, CFuncDefNode, StatListNode, DefNode
9
+ from ..Utils import OrderedSet
10
+
11
+
12
+ class FusedCFuncDefNode(StatListNode):
13
+ """
14
+ This node replaces a function with fused arguments. It deep-copies the
15
+ function for every permutation of fused types, and allocates a new local
16
+ scope for it. It keeps track of the original function in self.node, and
17
+ the entry of the original function in the symbol table is given the
18
+ 'fused_cfunction' attribute which points back to us.
19
+ Then when a function lookup occurs (to e.g. call it), the call can be
20
+ dispatched to the right function.
21
+
22
+ node FuncDefNode the original function
23
+ nodes [FuncDefNode] list of copies of node with different specific types
24
+ py_func DefNode the fused python function subscriptable from
25
+ Python space
26
+ __signatures__ A DictNode mapping signature specialization strings
27
+ to PyCFunction nodes
28
+ resulting_fused_function PyCFunction for the fused DefNode that delegates
29
+ to specializations
30
+ fused_func_assignment Assignment of the fused function to the function name
31
+ defaults_tuple TupleNode of defaults (letting PyCFunctionNode build
32
+ defaults would result in many different tuples)
33
+ specialized_pycfuncs List of synthesized pycfunction nodes for the
34
+ specializations
35
+ code_object CodeObjectNode shared by all specializations and the
36
+ fused function
37
+
38
+ fused_compound_types All fused (compound) types (e.g. floating[:])
39
+ """
40
+
41
+ __signatures__ = None
42
+ resulting_fused_function = None
43
+ fused_func_assignment = None
44
+ defaults_tuple = None
45
+ decorators = None
46
+
47
+ child_attrs = StatListNode.child_attrs + [
48
+ '__signatures__', 'resulting_fused_function', 'fused_func_assignment']
49
+
50
+ def __init__(self, node, env):
51
+ super(FusedCFuncDefNode, self).__init__(node.pos)
52
+
53
+ self.nodes = []
54
+ self.node = node
55
+
56
+ is_def = isinstance(self.node, DefNode)
57
+ if is_def:
58
+ # self.node.decorators = []
59
+ self.copy_def(env)
60
+ else:
61
+ self.copy_cdef(env)
62
+
63
+ # Perform some sanity checks. If anything fails, it's a bug
64
+ for n in self.nodes:
65
+ assert not n.entry.type.is_fused
66
+ assert not n.local_scope.return_type.is_fused
67
+ if node.return_type.is_fused:
68
+ assert not n.return_type.is_fused
69
+
70
+ if not is_def and n.cfunc_declarator.optional_arg_count:
71
+ assert n.type.op_arg_struct
72
+
73
+ node.entry.fused_cfunction = self
74
+ # Copy the nodes as AnalyseDeclarationsTransform will prepend
75
+ # self.py_func to self.stats, as we only want specialized
76
+ # CFuncDefNodes in self.nodes
77
+ self.stats = self.nodes[:]
78
+
79
+ def copy_def(self, env):
80
+ """
81
+ Create a copy of the original def or lambda function for specialized
82
+ versions.
83
+ """
84
+ fused_compound_types = PyrexTypes.unique(
85
+ [arg.type for arg in self.node.args if arg.type.is_fused])
86
+ fused_types = self._get_fused_base_types(fused_compound_types)
87
+ permutations = PyrexTypes.get_all_specialized_permutations(fused_types)
88
+
89
+ self.fused_compound_types = fused_compound_types
90
+
91
+ if self.node.entry in env.pyfunc_entries:
92
+ env.pyfunc_entries.remove(self.node.entry)
93
+
94
+ for cname, fused_to_specific in permutations:
95
+ copied_node = copy.deepcopy(self.node)
96
+ # keep signature object identity for special casing in DefNode.analyse_declarations()
97
+ copied_node.entry.signature = self.node.entry.signature
98
+
99
+ self._specialize_function_args(copied_node.args, fused_to_specific)
100
+ copied_node.return_type = self.node.return_type.specialize(
101
+ fused_to_specific)
102
+
103
+ copied_node.analyse_declarations(env)
104
+ # copied_node.is_staticmethod = self.node.is_staticmethod
105
+ # copied_node.is_classmethod = self.node.is_classmethod
106
+ self.create_new_local_scope(copied_node, env, fused_to_specific)
107
+ self.specialize_copied_def(copied_node, cname, self.node.entry,
108
+ fused_to_specific, fused_compound_types)
109
+
110
+ PyrexTypes.specialize_entry(copied_node.entry, cname)
111
+ copied_node.entry.used = True
112
+ env.entries[copied_node.entry.name] = copied_node.entry
113
+
114
+ if not self.replace_fused_typechecks(copied_node):
115
+ break
116
+
117
+ self.orig_py_func = self.node
118
+ self.py_func = self.make_fused_cpdef(self.node, env, is_def=True)
119
+
120
+ def copy_cdef(self, env):
121
+ """
122
+ Create a copy of the original c(p)def function for all specialized
123
+ versions.
124
+ """
125
+ permutations = self.node.type.get_all_specialized_permutations()
126
+ # print 'Node %s has %d specializations:' % (self.node.entry.name,
127
+ # len(permutations))
128
+ # import pprint; pprint.pprint([d for cname, d in permutations])
129
+
130
+ # Prevent copying of the python function
131
+ self.orig_py_func = orig_py_func = self.node.py_func
132
+ self.node.py_func = None
133
+ if orig_py_func:
134
+ env.pyfunc_entries.remove(orig_py_func.entry)
135
+
136
+ fused_types = self.node.type.get_fused_types()
137
+ self.fused_compound_types = fused_types
138
+
139
+ new_cfunc_entries = []
140
+ for cname, fused_to_specific in permutations:
141
+ copied_node = copy.deepcopy(self.node)
142
+
143
+ # Make the types in our CFuncType specific.
144
+ type = copied_node.type.specialize(fused_to_specific)
145
+ entry = copied_node.entry
146
+ type.specialize_entry(entry, cname)
147
+
148
+ # Reuse existing Entries (e.g. from .pxd files).
149
+ for i, orig_entry in enumerate(env.cfunc_entries):
150
+ if entry.cname == orig_entry.cname and type.same_as_resolved_type(orig_entry.type):
151
+ copied_node.entry = env.cfunc_entries[i]
152
+ if not copied_node.entry.func_cname:
153
+ copied_node.entry.func_cname = entry.func_cname
154
+ entry = copied_node.entry
155
+ type = entry.type
156
+ break
157
+ else:
158
+ new_cfunc_entries.append(entry)
159
+
160
+ copied_node.type = type
161
+ entry.type, type.entry = type, entry
162
+
163
+ entry.used = (entry.used or
164
+ self.node.entry.defined_in_pxd or
165
+ env.is_c_class_scope or
166
+ entry.is_cmethod)
167
+
168
+ if self.node.cfunc_declarator.optional_arg_count:
169
+ self.node.cfunc_declarator.declare_optional_arg_struct(
170
+ type, env, fused_cname=cname)
171
+
172
+ copied_node.return_type = type.return_type
173
+ self.create_new_local_scope(copied_node, env, fused_to_specific)
174
+
175
+ # Make the argument types in the CFuncDeclarator specific
176
+ self._specialize_function_args(copied_node.cfunc_declarator.args,
177
+ fused_to_specific)
178
+
179
+ # If a cpdef, declare all specialized cpdefs (this
180
+ # also calls analyse_declarations)
181
+ copied_node.declare_cpdef_wrapper(env)
182
+ if copied_node.py_func:
183
+ env.pyfunc_entries.remove(copied_node.py_func.entry)
184
+
185
+ self.specialize_copied_def(
186
+ copied_node.py_func, cname, self.node.entry.as_variable,
187
+ fused_to_specific, fused_types)
188
+
189
+ if not self.replace_fused_typechecks(copied_node):
190
+ break
191
+
192
+ # replace old entry with new entries
193
+ try:
194
+ cindex = env.cfunc_entries.index(self.node.entry)
195
+ except ValueError:
196
+ env.cfunc_entries.extend(new_cfunc_entries)
197
+ else:
198
+ env.cfunc_entries[cindex:cindex+1] = new_cfunc_entries
199
+
200
+ if orig_py_func:
201
+ self.py_func = self.make_fused_cpdef(orig_py_func, env,
202
+ is_def=False)
203
+ else:
204
+ self.py_func = orig_py_func
205
+
206
+ def _get_fused_base_types(self, fused_compound_types):
207
+ """
208
+ Get a list of unique basic fused types, from a list of
209
+ (possibly) compound fused types.
210
+ """
211
+ base_types = []
212
+ seen = set()
213
+ for fused_type in fused_compound_types:
214
+ fused_type.get_fused_types(result=base_types, seen=seen)
215
+ return base_types
216
+
217
+ def _specialize_function_args(self, args, fused_to_specific):
218
+ for arg in args:
219
+ if arg.type.is_fused:
220
+ arg.type = arg.type.specialize(fused_to_specific)
221
+ if arg.type.is_memoryviewslice:
222
+ arg.type.validate_memslice_dtype(arg.pos)
223
+
224
+ def create_new_local_scope(self, node, env, f2s):
225
+ """
226
+ Create a new local scope for the copied node and append it to
227
+ self.nodes. A new local scope is needed because the arguments with the
228
+ fused types are already in the local scope, and we need the specialized
229
+ entries created after analyse_declarations on each specialized version
230
+ of the (CFunc)DefNode.
231
+ f2s is a dict mapping each fused type to its specialized version
232
+ """
233
+ node.create_local_scope(env)
234
+ node.local_scope.fused_to_specific = f2s
235
+
236
+ # This is copied from the original function, set it to false to
237
+ # stop recursion
238
+ node.has_fused_arguments = False
239
+ self.nodes.append(node)
240
+
241
+ def specialize_copied_def(self, node, cname, py_entry, f2s, fused_compound_types):
242
+ """Specialize the copy of a DefNode given the copied node,
243
+ the specialization cname and the original DefNode entry"""
244
+ fused_types = self._get_fused_base_types(fused_compound_types)
245
+ type_strings = [
246
+ PyrexTypes.specialization_signature_string(fused_type, f2s)
247
+ for fused_type in fused_types
248
+ ]
249
+
250
+ node.specialized_signature_string = '|'.join(type_strings)
251
+
252
+ node.entry.pymethdef_cname = PyrexTypes.get_fused_cname(
253
+ cname, node.entry.pymethdef_cname)
254
+ node.entry.doc = py_entry.doc
255
+ node.entry.doc_cname = py_entry.doc_cname
256
+
257
+ def replace_fused_typechecks(self, copied_node):
258
+ """
259
+ Branch-prune fused type checks like
260
+
261
+ if fused_t is int:
262
+ ...
263
+
264
+ Returns whether an error was issued and whether we should stop in
265
+ in order to prevent a flood of errors.
266
+ """
267
+ num_errors = Errors.num_errors
268
+ transform = ParseTreeTransforms.ReplaceFusedTypeChecks(
269
+ copied_node.local_scope)
270
+ transform(copied_node)
271
+
272
+ if Errors.num_errors > num_errors:
273
+ return False
274
+
275
+ return True
276
+
277
+ def _fused_instance_checks(self, normal_types, pyx_code, env):
278
+ """
279
+ Generate Cython code for instance checks, matching an object to
280
+ specialized types.
281
+ """
282
+ for specialized_type in normal_types:
283
+ # all_numeric = all_numeric and specialized_type.is_numeric
284
+ pyx_code.context.update(
285
+ py_type_name=specialized_type.py_type_name(),
286
+ specialized_type_name=specialized_type.specialization_string,
287
+ )
288
+ pyx_code.put_chunk(
289
+ u"""
290
+ if isinstance(arg, {{py_type_name}}):
291
+ dest_sig[{{dest_sig_idx}}] = '{{specialized_type_name}}'; break
292
+ """)
293
+
294
+ def _dtype_name(self, dtype):
295
+ if dtype.is_typedef:
296
+ return '___pyx_%s' % dtype
297
+ return str(dtype).replace(' ', '_')
298
+
299
+ def _dtype_type(self, dtype):
300
+ if dtype.is_typedef:
301
+ return self._dtype_name(dtype)
302
+ return str(dtype)
303
+
304
+ def _sizeof_dtype(self, dtype):
305
+ if dtype.is_pyobject:
306
+ return 'sizeof(void *)'
307
+ else:
308
+ return "sizeof(%s)" % self._dtype_type(dtype)
309
+
310
+ def _buffer_check_numpy_dtype_setup_cases(self, pyx_code):
311
+ "Setup some common cases to match dtypes against specializations"
312
+ if pyx_code.indenter("if kind in b'iu':"):
313
+ pyx_code.putln("pass")
314
+ pyx_code.named_insertion_point("dtype_int")
315
+ pyx_code.dedent()
316
+
317
+ if pyx_code.indenter("elif kind == b'f':"):
318
+ pyx_code.putln("pass")
319
+ pyx_code.named_insertion_point("dtype_float")
320
+ pyx_code.dedent()
321
+
322
+ if pyx_code.indenter("elif kind == b'c':"):
323
+ pyx_code.putln("pass")
324
+ pyx_code.named_insertion_point("dtype_complex")
325
+ pyx_code.dedent()
326
+
327
+ if pyx_code.indenter("elif kind == b'O':"):
328
+ pyx_code.putln("pass")
329
+ pyx_code.named_insertion_point("dtype_object")
330
+ pyx_code.dedent()
331
+
332
+ match = "dest_sig[{{dest_sig_idx}}] = '{{specialized_type_name}}'"
333
+ no_match = "dest_sig[{{dest_sig_idx}}] = None"
334
+ def _buffer_check_numpy_dtype(self, pyx_code, specialized_buffer_types, pythran_types):
335
+ """
336
+ Match a numpy dtype object to the individual specializations.
337
+ """
338
+ self._buffer_check_numpy_dtype_setup_cases(pyx_code)
339
+
340
+ for specialized_type in pythran_types+specialized_buffer_types:
341
+ final_type = specialized_type
342
+ if specialized_type.is_pythran_expr:
343
+ specialized_type = specialized_type.org_buffer
344
+ dtype = specialized_type.dtype
345
+ pyx_code.context.update(
346
+ itemsize_match=self._sizeof_dtype(dtype) + " == itemsize",
347
+ signed_match="not (%s_is_signed ^ dtype_signed)" % self._dtype_name(dtype),
348
+ dtype=dtype,
349
+ specialized_type_name=final_type.specialization_string)
350
+
351
+ dtypes = [
352
+ (dtype.is_int, pyx_code.dtype_int),
353
+ (dtype.is_float, pyx_code.dtype_float),
354
+ (dtype.is_complex, pyx_code.dtype_complex)
355
+ ]
356
+
357
+ for dtype_category, codewriter in dtypes:
358
+ if dtype_category:
359
+ cond = '{{itemsize_match}} and (<Py_ssize_t>arg.ndim) == %d' % (
360
+ specialized_type.ndim,)
361
+ if dtype.is_int:
362
+ cond += ' and {{signed_match}}'
363
+
364
+ if final_type.is_pythran_expr:
365
+ cond += ' and arg_is_pythran_compatible'
366
+
367
+ if codewriter.indenter("if %s:" % cond):
368
+ #codewriter.putln("print 'buffer match found based on numpy dtype'")
369
+ codewriter.putln(self.match)
370
+ codewriter.putln("break")
371
+ codewriter.dedent()
372
+
373
+ def _buffer_parse_format_string_check(self, pyx_code, decl_code,
374
+ specialized_type, env):
375
+ """
376
+ For each specialized type, try to coerce the object to a memoryview
377
+ slice of that type. This means obtaining a buffer and parsing the
378
+ format string.
379
+ TODO: separate buffer acquisition from format parsing
380
+ """
381
+ dtype = specialized_type.dtype
382
+ if specialized_type.is_buffer:
383
+ axes = [('direct', 'strided')] * specialized_type.ndim
384
+ else:
385
+ axes = specialized_type.axes
386
+
387
+ memslice_type = PyrexTypes.MemoryViewSliceType(dtype, axes)
388
+ memslice_type.create_from_py_utility_code(env)
389
+ pyx_code.context.update(
390
+ coerce_from_py_func=memslice_type.from_py_function,
391
+ dtype=dtype)
392
+ decl_code.putln(
393
+ "{{memviewslice_cname}} {{coerce_from_py_func}}(object, int)")
394
+
395
+ pyx_code.context.update(
396
+ specialized_type_name=specialized_type.specialization_string,
397
+ sizeof_dtype=self._sizeof_dtype(dtype))
398
+
399
+ pyx_code.put_chunk(
400
+ u"""
401
+ # try {{dtype}}
402
+ if itemsize == -1 or itemsize == {{sizeof_dtype}}:
403
+ memslice = {{coerce_from_py_func}}(arg, 0)
404
+ if memslice.memview:
405
+ __PYX_XDEC_MEMVIEW(&memslice, 1)
406
+ # print 'found a match for the buffer through format parsing'
407
+ %s
408
+ break
409
+ else:
410
+ __pyx_PyErr_Clear()
411
+ """ % self.match)
412
+
413
+ def _buffer_checks(self, buffer_types, pythran_types, pyx_code, decl_code, env):
414
+ """
415
+ Generate Cython code to match objects to buffer specializations.
416
+ First try to get a numpy dtype object and match it against the individual
417
+ specializations. If that fails, try naively to coerce the object
418
+ to each specialization, which obtains the buffer each time and tries
419
+ to match the format string.
420
+ """
421
+ # The first thing to find a match in this loop breaks out of the loop
422
+ pyx_code.put_chunk(
423
+ u"""
424
+ """ + (u"arg_is_pythran_compatible = False" if pythran_types else u"") + u"""
425
+ if ndarray is not None:
426
+ if isinstance(arg, ndarray):
427
+ dtype = arg.dtype
428
+ """ + (u"arg_is_pythran_compatible = True" if pythran_types else u"") + u"""
429
+ elif __pyx_memoryview_check(arg):
430
+ arg_base = arg.base
431
+ if isinstance(arg_base, ndarray):
432
+ dtype = arg_base.dtype
433
+ else:
434
+ dtype = None
435
+ else:
436
+ dtype = None
437
+
438
+ itemsize = -1
439
+ if dtype is not None:
440
+ itemsize = dtype.itemsize
441
+ kind = ord(dtype.kind)
442
+ dtype_signed = kind == 'i'
443
+ """)
444
+ pyx_code.indent(2)
445
+ if pythran_types:
446
+ pyx_code.put_chunk(
447
+ u"""
448
+ # Pythran only supports the endianness of the current compiler
449
+ byteorder = dtype.byteorder
450
+ if byteorder == "<" and not __Pyx_Is_Little_Endian():
451
+ arg_is_pythran_compatible = False
452
+ elif byteorder == ">" and __Pyx_Is_Little_Endian():
453
+ arg_is_pythran_compatible = False
454
+ if arg_is_pythran_compatible:
455
+ cur_stride = itemsize
456
+ shape = arg.shape
457
+ strides = arg.strides
458
+ for i in range(arg.ndim-1, -1, -1):
459
+ if (<Py_ssize_t>strides[i]) != cur_stride:
460
+ arg_is_pythran_compatible = False
461
+ break
462
+ cur_stride *= <Py_ssize_t> shape[i]
463
+ else:
464
+ arg_is_pythran_compatible = not (arg.flags.f_contiguous and (<Py_ssize_t>arg.ndim) > 1)
465
+ """)
466
+ pyx_code.named_insertion_point("numpy_dtype_checks")
467
+ self._buffer_check_numpy_dtype(pyx_code, buffer_types, pythran_types)
468
+ pyx_code.dedent(2)
469
+
470
+ for specialized_type in buffer_types:
471
+ self._buffer_parse_format_string_check(
472
+ pyx_code, decl_code, specialized_type, env)
473
+
474
+ def _buffer_declarations(self, pyx_code, decl_code, all_buffer_types, pythran_types):
475
+ """
476
+ If we have any buffer specializations, write out some variable
477
+ declarations and imports.
478
+ """
479
+ decl_code.put_chunk(
480
+ u"""
481
+ ctypedef struct {{memviewslice_cname}}:
482
+ void *memview
483
+
484
+ void __PYX_XDEC_MEMVIEW({{memviewslice_cname}} *, int have_gil)
485
+ bint __pyx_memoryview_check(object)
486
+ """)
487
+
488
+ pyx_code.local_variable_declarations.put_chunk(
489
+ u"""
490
+ cdef {{memviewslice_cname}} memslice
491
+ cdef Py_ssize_t itemsize
492
+ cdef bint dtype_signed
493
+ cdef char kind
494
+
495
+ itemsize = -1
496
+ """)
497
+
498
+ if pythran_types:
499
+ pyx_code.local_variable_declarations.put_chunk(u"""
500
+ cdef bint arg_is_pythran_compatible
501
+ cdef Py_ssize_t cur_stride
502
+ """)
503
+
504
+ pyx_code.imports.put_chunk(
505
+ u"""
506
+ cdef type ndarray
507
+ ndarray = __Pyx_ImportNumPyArrayTypeIfAvailable()
508
+ """)
509
+
510
+ seen_typedefs = set()
511
+ seen_int_dtypes = set()
512
+ for buffer_type in all_buffer_types:
513
+ dtype = buffer_type.dtype
514
+ dtype_name = self._dtype_name(dtype)
515
+ if dtype.is_typedef:
516
+ if dtype_name not in seen_typedefs:
517
+ seen_typedefs.add(dtype_name)
518
+ decl_code.putln(
519
+ 'ctypedef %s %s "%s"' % (dtype.resolve(), dtype_name,
520
+ dtype.empty_declaration_code()))
521
+
522
+ if buffer_type.dtype.is_int:
523
+ if str(dtype) not in seen_int_dtypes:
524
+ seen_int_dtypes.add(str(dtype))
525
+ pyx_code.context.update(dtype_name=dtype_name,
526
+ dtype_type=self._dtype_type(dtype))
527
+ pyx_code.local_variable_declarations.put_chunk(
528
+ u"""
529
+ cdef bint {{dtype_name}}_is_signed
530
+ {{dtype_name}}_is_signed = not (<{{dtype_type}}> -1 > 0)
531
+ """)
532
+
533
+ def _split_fused_types(self, arg):
534
+ """
535
+ Specialize fused types and split into normal types and buffer types.
536
+ """
537
+ specialized_types = PyrexTypes.get_specialized_types(arg.type)
538
+
539
+ # Prefer long over int, etc by sorting (see type classes in PyrexTypes.py)
540
+ specialized_types.sort()
541
+
542
+ seen_py_type_names = set()
543
+ normal_types, buffer_types, pythran_types = [], [], []
544
+ has_object_fallback = False
545
+ for specialized_type in specialized_types:
546
+ py_type_name = specialized_type.py_type_name()
547
+ if py_type_name:
548
+ if py_type_name in seen_py_type_names:
549
+ continue
550
+ seen_py_type_names.add(py_type_name)
551
+ if py_type_name == 'object':
552
+ has_object_fallback = True
553
+ else:
554
+ normal_types.append(specialized_type)
555
+ elif specialized_type.is_pythran_expr:
556
+ pythran_types.append(specialized_type)
557
+ elif specialized_type.is_buffer or specialized_type.is_memoryviewslice:
558
+ buffer_types.append(specialized_type)
559
+
560
+ return normal_types, buffer_types, pythran_types, has_object_fallback
561
+
562
+ def _unpack_argument(self, pyx_code):
563
+ pyx_code.put_chunk(
564
+ u"""
565
+ # PROCESSING ARGUMENT {{arg_tuple_idx}}
566
+ if {{arg_tuple_idx}} < len(<tuple>args):
567
+ arg = (<tuple>args)[{{arg_tuple_idx}}]
568
+ elif kwargs is not None and '{{arg.name}}' in <dict>kwargs:
569
+ arg = (<dict>kwargs)['{{arg.name}}']
570
+ else:
571
+ {{if arg.default}}
572
+ arg = (<tuple>defaults)[{{default_idx}}]
573
+ {{else}}
574
+ {{if arg_tuple_idx < min_positional_args}}
575
+ raise TypeError("Expected at least %d argument%s, got %d" % (
576
+ {{min_positional_args}}, {{'"s"' if min_positional_args != 1 else '""'}}, len(<tuple>args)))
577
+ {{else}}
578
+ raise TypeError("Missing keyword-only argument: '%s'" % "{{arg.default}}")
579
+ {{endif}}
580
+ {{endif}}
581
+ """)
582
+
583
+ def make_fused_cpdef(self, orig_py_func, env, is_def):
584
+ """
585
+ This creates the function that is indexable from Python and does
586
+ runtime dispatch based on the argument types. The function gets the
587
+ arg tuple and kwargs dict (or None) and the defaults tuple
588
+ as arguments from the Binding Fused Function's tp_call.
589
+ """
590
+ from . import TreeFragment, Code, UtilityCode
591
+
592
+ fused_types = self._get_fused_base_types([
593
+ arg.type for arg in self.node.args if arg.type.is_fused])
594
+
595
+ context = {
596
+ 'memviewslice_cname': MemoryView.memviewslice_cname,
597
+ 'func_args': self.node.args,
598
+ 'n_fused': len(fused_types),
599
+ 'min_positional_args':
600
+ self.node.num_required_args - self.node.num_required_kw_args
601
+ if is_def else
602
+ sum(1 for arg in self.node.args if arg.default is None),
603
+ 'name': orig_py_func.entry.name,
604
+ }
605
+
606
+ pyx_code = Code.PyxCodeWriter(context=context)
607
+ decl_code = Code.PyxCodeWriter(context=context)
608
+ decl_code.put_chunk(
609
+ u"""
610
+ cdef extern from *:
611
+ void __pyx_PyErr_Clear "PyErr_Clear" ()
612
+ type __Pyx_ImportNumPyArrayTypeIfAvailable()
613
+ int __Pyx_Is_Little_Endian()
614
+ """)
615
+ decl_code.indent()
616
+
617
+ pyx_code.put_chunk(
618
+ u"""
619
+ def __pyx_fused_cpdef(signatures, args, kwargs, defaults):
620
+ # FIXME: use a typed signature - currently fails badly because
621
+ # default arguments inherit the types we specify here!
622
+
623
+ dest_sig = [None] * {{n_fused}}
624
+
625
+ if kwargs is not None and not kwargs:
626
+ kwargs = None
627
+
628
+ cdef Py_ssize_t i
629
+
630
+ # instance check body
631
+ """)
632
+
633
+ pyx_code.indent() # indent following code to function body
634
+ pyx_code.named_insertion_point("imports")
635
+ pyx_code.named_insertion_point("func_defs")
636
+ pyx_code.named_insertion_point("local_variable_declarations")
637
+
638
+ fused_index = 0
639
+ default_idx = 0
640
+ all_buffer_types = OrderedSet()
641
+ seen_fused_types = set()
642
+ for i, arg in enumerate(self.node.args):
643
+ if arg.type.is_fused:
644
+ arg_fused_types = arg.type.get_fused_types()
645
+ if len(arg_fused_types) > 1:
646
+ raise NotImplementedError("Determination of more than one fused base "
647
+ "type per argument is not implemented.")
648
+ fused_type = arg_fused_types[0]
649
+
650
+ if arg.type.is_fused and fused_type not in seen_fused_types:
651
+ seen_fused_types.add(fused_type)
652
+
653
+ context.update(
654
+ arg_tuple_idx=i,
655
+ arg=arg,
656
+ dest_sig_idx=fused_index,
657
+ default_idx=default_idx,
658
+ )
659
+
660
+ normal_types, buffer_types, pythran_types, has_object_fallback = self._split_fused_types(arg)
661
+ self._unpack_argument(pyx_code)
662
+
663
+ # 'unrolled' loop, first match breaks out of it
664
+ if pyx_code.indenter("while 1:"):
665
+ if normal_types:
666
+ self._fused_instance_checks(normal_types, pyx_code, env)
667
+ if buffer_types or pythran_types:
668
+ env.use_utility_code(Code.UtilityCode.load_cached("IsLittleEndian", "ModuleSetupCode.c"))
669
+ self._buffer_checks(buffer_types, pythran_types, pyx_code, decl_code, env)
670
+ if has_object_fallback:
671
+ pyx_code.context.update(specialized_type_name='object')
672
+ pyx_code.putln(self.match)
673
+ else:
674
+ pyx_code.putln(self.no_match)
675
+ pyx_code.putln("break")
676
+ pyx_code.dedent()
677
+
678
+ fused_index += 1
679
+ all_buffer_types.update(buffer_types)
680
+ all_buffer_types.update(ty.org_buffer for ty in pythran_types)
681
+
682
+ if arg.default:
683
+ default_idx += 1
684
+
685
+ if all_buffer_types:
686
+ self._buffer_declarations(pyx_code, decl_code, all_buffer_types, pythran_types)
687
+ env.use_utility_code(Code.UtilityCode.load_cached("Import", "ImportExport.c"))
688
+ env.use_utility_code(Code.UtilityCode.load_cached("ImportNumPyArray", "ImportExport.c"))
689
+
690
+ pyx_code.put_chunk(
691
+ u"""
692
+ candidates = []
693
+ for sig in <dict>signatures:
694
+ match_found = False
695
+ src_sig = sig.strip('()').split('|')
696
+ for i in range(len(dest_sig)):
697
+ dst_type = dest_sig[i]
698
+ if dst_type is not None:
699
+ if src_sig[i] == dst_type:
700
+ match_found = True
701
+ else:
702
+ match_found = False
703
+ break
704
+
705
+ if match_found:
706
+ candidates.append(sig)
707
+
708
+ if not candidates:
709
+ raise TypeError("No matching signature found")
710
+ elif len(candidates) > 1:
711
+ raise TypeError("Function call with ambiguous argument types")
712
+ else:
713
+ return (<dict>signatures)[candidates[0]]
714
+ """)
715
+
716
+ fragment_code = pyx_code.getvalue()
717
+ # print decl_code.getvalue()
718
+ # print fragment_code
719
+ from .Optimize import ConstantFolding
720
+ fragment = TreeFragment.TreeFragment(
721
+ fragment_code, level='module', pipeline=[ConstantFolding()])
722
+ ast = TreeFragment.SetPosTransform(self.node.pos)(fragment.root)
723
+ UtilityCode.declare_declarations_in_scope(
724
+ decl_code.getvalue(), env.global_scope())
725
+ ast.scope = env
726
+ # FIXME: for static methods of cdef classes, we build the wrong signature here: first arg becomes 'self'
727
+ ast.analyse_declarations(env)
728
+ py_func = ast.stats[-1] # the DefNode
729
+ self.fragment_scope = ast.scope
730
+
731
+ if isinstance(self.node, DefNode):
732
+ py_func.specialized_cpdefs = self.nodes[:]
733
+ else:
734
+ py_func.specialized_cpdefs = [n.py_func for n in self.nodes]
735
+
736
+ return py_func
737
+
738
+ def update_fused_defnode_entry(self, env):
739
+ copy_attributes = (
740
+ 'name', 'pos', 'cname', 'func_cname', 'pyfunc_cname',
741
+ 'pymethdef_cname', 'doc', 'doc_cname', 'is_member',
742
+ 'scope'
743
+ )
744
+
745
+ entry = self.py_func.entry
746
+
747
+ for attr in copy_attributes:
748
+ setattr(entry, attr,
749
+ getattr(self.orig_py_func.entry, attr))
750
+
751
+ self.py_func.name = self.orig_py_func.name
752
+ self.py_func.doc = self.orig_py_func.doc
753
+
754
+ env.entries.pop('__pyx_fused_cpdef', None)
755
+ if isinstance(self.node, DefNode):
756
+ env.entries[entry.name] = entry
757
+ else:
758
+ env.entries[entry.name].as_variable = entry
759
+
760
+ env.pyfunc_entries.append(entry)
761
+
762
+ self.py_func.entry.fused_cfunction = self
763
+ for node in self.nodes:
764
+ if isinstance(self.node, DefNode):
765
+ node.fused_py_func = self.py_func
766
+ else:
767
+ node.py_func.fused_py_func = self.py_func
768
+ node.entry.as_variable = entry
769
+
770
+ self.synthesize_defnodes()
771
+ self.stats.append(self.__signatures__)
772
+
773
+ def analyse_expressions(self, env):
774
+ """
775
+ Analyse the expressions. Take care to only evaluate default arguments
776
+ once and clone the result for all specializations
777
+ """
778
+ for fused_compound_type in self.fused_compound_types:
779
+ for fused_type in fused_compound_type.get_fused_types():
780
+ for specialization_type in fused_type.types:
781
+ if specialization_type.is_complex:
782
+ specialization_type.create_declaration_utility_code(env)
783
+
784
+ if self.py_func:
785
+ self.__signatures__ = self.__signatures__.analyse_expressions(env)
786
+ self.py_func = self.py_func.analyse_expressions(env)
787
+ self.resulting_fused_function = self.resulting_fused_function.analyse_expressions(env)
788
+ self.fused_func_assignment = self.fused_func_assignment.analyse_expressions(env)
789
+
790
+ self.defaults = defaults = []
791
+
792
+ for arg in self.node.args:
793
+ if arg.default:
794
+ arg.default = arg.default.analyse_expressions(env)
795
+ defaults.append(ProxyNode(arg.default))
796
+ else:
797
+ defaults.append(None)
798
+
799
+ for i, stat in enumerate(self.stats):
800
+ stat = self.stats[i] = stat.analyse_expressions(env)
801
+ if isinstance(stat, FuncDefNode):
802
+ for arg, default in zip(stat.args, defaults):
803
+ if default is not None:
804
+ arg.default = CloneNode(default).coerce_to(arg.type, env)
805
+
806
+ if self.py_func:
807
+ args = [CloneNode(default) for default in defaults if default]
808
+ self.defaults_tuple = TupleNode(self.pos, args=args)
809
+ self.defaults_tuple = self.defaults_tuple.analyse_types(env, skip_children=True).coerce_to_pyobject(env)
810
+ self.defaults_tuple = ProxyNode(self.defaults_tuple)
811
+ self.code_object = ProxyNode(self.specialized_pycfuncs[0].code_object)
812
+
813
+ fused_func = self.resulting_fused_function.arg
814
+ fused_func.defaults_tuple = CloneNode(self.defaults_tuple)
815
+ fused_func.code_object = CloneNode(self.code_object)
816
+
817
+ for i, pycfunc in enumerate(self.specialized_pycfuncs):
818
+ pycfunc.code_object = CloneNode(self.code_object)
819
+ pycfunc = self.specialized_pycfuncs[i] = pycfunc.analyse_types(env)
820
+ pycfunc.defaults_tuple = CloneNode(self.defaults_tuple)
821
+ return self
822
+
823
+ def synthesize_defnodes(self):
824
+ """
825
+ Create the __signatures__ dict of PyCFunctionNode specializations.
826
+ """
827
+ if isinstance(self.nodes[0], CFuncDefNode):
828
+ nodes = [node.py_func for node in self.nodes]
829
+ else:
830
+ nodes = self.nodes
831
+
832
+ signatures = [StringEncoding.EncodedString(node.specialized_signature_string)
833
+ for node in nodes]
834
+ keys = [ExprNodes.StringNode(node.pos, value=sig)
835
+ for node, sig in zip(nodes, signatures)]
836
+ values = [ExprNodes.PyCFunctionNode.from_defnode(node, binding=True)
837
+ for node in nodes]
838
+
839
+ self.__signatures__ = ExprNodes.DictNode.from_pairs(self.pos, zip(keys, values))
840
+
841
+ self.specialized_pycfuncs = values
842
+ for pycfuncnode in values:
843
+ pycfuncnode.is_specialization = True
844
+
845
+ def generate_function_definitions(self, env, code):
846
+ if self.py_func:
847
+ self.py_func.pymethdef_required = True
848
+ self.fused_func_assignment.generate_function_definitions(env, code)
849
+
850
+ for stat in self.stats:
851
+ if isinstance(stat, FuncDefNode) and stat.entry.used:
852
+ code.mark_pos(stat.pos)
853
+ stat.generate_function_definitions(env, code)
854
+
855
+ def generate_execution_code(self, code):
856
+ # Note: all def function specialization are wrapped in PyCFunction
857
+ # nodes in the self.__signatures__ dictnode.
858
+ for default in self.defaults:
859
+ if default is not None:
860
+ default.generate_evaluation_code(code)
861
+
862
+ if self.py_func:
863
+ self.defaults_tuple.generate_evaluation_code(code)
864
+ self.code_object.generate_evaluation_code(code)
865
+
866
+ for stat in self.stats:
867
+ code.mark_pos(stat.pos)
868
+ if isinstance(stat, ExprNodes.ExprNode):
869
+ stat.generate_evaluation_code(code)
870
+ else:
871
+ stat.generate_execution_code(code)
872
+
873
+ if self.__signatures__:
874
+ self.resulting_fused_function.generate_evaluation_code(code)
875
+
876
+ code.putln(
877
+ "((__pyx_FusedFunctionObject *) %s)->__signatures__ = %s;" %
878
+ (self.resulting_fused_function.result(),
879
+ self.__signatures__.result()))
880
+ code.put_giveref(self.__signatures__.result())
881
+ self.__signatures__.generate_post_assignment_code(code)
882
+ self.__signatures__.free_temps(code)
883
+
884
+ self.fused_func_assignment.generate_execution_code(code)
885
+
886
+ # Dispose of results
887
+ self.resulting_fused_function.generate_disposal_code(code)
888
+ self.resulting_fused_function.free_temps(code)
889
+ self.defaults_tuple.generate_disposal_code(code)
890
+ self.defaults_tuple.free_temps(code)
891
+ self.code_object.generate_disposal_code(code)
892
+ self.code_object.free_temps(code)
893
+
894
+ for default in self.defaults:
895
+ if default is not None:
896
+ default.generate_disposal_code(code)
897
+ default.free_temps(code)
898
+
899
+ def annotate(self, code):
900
+ for stat in self.stats:
901
+ stat.annotate(code)