cdxcore 0.1.11__py3-none-any.whl → 0.1.13__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 cdxcore might be problematic. Click here for more details.
- cdxcore/__init__.py +1 -1
- cdxcore/deferred.py +752 -0
- cdxcore/err.py +10 -5
- cdxcore/jcpool.py +2 -3
- cdxcore/util.py +72 -1
- cdxcore/verbose.py +15 -1
- {cdxcore-0.1.11.dist-info → cdxcore-0.1.13.dist-info}/METADATA +1 -1
- cdxcore-0.1.13.dist-info/RECORD +37 -0
- tests/test_config.py +1 -11
- tests/test_crman.py +1 -10
- tests/test_deferred.py +277 -0
- tests/test_err.py +2 -10
- tests/test_jcpool.py +83 -17
- tests/test_pretty.py +2 -12
- tests/test_subdir.py +1 -9
- tests/test_uniquehash.py +1 -9
- tests/test_util.py +100 -10
- tests/test_verbose.py +1 -10
- tests/test_version.py +1 -9
- cdxcore-0.1.11.dist-info/RECORD +0 -36
- tmp/deferred.py +0 -220
- {tmp → cdxcore}/dynaplot.py +0 -0
- {cdxcore-0.1.11.dist-info → cdxcore-0.1.13.dist-info}/WHEEL +0 -0
- {cdxcore-0.1.11.dist-info → cdxcore-0.1.13.dist-info}/licenses/LICENSE +0 -0
- {cdxcore-0.1.11.dist-info → cdxcore-0.1.13.dist-info}/top_level.txt +0 -0
cdxcore/err.py
CHANGED
|
@@ -95,6 +95,11 @@ def _fmt( text : str, args = None, kwargs = None, f : Callable = None ) -> str:
|
|
|
95
95
|
return text % tuple(args)
|
|
96
96
|
except TypeError as e:
|
|
97
97
|
raise TypeError(e, text, args)
|
|
98
|
+
|
|
99
|
+
# no keyword arguments --> must be plain text
|
|
100
|
+
if kwargs is None:
|
|
101
|
+
return text
|
|
102
|
+
|
|
98
103
|
# text
|
|
99
104
|
# python 2 and 3 mode
|
|
100
105
|
kwargs = dict() if kwargs is None else kwargs
|
|
@@ -117,7 +122,7 @@ def fmt(text : str|Callable, * args, ** kwargs) -> str:
|
|
|
117
122
|
one = 1
|
|
118
123
|
fmt(lambda : f"one {one:d}) # using a lambda function
|
|
119
124
|
fmt("one {one:d}", one=one) # using python 3 string.format()
|
|
120
|
-
fmt("one %
|
|
125
|
+
fmt("one %(one)ld", one=one) # using python 2 style
|
|
121
126
|
fmt("one %ld", one) # using c-style
|
|
122
127
|
|
|
123
128
|
As shown, do not use f-strings directly as they are immediately executed in the scope they are typed in
|
|
@@ -164,7 +169,7 @@ def error( text : str|Callable, *args, exception : Exception = RuntimeError, **k
|
|
|
164
169
|
one = 1
|
|
165
170
|
error(lambda : f"one {one:d}") # wrapped f-string
|
|
166
171
|
error("one {one:d}", one=one) # using python 3 string.format()
|
|
167
|
-
error("one %
|
|
172
|
+
error("one %(one)ld", one=one) # using python 2 style
|
|
168
173
|
error("one %ld", one) # using c-style
|
|
169
174
|
|
|
170
175
|
As shown, do not use f-strings directly as they are immediately executed in the scope they are typed in
|
|
@@ -214,7 +219,7 @@ def verify( cond : bool, text : str|Callable, *args, exception : Exception = Run
|
|
|
214
219
|
good = False # some condition
|
|
215
220
|
verify(good, lambda : f"one {one:d}") # wrapped f-string
|
|
216
221
|
verify(good, "one {one:d}", one=one) # using python 3 string.format()
|
|
217
|
-
verify(good, "one %
|
|
222
|
+
verify(good, "one %(one)ld", one=one) # using python 2 style
|
|
218
223
|
verify(good, "one %ld", one) # using c-style
|
|
219
224
|
|
|
220
225
|
As shown, do not use f-strings directly as they are immediately executed in the scope they are typed in
|
|
@@ -268,7 +273,7 @@ def warn( text : str|Callable, *args, warning = RuntimeWarning, stack_level : in
|
|
|
268
273
|
one = 1
|
|
269
274
|
warn(lambda : f"one {one:d}") # wrapped f-string
|
|
270
275
|
warn("one {one:d}", one=one) # using python 3 string.format()
|
|
271
|
-
warn("one %
|
|
276
|
+
warn("one %(one)ld", one=one) # using python 2 style
|
|
272
277
|
warn("one %ld", one) # using c-style
|
|
273
278
|
|
|
274
279
|
As shown, do not use f-strings directly as they are immediately executed in the scope they are typed in
|
|
@@ -322,7 +327,7 @@ def warn_if( cond : bool, text : str|Callable, *args, warning = RuntimeWarning,
|
|
|
322
327
|
bad = True # some conditon
|
|
323
328
|
warn_if(bad,lambda : f"one {one:d}") # wrapped f-string
|
|
324
329
|
warn_if(bad,"one {one:d}", one=one) # using python 3 string.format()
|
|
325
|
-
warn_if(bad,"one %
|
|
330
|
+
warn_if(bad,"one %(one)ld", one=one) # using python 2 style
|
|
326
331
|
warn_if(bad,"one %ld", one) # using c-style
|
|
327
332
|
|
|
328
333
|
As shown, do not use f-strings directly as they are immediately executed in the scope they are typed in
|
cdxcore/jcpool.py
CHANGED
|
@@ -51,7 +51,7 @@ class ParallelContextChannel( Context ):
|
|
|
51
51
|
printing.
|
|
52
52
|
"""
|
|
53
53
|
if get_thread_id() == self._maintid:
|
|
54
|
-
self._f_verbose.
|
|
54
|
+
self._f_verbose._raw(msg,end='',flush=flush)
|
|
55
55
|
else:
|
|
56
56
|
return self._queue.put( (msg, flush) )
|
|
57
57
|
|
|
@@ -125,13 +125,12 @@ class _ParallelContextOperator( object ):
|
|
|
125
125
|
raise r
|
|
126
126
|
msg, flush = r
|
|
127
127
|
if tme.interval_test(verbose_interval):
|
|
128
|
-
f_verbose.
|
|
128
|
+
f_verbose._raw(msg,end='',flush=flush)
|
|
129
129
|
|
|
130
130
|
def __enter__(self):
|
|
131
131
|
return self.mp_context
|
|
132
132
|
|
|
133
133
|
def __exit__(self, *kargs, **kwargs):
|
|
134
|
-
#self.terminate()
|
|
135
134
|
return False#raise exceptions
|
|
136
135
|
|
|
137
136
|
class _DIF(object):
|
cdxcore/util.py
CHANGED
|
@@ -159,6 +159,77 @@ def getsizeof(obj):
|
|
|
159
159
|
"""
|
|
160
160
|
return _get_recursive_size(obj,None)
|
|
161
161
|
|
|
162
|
+
def qualified_name( x, module : bool = False ):
|
|
163
|
+
"""
|
|
164
|
+
Return qualified name including module name of some Python element.
|
|
165
|
+
|
|
166
|
+
For the most part, this function will try to :func:`getattr` the ``__qualname__``
|
|
167
|
+
and ``__name__`` of ``x`` or its type. If all of these fail, an attempt is
|
|
168
|
+
made to convert ``type(x)`` into a string.
|
|
169
|
+
|
|
170
|
+
**Class Properties**
|
|
171
|
+
|
|
172
|
+
When reporting qualified names for a :dec:`property`, there is a nuance:
|
|
173
|
+
at class level, a property will be identified by its underlying function
|
|
174
|
+
name. Once an object is created, though, the property will be identified
|
|
175
|
+
by the return type of the property::
|
|
176
|
+
|
|
177
|
+
class A(object):
|
|
178
|
+
@property
|
|
179
|
+
def p(self):
|
|
180
|
+
return x
|
|
181
|
+
|
|
182
|
+
qualified_name(A.p) # -> "A.p"
|
|
183
|
+
qualified_name(A().p) # -> "int"
|
|
184
|
+
|
|
185
|
+
Parameters
|
|
186
|
+
----------
|
|
187
|
+
x : any
|
|
188
|
+
Some Python element.
|
|
189
|
+
|
|
190
|
+
module : bool, optional
|
|
191
|
+
Whether to also return the containing module if available.
|
|
192
|
+
Returns
|
|
193
|
+
-------
|
|
194
|
+
qualified name : str
|
|
195
|
+
The name, if ``module`` is ``False``.
|
|
196
|
+
|
|
197
|
+
(qualified name, module) : tuple
|
|
198
|
+
The name, if ``module`` is ``True``.
|
|
199
|
+
Note that the module name returned might be ``""`` if no module
|
|
200
|
+
name could be determined.
|
|
201
|
+
|
|
202
|
+
Raises
|
|
203
|
+
------
|
|
204
|
+
:class:`RuntimeError` if not qualfied name for ``x`` or its type could be found.
|
|
205
|
+
"""
|
|
206
|
+
if x is None:
|
|
207
|
+
if not module:
|
|
208
|
+
return "None"
|
|
209
|
+
else:
|
|
210
|
+
return "None", ""
|
|
211
|
+
|
|
212
|
+
# special cases
|
|
213
|
+
if isinstance(x, property):
|
|
214
|
+
x = x.fget
|
|
215
|
+
|
|
216
|
+
name = getattr(x, "__qualname__", None)
|
|
217
|
+
if name is None:
|
|
218
|
+
name = getattr(x, "__name__", None)
|
|
219
|
+
if name is None:
|
|
220
|
+
name = getattr(type(x), "__qualname__", None)
|
|
221
|
+
if name is None:
|
|
222
|
+
name = getattr(type(x), "__name__", None)
|
|
223
|
+
if name is None:
|
|
224
|
+
name = str(type(x))
|
|
225
|
+
if not module:
|
|
226
|
+
return name
|
|
227
|
+
|
|
228
|
+
module = getattr(x, "__module__", None)
|
|
229
|
+
if module is None:
|
|
230
|
+
module = getattr(type(x), "__module__", "")
|
|
231
|
+
return name, module
|
|
232
|
+
|
|
162
233
|
# =============================================================================
|
|
163
234
|
# string formatting
|
|
164
235
|
# =============================================================================
|
|
@@ -279,7 +350,7 @@ def fmt_digits( integer : int, sep : str = "," ):
|
|
|
279
350
|
String representation of an integer with 1000 separators: 10000 becomes "10,000".
|
|
280
351
|
|
|
281
352
|
Parameters
|
|
282
|
-
|
|
353
|
+
----------
|
|
283
354
|
integer : int
|
|
284
355
|
The number. The function will :func:`int()` the input which allows
|
|
285
356
|
for processing of a number of inputs (such as strings) but
|
cdxcore/verbose.py
CHANGED
|
@@ -592,8 +592,12 @@ class Context(object):
|
|
|
592
592
|
See above
|
|
593
593
|
"""
|
|
594
594
|
message = self.fmt( level, message, *args, head=head, **kwargs )
|
|
595
|
+
self._raw(message,end=end,flush=True)
|
|
596
|
+
|
|
597
|
+
def _raw( self, message : str, end : str, flush : bool ):
|
|
598
|
+
""" :meta private: used in JCPool """
|
|
595
599
|
if not message is None:
|
|
596
|
-
self.crman.write(message,end=end,flush=
|
|
600
|
+
self.crman.write(message,end=end,flush=flush,channel=self.channel )
|
|
597
601
|
|
|
598
602
|
def fmt( self, level : int, message : str|Callable, *args, head : bool = True, **kwargs ) -> str:
|
|
599
603
|
"""
|
|
@@ -809,6 +813,16 @@ class Context(object):
|
|
|
809
813
|
"""
|
|
810
814
|
return Context( self, channel=channel ) if channel != self.channel else self
|
|
811
815
|
|
|
816
|
+
# Dummy context
|
|
817
|
+
# -------------
|
|
818
|
+
|
|
819
|
+
def __enter__(self):
|
|
820
|
+
return self
|
|
821
|
+
|
|
822
|
+
def __exit__(self, *kargs, **kwargs):
|
|
823
|
+
return False#raise exceptions
|
|
824
|
+
|
|
825
|
+
|
|
812
826
|
|
|
813
827
|
quiet = Context(Context.QUIET)
|
|
814
828
|
all_ = Context(Context.ALL)
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
cdxcore/__init__.py,sha256=sOrqASZiA2WU_hqqm2O-KjIob25zt7MqoB8EaHcMvjM,127
|
|
2
|
+
cdxcore/config.py,sha256=YnIEJVFtMZ5EHlwzaB2JsSkCPhWPvEw9QSpe6mof_V4,98472
|
|
3
|
+
cdxcore/crman.py,sha256=83oKpuzNy98ObpmUeJg2McGRxaLk2AP5lN1yd1F9ueQ,5759
|
|
4
|
+
cdxcore/deferred.py,sha256=cPIvd0_CrC7Kn6dtaZXoHjWCA0L_3byPtLv8Op0uRI4,34181
|
|
5
|
+
cdxcore/dynaplot.py,sha256=kwrH_WccpJcfS7n_gzdAr4QxQobvIZZrrxgdsKLKfj0,48552
|
|
6
|
+
cdxcore/err.py,sha256=BwmhilSxofBjN_NSrekCHn8_Oz9U_XbbfTm5qFRUl90,14645
|
|
7
|
+
cdxcore/jcpool.py,sha256=kurdafk6lerCkv52Wjh9UN7EFMP8Xp07iqB2adE5bfY,27302
|
|
8
|
+
cdxcore/pretty.py,sha256=iUpgUCwmI8yb5O-WZFJEk3QvNYcj_GIFHUgZ5lK8F2I,17082
|
|
9
|
+
cdxcore/pretty.py_bak.py,sha256=JgWr5044HzCNGG0wKSAWlWiPRs7-bNzkwiKH0T3n0to,28658
|
|
10
|
+
cdxcore/subdir.py,sha256=NScdtAG-Wrt0D7_FcpO62qzII4bS9ABXFerkILPg4uE,173864
|
|
11
|
+
cdxcore/uniquehash.py,sha256=g-D8pqPIppSdRq5QfdE5aP3paZ-NkXWHfnn-uNB7fmg,50648
|
|
12
|
+
cdxcore/util.py,sha256=S-eaAlDfELZbOGyHCMO2M3TllOCpf9h8FgZV9pXgwZ4,34197
|
|
13
|
+
cdxcore/verbose.py,sha256=66n9v2TduNWlochcV3mixSqyQzznO_H0LPrDgr9_dEo,30240
|
|
14
|
+
cdxcore/version.py,sha256=m30oI2Ortg44dKSim-sIoeh9PioD1FWsSfVEP5rubhk,27173
|
|
15
|
+
cdxcore-0.1.13.dist-info/licenses/LICENSE,sha256=M-cisgK9kb1bqVRJ7vrCxHcMQQfDxdY3c2YFJJWfNQg,1090
|
|
16
|
+
docs/source/conf.py,sha256=Owctibh5XcSpSNcrpOr3ROIDjoklmFVrMhu8cOSe50o,4180
|
|
17
|
+
tests/test_config.py,sha256=N86mH3y7k3LXEmU8uPLfrmRMZ-80VhlD35nBbpLmebg,15617
|
|
18
|
+
tests/test_crman.py,sha256=YNNEAIcKvqfy9KifV1p1qzpphHIANrhjjPbccJFmzqk,1378
|
|
19
|
+
tests/test_deferred.py,sha256=GKAI9m3vs2RCvRVJUg7E3VqJwlzZehwzZv-7nslRhrU,7355
|
|
20
|
+
tests/test_err.py,sha256=4Pc7x2I0A_LBuiCMvstKNzN1JAcSPmm78dwLwp-N7s0,3146
|
|
21
|
+
tests/test_jcpool.py,sha256=bcGC3UcJ7SOHVgzZ-cooEJgncLWmhutBfqH7P5qB-iw,7901
|
|
22
|
+
tests/test_pretty.py,sha256=pVwTBjm3XqwEf2jq5GdZvT4cDSTGqiQFBMLqmGJYuB0,11644
|
|
23
|
+
tests/test_subdir.py,sha256=Ab6pCrUnbMR3kpLsKcDwLUP5QY1HvFVTmSI9D1lXhbM,11444
|
|
24
|
+
tests/test_uniquehash.py,sha256=n6ZCkdBw-iRsyzeAEmrnLK0hJLGH6l_Dtt_KIkSa6KA,24630
|
|
25
|
+
tests/test_util.py,sha256=MXQMOmGjlBWTEwyW3JBTvZzlpMj5kDzThyhM2JwPZy8,23776
|
|
26
|
+
tests/test_verbose.py,sha256=zXheIqAVOnwML2zsCjLugjYzB_KNzU_S4Xu2CSb4o10,4723
|
|
27
|
+
tests/test_version.py,sha256=m_RODPDFlXTC1jAIczm3t1v6tXzqczDiUFFJtGvRG98,4381
|
|
28
|
+
tmp/filelock.py,sha256=HqnHZhSCESaOA3ClrdWPW_GZpyo7c3VRSEofAV-khKM,18137
|
|
29
|
+
tmp/np.py,sha256=2MynhiaTfmx984Gz7TwfZH3t7GCmCAQiyeWzDDCL6_k,47686
|
|
30
|
+
tmp/npio.py,sha256=4Kwp5H4MgKHkOEhu4UJ5CcwpM7Pm8UFkaoL5FvOEFRI,10310
|
|
31
|
+
tmp/sharedarray.py,sha256=JuHuSlxA0evD0a-bEZgTFrfdlVPMgzfQNgfSjr1212w,11484
|
|
32
|
+
up/git_message.py,sha256=EfSH7Pit3ZoCiRqSMwRCUN_QyuwreU4LTIyGSutBlm4,123
|
|
33
|
+
up/pip_modify_setup.py,sha256=Esaml4yA9tFsqxLhk5bWSwvKCURONjQqfyChgFV2TSY,1584
|
|
34
|
+
cdxcore-0.1.13.dist-info/METADATA,sha256=vEmQg3-9uwcgD18Jrml9koI6pduBQt-GG6lLnjPCw98,754
|
|
35
|
+
cdxcore-0.1.13.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
36
|
+
cdxcore-0.1.13.dist-info/top_level.txt,sha256=phNSwCyJFe7UP2YMoi8o6ykhotatlIbJHjTp9EHM51k,26
|
|
37
|
+
cdxcore-0.1.13.dist-info/RECORD,,
|
tests/test_config.py
CHANGED
|
@@ -6,7 +6,6 @@ Created on Tue Apr 14 21:24:52 2020
|
|
|
6
6
|
|
|
7
7
|
import unittest as unittest
|
|
8
8
|
import dataclasses as dataclasses
|
|
9
|
-
import sys as sys
|
|
10
9
|
import os as os
|
|
11
10
|
import pickle as pickle
|
|
12
11
|
import tempfile as tempfile
|
|
@@ -16,7 +15,6 @@ def import_local():
|
|
|
16
15
|
"""
|
|
17
16
|
In order to be able to run our tests manually from the 'tests' directory
|
|
18
17
|
we force import from the local package.
|
|
19
|
-
We also force reloading all modules to make sure we are not running old code.
|
|
20
18
|
"""
|
|
21
19
|
me = "cdxcore"
|
|
22
20
|
import os
|
|
@@ -27,15 +25,7 @@ def import_local():
|
|
|
27
25
|
assert cwd[-5:] == "tests",("Expected current working directory to be in a 'tests' directory", cwd[-5:], "from", cwd)
|
|
28
26
|
assert cwd[-6] in ['/', '\\'],("Expected current working directory 'tests' to be lead by a '\\' or '/'", cwd[-6:], "from", cwd)
|
|
29
27
|
sys.path.insert( 0, cwd[:-6] )
|
|
30
|
-
|
|
31
|
-
# reload modules
|
|
32
|
-
import importlib as imp
|
|
33
|
-
modules = sys.modules.copy()
|
|
34
|
-
for name, mdata in modules.items():
|
|
35
|
-
if name[:len(me)] == me:
|
|
36
|
-
imp.reload(mdata)
|
|
37
|
-
print("Reloaded", name)
|
|
38
|
-
#import_local()
|
|
28
|
+
import_local()
|
|
39
29
|
|
|
40
30
|
from cdxcore.config import Config, Int, Float
|
|
41
31
|
from cdxcore.pretty import PrettyObject as pdct
|
tests/test_crman.py
CHANGED
|
@@ -10,7 +10,6 @@ def import_local():
|
|
|
10
10
|
"""
|
|
11
11
|
In order to be able to run our tests manually from the 'tests' directory
|
|
12
12
|
we force import from the local package.
|
|
13
|
-
We also force reloading all modules to make sure we are not running old code.
|
|
14
13
|
"""
|
|
15
14
|
me = "cdxcore"
|
|
16
15
|
import os
|
|
@@ -21,15 +20,7 @@ def import_local():
|
|
|
21
20
|
assert cwd[-5:] == "tests",("Expected current working directory to be in a 'tests' directory", cwd[-5:], "from", cwd)
|
|
22
21
|
assert cwd[-6] in ['/', '\\'],("Expected current working directory 'tests' to be lead by a '\\' or '/'", cwd[-6:], "from", cwd)
|
|
23
22
|
sys.path.insert( 0, cwd[:-6] )
|
|
24
|
-
|
|
25
|
-
# reload modules
|
|
26
|
-
import importlib as imp
|
|
27
|
-
modules = sys.modules.copy()
|
|
28
|
-
for name, mdata in modules.items():
|
|
29
|
-
if name[:len(me)] == me:
|
|
30
|
-
imp.reload(mdata)
|
|
31
|
-
print("Reloaded", name)
|
|
32
|
-
#import_local()
|
|
23
|
+
import_local()
|
|
33
24
|
|
|
34
25
|
from cdxcore.crman import CRMan
|
|
35
26
|
|
tests/test_deferred.py
ADDED
|
@@ -0,0 +1,277 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
"""
|
|
3
|
+
Created on Tue Apr 14 21:24:52 2020
|
|
4
|
+
@author: hansb
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
import unittest as unittest
|
|
8
|
+
import numpy as np
|
|
9
|
+
|
|
10
|
+
def import_local():
|
|
11
|
+
"""
|
|
12
|
+
In order to be able to run our tests manually from the 'tests' directory
|
|
13
|
+
we force import from the local package.
|
|
14
|
+
"""
|
|
15
|
+
me = "cdxcore"
|
|
16
|
+
import os
|
|
17
|
+
import sys
|
|
18
|
+
cwd = os.getcwd()
|
|
19
|
+
if cwd[-len(me):] == me:
|
|
20
|
+
return
|
|
21
|
+
assert cwd[-5:] == "tests",("Expected current working directory to be in a 'tests' directory", cwd[-5:], "from", cwd)
|
|
22
|
+
assert cwd[-6] in ['/', '\\'],("Expected current working directory 'tests' to be lead by a '\\' or '/'", cwd[-6:], "from", cwd)
|
|
23
|
+
sys.path.insert( 0, cwd[:-6] )
|
|
24
|
+
import_local()
|
|
25
|
+
|
|
26
|
+
from cdxcore.deferred import Deferred, ResolutionDependencyError
|
|
27
|
+
|
|
28
|
+
class qB(object):
|
|
29
|
+
def __init__(self):
|
|
30
|
+
self.m = 1
|
|
31
|
+
def f(self,y):
|
|
32
|
+
return self.m+y
|
|
33
|
+
|
|
34
|
+
class qA(object):
|
|
35
|
+
|
|
36
|
+
M = 7
|
|
37
|
+
|
|
38
|
+
def __init__(self):
|
|
39
|
+
self.m = 1
|
|
40
|
+
self.d = dict()
|
|
41
|
+
self.l = list()
|
|
42
|
+
self.b = qB()
|
|
43
|
+
|
|
44
|
+
def f(self, y=2):
|
|
45
|
+
return self.m*y
|
|
46
|
+
|
|
47
|
+
def fq(self, q):
|
|
48
|
+
return self.m*q.m
|
|
49
|
+
|
|
50
|
+
@property
|
|
51
|
+
def g(self):
|
|
52
|
+
return self.m*3
|
|
53
|
+
|
|
54
|
+
@staticmethod
|
|
55
|
+
def h(x,*,y=2):
|
|
56
|
+
return x*y
|
|
57
|
+
|
|
58
|
+
@property
|
|
59
|
+
def more(self):
|
|
60
|
+
return qB()
|
|
61
|
+
|
|
62
|
+
def moref(self):
|
|
63
|
+
return qB()
|
|
64
|
+
|
|
65
|
+
@classmethod
|
|
66
|
+
def j(cls, y=2):
|
|
67
|
+
return cls.M*y
|
|
68
|
+
|
|
69
|
+
def __iter__(self):
|
|
70
|
+
for i in range(self.x):
|
|
71
|
+
yield i
|
|
72
|
+
|
|
73
|
+
def __call__(self, x):
|
|
74
|
+
return self.m*x
|
|
75
|
+
|
|
76
|
+
def __getitem__(self, i):
|
|
77
|
+
return self.d[i]
|
|
78
|
+
|
|
79
|
+
def __setitem__(self, i, v):
|
|
80
|
+
self.d[i] = v
|
|
81
|
+
|
|
82
|
+
def __eq__(self, other):
|
|
83
|
+
return self.m == other.m
|
|
84
|
+
|
|
85
|
+
def __iadd__(self, integer):
|
|
86
|
+
self.m += integer
|
|
87
|
+
return self
|
|
88
|
+
|
|
89
|
+
def __rxor__(self, integer):
|
|
90
|
+
r = qA()
|
|
91
|
+
r.m = self.m^integer
|
|
92
|
+
return r
|
|
93
|
+
|
|
94
|
+
def some_function(x):
|
|
95
|
+
return x.m
|
|
96
|
+
|
|
97
|
+
# for detecting collisions
|
|
98
|
+
class AX(object):
|
|
99
|
+
def __init__(self):
|
|
100
|
+
self.x = 1
|
|
101
|
+
def f(self,other):
|
|
102
|
+
return self.x+(other.x if not isinstance(other, int) else other)
|
|
103
|
+
|
|
104
|
+
class Test(unittest.TestCase):
|
|
105
|
+
|
|
106
|
+
def test_deferred(self):
|
|
107
|
+
|
|
108
|
+
# some basic Python tests
|
|
109
|
+
|
|
110
|
+
with self.assertRaises(AttributeError):
|
|
111
|
+
getattr(int(1),"__getattr__") # __getattr__ can be read using 'getattr'
|
|
112
|
+
_ = getattr(int(1),"__setattr__")
|
|
113
|
+
_ = getattr(int(1),"__delattr__")
|
|
114
|
+
|
|
115
|
+
# does it work?
|
|
116
|
+
# we test the results of executing some code directly or delayed
|
|
117
|
+
def test_iadd(a):
|
|
118
|
+
a+=1
|
|
119
|
+
return a
|
|
120
|
+
|
|
121
|
+
def tester(a,b):
|
|
122
|
+
am = a.m
|
|
123
|
+
return dict(
|
|
124
|
+
aM = a.M,
|
|
125
|
+
am = am,
|
|
126
|
+
ag = a.g,
|
|
127
|
+
af2 = a.f(2),
|
|
128
|
+
afm = a.f(am),
|
|
129
|
+
af23 = a.f(y=2)*3+1,
|
|
130
|
+
ah = a.h(x=3,y=4),
|
|
131
|
+
aj = a.j(5),
|
|
132
|
+
a2j = 2+a.j(5),
|
|
133
|
+
amm = a.more.m,
|
|
134
|
+
amff = a.moref().f(y=3),
|
|
135
|
+
afqb = a.fq( b ),
|
|
136
|
+
eq = a==b,
|
|
137
|
+
iadd = test_iadd(a).m,
|
|
138
|
+
rxor = (1^a).m,#
|
|
139
|
+
some = some_function(a)
|
|
140
|
+
)
|
|
141
|
+
|
|
142
|
+
|
|
143
|
+
deferred_a = Deferred("a")
|
|
144
|
+
deferred_b = Deferred("b")
|
|
145
|
+
actual_a = qA()
|
|
146
|
+
actual_b = qA()
|
|
147
|
+
results_act = tester(actual_a, actual_b)
|
|
148
|
+
results_drf = tester(deferred_a, deferred_b)
|
|
149
|
+
|
|
150
|
+
deferred_b.deferred_resolve( qA() )
|
|
151
|
+
deferred_a.deferred_resolve( qA() )
|
|
152
|
+
|
|
153
|
+
results_tst = { k: v.deferred_action_result for k,v in results_drf.items() }
|
|
154
|
+
|
|
155
|
+
self.assertEqual( list(results_tst), list(results_act) )
|
|
156
|
+
for k, tst in results_tst.items():
|
|
157
|
+
act = results_act[k]
|
|
158
|
+
self.assertEqual( tst, act, msg=f"Step 1 {k} '{tst}' != '{act}'" )
|
|
159
|
+
|
|
160
|
+
# ops
|
|
161
|
+
|
|
162
|
+
def c1(a):
|
|
163
|
+
a+=3
|
|
164
|
+
return a
|
|
165
|
+
def c2(a):
|
|
166
|
+
a-=3
|
|
167
|
+
return a
|
|
168
|
+
def c3(a):
|
|
169
|
+
a = a.astype(np.float32)
|
|
170
|
+
a/=3
|
|
171
|
+
return a
|
|
172
|
+
def c4(a):
|
|
173
|
+
a//=3
|
|
174
|
+
return a
|
|
175
|
+
def c5(a):
|
|
176
|
+
a*=3
|
|
177
|
+
return a
|
|
178
|
+
def c6(a):
|
|
179
|
+
a^=3
|
|
180
|
+
return a
|
|
181
|
+
def c7(a):
|
|
182
|
+
a|=3
|
|
183
|
+
return a
|
|
184
|
+
def c8(a):
|
|
185
|
+
a&=3
|
|
186
|
+
return a
|
|
187
|
+
def c9(a):
|
|
188
|
+
a**=3
|
|
189
|
+
return a
|
|
190
|
+
def cA(a):
|
|
191
|
+
a@=a.T
|
|
192
|
+
return a
|
|
193
|
+
def cB(a):
|
|
194
|
+
a%=3
|
|
195
|
+
return a
|
|
196
|
+
def test_op(a):
|
|
197
|
+
return dict(
|
|
198
|
+
# left
|
|
199
|
+
a1 = a+3 ,
|
|
200
|
+
a2 = a-3 ,
|
|
201
|
+
a3 = a/3 ,
|
|
202
|
+
a4 = a//3 ,
|
|
203
|
+
a5 = a*3 ,
|
|
204
|
+
a6 = a^3 ,
|
|
205
|
+
a7 = a|3 ,
|
|
206
|
+
a8 = a&3 ,
|
|
207
|
+
a9 = a**3 ,
|
|
208
|
+
aA = a@np.full((2,1),2) ,
|
|
209
|
+
aB = a%3 ,
|
|
210
|
+
# right
|
|
211
|
+
b1 = 3+a ,
|
|
212
|
+
b2 = 3-a ,
|
|
213
|
+
b3 = 3/a ,
|
|
214
|
+
b4 = 3//a ,
|
|
215
|
+
b5 = 3*a ,
|
|
216
|
+
b6 = 3^a ,
|
|
217
|
+
b7 = 3|a ,
|
|
218
|
+
b8 = 3&a ,
|
|
219
|
+
b9 = 3**a ,
|
|
220
|
+
bA = a.T @ a,
|
|
221
|
+
bB = 3%a ,
|
|
222
|
+
bC = [3]+a ,
|
|
223
|
+
# in place
|
|
224
|
+
c1 = c1(a),
|
|
225
|
+
c2 = c2(a),
|
|
226
|
+
c3 = c3(a),
|
|
227
|
+
c4 = c4(a),
|
|
228
|
+
c5 = c5(a),
|
|
229
|
+
c6 = c6(a),
|
|
230
|
+
c7 = c7(a),
|
|
231
|
+
c8 = c8(a),
|
|
232
|
+
c9 = c9(a),
|
|
233
|
+
cB = cB(a)
|
|
234
|
+
)
|
|
235
|
+
|
|
236
|
+
deferred_a = Deferred("a")
|
|
237
|
+
actual_a = np.full((4,2),3,dtype=np.int32)
|
|
238
|
+
results_act = test_op(actual_a)
|
|
239
|
+
results_drf = test_op(deferred_a)
|
|
240
|
+
|
|
241
|
+
deferred_a.deferred_resolve( np.full((4,2),3,dtype=np.int32) )
|
|
242
|
+
|
|
243
|
+
results_act = { k: v.astype(np.int32) for k,v in results_act.items() }
|
|
244
|
+
results_tst = { k: v.deferred_action_result.astype(np.int32) for k,v in results_drf.items() }
|
|
245
|
+
|
|
246
|
+
self.assertEqual( list(results_tst), list(results_act) )
|
|
247
|
+
for k, tst in results_tst.items():
|
|
248
|
+
act = results_act[k]
|
|
249
|
+
self.assertEqual( act.shape, tst.shape, msg=k )
|
|
250
|
+
self.assertTrue( np.all( tst == act ), msg=f"Step 2 {k} '{tst}' != '{act}'" )
|
|
251
|
+
|
|
252
|
+
# info test
|
|
253
|
+
|
|
254
|
+
a = Deferred("a")
|
|
255
|
+
b = Deferred("b")
|
|
256
|
+
_ = a.f( b.g(1) )
|
|
257
|
+
self.assertEqual( _.deferred_info, '$a.f({$b.g(1)})' )
|
|
258
|
+
|
|
259
|
+
a = Deferred("a")
|
|
260
|
+
b = Deferred("b")
|
|
261
|
+
_ = a.f( b.g(1) )
|
|
262
|
+
src = list(_.deferred_sources.values())
|
|
263
|
+
self.assertEqual( src, ['$a', '$b'] )
|
|
264
|
+
src = _.deferred_sources_names
|
|
265
|
+
self.assertEqual( src, ['$a', '$b'] )
|
|
266
|
+
|
|
267
|
+
# collision test
|
|
268
|
+
|
|
269
|
+
a = Deferred("A")
|
|
270
|
+
b = Deferred("B")
|
|
271
|
+
_ = a.f(b) # <- execution depends on b
|
|
272
|
+
|
|
273
|
+
with self.assertRaises(ResolutionDependencyError):
|
|
274
|
+
a.deferred_resolve( AX() ) # <- must fail
|
|
275
|
+
|
|
276
|
+
if __name__ == '__main__':
|
|
277
|
+
unittest.main()
|
tests/test_err.py
CHANGED
|
@@ -5,13 +5,11 @@ Created on Tue Apr 14 21:24:52 2020
|
|
|
5
5
|
"""
|
|
6
6
|
|
|
7
7
|
import unittest as unittest
|
|
8
|
-
import warnings as warnings
|
|
9
8
|
|
|
10
9
|
def import_local():
|
|
11
10
|
"""
|
|
12
11
|
In order to be able to run our tests manually from the 'tests' directory
|
|
13
12
|
we force import from the local package.
|
|
14
|
-
We also force reloading all modules to make sure we are not running old code.
|
|
15
13
|
"""
|
|
16
14
|
me = "cdxcore"
|
|
17
15
|
import os
|
|
@@ -22,15 +20,9 @@ def import_local():
|
|
|
22
20
|
assert cwd[-5:] == "tests",("Expected current working directory to be in a 'tests' directory", cwd[-5:], "from", cwd)
|
|
23
21
|
assert cwd[-6] in ['/', '\\'],("Expected current working directory 'tests' to be lead by a '\\' or '/'", cwd[-6:], "from", cwd)
|
|
24
22
|
sys.path.insert( 0, cwd[:-6] )
|
|
23
|
+
import_local()
|
|
25
24
|
|
|
26
|
-
|
|
27
|
-
import importlib as imp
|
|
28
|
-
modules = sys.modules.copy()
|
|
29
|
-
for name, mdata in modules.items():
|
|
30
|
-
if name[:len(me)] == me:
|
|
31
|
-
imp.reload(mdata)
|
|
32
|
-
print("Reloaded", name)
|
|
33
|
-
#import_local()
|
|
25
|
+
import warnings as warnings
|
|
34
26
|
|
|
35
27
|
from cdxcore.err import fmt, error, verify, warn, warn_if
|
|
36
28
|
|