Cython 3.2.0__cp39-abi3-win32.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- Cython/Build/BuildExecutable.py +169 -0
- Cython/Build/Cache.py +199 -0
- Cython/Build/Cythonize.py +350 -0
- Cython/Build/Dependencies.py +1314 -0
- Cython/Build/Distutils.py +1 -0
- Cython/Build/Inline.py +463 -0
- Cython/Build/IpythonMagic.py +560 -0
- Cython/Build/SharedModule.py +94 -0
- Cython/Build/Tests/TestCyCache.py +194 -0
- Cython/Build/Tests/TestCythonizeArgsParser.py +481 -0
- Cython/Build/Tests/TestDependencies.py +133 -0
- Cython/Build/Tests/TestInline.py +177 -0
- Cython/Build/Tests/TestIpythonMagic.py +287 -0
- Cython/Build/Tests/TestRecythonize.py +212 -0
- Cython/Build/Tests/TestStripLiterals.py +155 -0
- Cython/Build/Tests/__init__.py +1 -0
- Cython/Build/__init__.py +11 -0
- Cython/CodeWriter.py +815 -0
- Cython/Compiler/AnalysedTreeTransforms.py +97 -0
- Cython/Compiler/Annotate.py +328 -0
- Cython/Compiler/AutoDocTransforms.py +320 -0
- Cython/Compiler/Buffer.py +680 -0
- Cython/Compiler/Builtin.py +984 -0
- Cython/Compiler/CmdLine.py +263 -0
- Cython/Compiler/Code.pxd +149 -0
- Cython/Compiler/Code.py +3746 -0
- Cython/Compiler/Code.pyd +0 -0
- Cython/Compiler/CodeGeneration.py +33 -0
- Cython/Compiler/CythonScope.py +191 -0
- Cython/Compiler/Dataclass.py +864 -0
- Cython/Compiler/DebugFlags.py +24 -0
- Cython/Compiler/Errors.py +297 -0
- Cython/Compiler/ExprNodes.py +15562 -0
- Cython/Compiler/FlowControl.pxd +97 -0
- Cython/Compiler/FlowControl.py +1451 -0
- Cython/Compiler/FlowControl.pyd +0 -0
- Cython/Compiler/FusedNode.py +971 -0
- Cython/Compiler/FusedNode.pyd +0 -0
- Cython/Compiler/Future.py +16 -0
- Cython/Compiler/Interpreter.py +57 -0
- Cython/Compiler/Lexicon.py +421 -0
- Cython/Compiler/LineTable.py +114 -0
- Cython/Compiler/LineTable.pyd +0 -0
- Cython/Compiler/Main.py +857 -0
- Cython/Compiler/MatchCaseNodes.py +259 -0
- Cython/Compiler/MemoryView.py +905 -0
- Cython/Compiler/ModuleNode.py +4235 -0
- Cython/Compiler/Naming.py +363 -0
- Cython/Compiler/Nodes.py +10831 -0
- Cython/Compiler/Optimize.py +5288 -0
- Cython/Compiler/Options.py +843 -0
- Cython/Compiler/ParseTreeTransforms.pxd +78 -0
- Cython/Compiler/ParseTreeTransforms.py +4638 -0
- Cython/Compiler/Parsing.pxd +9 -0
- Cython/Compiler/Parsing.py +4775 -0
- Cython/Compiler/Parsing.pyd +0 -0
- Cython/Compiler/Pipeline.py +439 -0
- Cython/Compiler/PyrexTypes.py +5870 -0
- Cython/Compiler/Pythran.py +232 -0
- Cython/Compiler/Scanning.pxd +48 -0
- Cython/Compiler/Scanning.py +701 -0
- Cython/Compiler/Scanning.pyd +0 -0
- Cython/Compiler/StringEncoding.py +298 -0
- Cython/Compiler/Symtab.py +3073 -0
- Cython/Compiler/Tests/TestBuffer.py +105 -0
- Cython/Compiler/Tests/TestBuiltin.py +72 -0
- Cython/Compiler/Tests/TestCmdLine.py +586 -0
- Cython/Compiler/Tests/TestCode.py +144 -0
- Cython/Compiler/Tests/TestFlowControl.py +65 -0
- Cython/Compiler/Tests/TestGrammar.py +202 -0
- Cython/Compiler/Tests/TestMemView.py +71 -0
- Cython/Compiler/Tests/TestParseTreeTransforms.py +285 -0
- Cython/Compiler/Tests/TestScanning.py +134 -0
- Cython/Compiler/Tests/TestSignatureMatching.py +73 -0
- Cython/Compiler/Tests/TestStringEncoding.py +21 -0
- Cython/Compiler/Tests/TestTreeFragment.py +63 -0
- Cython/Compiler/Tests/TestTreePath.py +103 -0
- Cython/Compiler/Tests/TestTypes.py +75 -0
- Cython/Compiler/Tests/TestUtilityLoad.py +112 -0
- Cython/Compiler/Tests/TestVisitor.py +61 -0
- Cython/Compiler/Tests/Utils.py +36 -0
- Cython/Compiler/Tests/__init__.py +1 -0
- Cython/Compiler/TreeFragment.py +278 -0
- Cython/Compiler/TreePath.py +303 -0
- Cython/Compiler/TypeInference.py +591 -0
- Cython/Compiler/TypeSlots.py +1174 -0
- Cython/Compiler/UFuncs.py +311 -0
- Cython/Compiler/UtilNodes.py +389 -0
- Cython/Compiler/UtilityCode.py +344 -0
- Cython/Compiler/Version.py +8 -0
- Cython/Compiler/Visitor.pxd +53 -0
- Cython/Compiler/Visitor.py +861 -0
- Cython/Compiler/Visitor.pyd +0 -0
- Cython/Compiler/__init__.py +1 -0
- Cython/Coverage.py +448 -0
- Cython/Debugger/Cygdb.py +177 -0
- Cython/Debugger/DebugWriter.py +82 -0
- Cython/Debugger/Tests/TestLibCython.py +275 -0
- Cython/Debugger/Tests/__init__.py +1 -0
- Cython/Debugger/Tests/cfuncs.c +8 -0
- Cython/Debugger/Tests/codefile +49 -0
- Cython/Debugger/Tests/test_libcython_in_gdb.py +578 -0
- Cython/Debugger/Tests/test_libpython_in_gdb.py +90 -0
- Cython/Debugger/__init__.py +1 -0
- Cython/Debugger/libcython.py +1548 -0
- Cython/Debugger/libpython.py +2821 -0
- Cython/Debugging.py +20 -0
- Cython/Distutils/__init__.py +2 -0
- Cython/Distutils/build_ext.py +139 -0
- Cython/Distutils/extension.py +96 -0
- Cython/Distutils/old_build_ext.py +351 -0
- Cython/Includes/cpython/__init__.pxd +173 -0
- Cython/Includes/cpython/array.pxd +178 -0
- Cython/Includes/cpython/bool.pxd +37 -0
- Cython/Includes/cpython/buffer.pxd +112 -0
- Cython/Includes/cpython/bytearray.pxd +33 -0
- Cython/Includes/cpython/bytes.pxd +200 -0
- Cython/Includes/cpython/cellobject.pxd +35 -0
- Cython/Includes/cpython/ceval.pxd +8 -0
- Cython/Includes/cpython/codecs.pxd +121 -0
- Cython/Includes/cpython/complex.pxd +60 -0
- Cython/Includes/cpython/contextvars.pxd +145 -0
- Cython/Includes/cpython/conversion.pxd +36 -0
- Cython/Includes/cpython/datetime.pxd +395 -0
- Cython/Includes/cpython/descr.pxd +26 -0
- Cython/Includes/cpython/dict.pxd +187 -0
- Cython/Includes/cpython/exc.pxd +263 -0
- Cython/Includes/cpython/fileobject.pxd +57 -0
- Cython/Includes/cpython/float.pxd +47 -0
- Cython/Includes/cpython/function.pxd +65 -0
- Cython/Includes/cpython/genobject.pxd +25 -0
- Cython/Includes/cpython/getargs.pxd +12 -0
- Cython/Includes/cpython/instance.pxd +25 -0
- Cython/Includes/cpython/iterator.pxd +36 -0
- Cython/Includes/cpython/iterobject.pxd +24 -0
- Cython/Includes/cpython/list.pxd +92 -0
- Cython/Includes/cpython/long.pxd +149 -0
- Cython/Includes/cpython/longintrepr.pxd +14 -0
- Cython/Includes/cpython/mapping.pxd +63 -0
- Cython/Includes/cpython/marshal.pxd +66 -0
- Cython/Includes/cpython/mem.pxd +120 -0
- Cython/Includes/cpython/memoryview.pxd +50 -0
- Cython/Includes/cpython/method.pxd +49 -0
- Cython/Includes/cpython/module.pxd +208 -0
- Cython/Includes/cpython/number.pxd +258 -0
- Cython/Includes/cpython/object.pxd +433 -0
- Cython/Includes/cpython/pycapsule.pxd +143 -0
- Cython/Includes/cpython/pylifecycle.pxd +68 -0
- Cython/Includes/cpython/pyport.pxd +8 -0
- Cython/Includes/cpython/pystate.pxd +95 -0
- Cython/Includes/cpython/pythread.pxd +53 -0
- Cython/Includes/cpython/ref.pxd +141 -0
- Cython/Includes/cpython/sequence.pxd +134 -0
- Cython/Includes/cpython/set.pxd +119 -0
- Cython/Includes/cpython/slice.pxd +70 -0
- Cython/Includes/cpython/time.pxd +129 -0
- Cython/Includes/cpython/tuple.pxd +72 -0
- Cython/Includes/cpython/type.pxd +53 -0
- Cython/Includes/cpython/unicode.pxd +639 -0
- Cython/Includes/cpython/version.pxd +32 -0
- Cython/Includes/cpython/weakref.pxd +78 -0
- Cython/Includes/libc/__init__.pxd +1 -0
- Cython/Includes/libc/complex.pxd +35 -0
- Cython/Includes/libc/errno.pxd +127 -0
- Cython/Includes/libc/float.pxd +43 -0
- Cython/Includes/libc/limits.pxd +28 -0
- Cython/Includes/libc/locale.pxd +46 -0
- Cython/Includes/libc/math.pxd +209 -0
- Cython/Includes/libc/setjmp.pxd +10 -0
- Cython/Includes/libc/signal.pxd +64 -0
- Cython/Includes/libc/stddef.pxd +9 -0
- Cython/Includes/libc/stdint.pxd +105 -0
- Cython/Includes/libc/stdio.pxd +80 -0
- Cython/Includes/libc/stdlib.pxd +72 -0
- Cython/Includes/libc/string.pxd +50 -0
- Cython/Includes/libc/threads.pxd +234 -0
- Cython/Includes/libc/time.pxd +52 -0
- Cython/Includes/libcpp/__init__.pxd +4 -0
- Cython/Includes/libcpp/algorithm.pxd +320 -0
- Cython/Includes/libcpp/any.pxd +16 -0
- Cython/Includes/libcpp/atomic.pxd +59 -0
- Cython/Includes/libcpp/barrier.pxd +22 -0
- Cython/Includes/libcpp/bit.pxd +29 -0
- Cython/Includes/libcpp/cast.pxd +12 -0
- Cython/Includes/libcpp/cmath.pxd +518 -0
- Cython/Includes/libcpp/complex.pxd +106 -0
- Cython/Includes/libcpp/condition_variable.pxd +322 -0
- Cython/Includes/libcpp/deque.pxd +165 -0
- Cython/Includes/libcpp/exception.pxd +86 -0
- Cython/Includes/libcpp/execution.pxd +15 -0
- Cython/Includes/libcpp/forward_list.pxd +63 -0
- Cython/Includes/libcpp/functional.pxd +26 -0
- Cython/Includes/libcpp/future.pxd +103 -0
- Cython/Includes/libcpp/iterator.pxd +34 -0
- Cython/Includes/libcpp/latch.pxd +17 -0
- Cython/Includes/libcpp/limits.pxd +61 -0
- Cython/Includes/libcpp/list.pxd +117 -0
- Cython/Includes/libcpp/map.pxd +252 -0
- Cython/Includes/libcpp/memory.pxd +115 -0
- Cython/Includes/libcpp/mutex.pxd +387 -0
- Cython/Includes/libcpp/numbers.pxd +15 -0
- Cython/Includes/libcpp/numeric.pxd +131 -0
- Cython/Includes/libcpp/optional.pxd +34 -0
- Cython/Includes/libcpp/pair.pxd +1 -0
- Cython/Includes/libcpp/queue.pxd +25 -0
- Cython/Includes/libcpp/random.pxd +166 -0
- Cython/Includes/libcpp/semaphore.pxd +43 -0
- Cython/Includes/libcpp/set.pxd +228 -0
- Cython/Includes/libcpp/shared_mutex.pxd +96 -0
- Cython/Includes/libcpp/span.pxd +87 -0
- Cython/Includes/libcpp/stack.pxd +11 -0
- Cython/Includes/libcpp/stop_token.pxd +117 -0
- Cython/Includes/libcpp/string.pxd +355 -0
- Cython/Includes/libcpp/string_view.pxd +183 -0
- Cython/Includes/libcpp/typeindex.pxd +15 -0
- Cython/Includes/libcpp/typeinfo.pxd +10 -0
- Cython/Includes/libcpp/unordered_map.pxd +193 -0
- Cython/Includes/libcpp/unordered_set.pxd +152 -0
- Cython/Includes/libcpp/utility.pxd +30 -0
- Cython/Includes/libcpp/vector.pxd +186 -0
- Cython/Includes/numpy/math.pxd +150 -0
- Cython/Includes/openmp.pxd +50 -0
- Cython/Includes/posix/__init__.pxd +1 -0
- Cython/Includes/posix/dlfcn.pxd +14 -0
- Cython/Includes/posix/fcntl.pxd +86 -0
- Cython/Includes/posix/ioctl.pxd +4 -0
- Cython/Includes/posix/mman.pxd +101 -0
- Cython/Includes/posix/resource.pxd +57 -0
- Cython/Includes/posix/select.pxd +21 -0
- Cython/Includes/posix/signal.pxd +73 -0
- Cython/Includes/posix/stat.pxd +98 -0
- Cython/Includes/posix/stdio.pxd +37 -0
- Cython/Includes/posix/stdlib.pxd +29 -0
- Cython/Includes/posix/strings.pxd +9 -0
- Cython/Includes/posix/time.pxd +71 -0
- Cython/Includes/posix/types.pxd +30 -0
- Cython/Includes/posix/uio.pxd +26 -0
- Cython/Includes/posix/unistd.pxd +271 -0
- Cython/Includes/posix/wait.pxd +38 -0
- Cython/Plex/Actions.pxd +24 -0
- Cython/Plex/Actions.py +119 -0
- Cython/Plex/Actions.pyd +0 -0
- Cython/Plex/DFA.pxd +14 -0
- Cython/Plex/DFA.py +164 -0
- Cython/Plex/DFA.pyd +0 -0
- Cython/Plex/Errors.py +48 -0
- Cython/Plex/Lexicons.py +178 -0
- Cython/Plex/Machines.pxd +36 -0
- Cython/Plex/Machines.py +238 -0
- Cython/Plex/Machines.pyd +0 -0
- Cython/Plex/Regexps.py +535 -0
- Cython/Plex/Scanners.pxd +45 -0
- Cython/Plex/Scanners.py +328 -0
- Cython/Plex/Scanners.pyd +0 -0
- Cython/Plex/Transitions.pxd +14 -0
- Cython/Plex/Transitions.py +239 -0
- Cython/Plex/Transitions.pyd +0 -0
- Cython/Plex/__init__.py +34 -0
- Cython/Runtime/__init__.py +1 -0
- Cython/Runtime/refnanny.pyd +0 -0
- Cython/Runtime/refnanny.pyx +237 -0
- Cython/Shadow.py +690 -0
- Cython/Shadow.pyi +521 -0
- Cython/StringIOTree.py +170 -0
- Cython/StringIOTree.pyd +0 -0
- Cython/Tempita/__init__.py +4 -0
- Cython/Tempita/_looper.py +154 -0
- Cython/Tempita/_tempita.py +1091 -0
- Cython/Tempita/_tempita.pyd +0 -0
- Cython/TestUtils.py +422 -0
- Cython/Tests/TestCodeWriter.py +128 -0
- Cython/Tests/TestCythonUtils.py +202 -0
- Cython/Tests/TestJediTyper.py +223 -0
- Cython/Tests/TestShadow.py +114 -0
- Cython/Tests/TestStringIOTree.py +67 -0
- Cython/Tests/TestTestUtils.py +90 -0
- Cython/Tests/__init__.py +1 -0
- Cython/Tests/xmlrunner.py +390 -0
- Cython/Utility/AsyncGen.c +1031 -0
- Cython/Utility/Buffer.c +865 -0
- Cython/Utility/BufferFormatFromTypeInfo.pxd +2 -0
- Cython/Utility/Builtins.c +810 -0
- Cython/Utility/CConvert.pyx +134 -0
- Cython/Utility/CMath.c +104 -0
- Cython/Utility/CommonStructures.c +226 -0
- Cython/Utility/Complex.c +378 -0
- Cython/Utility/Coroutine.c +2300 -0
- Cython/Utility/CpdefEnums.pyx +103 -0
- Cython/Utility/CppConvert.pyx +282 -0
- Cython/Utility/CppSupport.cpp +151 -0
- Cython/Utility/CythonFunction.c +1832 -0
- Cython/Utility/Dataclasses.c +101 -0
- Cython/Utility/Embed.c +121 -0
- Cython/Utility/Exceptions.c +1016 -0
- Cython/Utility/ExtensionTypes.c +996 -0
- Cython/Utility/FunctionArguments.c +1043 -0
- Cython/Utility/FusedFunction.pyx +44 -0
- Cython/Utility/ImportExport.c +907 -0
- Cython/Utility/MemoryView.pxd +188 -0
- Cython/Utility/MemoryView.pyx +1482 -0
- Cython/Utility/MemoryView_C.c +927 -0
- Cython/Utility/ModuleSetupCode.c +3203 -0
- Cython/Utility/NumpyImportArray.c +46 -0
- Cython/Utility/ObjectHandling.c +3273 -0
- Cython/Utility/Optimize.c +1603 -0
- Cython/Utility/Overflow.c +384 -0
- Cython/Utility/Printing.c +86 -0
- Cython/Utility/Profile.c +732 -0
- Cython/Utility/StringTools.c +1379 -0
- Cython/Utility/Synchronization.c +399 -0
- Cython/Utility/TString.c +356 -0
- Cython/Utility/TestCyUtilityLoader.pyx +8 -0
- Cython/Utility/TestCythonScope.pyx +75 -0
- Cython/Utility/TestUtilityLoader.c +12 -0
- Cython/Utility/TypeConversion.c +1385 -0
- Cython/Utility/UFuncs.pyx +50 -0
- Cython/Utility/UFuncs_C.c +89 -0
- Cython/Utility/__init__.py +28 -0
- Cython/Utility/arrayarray.h +167 -0
- Cython/Utils.py +687 -0
- Cython/Utils.pyd +0 -0
- Cython/__init__.py +10 -0
- Cython/__init__.pyi +7 -0
- Cython/py.typed +0 -0
- cython-3.2.0.dist-info/METADATA +85 -0
- cython-3.2.0.dist-info/RECORD +333 -0
- cython-3.2.0.dist-info/WHEEL +5 -0
- cython-3.2.0.dist-info/entry_points.txt +4 -0
- cython-3.2.0.dist-info/top_level.txt +3 -0
- cython.py +29 -0
- pyximport/__init__.py +4 -0
- pyximport/pyxbuild.py +160 -0
- pyximport/pyximport.py +482 -0
|
@@ -0,0 +1,303 @@
|
|
|
1
|
+
"""
|
|
2
|
+
A simple XPath-like language for tree traversal.
|
|
3
|
+
|
|
4
|
+
This works by creating a filter chain of generator functions. Each
|
|
5
|
+
function selects a part of the expression, e.g. a child node, a
|
|
6
|
+
specific descendant or a node that holds an attribute.
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
import re
|
|
11
|
+
import operator
|
|
12
|
+
|
|
13
|
+
path_tokenizer = re.compile(
|
|
14
|
+
r"("
|
|
15
|
+
r"b?'[^']*'|b?\"[^\"]*\"|"
|
|
16
|
+
r"//?|"
|
|
17
|
+
r"\(\)|"
|
|
18
|
+
r"==?|"
|
|
19
|
+
r"[/.*\[\]()@])|"
|
|
20
|
+
r"([^/\[\]()@=\s]+)|"
|
|
21
|
+
r"\s+"
|
|
22
|
+
).findall
|
|
23
|
+
|
|
24
|
+
def iterchildren(node, attr_name):
|
|
25
|
+
# returns an iterable of all child nodes of that name
|
|
26
|
+
child = getattr(node, attr_name)
|
|
27
|
+
if child is not None:
|
|
28
|
+
if type(child) is list:
|
|
29
|
+
return child
|
|
30
|
+
else:
|
|
31
|
+
return [child]
|
|
32
|
+
else:
|
|
33
|
+
return ()
|
|
34
|
+
|
|
35
|
+
def _get_first_or_none(it):
|
|
36
|
+
try:
|
|
37
|
+
return next(it)
|
|
38
|
+
except StopIteration:
|
|
39
|
+
return None
|
|
40
|
+
|
|
41
|
+
def type_name(node):
|
|
42
|
+
return node.__class__.__name__.split('.')[-1]
|
|
43
|
+
|
|
44
|
+
def parse_func(next, token):
|
|
45
|
+
name = token[1]
|
|
46
|
+
token = next()
|
|
47
|
+
if token[0] != '(':
|
|
48
|
+
raise ValueError("Expected '(' after function name '%s'" % name)
|
|
49
|
+
predicate = handle_predicate(next, token)
|
|
50
|
+
return name, predicate
|
|
51
|
+
|
|
52
|
+
def handle_func_not(next, token):
|
|
53
|
+
"""
|
|
54
|
+
not(...)
|
|
55
|
+
"""
|
|
56
|
+
name, predicate = parse_func(next, token)
|
|
57
|
+
|
|
58
|
+
def select(result):
|
|
59
|
+
for node in result:
|
|
60
|
+
if _get_first_or_none(predicate([node])) is None:
|
|
61
|
+
yield node
|
|
62
|
+
return select
|
|
63
|
+
|
|
64
|
+
def handle_name(next, token):
|
|
65
|
+
"""
|
|
66
|
+
/NodeName/
|
|
67
|
+
or
|
|
68
|
+
func(...)
|
|
69
|
+
"""
|
|
70
|
+
name = token[1]
|
|
71
|
+
if name in functions:
|
|
72
|
+
return functions[name](next, token)
|
|
73
|
+
def select(result):
|
|
74
|
+
for node in result:
|
|
75
|
+
for attr_name in node.child_attrs:
|
|
76
|
+
for child in iterchildren(node, attr_name):
|
|
77
|
+
if type_name(child) == name:
|
|
78
|
+
yield child
|
|
79
|
+
return select
|
|
80
|
+
|
|
81
|
+
def handle_star(next, token):
|
|
82
|
+
"""
|
|
83
|
+
/*/
|
|
84
|
+
"""
|
|
85
|
+
def select(result):
|
|
86
|
+
for node in result:
|
|
87
|
+
for name in node.child_attrs:
|
|
88
|
+
yield from iterchildren(node, name)
|
|
89
|
+
return select
|
|
90
|
+
|
|
91
|
+
def handle_dot(next, token):
|
|
92
|
+
"""
|
|
93
|
+
/./
|
|
94
|
+
"""
|
|
95
|
+
def select(result):
|
|
96
|
+
return result
|
|
97
|
+
return select
|
|
98
|
+
|
|
99
|
+
def handle_descendants(next, token):
|
|
100
|
+
"""
|
|
101
|
+
//...
|
|
102
|
+
"""
|
|
103
|
+
token = next()
|
|
104
|
+
if token[0] == "*":
|
|
105
|
+
def iter_recursive(node):
|
|
106
|
+
for name in node.child_attrs:
|
|
107
|
+
for child in iterchildren(node, name):
|
|
108
|
+
yield child
|
|
109
|
+
yield from iter_recursive(child)
|
|
110
|
+
elif not token[0]:
|
|
111
|
+
node_name = token[1]
|
|
112
|
+
def iter_recursive(node):
|
|
113
|
+
for name in node.child_attrs:
|
|
114
|
+
for child in iterchildren(node, name):
|
|
115
|
+
if type_name(child) == node_name:
|
|
116
|
+
yield child
|
|
117
|
+
yield from iter_recursive(child)
|
|
118
|
+
else:
|
|
119
|
+
raise ValueError("Expected node name after '//'")
|
|
120
|
+
|
|
121
|
+
def select(result):
|
|
122
|
+
for node in result:
|
|
123
|
+
yield from iter_recursive(node)
|
|
124
|
+
|
|
125
|
+
return select
|
|
126
|
+
|
|
127
|
+
|
|
128
|
+
def handle_attribute(next, token):
|
|
129
|
+
token = next()
|
|
130
|
+
if token[0]:
|
|
131
|
+
raise ValueError("Expected attribute name")
|
|
132
|
+
name = token[1]
|
|
133
|
+
value = None
|
|
134
|
+
token = next.peek()
|
|
135
|
+
if token[0] == '=':
|
|
136
|
+
next()
|
|
137
|
+
value = parse_path_value(next)
|
|
138
|
+
|
|
139
|
+
readattr = operator.attrgetter(name)
|
|
140
|
+
if value is None:
|
|
141
|
+
def select(result):
|
|
142
|
+
for node in result:
|
|
143
|
+
try:
|
|
144
|
+
attr_value = readattr(node)
|
|
145
|
+
except AttributeError:
|
|
146
|
+
continue
|
|
147
|
+
if attr_value is not None:
|
|
148
|
+
yield attr_value
|
|
149
|
+
else:
|
|
150
|
+
def select(result):
|
|
151
|
+
for node in result:
|
|
152
|
+
try:
|
|
153
|
+
attr_value = readattr(node)
|
|
154
|
+
except AttributeError:
|
|
155
|
+
continue
|
|
156
|
+
if attr_value == value:
|
|
157
|
+
yield attr_value
|
|
158
|
+
elif (isinstance(attr_value, bytes) and isinstance(value, str) and
|
|
159
|
+
attr_value == value.encode()):
|
|
160
|
+
# allow a bytes-to-string comparison too
|
|
161
|
+
yield attr_value
|
|
162
|
+
|
|
163
|
+
return select
|
|
164
|
+
|
|
165
|
+
|
|
166
|
+
def parse_path_value(next):
|
|
167
|
+
token = next()
|
|
168
|
+
value = token[0]
|
|
169
|
+
if value:
|
|
170
|
+
if value[:1] == "'" or value[:1] == '"':
|
|
171
|
+
assert value[-1] == value[0]
|
|
172
|
+
return value[1:-1]
|
|
173
|
+
if value[:2] == "b'" or value[:2] == 'b"':
|
|
174
|
+
assert value[-1] == value[1]
|
|
175
|
+
return value[2:-1].encode('UTF-8')
|
|
176
|
+
try:
|
|
177
|
+
return int(value)
|
|
178
|
+
except ValueError:
|
|
179
|
+
pass
|
|
180
|
+
elif token[1].isdigit():
|
|
181
|
+
return int(token[1])
|
|
182
|
+
else:
|
|
183
|
+
name = token[1].lower()
|
|
184
|
+
if name == 'true':
|
|
185
|
+
return True
|
|
186
|
+
elif name == 'false':
|
|
187
|
+
return False
|
|
188
|
+
raise ValueError(f"Invalid attribute predicate: '{value}'")
|
|
189
|
+
|
|
190
|
+
|
|
191
|
+
def handle_predicate(next, token):
|
|
192
|
+
token = next()
|
|
193
|
+
|
|
194
|
+
and_conditions = [[]]
|
|
195
|
+
or_conditions = [and_conditions]
|
|
196
|
+
|
|
197
|
+
while token[0] not in (']', ')'):
|
|
198
|
+
and_conditions[-1].append( operations[token[0]](next, token) )
|
|
199
|
+
try:
|
|
200
|
+
token = next()
|
|
201
|
+
except StopIteration:
|
|
202
|
+
break
|
|
203
|
+
else:
|
|
204
|
+
if token[0] == "/":
|
|
205
|
+
token = next()
|
|
206
|
+
|
|
207
|
+
if not token[0]:
|
|
208
|
+
if token[1] == 'and':
|
|
209
|
+
and_conditions.append([])
|
|
210
|
+
token = next()
|
|
211
|
+
elif token[1] == 'or':
|
|
212
|
+
and_conditions = [[]]
|
|
213
|
+
or_conditions.append(and_conditions)
|
|
214
|
+
token = next()
|
|
215
|
+
|
|
216
|
+
if not and_conditions[-1]:
|
|
217
|
+
raise ValueError("Incomplete predicate")
|
|
218
|
+
|
|
219
|
+
def select(result):
|
|
220
|
+
for node in result:
|
|
221
|
+
node_base = (node,)
|
|
222
|
+
for and_conditions in or_conditions:
|
|
223
|
+
for condition in and_conditions:
|
|
224
|
+
subresult = iter(node_base)
|
|
225
|
+
for select in condition:
|
|
226
|
+
subresult = select(subresult)
|
|
227
|
+
predicate_result = _get_first_or_none(subresult)
|
|
228
|
+
if predicate_result is None:
|
|
229
|
+
# Fail current 'and' condition and skip to next 'or' condition.
|
|
230
|
+
break
|
|
231
|
+
else:
|
|
232
|
+
# All 'and' conditions matched, report and skip following 'or' conditions.
|
|
233
|
+
yield node
|
|
234
|
+
break
|
|
235
|
+
|
|
236
|
+
return select
|
|
237
|
+
|
|
238
|
+
|
|
239
|
+
operations = {
|
|
240
|
+
"@": handle_attribute,
|
|
241
|
+
"": handle_name,
|
|
242
|
+
"*": handle_star,
|
|
243
|
+
".": handle_dot,
|
|
244
|
+
"//": handle_descendants,
|
|
245
|
+
"[": handle_predicate,
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
functions = {
|
|
249
|
+
'not' : handle_func_not
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
|
|
253
|
+
class _LookAheadTokenizer:
|
|
254
|
+
def __init__(self, path):
|
|
255
|
+
self._tokens = [
|
|
256
|
+
(special, text)
|
|
257
|
+
for (special, text) in path_tokenizer(path)
|
|
258
|
+
if special or text
|
|
259
|
+
]
|
|
260
|
+
self._tokens.reverse() # allow efficient .pop()
|
|
261
|
+
|
|
262
|
+
def peek(self, default=(None, None)):
|
|
263
|
+
return self._tokens[-1] if self._tokens else default
|
|
264
|
+
|
|
265
|
+
def __call__(self):
|
|
266
|
+
try:
|
|
267
|
+
return self._tokens.pop()
|
|
268
|
+
except IndexError:
|
|
269
|
+
raise StopIteration from None
|
|
270
|
+
|
|
271
|
+
|
|
272
|
+
def _build_path_iterator(path):
|
|
273
|
+
# parse pattern
|
|
274
|
+
_next = _LookAheadTokenizer(path)
|
|
275
|
+
token = _next()
|
|
276
|
+
selector = []
|
|
277
|
+
while 1:
|
|
278
|
+
try:
|
|
279
|
+
selector.append(operations[token[0]](_next, token))
|
|
280
|
+
except StopIteration:
|
|
281
|
+
raise ValueError("invalid path")
|
|
282
|
+
try:
|
|
283
|
+
token = _next()
|
|
284
|
+
if token[0] == "/":
|
|
285
|
+
token = _next()
|
|
286
|
+
except StopIteration:
|
|
287
|
+
break
|
|
288
|
+
return selector
|
|
289
|
+
|
|
290
|
+
# main module API
|
|
291
|
+
|
|
292
|
+
def iterfind(node, path):
|
|
293
|
+
selector_chain = _build_path_iterator(path)
|
|
294
|
+
result = iter((node,))
|
|
295
|
+
for select in selector_chain:
|
|
296
|
+
result = select(result)
|
|
297
|
+
return result
|
|
298
|
+
|
|
299
|
+
def find_first(node, path):
|
|
300
|
+
return _get_first_or_none(iterfind(node, path))
|
|
301
|
+
|
|
302
|
+
def find_all(node, path):
|
|
303
|
+
return list(iterfind(node, path))
|