numbox 0.2.17__py3-none-any.whl → 0.3.1__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/variable/__init__.py +0 -0
- numbox/core/variable/variable.py +428 -0
- {numbox-0.2.17.dist-info → numbox-0.3.1.dist-info}/METADATA +3 -2
- {numbox-0.2.17.dist-info → numbox-0.3.1.dist-info}/RECORD +8 -6
- {numbox-0.2.17.dist-info → numbox-0.3.1.dist-info}/LICENSE +0 -0
- {numbox-0.2.17.dist-info → numbox-0.3.1.dist-info}/WHEEL +0 -0
- {numbox-0.2.17.dist-info → numbox-0.3.1.dist-info}/top_level.txt +0 -0
numbox/__init__.py
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
__version__ = '0.
|
|
1
|
+
__version__ = '0.3.1'
|
|
File without changes
|
|
@@ -0,0 +1,428 @@
|
|
|
1
|
+
import warnings
|
|
2
|
+
|
|
3
|
+
from collections import defaultdict
|
|
4
|
+
from dataclasses import dataclass, field
|
|
5
|
+
from typing import (
|
|
6
|
+
Any, Callable, Dict, List, Mapping, Set, Tuple, TypeAlias, Union
|
|
7
|
+
)
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
Namespace: TypeAlias = Union['External', 'Variables']
|
|
11
|
+
VarSpec: TypeAlias = Dict[str, Callable | Dict[str, str] | str]
|
|
12
|
+
VarValue: TypeAlias = Any
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
class _Null:
|
|
16
|
+
""" Value of `Variable` that has not been calculated. """
|
|
17
|
+
pass
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
_null = _Null()
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
QUAL_SEP = "."
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
def _make_qual_name(namespace_name: str, var_name: str) -> str:
|
|
27
|
+
""" Each `Variable` instance is best contained in a
|
|
28
|
+
mapping namespace, with the given `namespace_name`.
|
|
29
|
+
This function thereby returns qualified name of the
|
|
30
|
+
`Variable` instance. """
|
|
31
|
+
return f"{namespace_name}{QUAL_SEP}{var_name}"
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
class External:
|
|
35
|
+
"""
|
|
36
|
+
A dictionary that facilitates discovery of required names.
|
|
37
|
+
When requested a `Variable` with the given name via a
|
|
38
|
+
typical `__getitem__` call, if the `Variable` is not
|
|
39
|
+
found, it will be created and added to this dictionary.
|
|
40
|
+
This way the user will be able to infer which variables
|
|
41
|
+
are required from the external source abstracted by this
|
|
42
|
+
dictionary.
|
|
43
|
+
"""
|
|
44
|
+
def __init__(self, name: str):
|
|
45
|
+
self.name = name
|
|
46
|
+
self._vars = {}
|
|
47
|
+
|
|
48
|
+
def __getitem__(self, name):
|
|
49
|
+
variable = self._vars.get(name)
|
|
50
|
+
if variable is None:
|
|
51
|
+
variable = Variable(
|
|
52
|
+
name=name,
|
|
53
|
+
source=self.name
|
|
54
|
+
)
|
|
55
|
+
self._vars[name] = variable
|
|
56
|
+
return variable
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
@dataclass(frozen=True)
|
|
60
|
+
class Variable:
|
|
61
|
+
"""
|
|
62
|
+
An instance of `Variable` is anything that can be calculated
|
|
63
|
+
from the values of the given input dependencies using the
|
|
64
|
+
provided formula (i.e., a function).
|
|
65
|
+
|
|
66
|
+
Calculated value can be `None`, that is why a non-calculated
|
|
67
|
+
value is designated with `_null`.
|
|
68
|
+
|
|
69
|
+
An instance of `Variable` is best created directly within
|
|
70
|
+
the given `Namespace`, that is, when it is instantiated upon
|
|
71
|
+
initialization of that `Namespace` and made then available
|
|
72
|
+
through a `__getitem__` call to either a collection of
|
|
73
|
+
variables created as an instance of `Variables` (see below)
|
|
74
|
+
or a non-`Variables` mapping, referred to (or abstracted by),
|
|
75
|
+
in general, as an `External` collection. The namespace is
|
|
76
|
+
also referred to as the 'source' of the `Variable`.
|
|
77
|
+
|
|
78
|
+
Qualified name of a `Variable` incorporates both the name
|
|
79
|
+
of the `Variable` and the name of its source / namespace.
|
|
80
|
+
|
|
81
|
+
It is therefore recommended to create `Variable` only in
|
|
82
|
+
the `External` or `Variables` containers rather than in
|
|
83
|
+
isolation.
|
|
84
|
+
|
|
85
|
+
:param name: name of the `Variable` instance.
|
|
86
|
+
:param source: name of the `Variables` or `External` instance
|
|
87
|
+
which is namespaces / source of this `Variable`.
|
|
88
|
+
:param inputs: (optional) map from names of the `Variable`
|
|
89
|
+
inputs (which are names of other `Variable` instances) to
|
|
90
|
+
the names of their sources, i.e., names of either
|
|
91
|
+
`Variables` or 'External' mapping collections referencing
|
|
92
|
+
these variables.
|
|
93
|
+
:param formula: (optional) function that calculates value
|
|
94
|
+
of this `Variable` from its sources.
|
|
95
|
+
:param cacheable: (default `False`) when `True`, the
|
|
96
|
+
corresponding `Value` (see below) will be cached during
|
|
97
|
+
calculation by the `id` of the corresponding Python object
|
|
98
|
+
containing that value. When attempted to recompute with
|
|
99
|
+
the same inputs, cached value will be returned instead.
|
|
100
|
+
"""
|
|
101
|
+
name: str
|
|
102
|
+
source: str = field(default="")
|
|
103
|
+
inputs: Mapping[str, str] = field(default_factory=lambda: {})
|
|
104
|
+
formula: Callable = field(default=None)
|
|
105
|
+
cacheable: bool = field(default=False)
|
|
106
|
+
|
|
107
|
+
def __hash__(self):
|
|
108
|
+
return hash((self.source, self.name))
|
|
109
|
+
|
|
110
|
+
def __eq__(self, other):
|
|
111
|
+
return isinstance(other, Variable) and self.name == other.name and self.source == other.source
|
|
112
|
+
|
|
113
|
+
def qual_name(self) -> str:
|
|
114
|
+
return _make_qual_name(self.source, self.name)
|
|
115
|
+
|
|
116
|
+
|
|
117
|
+
class Variables:
|
|
118
|
+
def __init__(
|
|
119
|
+
self,
|
|
120
|
+
name: str,
|
|
121
|
+
variables: List[VarSpec],
|
|
122
|
+
):
|
|
123
|
+
"""
|
|
124
|
+
Namespace of `Variable` instances.
|
|
125
|
+
|
|
126
|
+
:param name: name of the `Variables` instance namespace.
|
|
127
|
+
:param variables: initializer list of `VarSpec` specs that can be used
|
|
128
|
+
to create instances of `Variable` to be stored in this namespace.
|
|
129
|
+
"""
|
|
130
|
+
self.name = name
|
|
131
|
+
self.variables = {variable["name"]: Variable(source=self.name, **variable) for variable in variables}
|
|
132
|
+
|
|
133
|
+
def __getitem__(self, variable_name: str) -> Variable:
|
|
134
|
+
"""
|
|
135
|
+
:param variable_name: name of the `Variable` to retrieve,
|
|
136
|
+
it is expected that `Variables` and `External` all expose
|
|
137
|
+
this method that returns an instance of the `Variable` with
|
|
138
|
+
the given name in either a `Variables` namespace or an
|
|
139
|
+
`External` namespace, respectively.
|
|
140
|
+
"""
|
|
141
|
+
return self.variables[variable_name]
|
|
142
|
+
|
|
143
|
+
|
|
144
|
+
@dataclass
|
|
145
|
+
class Value:
|
|
146
|
+
"""
|
|
147
|
+
Value of the corresponding `Variable`.
|
|
148
|
+
"""
|
|
149
|
+
variable: Variable
|
|
150
|
+
value: VarValue | _Null = field(default_factory=lambda: _null)
|
|
151
|
+
|
|
152
|
+
|
|
153
|
+
class Values:
|
|
154
|
+
""" Values of all `Variable`s, computed and external,
|
|
155
|
+
will be held here. """
|
|
156
|
+
def __init__(self):
|
|
157
|
+
self.values: Dict[Variable, Value] = {}
|
|
158
|
+
self.cache: Dict[tuple, VarValue] = {}
|
|
159
|
+
|
|
160
|
+
def get(self, variable: Variable) -> Value:
|
|
161
|
+
if variable not in self.values:
|
|
162
|
+
self.values[variable] = Value(variable=variable)
|
|
163
|
+
return self.values[variable]
|
|
164
|
+
|
|
165
|
+
|
|
166
|
+
@dataclass(frozen=True)
|
|
167
|
+
class CompiledNode:
|
|
168
|
+
variable: Variable
|
|
169
|
+
inputs: List[Variable]
|
|
170
|
+
|
|
171
|
+
def __post_init__(self):
|
|
172
|
+
if self.variable.formula is None and self.inputs:
|
|
173
|
+
raise RuntimeError(f"{self.variable} contains inputs but no formula, how come?")
|
|
174
|
+
|
|
175
|
+
def __hash__(self):
|
|
176
|
+
return hash((self.variable.source, self.variable.name))
|
|
177
|
+
|
|
178
|
+
def __eq__(self, other):
|
|
179
|
+
return (
|
|
180
|
+
isinstance(other, CompiledNode) and
|
|
181
|
+
self.variable.name == other.variable.name and
|
|
182
|
+
self.variable.source == other.variable.source
|
|
183
|
+
)
|
|
184
|
+
|
|
185
|
+
|
|
186
|
+
@dataclass(frozen=True)
|
|
187
|
+
class CompiledGraph:
|
|
188
|
+
ordered_nodes: List[CompiledNode]
|
|
189
|
+
required_external_variables: Dict[str, Dict[str, Variable]]
|
|
190
|
+
dependents: Dict[Variable, List[CompiledNode]] = field(default_factory=lambda: defaultdict(list))
|
|
191
|
+
|
|
192
|
+
def __post_init__(self):
|
|
193
|
+
for node in self.ordered_nodes:
|
|
194
|
+
for inp in node.inputs:
|
|
195
|
+
self.dependents[inp].append(node)
|
|
196
|
+
|
|
197
|
+
def execute(
|
|
198
|
+
self,
|
|
199
|
+
external_values: Dict[str, Dict[str, VarValue]],
|
|
200
|
+
values: Values,
|
|
201
|
+
):
|
|
202
|
+
"""
|
|
203
|
+
Main entry point to calculation of compiled graph.
|
|
204
|
+
Calculation requires the following inputs:
|
|
205
|
+
|
|
206
|
+
:param external_values: actual values of all required external
|
|
207
|
+
variables, this can be a superset of what is really needed for
|
|
208
|
+
the calculation. The map is first from the name of the external
|
|
209
|
+
source and then from the name of the variable within that
|
|
210
|
+
source to the variable's actual value.
|
|
211
|
+
:param values: runtime storage of all values, instance of `Values`.
|
|
212
|
+
:return:
|
|
213
|
+
"""
|
|
214
|
+
self._assign_external_values(external_values, values)
|
|
215
|
+
self._calculate(self.ordered_nodes, values)
|
|
216
|
+
|
|
217
|
+
def _assign_external_values(
|
|
218
|
+
self,
|
|
219
|
+
external_values: Dict[str, Dict[str, VarValue]],
|
|
220
|
+
values: Values
|
|
221
|
+
):
|
|
222
|
+
"""
|
|
223
|
+
For the external variables required for this calculation,
|
|
224
|
+
populate their values into the `Values` container.
|
|
225
|
+
|
|
226
|
+
:param external_values: mapping from names of external sources
|
|
227
|
+
to dictionary from names of external `Variable`s to their instances,
|
|
228
|
+
that are needed for the given calculation.
|
|
229
|
+
:param external_values: dictionary of `External` name to a mapping
|
|
230
|
+
of `Variable` names to their values.
|
|
231
|
+
:param values: an instance of `Values` storage of all calculated
|
|
232
|
+
values.
|
|
233
|
+
"""
|
|
234
|
+
for source_name, variables in self.required_external_variables.items():
|
|
235
|
+
provided = external_values.get(source_name)
|
|
236
|
+
if provided is None:
|
|
237
|
+
raise KeyError(f"Missing external source '{source_name}'")
|
|
238
|
+
for var_name, variable in variables.items():
|
|
239
|
+
if var_name not in provided:
|
|
240
|
+
raise KeyError(
|
|
241
|
+
f"Missing value for external variable '{source_name}.{var_name}'"
|
|
242
|
+
)
|
|
243
|
+
values.get(variable).value = provided[var_name]
|
|
244
|
+
|
|
245
|
+
def _collect_affected(self, changed_vars: Set[Variable]) -> List[CompiledNode]:
|
|
246
|
+
"""
|
|
247
|
+
Return subset of `self.ordered_nodes` consisting of nodes
|
|
248
|
+
affected by `changed_vars`, in the same order as in the original.
|
|
249
|
+
"""
|
|
250
|
+
affected = set()
|
|
251
|
+
stack = list(changed_vars)
|
|
252
|
+
while stack:
|
|
253
|
+
v = stack.pop()
|
|
254
|
+
for node in self.dependents.get(v, []):
|
|
255
|
+
if node not in affected:
|
|
256
|
+
affected.add(node)
|
|
257
|
+
stack.append(node.variable)
|
|
258
|
+
return [node for node in self.ordered_nodes if node in affected]
|
|
259
|
+
|
|
260
|
+
@staticmethod
|
|
261
|
+
def _calculate(nodes: List[CompiledNode], values: Values):
|
|
262
|
+
"""
|
|
263
|
+
Calculate the values of the `Variable`s using their own callables
|
|
264
|
+
by evaluating them as functions of the values of the specified
|
|
265
|
+
inputs.
|
|
266
|
+
|
|
267
|
+
All inputs need to be calculated first (i.e., to be non-`_null`)
|
|
268
|
+
before the value of the given `Variable` can be `calculate`d.
|
|
269
|
+
|
|
270
|
+
This is possible because the `Variable`s are supplied as a
|
|
271
|
+
topologically ordered list `ordered_variables`.
|
|
272
|
+
"""
|
|
273
|
+
for node in nodes:
|
|
274
|
+
if node.variable.formula is None:
|
|
275
|
+
continue
|
|
276
|
+
args = tuple(values.get(input_).value for input_ in node.inputs)
|
|
277
|
+
# assert _null not in args, f"Uninitialized input for {node.variable}, args = {args}"
|
|
278
|
+
cache_key = (node.variable, args)
|
|
279
|
+
if node.variable.cacheable:
|
|
280
|
+
if cache_key in values.cache:
|
|
281
|
+
values.get(node.variable).value = values.cache[cache_key]
|
|
282
|
+
continue
|
|
283
|
+
result = node.variable.formula(*args)
|
|
284
|
+
if node.variable.cacheable:
|
|
285
|
+
values.cache[cache_key] = result
|
|
286
|
+
values.get(node.variable).value = result
|
|
287
|
+
|
|
288
|
+
def recompute(self, changed: Dict[str, Dict[str, VarValue]], values: Values):
|
|
289
|
+
"""
|
|
290
|
+
:param changed: dict of sources to names to new values of changed `Variable`s.
|
|
291
|
+
:param values: storage of all the `Variable` values.
|
|
292
|
+
"""
|
|
293
|
+
changed_vars = set()
|
|
294
|
+
for src, vals in changed.items():
|
|
295
|
+
for name, val in vals.items():
|
|
296
|
+
variable = self.required_external_variables.get(src, {}).get(name)
|
|
297
|
+
qual = _make_qual_name(src, name)
|
|
298
|
+
if variable is None:
|
|
299
|
+
try:
|
|
300
|
+
variable = next(n.variable for n in self.ordered_nodes if n.variable.qual_name() == qual)
|
|
301
|
+
except StopIteration:
|
|
302
|
+
warnings.warn(f"{qual} is not in the calculation path, update has no effect.")
|
|
303
|
+
continue
|
|
304
|
+
values.get(variable).value = val
|
|
305
|
+
changed_vars.add(variable)
|
|
306
|
+
affected_nodes = self._collect_affected(changed_vars)
|
|
307
|
+
for node in affected_nodes:
|
|
308
|
+
values.get(node.variable).value = _null
|
|
309
|
+
self._calculate(affected_nodes, values)
|
|
310
|
+
|
|
311
|
+
|
|
312
|
+
class Graph:
|
|
313
|
+
def __init__(
|
|
314
|
+
self,
|
|
315
|
+
variables_lists: Dict[str, List[VarSpec]],
|
|
316
|
+
external_source_names: List[str]
|
|
317
|
+
):
|
|
318
|
+
"""
|
|
319
|
+
:param variables_lists: mapping of names of `Variables`
|
|
320
|
+
namespace to the list of `Variable` instances to be added
|
|
321
|
+
to that namespace.
|
|
322
|
+
:param external_source_names: list of names of possible
|
|
323
|
+
`External` sources from which `Variable` inputs might
|
|
324
|
+
be coming from.
|
|
325
|
+
"""
|
|
326
|
+
self.external_source_names = external_source_names
|
|
327
|
+
self.registry = {}
|
|
328
|
+
self.external = {
|
|
329
|
+
external_source_name: External(external_source_name) for external_source_name in external_source_names
|
|
330
|
+
}
|
|
331
|
+
for variables_name, variables_list in variables_lists.items():
|
|
332
|
+
assert variables_name not in self.registry, (
|
|
333
|
+
f"Variables instance {variables_name} has already been created in this registry"
|
|
334
|
+
)
|
|
335
|
+
variables = Variables(
|
|
336
|
+
name=variables_name,
|
|
337
|
+
variables=variables_list
|
|
338
|
+
)
|
|
339
|
+
self.registry[variables_name] = variables
|
|
340
|
+
for external_name, external_ in self.external.items():
|
|
341
|
+
registered_external = self.registry.get(external_name)
|
|
342
|
+
if registered_external is not None:
|
|
343
|
+
assert registered_external == external_, (
|
|
344
|
+
f"{external_name} external already registered as {registered_external}"
|
|
345
|
+
)
|
|
346
|
+
else:
|
|
347
|
+
self.registry[external_name] = external_
|
|
348
|
+
self.compiled_graphs = {}
|
|
349
|
+
|
|
350
|
+
def compile(self, required: List[str] | str) -> CompiledGraph:
|
|
351
|
+
if isinstance(required, str):
|
|
352
|
+
required = [required]
|
|
353
|
+
required_tup = tuple(sorted(required))
|
|
354
|
+
compiled_graph = self.compiled_graphs.get(required_tup)
|
|
355
|
+
if compiled_graph is not None:
|
|
356
|
+
return compiled_graph
|
|
357
|
+
ordered_variables, used_external_vars = self._topological_order(required)
|
|
358
|
+
ordered_nodes = [
|
|
359
|
+
CompiledNode(
|
|
360
|
+
variable=var,
|
|
361
|
+
inputs=[self.registry[var.inputs[input_name]][input_name] for input_name in var.inputs.keys()]
|
|
362
|
+
) for var in ordered_variables
|
|
363
|
+
]
|
|
364
|
+
required_external_variables = self._required_external_variables(used_external_vars)
|
|
365
|
+
compiled = CompiledGraph(
|
|
366
|
+
ordered_nodes=ordered_nodes,
|
|
367
|
+
required_external_variables=required_external_variables,
|
|
368
|
+
)
|
|
369
|
+
self.compiled_graphs[required_tup] = compiled
|
|
370
|
+
return compiled
|
|
371
|
+
|
|
372
|
+
def _get_source(self, source_name: str) -> Namespace:
|
|
373
|
+
"""
|
|
374
|
+
:param source_name: name of the source (either an instance
|
|
375
|
+
of `Variables` or an `External` source) that is requested.
|
|
376
|
+
"""
|
|
377
|
+
variables_source = self.registry.get(source_name)
|
|
378
|
+
if variables_source is not None:
|
|
379
|
+
return variables_source
|
|
380
|
+
raise KeyError(f"Unknown source {source_name}")
|
|
381
|
+
|
|
382
|
+
def _topological_order(self, required: List | Tuple | str):
|
|
383
|
+
"""
|
|
384
|
+
:param required: qualified name(s) of `Variable` instance(s)
|
|
385
|
+
for which a topological ordering of a DAG is to be determined.
|
|
386
|
+
"""
|
|
387
|
+
if isinstance(required, str):
|
|
388
|
+
required = [required]
|
|
389
|
+
|
|
390
|
+
visited = set()
|
|
391
|
+
visiting = set()
|
|
392
|
+
ordered_variables = []
|
|
393
|
+
|
|
394
|
+
used_external_vars: Set[Variable] = set()
|
|
395
|
+
|
|
396
|
+
def visit(qual_name: str):
|
|
397
|
+
if qual_name in visited:
|
|
398
|
+
return
|
|
399
|
+
if qual_name in visiting:
|
|
400
|
+
raise RuntimeError(f"Cycle detected at {qual_name}")
|
|
401
|
+
visiting.add(qual_name)
|
|
402
|
+
source_name, variable_name = qual_name.split(QUAL_SEP)
|
|
403
|
+
source = self._get_source(source_name)
|
|
404
|
+
variable = source[variable_name]
|
|
405
|
+
if isinstance(source, External):
|
|
406
|
+
used_external_vars.add(variable)
|
|
407
|
+
for input_name, input_source in variable.inputs.items():
|
|
408
|
+
visit(_make_qual_name(input_source, input_name))
|
|
409
|
+
visiting.remove(qual_name)
|
|
410
|
+
visited.add(qual_name)
|
|
411
|
+
ordered_variables.append(variable)
|
|
412
|
+
|
|
413
|
+
for r in required:
|
|
414
|
+
visit(r)
|
|
415
|
+
return ordered_variables, used_external_vars
|
|
416
|
+
|
|
417
|
+
@staticmethod
|
|
418
|
+
def _required_external_variables(used_external_vars: Set[Variable]) -> Dict[str, Dict[str, Variable]]:
|
|
419
|
+
"""
|
|
420
|
+
For requested `External` sources, return the list of required
|
|
421
|
+
external `Variable` instances.
|
|
422
|
+
"""
|
|
423
|
+
required_external_variables = defaultdict(dict)
|
|
424
|
+
for variable in used_external_vars:
|
|
425
|
+
variable_name = variable.name
|
|
426
|
+
variable_source = variable.source
|
|
427
|
+
required_external_variables[variable_source][variable_name] = variable
|
|
428
|
+
return required_external_variables
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: numbox
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.3.1
|
|
4
4
|
Author: Mikhail Goykhman
|
|
5
5
|
License: MIT License (with Citation Clause)
|
|
6
6
|
|
|
@@ -50,8 +50,9 @@ Documentation is available at [numbox](https://goykhman.github.io/numbox).
|
|
|
50
50
|
|
|
51
51
|
- **Any**: A lightweight structure that wraps any value into the same type leveraging a variant of the type erasure technique.
|
|
52
52
|
- **Bindings**: JIT-wrappers of functions imported from dynamically linked libraries.
|
|
53
|
-
- **Node
|
|
53
|
+
- **Node**: A lightweight JIT-compatible graph node with type-erased dependencies in a uniform dynamically-sized vector (numba List).
|
|
54
54
|
- **Proxy**: Create a proxy for a decorated function with specified signatures, enabling efficient JIT compilation and caching.
|
|
55
|
+
- **Variable**: Pure Python framework of a graph calculation. JIT-compiled dispatchers can be invoked by it.
|
|
55
56
|
- **Work**: JIT-compatible unit of calculation work with dependencies, inner states, and custom calculation.
|
|
56
57
|
|
|
57
58
|
## Installation
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
numbox/__init__.py,sha256=
|
|
1
|
+
numbox/__init__.py,sha256=TZkGuMIRSRmUY3XCIs5owt2o60vXyqYMHWIkhx65uYE,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
|
|
@@ -14,6 +14,8 @@ numbox/core/bindings/signatures.py,sha256=OcSBDpJ422eoWkJXxHPEanMNbVB7bq9f5bRq5L
|
|
|
14
14
|
numbox/core/bindings/utils.py,sha256=OATfF4k8e5oPa9_wlHHkLQhY_DhrPNKYdeeGu9Nj5yg,1180
|
|
15
15
|
numbox/core/proxy/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
16
16
|
numbox/core/proxy/proxy.py,sha256=Wt7yzswDmeQXt0yjcTcnLi2coneowSHWXy_IFpZZJMU,3612
|
|
17
|
+
numbox/core/variable/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
18
|
+
numbox/core/variable/variable.py,sha256=GoCsB1hUDJJzZByK1OK13RZn4M-maBDjXfnbvRFjcS8,16371
|
|
17
19
|
numbox/core/work/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
18
20
|
numbox/core/work/builder.py,sha256=d0DRwJoyskp-6tYQyV1VE-v9eX99qJbQJ_FdAFrjuiE,6273
|
|
19
21
|
numbox/core/work/builder_utils.py,sha256=z8au1x10AwnzQ0_MAbQ6DnKTp3u9HeYZ1jyfkUMYjVg,1213
|
|
@@ -33,8 +35,8 @@ numbox/utils/meminfo.py,sha256=ykFi8Vt0WcHI3ztgMwvpn6NqaflDSQGL8tjI01jrzm0,1759
|
|
|
33
35
|
numbox/utils/standard.py,sha256=SPsQcyLZw21RaNCdfkIGE_QBaVnMtZjJY4F40_GGuak,347
|
|
34
36
|
numbox/utils/timer.py,sha256=5_d690Fb3L2axJBRxtoB0qe23exBosNR4qu6cno4QfY,641
|
|
35
37
|
numbox/utils/void_type.py,sha256=IkZsjNeAIShYJtvWbvERdHnl_mbF1rCRWiM3gp6II8U,404
|
|
36
|
-
numbox-0.
|
|
37
|
-
numbox-0.
|
|
38
|
-
numbox-0.
|
|
39
|
-
numbox-0.
|
|
40
|
-
numbox-0.
|
|
38
|
+
numbox-0.3.1.dist-info/LICENSE,sha256=YYgNvjH_p6-1NsdrIqGJnr1GUbZzA_8DxsP6vVfM6nY,1446
|
|
39
|
+
numbox-0.3.1.dist-info/METADATA,sha256=L2Ol4D5QRR_K8j31xvFgbdJtxFiFLDJG2MPWrmS81Zk,2996
|
|
40
|
+
numbox-0.3.1.dist-info/WHEEL,sha256=WnJ8fYhv8N4SYVK2lLYNI6N0kVATA7b0piVUNvqIIJE,91
|
|
41
|
+
numbox-0.3.1.dist-info/top_level.txt,sha256=A67jOkfqidCSYYm6ifjN_WZyIiR1B27fjxv6nNbPvjc,7
|
|
42
|
+
numbox-0.3.1.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|