numbox 0.2.4__py3-none-any.whl → 0.2.6__py3-none-any.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.
Potentially problematic release.
This version of numbox might be problematic. Click here for more details.
- numbox/__init__.py +1 -1
- numbox/core/work/builder.py +69 -28
- numbox/core/work/explain.py +38 -0
- numbox/core/work/work.py +7 -3
- {numbox-0.2.4.dist-info → numbox-0.2.6.dist-info}/METADATA +1 -1
- {numbox-0.2.4.dist-info → numbox-0.2.6.dist-info}/RECORD +9 -8
- {numbox-0.2.4.dist-info → numbox-0.2.6.dist-info}/LICENSE +0 -0
- {numbox-0.2.4.dist-info → numbox-0.2.6.dist-info}/WHEEL +0 -0
- {numbox-0.2.4.dist-info → numbox-0.2.6.dist-info}/top_level.txt +0 -0
numbox/__init__.py
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
__version__ = '0.2.
|
|
1
|
+
__version__ = '0.2.6'
|
numbox/core/work/builder.py
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
|
+
from collections import namedtuple
|
|
1
2
|
from hashlib import md5
|
|
2
3
|
from inspect import getfile, getmodule, getsource
|
|
3
4
|
from io import StringIO
|
|
4
5
|
from itertools import chain
|
|
5
6
|
from numba import njit, typeof
|
|
6
7
|
from numba.core.types import Type
|
|
7
|
-
from typing import Any, Callable, NamedTuple, Optional, Sequence, Union
|
|
8
|
+
from typing import Any, Callable, Dict, NamedTuple, Optional, Sequence, Union
|
|
8
9
|
|
|
9
10
|
from numbox.core.configurations import default_jit_options
|
|
10
11
|
from numbox.core.work.lowlevel_work_utils import ll_make_work
|
|
@@ -15,13 +16,33 @@ def _file_anchor():
|
|
|
15
16
|
raise NotImplementedError
|
|
16
17
|
|
|
17
18
|
|
|
18
|
-
|
|
19
|
+
_specs_registry = dict()
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
class _End(NamedTuple):
|
|
19
23
|
name: str
|
|
20
24
|
init_value: Any
|
|
21
25
|
ty: Optional[type | Type] = None
|
|
22
26
|
|
|
23
27
|
|
|
24
|
-
|
|
28
|
+
def _new(cls, super_proxy, *args, **kwargs):
|
|
29
|
+
name = kwargs.get("name")
|
|
30
|
+
assert name, "`name` key-word argument has not been provided"
|
|
31
|
+
if name in _specs_registry:
|
|
32
|
+
raise ValueError(f"Node '{name}' has already been defined on this graph. Pick a different name.")
|
|
33
|
+
spec_ = super_proxy.__new__(cls, *args, **kwargs)
|
|
34
|
+
_specs_registry[name] = spec_
|
|
35
|
+
return spec_
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
class End(_End):
|
|
39
|
+
__slots__ = ()
|
|
40
|
+
|
|
41
|
+
def __new__(cls, *args, **kwargs):
|
|
42
|
+
return _new(cls, super(), *args, **kwargs)
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
class _Derived(NamedTuple):
|
|
25
46
|
name: str
|
|
26
47
|
init_value: Any
|
|
27
48
|
derive: Callable
|
|
@@ -29,6 +50,13 @@ class Derived(NamedTuple):
|
|
|
29
50
|
ty: Optional[type | Type] = None
|
|
30
51
|
|
|
31
52
|
|
|
53
|
+
class Derived(_Derived):
|
|
54
|
+
__slots__ = ()
|
|
55
|
+
|
|
56
|
+
def __new__(cls, *args, **kwargs):
|
|
57
|
+
return _new(cls, super(), *args, **kwargs)
|
|
58
|
+
|
|
59
|
+
|
|
32
60
|
SpecTy = Derived | End
|
|
33
61
|
|
|
34
62
|
|
|
@@ -50,6 +78,9 @@ def get_ty(spec_):
|
|
|
50
78
|
return spec_.ty or typeof(spec_.init_value)
|
|
51
79
|
|
|
52
80
|
|
|
81
|
+
_derive_funcs = {}
|
|
82
|
+
|
|
83
|
+
|
|
53
84
|
def _derived_cres(ty, sources: Sequence[End], derive, jit_options=None):
|
|
54
85
|
jit_options = jit_options if jit_options is not None else {}
|
|
55
86
|
sources_ty = []
|
|
@@ -58,6 +89,7 @@ def _derived_cres(ty, sources: Sequence[End], derive, jit_options=None):
|
|
|
58
89
|
sources_ty.append(source_ty)
|
|
59
90
|
derive_sig = ty(*sources_ty)
|
|
60
91
|
derive_cres = cres(derive_sig, **jit_options)(derive)
|
|
92
|
+
_derive_funcs[id(derive_cres)] = derive
|
|
61
93
|
return derive_cres
|
|
62
94
|
|
|
63
95
|
|
|
@@ -81,29 +113,34 @@ def _derived_line(
|
|
|
81
113
|
return f"""{name_} = ll_make_work("{name_}", {init_name}, ({sources_}), {derive_name})"""
|
|
82
114
|
|
|
83
115
|
|
|
84
|
-
def _verify_access_nodes(
|
|
85
|
-
all_inputs_: Sequence[End],
|
|
86
|
-
all_derived_: Sequence[Derived],
|
|
87
|
-
access_nodes: Sequence[SpecTy]
|
|
88
|
-
):
|
|
89
|
-
for access_node in access_nodes:
|
|
90
|
-
assert access_node in all_inputs_ or access_node in all_derived_, f"{access_node} cannot be reached"
|
|
91
|
-
|
|
92
|
-
|
|
93
116
|
def code_block_hash(code_txt: str):
|
|
94
117
|
""" Re-compile and re-save cache when source code has changed. """
|
|
95
118
|
return md5(code_txt.encode("utf-8")).hexdigest()
|
|
96
119
|
|
|
97
120
|
|
|
98
|
-
def
|
|
99
|
-
all_inputs_:
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
121
|
+
def _infer_end_and_derived_nodes(spec: SpecTy, all_inputs_: Dict[str, Type], all_derived_: Dict[str, Type]):
|
|
122
|
+
if spec.name in all_inputs_ or spec.name in all_derived_:
|
|
123
|
+
return
|
|
124
|
+
if isinstance(spec, End):
|
|
125
|
+
all_inputs_[spec.name] = get_ty(spec)
|
|
126
|
+
return
|
|
127
|
+
for source in spec.sources:
|
|
128
|
+
_infer_end_and_derived_nodes(source, all_inputs_, all_derived_)
|
|
129
|
+
all_derived_[spec.name] = get_ty(spec)
|
|
130
|
+
|
|
131
|
+
|
|
132
|
+
def infer_end_and_derived_nodes(access_nodes: SpecTy | Sequence[SpecTy]):
|
|
133
|
+
all_inputs_ = dict()
|
|
134
|
+
all_derived_ = dict()
|
|
135
|
+
for access_node in access_nodes:
|
|
136
|
+
_infer_end_and_derived_nodes(access_node, all_inputs_, all_derived_)
|
|
137
|
+
all_inputs_lst = [_specs_registry[name] for name in all_inputs_.keys()]
|
|
138
|
+
all_derived_lst = [_specs_registry[name] for name in all_derived_.keys()]
|
|
139
|
+
return all_inputs_lst, all_derived_lst
|
|
140
|
+
|
|
141
|
+
|
|
142
|
+
def make_graph(*access_nodes: SpecTy | Sequence[SpecTy], jit_options: Optional[dict] = None):
|
|
143
|
+
all_inputs_, all_derived_ = infer_end_and_derived_nodes(access_nodes)
|
|
107
144
|
if jit_options is None:
|
|
108
145
|
jit_options = {}
|
|
109
146
|
jit_options = {**default_jit_options, **jit_options}
|
|
@@ -114,26 +151,30 @@ def make_graph(
|
|
|
114
151
|
_make_args = []
|
|
115
152
|
code_txt = StringIO()
|
|
116
153
|
initializers = {}
|
|
117
|
-
derive_hashes=[]
|
|
154
|
+
derive_hashes = []
|
|
118
155
|
for input_ in all_inputs_:
|
|
119
156
|
line_ = _input_line(input_, ns, initializers)
|
|
120
157
|
code_txt.write(f"\n\t{line_}")
|
|
121
158
|
for derived_ in all_derived_:
|
|
122
159
|
line_ = _derived_line(derived_, ns, initializers, derive_hashes, _make_args, jit_options)
|
|
123
160
|
code_txt.write(f"\n\t{line_}")
|
|
124
|
-
hash_str = f"code_block = {code_txt.getvalue()} initializers = {list(initializers.values())} derive_hashes = {derive_hashes}"
|
|
161
|
+
hash_str = f"code_block = {code_txt.getvalue()} initializers = {list(initializers.values())} derive_hashes = {derive_hashes}" # noqa: E501
|
|
125
162
|
hash_ = code_block_hash(hash_str)
|
|
126
|
-
|
|
127
|
-
|
|
163
|
+
access_nodes_names = [n.name for n in access_nodes]
|
|
164
|
+
tup_ = ", ".join(access_nodes_names)
|
|
165
|
+
tup_ = tup_ + ", " if ", " not in tup_ else tup_
|
|
166
|
+
code_txt.write(f"""\n\taccess_tuple = ({tup_})""")
|
|
167
|
+
code_txt.write("\n\treturn access_tuple")
|
|
128
168
|
code_txt = code_txt.getvalue()
|
|
129
169
|
make_params = ", ".join(chain(_make_args, initializers.keys()))
|
|
130
170
|
make_name = f"_make_{hash_}"
|
|
131
171
|
code_txt = f"""
|
|
132
172
|
@njit(**jit_options)
|
|
133
173
|
def {make_name}({make_params}):""" + code_txt + f"""
|
|
134
|
-
|
|
174
|
+
access_tuple_ = {make_name}({make_params})
|
|
135
175
|
"""
|
|
136
176
|
code = compile(code_txt, getfile(_file_anchor), mode="exec")
|
|
137
177
|
exec(code, ns)
|
|
138
|
-
|
|
139
|
-
|
|
178
|
+
access_tuple_ = ns["access_tuple_"]
|
|
179
|
+
Access = namedtuple("Access", access_nodes_names)
|
|
180
|
+
return Access(*access_tuple_)
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
from inspect import getsource
|
|
2
|
+
from textwrap import indent
|
|
3
|
+
|
|
4
|
+
from numbox.core.work.builder import _derive_funcs
|
|
5
|
+
from numbox.core.work.work import Work
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
def get_func_code(derive_func_p_):
|
|
9
|
+
derive_func_ = _derive_funcs.get(derive_func_p_)
|
|
10
|
+
return derive_func_.__name__, indent(getsource(derive_func_), " ")
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
def _explain(work: Work, derivation_: list, derived_: set):
|
|
14
|
+
if work.name in derived_:
|
|
15
|
+
return
|
|
16
|
+
if len(work.sources) == 0:
|
|
17
|
+
derivation_.append(f"{work.name}: end node\n")
|
|
18
|
+
derived_.add(work.name)
|
|
19
|
+
return
|
|
20
|
+
inputs_names = []
|
|
21
|
+
for source in work.sources:
|
|
22
|
+
_explain(source, derivation_, derived_)
|
|
23
|
+
inputs_names.append(source.name)
|
|
24
|
+
derive_func_ptrs = work.derive
|
|
25
|
+
derive_func_name, derive_func_code = get_func_code(derive_func_ptrs[1])
|
|
26
|
+
derivation_.append(f"""{work.name}: {derive_func_name}({", ".join(inputs_names)})
|
|
27
|
+
|
|
28
|
+
{derive_func_code}""")
|
|
29
|
+
derived_.add(work.name)
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
def explain(work: Work):
|
|
33
|
+
all_end_nodes = work.all_end_nodes()
|
|
34
|
+
derivation = []
|
|
35
|
+
_explain(work, derivation, set())
|
|
36
|
+
explain_txt = f"All required end nodes: {all_end_nodes}\n\n"
|
|
37
|
+
explain_txt += "\n".join(derivation)
|
|
38
|
+
return explain_txt
|
numbox/core/work/work.py
CHANGED
|
@@ -17,7 +17,7 @@ from numbox.core.work.lowlevel_work_utils import ll_make_work, WorkTypeClass
|
|
|
17
17
|
from numbox.core.work.node import NodeType
|
|
18
18
|
from numbox.core.work.node_base import NodeBase, NodeBaseType
|
|
19
19
|
from numbox.utils.lowlevel import (
|
|
20
|
-
extract_struct_member, _cast, is_not_null, get_func_p_from_func_struct, get_ll_func_sig
|
|
20
|
+
extract_struct_member, _cast, _get_func_tuple, is_not_null, get_func_p_from_func_struct, get_ll_func_sig
|
|
21
21
|
)
|
|
22
22
|
|
|
23
23
|
|
|
@@ -73,6 +73,11 @@ class Work(NodeBase):
|
|
|
73
73
|
def sources(self):
|
|
74
74
|
return self.sources
|
|
75
75
|
|
|
76
|
+
@property
|
|
77
|
+
@njit(**default_jit_options)
|
|
78
|
+
def derive(self):
|
|
79
|
+
return _get_func_tuple(self.derive)
|
|
80
|
+
|
|
76
81
|
@property
|
|
77
82
|
@njit(**default_jit_options)
|
|
78
83
|
def derived(self):
|
|
@@ -441,9 +446,8 @@ def ol_depends_on(self_ty, obj_ty):
|
|
|
441
446
|
node = self.as_node()
|
|
442
447
|
return name_ in node.all_inputs_names()
|
|
443
448
|
else:
|
|
444
|
-
assert isinstance(obj_ty, WorkTypeClass), f"Cannot handle {obj_ty}"
|
|
445
|
-
|
|
446
449
|
def _(self, obj_):
|
|
447
450
|
node = self.as_node()
|
|
448
451
|
return obj_.name in node.all_inputs_names()
|
|
452
|
+
assert isinstance(obj_ty, WorkTypeClass), f"Cannot handle {obj_ty}"
|
|
449
453
|
return _
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
numbox/__init__.py,sha256=
|
|
1
|
+
numbox/__init__.py,sha256=T150U4daRZ7ULOwxGUzzoBDAqm3bW9UydvCf0KJii9I,22
|
|
2
2
|
numbox/core/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
3
3
|
numbox/core/configurations.py,sha256=0bCmxXL-QMwtvyIDhpXLeT-1KJMf_QpH0wLuEvYLGxQ,68
|
|
4
4
|
numbox/core/any/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
@@ -15,14 +15,15 @@ numbox/core/bindings/utils.py,sha256=aRtN8oUYBk9vgoUGaUJosGx0Za-vvCNwwbZg_g_-LRs
|
|
|
15
15
|
numbox/core/proxy/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
16
16
|
numbox/core/proxy/proxy.py,sha256=kGYlEdLK40lxxu56e_S32s9YuQ6AuQnFegt5uQrUw5w,3889
|
|
17
17
|
numbox/core/work/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
18
|
-
numbox/core/work/builder.py,sha256=
|
|
18
|
+
numbox/core/work/builder.py,sha256=WFZmH8dHTQNx1TwjpJVtZXN5ud4K2j500HgbF-Msu4c,6063
|
|
19
19
|
numbox/core/work/combine_utils.py,sha256=qTVGke_ydzaTQ7o29DFjZWZzKjRNKb0L3yJMaR3TLII,2430
|
|
20
|
+
numbox/core/work/explain.py,sha256=ESwvsTgfe0w7UnM13yyVpVDtfJyAK2A1sNdF3RNb-jU,1200
|
|
20
21
|
numbox/core/work/loader_utils.py,sha256=g83mDWidZJ8oLWP3I3rK8aGISYOO2S-w6HDgtosCyck,1572
|
|
21
22
|
numbox/core/work/lowlevel_work_utils.py,sha256=TgRRcNfks0oaOXGXXr3ptafd_Xv_lpmH8sjBrJ9bPuI,5748
|
|
22
23
|
numbox/core/work/node.py,sha256=CMolyoRQjG2A-pTQqZQ0kxKOYTKipWRC0mu8RWHuTUI,5096
|
|
23
24
|
numbox/core/work/node_base.py,sha256=uI7asM2itQcHuOByXyJtqvrd4ovW6EXDRdHYp3JVHQ0,998
|
|
24
25
|
numbox/core/work/print_tree.py,sha256=y2u7xmbHvpcA57y8PrGSqOunLNCqhgNXdVtXHqvy1M0,2340
|
|
25
|
-
numbox/core/work/work.py,sha256=
|
|
26
|
+
numbox/core/work/work.py,sha256=V_pYW0sqdYHh45ago3aMz0fG4U_UfsNLIcpBejn_ttU,14725
|
|
26
27
|
numbox/core/work/work_utils.py,sha256=3q_nnBdzuxWWcdFpbRL2H0T9ZNkUgx1J1uhiZkX3YG4,1039
|
|
27
28
|
numbox/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
28
29
|
numbox/utils/highlevel.py,sha256=gXYzLsFPKHQfGqaz-Z4DWcCQddv0dS6SKwIsM-_xjYg,1487
|
|
@@ -30,8 +31,8 @@ numbox/utils/lowlevel.py,sha256=ACpf8_HyOIsobPlZ31bapkEyuCsV5dojW3AFrcKykrw,1071
|
|
|
30
31
|
numbox/utils/meminfo.py,sha256=ykFi8Vt0WcHI3ztgMwvpn6NqaflDSQGL8tjI01jrzm0,1759
|
|
31
32
|
numbox/utils/timer.py,sha256=KkAkWOHQ72WtPjyiAzt_tF1q0DcOnCDkITTb85DvkUM,553
|
|
32
33
|
numbox/utils/void_type.py,sha256=IkZsjNeAIShYJtvWbvERdHnl_mbF1rCRWiM3gp6II8U,404
|
|
33
|
-
numbox-0.2.
|
|
34
|
-
numbox-0.2.
|
|
35
|
-
numbox-0.2.
|
|
36
|
-
numbox-0.2.
|
|
37
|
-
numbox-0.2.
|
|
34
|
+
numbox-0.2.6.dist-info/LICENSE,sha256=YYgNvjH_p6-1NsdrIqGJnr1GUbZzA_8DxsP6vVfM6nY,1446
|
|
35
|
+
numbox-0.2.6.dist-info/METADATA,sha256=H7eyqJTneiiqllMj4Boqaxpj-gwZpLjkQlGEhiOuJlE,2792
|
|
36
|
+
numbox-0.2.6.dist-info/WHEEL,sha256=iAkIy5fosb7FzIOwONchHf19Qu7_1wCWyFNR5gu9nU0,91
|
|
37
|
+
numbox-0.2.6.dist-info/top_level.txt,sha256=A67jOkfqidCSYYm6ifjN_WZyIiR1B27fjxv6nNbPvjc,7
|
|
38
|
+
numbox-0.2.6.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|