numbox 0.2.6__py3-none-any.whl → 0.2.8__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/proxy/proxy.py +2 -9
- numbox/core/work/builder.py +3 -3
- numbox/core/work/work.py +50 -37
- numbox/utils/highlevel.py +172 -1
- numbox/utils/standard.py +17 -0
- numbox/utils/timer.py +4 -1
- {numbox-0.2.6.dist-info → numbox-0.2.8.dist-info}/METADATA +5 -1
- {numbox-0.2.6.dist-info → numbox-0.2.8.dist-info}/RECORD +12 -11
- {numbox-0.2.6.dist-info → numbox-0.2.8.dist-info}/LICENSE +0 -0
- {numbox-0.2.6.dist-info → numbox-0.2.8.dist-info}/WHEEL +0 -0
- {numbox-0.2.6.dist-info → numbox-0.2.8.dist-info}/top_level.txt +0 -0
numbox/__init__.py
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
__version__ = '0.2.
|
|
1
|
+
__version__ = '0.2.8'
|
numbox/core/proxy/proxy.py
CHANGED
|
@@ -7,20 +7,13 @@ from numba.extending import intrinsic # noqa: F401
|
|
|
7
7
|
from types import FunctionType as PyFunctionType
|
|
8
8
|
from typing import List, Optional, Tuple
|
|
9
9
|
|
|
10
|
+
from numbox.utils.standard import make_params_strings
|
|
11
|
+
|
|
10
12
|
|
|
11
13
|
def make_proxy_name(name):
|
|
12
14
|
return f'__{name}'
|
|
13
15
|
|
|
14
16
|
|
|
15
|
-
def make_params_strings(func):
|
|
16
|
-
func_params = inspect.signature(func).parameters
|
|
17
|
-
func_params_str = ', '.join(
|
|
18
|
-
[k if v.default == inspect._empty else f'{k}={v.default}' for k, v in func_params.items()]
|
|
19
|
-
)
|
|
20
|
-
func_names_params_str = ', '.join(func_params.keys())
|
|
21
|
-
return func_params_str, func_names_params_str
|
|
22
|
-
|
|
23
|
-
|
|
24
17
|
def proxy(sig, jit_options: Optional[dict] = None):
|
|
25
18
|
""" Create a proxy for the decorated function `func` with the given signature(s) `sig`.
|
|
26
19
|
|
numbox/core/work/builder.py
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
from collections import namedtuple
|
|
2
|
-
from hashlib import
|
|
2
|
+
from hashlib import sha256
|
|
3
3
|
from inspect import getfile, getmodule, getsource
|
|
4
4
|
from io import StringIO
|
|
5
5
|
from itertools import chain
|
|
@@ -102,7 +102,7 @@ def _derived_line(
|
|
|
102
102
|
sources_ = sources_ + ", " if "," not in sources_ else sources_
|
|
103
103
|
ty_ = get_ty(derived_)
|
|
104
104
|
derive_func = derived_.derive
|
|
105
|
-
derive_hashes.append(
|
|
105
|
+
derive_hashes.append(sha256(getsource(derive_func).encode("utf-8")).hexdigest())
|
|
106
106
|
derive_ = _derived_cres(ty_, derived_.sources, derive_func, jit_options)
|
|
107
107
|
derive_name = f"{name_}_derive"
|
|
108
108
|
init_name = f"{name_}_init"
|
|
@@ -115,7 +115,7 @@ def _derived_line(
|
|
|
115
115
|
|
|
116
116
|
def code_block_hash(code_txt: str):
|
|
117
117
|
""" Re-compile and re-save cache when source code has changed. """
|
|
118
|
-
return
|
|
118
|
+
return sha256(code_txt.encode("utf-8")).hexdigest()
|
|
119
119
|
|
|
120
120
|
|
|
121
121
|
def _infer_end_and_derived_nodes(spec: SpecTy, all_inputs_: Dict[str, Type], all_derived_: Dict[str, Type]):
|
numbox/core/work/work.py
CHANGED
|
@@ -166,6 +166,9 @@ def _call_derive(typingctx: Context, derive_ty: FunctionType, sources_ty: Tuple)
|
|
|
166
166
|
return sig, codegen
|
|
167
167
|
|
|
168
168
|
|
|
169
|
+
_source_getter_registry = {}
|
|
170
|
+
|
|
171
|
+
|
|
169
172
|
def _make_source_getter(source_ind):
|
|
170
173
|
return f"""
|
|
171
174
|
@intrinsic
|
|
@@ -182,8 +185,6 @@ def _get_source_{source_ind}(typingctx: Context, sources_ty: Tuple):
|
|
|
182
185
|
|
|
183
186
|
def _make_calculate_code(num_sources):
|
|
184
187
|
code_txt = StringIO()
|
|
185
|
-
for source_ind_ in range(num_sources):
|
|
186
|
-
code_txt.write(_make_source_getter(source_ind_))
|
|
187
188
|
code_txt.write("""
|
|
188
189
|
def _calculate_(work_):
|
|
189
190
|
if work_.derived:
|
|
@@ -194,7 +195,8 @@ def _calculate_(work_):
|
|
|
194
195
|
for source_ind_ in range(num_sources):
|
|
195
196
|
code_txt.write(f"""
|
|
196
197
|
source_{source_ind_} = _get_source_{source_ind_}(sources)
|
|
197
|
-
source_{source_ind_}.
|
|
198
|
+
if not source_{source_ind_}.derived:
|
|
199
|
+
source_{source_ind_}.calculate()""")
|
|
198
200
|
code_txt.write("""
|
|
199
201
|
v = _call_derive(work_.derive, work_.sources)
|
|
200
202
|
work_.derived = True
|
|
@@ -206,6 +208,15 @@ def _calculate_(work_):
|
|
|
206
208
|
_calculate_registry = {}
|
|
207
209
|
|
|
208
210
|
|
|
211
|
+
def ensure_presence_of_source_getters_in_ns(num_sources_, ns_):
|
|
212
|
+
for source_i in range(num_sources_):
|
|
213
|
+
_source_getter = _source_getter_registry.get(source_i, None)
|
|
214
|
+
source_getter_code_txt = _make_source_getter(source_i)
|
|
215
|
+
source_getter_code = compile(source_getter_code_txt, getfile(_file_anchor), mode="exec")
|
|
216
|
+
exec(source_getter_code, ns_)
|
|
217
|
+
_source_getter_registry[source_i] = True
|
|
218
|
+
|
|
219
|
+
|
|
209
220
|
@overload_method(WorkTypeClass, "calculate", strict=False, jit_options=default_jit_options)
|
|
210
221
|
def ol_calculate(self_ty):
|
|
211
222
|
derive_ty = self_ty.field_dict["derive"]
|
|
@@ -217,13 +228,15 @@ def ol_calculate(self_ty):
|
|
|
217
228
|
sources_ty = self_ty.field_dict["sources"]
|
|
218
229
|
num_sources = sources_ty.count
|
|
219
230
|
_calculate = _calculate_registry.get(num_sources, None)
|
|
220
|
-
if _calculate is None:
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
231
|
+
if _calculate is not None:
|
|
232
|
+
return _calculate
|
|
233
|
+
ns = getmodule(_file_anchor).__dict__
|
|
234
|
+
ensure_presence_of_source_getters_in_ns(num_sources, ns)
|
|
235
|
+
code_txt = _make_calculate_code(num_sources)
|
|
236
|
+
code = compile(code_txt, getfile(_file_anchor), mode="exec")
|
|
237
|
+
exec(code, ns)
|
|
238
|
+
_calculate = ns["_calculate_"]
|
|
239
|
+
_calculate_registry[num_sources] = _calculate
|
|
227
240
|
return _calculate
|
|
228
241
|
|
|
229
242
|
|
|
@@ -246,8 +259,6 @@ def _cast_to_work_data(typingctx, work_ty, data_as_erased_ty: ErasedType):
|
|
|
246
259
|
|
|
247
260
|
def _make_loader_code(num_sources):
|
|
248
261
|
code_txt = StringIO()
|
|
249
|
-
for source_ind_ in range(num_sources):
|
|
250
|
-
code_txt.write(_make_source_getter(source_ind_))
|
|
251
262
|
code_txt.write("""
|
|
252
263
|
def _loader_(work_, data_):
|
|
253
264
|
reset = False
|
|
@@ -282,20 +293,20 @@ def ol_load(work_ty, data_ty: DictType):
|
|
|
282
293
|
sources_ty = work_ty.field_dict["sources"]
|
|
283
294
|
num_sources = sources_ty.count
|
|
284
295
|
_loader = _loader_registry.get(num_sources, None)
|
|
285
|
-
if _loader is None:
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
296
|
+
if _loader is not None:
|
|
297
|
+
return _loader
|
|
298
|
+
ns = getmodule(_file_anchor).__dict__
|
|
299
|
+
ensure_presence_of_source_getters_in_ns(num_sources, ns)
|
|
300
|
+
code_txt = _make_loader_code(num_sources)
|
|
301
|
+
code = compile(code_txt, getfile(_file_anchor), mode="exec")
|
|
302
|
+
exec(code, ns)
|
|
303
|
+
_loader = ns["_loader_"]
|
|
304
|
+
_loader_registry[num_sources] = _loader
|
|
292
305
|
return _loader
|
|
293
306
|
|
|
294
307
|
|
|
295
308
|
def _make_combine_code(num_sources):
|
|
296
309
|
code_txt = StringIO()
|
|
297
|
-
for source_ind_ in range(num_sources):
|
|
298
|
-
code_txt.write(_make_source_getter(source_ind_))
|
|
299
310
|
code_txt.write("""
|
|
300
311
|
def _combine_(work_, data_, harvested_=None):
|
|
301
312
|
if harvested_ is None:
|
|
@@ -331,13 +342,15 @@ def ol_combine(work_ty, data_ty: DictType, harvested_ty=NoneType):
|
|
|
331
342
|
sources_ty = work_ty.field_dict["sources"]
|
|
332
343
|
num_sources = sources_ty.count
|
|
333
344
|
_combine = _combine_registry.get(num_sources, None)
|
|
334
|
-
if _combine is None:
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
345
|
+
if _combine is not None:
|
|
346
|
+
return _combine
|
|
347
|
+
ns = {**getmodule(_file_anchor).__dict__, **{"boolean": boolean, "Dict": Dict}}
|
|
348
|
+
ensure_presence_of_source_getters_in_ns(num_sources, ns)
|
|
349
|
+
code_txt = _make_combine_code(num_sources)
|
|
350
|
+
code = compile(code_txt, getfile(_file_anchor), mode="exec")
|
|
351
|
+
exec(code, ns)
|
|
352
|
+
_combine = ns["_combine_"]
|
|
353
|
+
_combine_registry[num_sources] = _combine
|
|
341
354
|
return _combine
|
|
342
355
|
|
|
343
356
|
|
|
@@ -364,8 +377,6 @@ def ol_get_inputs_names(self_ty):
|
|
|
364
377
|
|
|
365
378
|
def _make_inputs_vector_code(num_sources):
|
|
366
379
|
code_txt = StringIO()
|
|
367
|
-
for source_ind_ in range(num_sources):
|
|
368
|
-
code_txt.write(_make_source_getter(source_ind_))
|
|
369
380
|
code_txt.write("""
|
|
370
381
|
def _inputs_vector_(work_):
|
|
371
382
|
node = work_.node
|
|
@@ -399,13 +410,15 @@ def ol_make_inputs_vector(self_ty):
|
|
|
399
410
|
return inputs_vector
|
|
400
411
|
return _
|
|
401
412
|
_inputs_vector = _inputs_vector_registry.get(num_sources, None)
|
|
402
|
-
if _inputs_vector is None:
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
413
|
+
if _inputs_vector is not None:
|
|
414
|
+
return _inputs_vector
|
|
415
|
+
ns = {**getmodule(_file_anchor).__dict__, **{"new": new}}
|
|
416
|
+
ensure_presence_of_source_getters_in_ns(num_sources, ns)
|
|
417
|
+
code_txt = _make_inputs_vector_code(num_sources)
|
|
418
|
+
code = compile(code_txt, getfile(_file_anchor), mode="exec")
|
|
419
|
+
exec(code, ns)
|
|
420
|
+
_inputs_vector = ns["_inputs_vector_"]
|
|
421
|
+
_inputs_vector_registry[num_sources] = _inputs_vector
|
|
409
422
|
return _inputs_vector
|
|
410
423
|
|
|
411
424
|
|
numbox/utils/highlevel.py
CHANGED
|
@@ -1,4 +1,7 @@
|
|
|
1
1
|
import hashlib
|
|
2
|
+
import re
|
|
3
|
+
from inspect import getfile, getmodule, getsource
|
|
4
|
+
from io import StringIO
|
|
2
5
|
from numba import njit
|
|
3
6
|
from numba.core.itanium_mangler import mangle_type_or_value
|
|
4
7
|
from numba.core.types import Type
|
|
@@ -6,6 +9,17 @@ from numba.core.types.functions import Dispatcher
|
|
|
6
9
|
from numba.core.types.function_type import CompileResultWAP
|
|
7
10
|
from numba.core.typing.templates import Signature
|
|
8
11
|
from numba.experimental.function_type import FunctionType
|
|
12
|
+
from numba.experimental.structref import define_boxing, new, StructRefProxy
|
|
13
|
+
from numba.extending import overload, overload_method
|
|
14
|
+
from textwrap import dedent, indent
|
|
15
|
+
from typing import Callable, Dict, Iterable, Optional
|
|
16
|
+
|
|
17
|
+
from numbox.core.configurations import default_jit_options
|
|
18
|
+
from numbox.utils.standard import make_params_strings
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
def _file_anchor():
|
|
22
|
+
raise NotImplementedError
|
|
9
23
|
|
|
10
24
|
|
|
11
25
|
def cres(sig, **kwargs):
|
|
@@ -32,7 +46,164 @@ def determine_field_index(struct_ty, field_name):
|
|
|
32
46
|
|
|
33
47
|
def hash_type(ty: Type):
|
|
34
48
|
mangled_ty = mangle_type_or_value(ty)
|
|
35
|
-
return hashlib.sha256(mangled_ty.encode(
|
|
49
|
+
return hashlib.sha256(mangled_ty.encode("utf-8")).hexdigest()
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
def make_structref_code_txt(
|
|
53
|
+
struct_name: str,
|
|
54
|
+
struct_fields: Iterable[str] | Dict[str, Type],
|
|
55
|
+
struct_type_class: type | Type,
|
|
56
|
+
struct_methods: Optional[Dict[str, Callable]] = None,
|
|
57
|
+
jit_options: Optional[dict] = None
|
|
58
|
+
):
|
|
59
|
+
if isinstance(struct_fields, dict):
|
|
60
|
+
struct_fields, fields_types = list(struct_fields.keys()), list(struct_fields.values())
|
|
61
|
+
else:
|
|
62
|
+
assert isinstance(struct_fields, (list, tuple)), struct_fields
|
|
63
|
+
fields_types = None
|
|
64
|
+
struct_fields_str = ", ".join([field for field in struct_fields])
|
|
65
|
+
make_name = f"make_{struct_name.lower()}"
|
|
66
|
+
new_returns = f"{make_name}({struct_fields_str})"
|
|
67
|
+
repr_str = f"f'{struct_name}(" + ", ".join([f"{field}={{self.{field}}}" for field in struct_fields]) + ")'"
|
|
68
|
+
code_txt = StringIO()
|
|
69
|
+
code_txt.write(f"""
|
|
70
|
+
class {struct_name}(StructRefProxy):
|
|
71
|
+
def __new__(cls, {struct_fields_str}):
|
|
72
|
+
return {new_returns}
|
|
73
|
+
|
|
74
|
+
def __repr__(self):
|
|
75
|
+
return {repr_str}
|
|
76
|
+
""")
|
|
77
|
+
for field in struct_fields:
|
|
78
|
+
code_txt.write(f"""
|
|
79
|
+
@property
|
|
80
|
+
@njit(**jit_options)
|
|
81
|
+
def {field}(self):
|
|
82
|
+
return self.{field}
|
|
83
|
+
""")
|
|
84
|
+
methods_code_txt = StringIO()
|
|
85
|
+
if struct_methods is not None:
|
|
86
|
+
assert isinstance(struct_methods, dict), f"""
|
|
87
|
+
Expected dictionary of methods names to callable, got {struct_methods}"""
|
|
88
|
+
for method_name, method in struct_methods.items():
|
|
89
|
+
params_str, names_params_str = make_params_strings(method)
|
|
90
|
+
names_params_lst = names_params_str.split(", ")
|
|
91
|
+
self_name = names_params_lst[0]
|
|
92
|
+
names_params_str_wo_self = ", ".join(names_params_lst[1:])
|
|
93
|
+
method_source = dedent(getsource(method))
|
|
94
|
+
method_hash = hashlib.sha256(method_source.encode("utf-8")).hexdigest()
|
|
95
|
+
code_txt.write(f"""
|
|
96
|
+
def {method_name}({params_str}):
|
|
97
|
+
return {self_name}.{method_name}_{method_hash}({names_params_str_wo_self})
|
|
98
|
+
|
|
99
|
+
@njit(**jit_options)
|
|
100
|
+
def {method_name}_{method_hash}({params_str}):
|
|
101
|
+
return {self_name}.{method_name}({names_params_str_wo_self})
|
|
102
|
+
""")
|
|
103
|
+
method_header = re.findall(r"^\s*def\s+([a-zA-Z_]\w*)\s*\(([^)]*)\)\s*:[^\n]*", method_source, re.MULTILINE)
|
|
104
|
+
assert len(method_header) == 1, method_header
|
|
105
|
+
method_name, params_str_ = method_header[0]
|
|
106
|
+
assert params_str == params_str_, (params_str, params_str_)
|
|
107
|
+
method_source = re.sub(r"\bdef\s+([a-zA-Z_]\w*)\b", f"def _", method_source)
|
|
108
|
+
methods_code_txt.write(f"""
|
|
109
|
+
@overload_method({struct_type_class.__name__}, "{method_name}", jit_options=jit_options)
|
|
110
|
+
def ol_{method_name}({params_str}):
|
|
111
|
+
{indent(method_source, " ")}
|
|
112
|
+
return _
|
|
113
|
+
""")
|
|
114
|
+
code_txt.write(f"""
|
|
115
|
+
define_boxing({struct_type_class.__name__}, {struct_name})
|
|
116
|
+
""")
|
|
117
|
+
struct_type_name = f"{struct_name}Type"
|
|
118
|
+
struct_fields_ty_str = ", ".join([f"{field}_ty" for field in struct_fields])
|
|
119
|
+
struct_type_code_block = ""
|
|
120
|
+
if fields_types is None:
|
|
121
|
+
struct_type_code_block = f"""fields_types = [{struct_fields_ty_str}]
|
|
122
|
+
fields_and_their_types = list(zip(fields, fields_types))
|
|
123
|
+
{struct_name}Type = {struct_type_class.__name__}(fields_and_their_types)
|
|
124
|
+
"""
|
|
125
|
+
else:
|
|
126
|
+
code_txt.write(f"""
|
|
127
|
+
fields_and_their_types = list(zip(fields, fields_types))
|
|
128
|
+
{struct_name}Type = {struct_type_class.__name__}(fields_and_their_types)
|
|
129
|
+
""")
|
|
130
|
+
ctor_code_block = "\n".join([f" struct_.{field} = {field}" for field in struct_fields])
|
|
131
|
+
code_txt.write(f"""
|
|
132
|
+
@overload({struct_name}, strict=False, jit_options=jit_options)
|
|
133
|
+
def ol_{struct_name.lower()}({struct_fields_ty_str}):
|
|
134
|
+
{struct_type_code_block}
|
|
135
|
+
def ctor({struct_fields_str}):
|
|
136
|
+
struct_ = new({struct_type_name})
|
|
137
|
+
{ctor_code_block}
|
|
138
|
+
return struct_
|
|
139
|
+
return ctor
|
|
140
|
+
""")
|
|
141
|
+
if fields_types is not None:
|
|
142
|
+
code_txt.write(f"""
|
|
143
|
+
{make_name}_sig = {struct_name}Type(*fields_types)
|
|
144
|
+
""")
|
|
145
|
+
else:
|
|
146
|
+
code_txt.write(f"""
|
|
147
|
+
{make_name}_sig = None
|
|
148
|
+
""")
|
|
149
|
+
code_txt.write(f"""
|
|
150
|
+
@njit({make_name}_sig, **jit_options)
|
|
151
|
+
def {make_name}({struct_fields_str}):
|
|
152
|
+
return {struct_name}({struct_fields_str})
|
|
153
|
+
""")
|
|
154
|
+
code_txt = code_txt.getvalue() + methods_code_txt.getvalue()
|
|
155
|
+
return code_txt, fields_types
|
|
156
|
+
|
|
157
|
+
|
|
158
|
+
def make_structref(
|
|
159
|
+
struct_name: str,
|
|
160
|
+
struct_fields: Iterable[str] | Dict[str, Type],
|
|
161
|
+
struct_type_class: type | Type,
|
|
162
|
+
*,
|
|
163
|
+
struct_methods: Optional[Dict[str, Callable]] = None,
|
|
164
|
+
jit_options: Optional[dict] = None
|
|
165
|
+
):
|
|
166
|
+
"""
|
|
167
|
+
Makes structure type with `struct_name` and `struct_fields` from the StructRef type class.
|
|
168
|
+
|
|
169
|
+
A unique `struct_type_class` for each structref needs to be provided.
|
|
170
|
+
If caching of code that will be using the created struct type is desired,
|
|
171
|
+
these type class(es) need/s to be defined in a python module that is *not* executed.
|
|
172
|
+
(Same requirement is also to observed even when the full definition of StructRef
|
|
173
|
+
is entirely hard-coded rather than created dynamically.)
|
|
174
|
+
|
|
175
|
+
In particular, that's why `struct_type_class` cannot be incorporated into
|
|
176
|
+
the dynamic compile / exec routine here.
|
|
177
|
+
|
|
178
|
+
Dictionary of methods to be bound to the created structref can be provided as well.
|
|
179
|
+
Struct methods will get inlined into the caller if numba deems it to be optimal
|
|
180
|
+
(even if `jit_options` says otherwise), therefore changing the methods code
|
|
181
|
+
without poking the jitted caller can result in a stale cache - when the latter is
|
|
182
|
+
cached. This is not an exclusive limitation of a dynamic structref creation via
|
|
183
|
+
this function and is equally true when the structref definition is coded explicitly.
|
|
184
|
+
"""
|
|
185
|
+
code_txt, fields_types = make_structref_code_txt(
|
|
186
|
+
struct_name, struct_fields, struct_type_class, struct_methods, jit_options
|
|
187
|
+
)
|
|
188
|
+
if jit_options is None:
|
|
189
|
+
jit_options = default_jit_options
|
|
190
|
+
ns = {
|
|
191
|
+
**getmodule(_file_anchor).__dict__,
|
|
192
|
+
**{
|
|
193
|
+
"fields": struct_fields,
|
|
194
|
+
"fields_types": fields_types,
|
|
195
|
+
"define_boxing": define_boxing,
|
|
196
|
+
"jit_options": jit_options,
|
|
197
|
+
"new": new,
|
|
198
|
+
"njit": njit,
|
|
199
|
+
"overload_method": overload_method,
|
|
200
|
+
"StructRefProxy": StructRefProxy,
|
|
201
|
+
struct_type_class.__name__: struct_type_class
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
code = compile(code_txt, getfile(_file_anchor), mode="exec")
|
|
205
|
+
exec(code, ns)
|
|
206
|
+
return ns[struct_name]
|
|
36
207
|
|
|
37
208
|
|
|
38
209
|
def prune_type(ty):
|
numbox/utils/standard.py
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import inspect
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
def make_params_strings(func):
|
|
5
|
+
func_params = inspect.signature(func).parameters
|
|
6
|
+
func_params_str = ', '.join(
|
|
7
|
+
[k if v.default == inspect._empty else f'{k}={v.default}' for k, v in func_params.items()]
|
|
8
|
+
)
|
|
9
|
+
func_names_params_str = ', '.join(func_params.keys())
|
|
10
|
+
return func_params_str, func_names_params_str
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
if __name__ == "__main__":
|
|
14
|
+
def aux(x, y, z=1):
|
|
15
|
+
pass
|
|
16
|
+
print(make_params_strings(aux))
|
|
17
|
+
|
numbox/utils/timer.py
CHANGED
|
@@ -9,13 +9,16 @@ logging.basicConfig(level=logging.WARNING)
|
|
|
9
9
|
class Timer:
|
|
10
10
|
times = {}
|
|
11
11
|
|
|
12
|
+
def __init__(self, precision=3):
|
|
13
|
+
self.precision = precision
|
|
14
|
+
|
|
12
15
|
def __call__(self, func):
|
|
13
16
|
def _(*args, **kws):
|
|
14
17
|
t_start = perf_counter()
|
|
15
18
|
res = func(*args, **kws)
|
|
16
19
|
t_end = perf_counter()
|
|
17
20
|
duration = t_end - t_start
|
|
18
|
-
logger.warning(f"Execution of {func.__name__} took {duration:.
|
|
21
|
+
logger.warning(f"Execution of {func.__name__} took {duration:.{self.precision}f}s")
|
|
19
22
|
self.times[func.__name__] = duration
|
|
20
23
|
return res
|
|
21
24
|
return _
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: numbox
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.8
|
|
4
4
|
Author: Mikhail Goykhman
|
|
5
5
|
License: MIT License (with Citation Clause)
|
|
6
6
|
|
|
@@ -34,8 +34,12 @@ Keywords: llvmlite,numba,numpy
|
|
|
34
34
|
Requires-Python: >=3.9
|
|
35
35
|
Description-Content-Type: text/markdown
|
|
36
36
|
License-File: LICENSE
|
|
37
|
+
Requires-Dist: llvmlite==0.44.0
|
|
38
|
+
Requires-Dist: numba~=0.61.0
|
|
39
|
+
Requires-Dist: numpy~=2.1.3
|
|
37
40
|
Provides-Extra: docs
|
|
38
41
|
Requires-Dist: sphinx==8.1.3; extra == "docs"
|
|
42
|
+
Requires-Dist: sphinx-sitemap==2.7.2; extra == "docs"
|
|
39
43
|
Requires-Dist: sphinx-rtd-theme; extra == "docs"
|
|
40
44
|
|
|
41
45
|
# numbox
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
numbox/__init__.py,sha256=
|
|
1
|
+
numbox/__init__.py,sha256=QS1piWKz3Mys2vOiR2kTlrqfdbiwJYEfhOlgbh73Sg8,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
|
|
@@ -13,9 +13,9 @@ numbox/core/bindings/call.py,sha256=LrSsp-b4Mz0Zjg7H3XkThEIOEqVcrcViEjI9yqhuMV4,
|
|
|
13
13
|
numbox/core/bindings/signatures.py,sha256=OcSBDpJ422eoWkJXxHPEanMNbVB7bq9f5bRq5LGr86w,479
|
|
14
14
|
numbox/core/bindings/utils.py,sha256=aRtN8oUYBk9vgoUGaUJosGx0Za-vvCNwwbZg_g_-LRs,460
|
|
15
15
|
numbox/core/proxy/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
16
|
-
numbox/core/proxy/proxy.py,sha256=
|
|
16
|
+
numbox/core/proxy/proxy.py,sha256=Wt7yzswDmeQXt0yjcTcnLi2coneowSHWXy_IFpZZJMU,3612
|
|
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=U7hxopSwOc1ke1Hqup6xCliO7bqjq91zVX1SixYPxoM,6072
|
|
19
19
|
numbox/core/work/combine_utils.py,sha256=qTVGke_ydzaTQ7o29DFjZWZzKjRNKb0L3yJMaR3TLII,2430
|
|
20
20
|
numbox/core/work/explain.py,sha256=ESwvsTgfe0w7UnM13yyVpVDtfJyAK2A1sNdF3RNb-jU,1200
|
|
21
21
|
numbox/core/work/loader_utils.py,sha256=g83mDWidZJ8oLWP3I3rK8aGISYOO2S-w6HDgtosCyck,1572
|
|
@@ -23,16 +23,17 @@ numbox/core/work/lowlevel_work_utils.py,sha256=TgRRcNfks0oaOXGXXr3ptafd_Xv_lpmH8
|
|
|
23
23
|
numbox/core/work/node.py,sha256=CMolyoRQjG2A-pTQqZQ0kxKOYTKipWRC0mu8RWHuTUI,5096
|
|
24
24
|
numbox/core/work/node_base.py,sha256=uI7asM2itQcHuOByXyJtqvrd4ovW6EXDRdHYp3JVHQ0,998
|
|
25
25
|
numbox/core/work/print_tree.py,sha256=y2u7xmbHvpcA57y8PrGSqOunLNCqhgNXdVtXHqvy1M0,2340
|
|
26
|
-
numbox/core/work/work.py,sha256=
|
|
26
|
+
numbox/core/work/work.py,sha256=596flxydeHuEJ3oUhNz3PYPtA58nxERifvBCh8BWVug,15091
|
|
27
27
|
numbox/core/work/work_utils.py,sha256=3q_nnBdzuxWWcdFpbRL2H0T9ZNkUgx1J1uhiZkX3YG4,1039
|
|
28
28
|
numbox/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
29
|
-
numbox/utils/highlevel.py,sha256=
|
|
29
|
+
numbox/utils/highlevel.py,sha256=0sUVGOFAzFaGycKrXloGySLjp5EAPaf1B0AcOT1dfbw,8326
|
|
30
30
|
numbox/utils/lowlevel.py,sha256=ACpf8_HyOIsobPlZ31bapkEyuCsV5dojW3AFrcKykrw,10712
|
|
31
31
|
numbox/utils/meminfo.py,sha256=ykFi8Vt0WcHI3ztgMwvpn6NqaflDSQGL8tjI01jrzm0,1759
|
|
32
|
-
numbox/utils/
|
|
32
|
+
numbox/utils/standard.py,sha256=2fPrMlSXe2TG3CIfjJOT8LQkHEH86oOOj1AvwQkYCfA,450
|
|
33
|
+
numbox/utils/timer.py,sha256=5_d690Fb3L2axJBRxtoB0qe23exBosNR4qu6cno4QfY,641
|
|
33
34
|
numbox/utils/void_type.py,sha256=IkZsjNeAIShYJtvWbvERdHnl_mbF1rCRWiM3gp6II8U,404
|
|
34
|
-
numbox-0.2.
|
|
35
|
-
numbox-0.2.
|
|
36
|
-
numbox-0.2.
|
|
37
|
-
numbox-0.2.
|
|
38
|
-
numbox-0.2.
|
|
35
|
+
numbox-0.2.8.dist-info/LICENSE,sha256=YYgNvjH_p6-1NsdrIqGJnr1GUbZzA_8DxsP6vVfM6nY,1446
|
|
36
|
+
numbox-0.2.8.dist-info/METADATA,sha256=krcMK7v4WNgTrcuriQAWMASeaRod9KybPc57tRUE7w0,2935
|
|
37
|
+
numbox-0.2.8.dist-info/WHEEL,sha256=iAkIy5fosb7FzIOwONchHf19Qu7_1wCWyFNR5gu9nU0,91
|
|
38
|
+
numbox-0.2.8.dist-info/top_level.txt,sha256=A67jOkfqidCSYYm6ifjN_WZyIiR1B27fjxv6nNbPvjc,7
|
|
39
|
+
numbox-0.2.8.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|