immlib 1.0.0.dev2__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.
Files changed (45) hide show
  1. immlib/__init__.py +131 -0
  2. immlib/_init.py +108 -0
  3. immlib/_version.py +235 -0
  4. immlib/doc/__init__.py +38 -0
  5. immlib/doc/_core.py +311 -0
  6. immlib/iolib/__init__.py +29 -0
  7. immlib/iolib/_core.py +720 -0
  8. immlib/pathlib/__init__.py +69 -0
  9. immlib/pathlib/_cache.py +152 -0
  10. immlib/pathlib/_core.py +869 -0
  11. immlib/pathlib/_osf.py +538 -0
  12. immlib/test/__init__.py +16 -0
  13. immlib/test/__main__.py +10 -0
  14. immlib/test/doc/__init__.py +6 -0
  15. immlib/test/doc/test_core.py +91 -0
  16. immlib/test/iolib/__init__.py +7 -0
  17. immlib/test/iolib/test_core.py +81 -0
  18. immlib/test/pathlib/__init__.py +11 -0
  19. immlib/test/pathlib/test_core.py +146 -0
  20. immlib/test/pathlib/test_osf.py +54 -0
  21. immlib/test/types/__init__.py +5 -0
  22. immlib/test/types/test_core.py +110 -0
  23. immlib/test/util/__init__.py +11 -0
  24. immlib/test/util/test_core.py +681 -0
  25. immlib/test/util/test_numeric.py +1374 -0
  26. immlib/test/util/test_quantity.py +218 -0
  27. immlib/test/util/test_url.py +51 -0
  28. immlib/test/workflow/__init__.py +9 -0
  29. immlib/test/workflow/test_core.py +418 -0
  30. immlib/test/workflow/test_plantype.py +248 -0
  31. immlib/types/__init__.py +29 -0
  32. immlib/types/_core.py +333 -0
  33. immlib/util/__init__.py +283 -0
  34. immlib/util/_core.py +2524 -0
  35. immlib/util/_numeric.py +2651 -0
  36. immlib/util/_quantity.py +523 -0
  37. immlib/util/_url.py +114 -0
  38. immlib/workflow/__init__.py +48 -0
  39. immlib/workflow/_core.py +1635 -0
  40. immlib/workflow/_plantype.py +334 -0
  41. immlib-1.0.0.dev2.dist-info/METADATA +76 -0
  42. immlib-1.0.0.dev2.dist-info/RECORD +45 -0
  43. immlib-1.0.0.dev2.dist-info/WHEEL +5 -0
  44. immlib-1.0.0.dev2.dist-info/licenses/LICENSE +21 -0
  45. immlib-1.0.0.dev2.dist-info/top_level.txt +1 -0
@@ -0,0 +1,681 @@
1
+ # -*- coding: utf-8 -*-
2
+ ################################################################################
3
+ # immlib/test/util/test_core.py
4
+
5
+ """Tests of the core utilities module in immlib: i.e., tests for the code in the
6
+ immlib.util._core module.
7
+ """
8
+
9
+
10
+ # Dependencies #################################################################
11
+
12
+ from unittest import TestCase
13
+
14
+ import numpy as np
15
+
16
+
17
+ # Tests ########################################################################
18
+
19
+ class TestUtilCore(TestCase):
20
+ """Tests the immlib.util._core module."""
21
+
22
+ # String Functions #########################################################
23
+ def test_is_str(self):
24
+ from immlib import is_str
25
+ # is_str is just a wrapper for isinstance(obj, str).
26
+ self.assertTrue(is_str('abc'))
27
+ self.assertTrue(is_str(''))
28
+ self.assertFalse(is_str(100))
29
+ self.assertFalse(is_str(None))
30
+ def test_strnorm(self):
31
+ from immlib import strnorm
32
+ # There are a lot of string encoding details that should probably be
33
+ # tested carefully here, but for now, we're mostly concerned that the
34
+ # most basic strings get normalized properly.
35
+ self.assertEqual('abc', strnorm('abc'))
36
+ self.assertEqual('abc', strnorm('aBc', case=True))
37
+ def test_strcmp(self):
38
+ from immlib import strcmp
39
+ # strcmp is, at its simplest, just a string-comparison function.
40
+ self.assertEqual(0, strcmp('abc', 'abc'))
41
+ self.assertEqual(-1, strcmp('abc', 'bca'))
42
+ self.assertEqual(1, strcmp('bca', 'abc'))
43
+ # There are a few bells and whistles for strcmp, thought. First, the
44
+ # case option lets you decide whether to ignore case (via strnorm).
45
+ self.assertEqual(-1, strcmp('ABC', 'abc'))
46
+ self.assertEqual(0, strcmp('ABC', 'abc', case=False))
47
+ # The strip option lets one ignore whitespace on either side of the
48
+ # arguments.
49
+ self.assertEqual(-1, strcmp(' abc', 'abc '))
50
+ self.assertEqual(0, strcmp(' abc', 'abc ', strip=True))
51
+ self.assertEqual(-1, strcmp('_abc', 'abc__', strip=True))
52
+ self.assertEqual(0, strcmp('_abc', 'abc__', strip='_'))
53
+ # The split argument lets you split on whitespace then compare the
54
+ # individual split parts (i.e., this option should make all strings that
55
+ # are identical up to the amount of whitespace should be equal).
56
+ self.assertEqual(1, strcmp('abc def ghi', ' abc def ghi '))
57
+ self.assertEqual(0, strcmp('abc def ghi', ' abc def ghi ', split=True))
58
+ self.assertEqual(0, strcmp('abc_def_ghi', 'abc_def_ghi', split='_'))
59
+ self.assertEqual(-1, strcmp('abc def ghi', ' bbc def ghi ', split=True))
60
+ self.assertEqual(1, strcmp('abc eef ghi', ' abc def ghi ', split=True))
61
+ self.assertEqual(0, strcmp('a b c d', 'a b c d', split=True))
62
+ self.assertEqual(1, strcmp('a b c d', 'a b c', split=True))
63
+ self.assertEqual(-1, strcmp('a b c', 'a b c d', split=True))
64
+ self.assertEqual(0, strcmp('abc def ghi', ' abc def ghi ', split=True))
65
+ # In some cases, we can split and strip:
66
+ self.assertEqual(
67
+ strcmp('abc_def_ghi', '_abc_def_ghi_', split='_', strip='_'),
68
+ 0)
69
+ # If one of the arguments isn't a string, strcmp returns None.
70
+ self.assertIsNone(strcmp(None, 10))
71
+ def test_streq(self):
72
+ from immlib import streq
73
+ # streq is just a string equality predicate function.
74
+ self.assertTrue(streq('abc', 'abc'))
75
+ self.assertFalse(streq('abc', 'def'))
76
+ # The case option can tell it to ignore case.
77
+ self.assertFalse(streq('ABC', 'abc'))
78
+ self.assertTrue(streq('ABC', 'abc', case=False))
79
+ # The strip option can be used to ignore trailing/leading whitespace.
80
+ self.assertFalse(streq(' abc', 'abc '))
81
+ self.assertTrue(streq(' abc', 'abc ', strip=True))
82
+ # The split argument lets you split on whitespace then compare the
83
+ # individual split parts (i.e., this option should make all strings that
84
+ # are identical up to the amount of whitespace should be equal).
85
+ self.assertFalse(streq('abc def ghi', ' abc def ghi '))
86
+ self.assertTrue(streq('abc def ghi', ' abc def ghi ', split=True))
87
+ # Nonstring arguments return None.
88
+ self.assertIsNone(streq(None, 'abc'))
89
+ def test_strends(self):
90
+ from immlib import strends
91
+ # strends is just a string equality predicate function.
92
+ self.assertTrue(strends('abcdef', 'def'))
93
+ self.assertFalse(strends('abcdef', 'bcd'))
94
+ # The case option can tell it to ignore case.
95
+ self.assertFalse(strends('ABCDEF', 'def'))
96
+ self.assertTrue(strends('ABCDEF', 'def', case=False))
97
+ # The strip option can be used to ignore trailing/leading whitespace.
98
+ self.assertFalse(strends(' abcdef ', 'def '))
99
+ self.assertTrue(strends(' abcdef ', 'def ', strip=True))
100
+ # Nonstring arguments return None.
101
+ self.assertIsNone(strends(None, 'abc'))
102
+ def test_strstarts(self):
103
+ from immlib import strstarts
104
+ # strstarts is just a string equality predicate function.
105
+ self.assertTrue(strstarts('abcdef', 'abc'))
106
+ self.assertFalse(strstarts('abcdef', 'bcd'))
107
+ # The case option can tell it to ignore case.
108
+ self.assertFalse(strstarts('ABCDEF', 'abc'))
109
+ self.assertTrue(strstarts('ABCDEF', 'abc', case=False))
110
+ # The strip option can be used to ignore trailing/leading whitespace.
111
+ self.assertFalse(strstarts(' abcdef ', ' abc'))
112
+ self.assertTrue(strstarts(' abcdef ', ' abc', strip=True))
113
+ # Nonstring arguments return None.
114
+ self.assertIsNone(strstarts(None, 'abc'))
115
+ def test_strissym(self):
116
+ from immlib import strissym
117
+ # strissym tests whether a string is both a string and a valid Python
118
+ # symbol.
119
+ self.assertTrue(strissym('abc'))
120
+ self.assertTrue(strissym('def123'))
121
+ self.assertTrue(strissym('_10xyz'))
122
+ self.assertFalse(strissym('abc def'))
123
+ self.assertFalse(strissym(' abcdef '))
124
+ self.assertFalse(strissym('a-b'))
125
+ self.assertFalse(strissym('10'))
126
+ # Keywords are allowed.
127
+ self.assertTrue(strissym('for'))
128
+ self.assertTrue(strissym('and'))
129
+ # Non-strings return Nonee.
130
+ self.assertFalse(strissym(None))
131
+ self.assertFalse(strissym(10))
132
+ def test_striskey(self):
133
+ from immlib import striskey
134
+ # striskey tests whether a string is (1) a string, (2) a valid Python
135
+ # symbol, and (3) an existing Python keyword.
136
+ self.assertTrue(striskey('for'))
137
+ self.assertTrue(striskey('and'))
138
+ self.assertTrue(striskey('None'))
139
+ self.assertFalse(striskey('abc'))
140
+ self.assertFalse(striskey('def123'))
141
+ self.assertFalse(striskey('_10xyz'))
142
+ self.assertFalse(striskey('abc def'))
143
+ self.assertFalse(striskey(' abcdef '))
144
+ self.assertFalse(striskey('a-b'))
145
+ self.assertFalse(striskey('10'))
146
+ # Non-strings return None.
147
+ self.assertIsNone(striskey(None))
148
+ self.assertIsNone(striskey(10))
149
+ def test_strisvar(self):
150
+ from immlib import strisvar
151
+ # strisvar tests whether a string is (1) a string, (2) a valid Python
152
+ # symbol, and (3) an *not* existing Python keyword.
153
+ self.assertFalse(strisvar('for'))
154
+ self.assertFalse(strisvar('and'))
155
+ self.assertFalse(strisvar('None'))
156
+ self.assertTrue(strisvar('abc'))
157
+ self.assertTrue(strisvar('def123'))
158
+ self.assertTrue(strisvar('_10xyz'))
159
+ self.assertFalse(strisvar('abc def'))
160
+ self.assertFalse(strisvar(' abcdef '))
161
+ self.assertFalse(strisvar('a-b'))
162
+ self.assertFalse(strisvar('10'))
163
+ # Non-strings return Nonee.
164
+ self.assertIsNone(strisvar(None))
165
+ self.assertIsNone(strisvar(10))
166
+
167
+ # Freeze/Thaw Utilities ####################################################
168
+ def test_frozenarray(self):
169
+ "Tests the frozenarray() and freezearray() functions."
170
+ from immlib.util import frozenarray, freezearray
171
+ from immlib import quant
172
+ import numpy as np
173
+ # frozenarray converts a read-write numpy array into a frozen one.
174
+ x = np.linspace(0, 1, 25)
175
+ y = frozenarray(x)
176
+ self.assertTrue(np.array_equal(x, y))
177
+ self.assertIsNot(x, y)
178
+ self.assertTrue(x.flags['WRITEABLE'])
179
+ self.assertFalse(y.flags['WRITEABLE'])
180
+ # If a frozenarray of an already frozen array is requested, the array is
181
+ # returned as-is.
182
+ self.assertIs(y, frozenarray(y))
183
+ # However, one can override this with the copy argument.
184
+ self.assertIsNot(y, frozenarray(y, copy=True))
185
+ # Typically a copy is made of the original array if it is not already
186
+ # frozen, but one can use freezearray to prevent copying.
187
+ z = frozenarray(x)
188
+ self.assertIsNot(z, x)
189
+ self.assertTrue(x.flags['WRITEABLE'])
190
+ freezearray(x)
191
+ self.assertFalse(x.flags['WRITEABLE'])
192
+ # frozenarray also works with sparse arrays.
193
+ import scipy.sparse as sps
194
+ x = sps.csr_array(
195
+ ([1.0, 2.0, 3.5, 6.0], ([0,1,3,4], [3,4,2,1])),
196
+ shape=(5,5))
197
+ y = frozenarray(x)
198
+ self.assertIsNot(x, y)
199
+ self.assertIs(frozenarray(y), y)
200
+ self.assertIsNot(y, frozenarray(y, copy=True))
201
+ self.assertFalse(y.data.flags['WRITEABLE'])
202
+ self.assertTrue(x.data.flags['WRITEABLE'])
203
+ self.assertTrue(np.array_equal(x.data, y.data))
204
+ # As does freeze:
205
+ freezearray(x)
206
+ self.assertFalse(x.data.flags['WRITEABLE'])
207
+ # Both also work with quantities.
208
+ x = quant(
209
+ sps.csr_array(
210
+ ([1.0, 2.0, 3.5, 6.0], ([0,1,3,4], [3,4,2,1])),
211
+ shape=(5,5)),
212
+ 'mm')
213
+ y = frozenarray(x)
214
+ self.assertIsNot(x, y)
215
+ self.assertIs(frozenarray(y), y)
216
+ self.assertIsNot(y, frozenarray(y, copy=True))
217
+ self.assertFalse(y.m.data.flags['WRITEABLE'])
218
+ self.assertTrue(x.m.data.flags['WRITEABLE'])
219
+ self.assertTrue(np.array_equal(x.m.data, y.m.data))
220
+ freezearray(x)
221
+ self.assertFalse(x.m.data.flags['WRITEABLE'])
222
+ # We can also use frozenarray as a substitute for the array function:
223
+ x = frozenarray([1,2,3,4])
224
+ self.assertIsInstance(x, np.ndarray)
225
+ self.assertFalse(x.flags['WRITEABLE'])
226
+ self.assertTrue(np.array_equal(x, [1,2,3,4]))
227
+ # freezearray fails when given objects not compatible with arrays:
228
+ with self.assertRaises(TypeError):
229
+ freezearray(Ellipsis)
230
+ def test_to_pcoll(self):
231
+ from immlib.util import to_pcoll
232
+ from pcollections import pdict, plist, pset
233
+ x = pdict(a=1, b=2)
234
+ y = plist([1,3,4,5,6])
235
+ z = pset(['a', 'b', 'c'])
236
+ # to_pcoll leaves persistent collections untouched.
237
+ self.assertIs(to_pcoll(x), x)
238
+ self.assertIs(to_pcoll(y), y)
239
+ self.assertIs(to_pcoll(z), z)
240
+ # They convert equivalent non-persistent objects into persistent ones.
241
+ self.assertIsInstance(to_pcoll(dict(x)), pdict)
242
+ self.assertEqual(to_pcoll(dict(x)), x)
243
+ self.assertIsInstance(to_pcoll(list(y)), plist)
244
+ self.assertEqual(to_pcoll(list(y)), y)
245
+ self.assertIsInstance(to_pcoll(set(z)), pset)
246
+ self.assertEqual(to_pcoll(set(z)), z)
247
+ # If the argument isn't a valid collection, it raises an error.
248
+ with self.assertRaises(TypeError):
249
+ to_pcoll(10)
250
+ def test_to_tcoll(self):
251
+ from immlib.util import to_tcoll
252
+ from pcollections import pdict, plist, pset, tdict, tlist, tset
253
+ x = pdict(a=1, b=2)
254
+ y = plist([1,3,4,5,6])
255
+ z = pset(['a', 'b', 'c'])
256
+ # to_tcoll makes equal copies of the transient types.
257
+ tx = to_tcoll(x)
258
+ ty = to_tcoll(y)
259
+ tz = to_tcoll(z)
260
+ self.assertEqual(tx, x)
261
+ self.assertEqual(ty, y)
262
+ self.assertEqual(tz, z)
263
+ self.assertIsInstance(tx, tdict)
264
+ self.assertIsInstance(ty, tlist)
265
+ self.assertIsInstance(tz, tset)
266
+ # to_tcoll always makes a copy...
267
+ self.assertIsNot(tx, to_tcoll(tx))
268
+ # ...unless requested not to...
269
+ self.assertIs(tx, to_tcoll(tx, copy=False))
270
+ # They convert equivalent non-transient objects into transient ones.
271
+ self.assertIsInstance(to_tcoll(dict(x)), tdict)
272
+ self.assertEqual(to_tcoll(dict(x)), x)
273
+ self.assertIsInstance(to_tcoll(list(y)), tlist)
274
+ self.assertEqual(to_tcoll(list(y)), y)
275
+ self.assertIsInstance(to_tcoll(set(z)), tset)
276
+ self.assertEqual(to_tcoll(set(z)), z)
277
+ # If the argument isn't a valid collection, it raises an error.
278
+ with self.assertRaises(TypeError):
279
+ to_tcoll(10)
280
+ def test_to_mcoll(self):
281
+ from immlib.util import to_mcoll
282
+ from pcollections import pdict, plist, pset, tdict, tlist, tset
283
+ x = pdict(a=1, b=2)
284
+ y = plist([1,3,4,5,6])
285
+ z = pset(['a', 'b', 'c'])
286
+ # to_mcoll makes equal copies of the mutable types.
287
+ mx = to_mcoll(x)
288
+ my = to_mcoll(y)
289
+ mz = to_mcoll(z)
290
+ self.assertEqual(mx, x)
291
+ self.assertEqual(my, y)
292
+ self.assertEqual(mz, z)
293
+ self.assertIsInstance(mx, dict)
294
+ self.assertIsInstance(my, list)
295
+ self.assertIsInstance(mz, set)
296
+ # to_mcoll always makes a copy...
297
+ self.assertIsNot(mx, to_mcoll(mx))
298
+ # ...unless requested not to.
299
+ self.assertIs(mx, to_mcoll(mx, copy=False))
300
+ # They convert equivalent non-transient objects into transient ones.
301
+ self.assertIsInstance(to_mcoll(dict(x)), dict)
302
+ self.assertEqual(to_mcoll(dict(x)), x)
303
+ self.assertIsInstance(to_mcoll(list(y)), list)
304
+ self.assertEqual(to_mcoll(list(y)), y)
305
+ self.assertIsInstance(to_mcoll(set(z)), set)
306
+ self.assertEqual(to_mcoll(set(z)), z)
307
+ # If the argument isn't a valid collection, it raises an error.
308
+ with self.assertRaises(TypeError):
309
+ to_mcoll(10)
310
+
311
+ # Other Utilities ##########################################################
312
+ def test_predicates(self):
313
+ from immlib.util import (
314
+ is_acallable, is_lambda, is_asized, is_acontainer,
315
+ is_aiterable, is_aiterator, is_areversible, is_acoll,
316
+ is_abytes, is_bytes, is_ahashable, is_tuple, is_frozenset,
317
+ is_aseq, is_amseq, is_apseq,
318
+ is_aset, is_amset, is_apset,
319
+ is_amap, is_ammap, is_apmap,
320
+ is_list, is_plist, is_tlist, is_llist,
321
+ is_set, is_pset, is_tset,
322
+ is_dict, is_odict, is_ddict, is_pdict, is_tdict, is_ldict,
323
+ is_pcoll, is_tcoll, is_mcoll)
324
+ from pcollections import (
325
+ pset, tset, pdict, tdict, plist, tlist, ldict, llist)
326
+ from collections import (OrderedDict, defaultdict)
327
+ # For each of these we just do one True and one False example:
328
+ self.assertTrue(is_acallable(lambda:True))
329
+ self.assertFalse(is_acallable(10))
330
+ self.assertTrue(is_lambda(lambda:0))
331
+ self.assertFalse(is_lambda(10))
332
+ self.assertTrue(is_asized([]))
333
+ self.assertFalse(is_asized(0))
334
+ self.assertTrue(is_acontainer([]))
335
+ self.assertFalse(is_acontainer(None))
336
+ self.assertTrue(is_aiterable([]))
337
+ self.assertFalse(is_aiterable(None))
338
+ self.assertTrue(is_aiterator(iter('abc')))
339
+ self.assertFalse(is_aiterator('abc'))
340
+ self.assertTrue(is_areversible([]))
341
+ self.assertFalse(is_areversible(set([1,2,3])))
342
+ self.assertTrue(is_acoll([]))
343
+ self.assertFalse(is_acoll(10))
344
+ self.assertTrue(is_abytes(b'abc'))
345
+ self.assertFalse(is_abytes('abc'))
346
+ self.assertTrue(is_bytes(b'abc'))
347
+ self.assertFalse(is_bytes('abc'))
348
+ self.assertTrue(is_ahashable('abc'))
349
+ self.assertFalse(is_ahashable({}))
350
+ self.assertTrue(is_tuple((1,2,3)))
351
+ self.assertFalse(is_tuple([]))
352
+ self.assertTrue(is_frozenset(frozenset((1,2,3))))
353
+ self.assertFalse(is_frozenset(set()))
354
+ self.assertTrue(is_aseq([1,2,3]))
355
+ self.assertFalse(is_aseq({}))
356
+ self.assertTrue(is_amseq([]))
357
+ self.assertTrue(is_amseq(tlist()))
358
+ self.assertFalse(is_amseq(plist()))
359
+ self.assertTrue(is_apseq(plist()))
360
+ self.assertFalse(is_apseq(tlist()))
361
+ self.assertFalse(is_apseq([]))
362
+ self.assertTrue(is_aset(set()))
363
+ self.assertFalse(is_aset({}))
364
+ self.assertTrue(is_amset(tset()))
365
+ self.assertFalse(is_amset(pset()))
366
+ self.assertTrue(is_apset(pset()))
367
+ self.assertFalse(is_apset(set()))
368
+ self.assertTrue(is_amap(dict()))
369
+ self.assertFalse(is_amap([]))
370
+ self.assertTrue(is_ammap(tdict()))
371
+ self.assertFalse(is_ammap(pdict()))
372
+ self.assertTrue(is_apmap(pdict()))
373
+ self.assertFalse(is_apmap(dict()))
374
+ self.assertTrue(is_list([]))
375
+ self.assertFalse(is_list(llist()))
376
+ self.assertTrue(is_plist(plist()))
377
+ self.assertFalse(is_plist([]))
378
+ self.assertTrue(is_tlist(tlist()))
379
+ self.assertFalse(is_tlist([]))
380
+ self.assertTrue(is_llist(llist()))
381
+ self.assertFalse(is_llist(plist()))
382
+ self.assertTrue(is_set(set()))
383
+ self.assertFalse(is_set(pset()))
384
+ self.assertTrue(is_pset(pset()))
385
+ self.assertFalse(is_pset(tset()))
386
+ self.assertTrue(is_tset(tset()))
387
+ self.assertFalse(is_tset(set()))
388
+ self.assertTrue(is_dict(dict()))
389
+ self.assertFalse(is_dict(pdict()))
390
+ self.assertTrue(is_odict(OrderedDict()))
391
+ self.assertFalse(is_odict(dict()))
392
+ self.assertTrue(is_ddict(defaultdict(lambda:[])))
393
+ self.assertFalse(is_ddict(dict()))
394
+ self.assertTrue(is_pdict(pdict()))
395
+ self.assertFalse(is_pdict(dict()))
396
+ self.assertTrue(is_tdict(tdict()))
397
+ self.assertFalse(is_tdict(pdict()))
398
+ self.assertTrue(is_ldict(ldict()))
399
+ self.assertFalse(is_ldict(pdict()))
400
+ self.assertTrue(is_pcoll(pdict()))
401
+ self.assertFalse(is_pcoll([]))
402
+ self.assertTrue(is_tcoll(tset()))
403
+ self.assertFalse(is_tcoll(pset()))
404
+ self.assertTrue(is_mcoll({}))
405
+ self.assertFalse(is_mcoll(pdict()))
406
+ def test_hashsafe(self):
407
+ from immlib import hashsafe
408
+ # hashsafe returns hash(x) if x is hashable and None otherwise.
409
+ self.assertIsNone(hashsafe({}))
410
+ self.assertIsNone(hashsafe([1, 2, 3]))
411
+ self.assertIsNone(hashsafe(set(['a', 'b'])))
412
+ self.assertEqual(hash(10), hashsafe(10))
413
+ self.assertEqual(hash('abc'), hashsafe('abc'))
414
+ self.assertEqual(hash((1, 10, 100)), hashsafe((1, 10, 100)))
415
+ def test_can_hash(self):
416
+ from immlib import can_hash
417
+ # can_hash(x) returns True if hash(x) will successfully return a hash
418
+ # and returns False if such a call would raise an error.
419
+ self.assertTrue(can_hash(10))
420
+ self.assertTrue(can_hash('abc'))
421
+ self.assertTrue(can_hash((1, 10, 100)))
422
+ self.assertFalse(can_hash({}))
423
+ self.assertFalse(can_hash([1, 2, 3]))
424
+ self.assertFalse(can_hash(set(['a', 'b'])))
425
+ def test_itersafe(self):
426
+ from immlib import itersafe
427
+ # itersafe returns iter(x) if x is iterable and None otherwise.
428
+ self.assertIsNone(itersafe(10))
429
+ self.assertIsNone(itersafe(lambda x:x))
430
+ self.assertEqual(list(itersafe([1, 2, 3])), [1, 2, 3])
431
+ def test_can_iter(self):
432
+ from immlib import can_iter
433
+ # can_iter(x) returns True if iter(x) will successfully return an
434
+ # iterator and returns False if such a call would raise an error.
435
+ self.assertTrue(can_iter('abc'))
436
+ self.assertTrue(can_iter([]))
437
+ self.assertTrue(can_iter((1, 10, 100)))
438
+ self.assertFalse(can_iter(10))
439
+ self.assertFalse(can_iter(lambda x:x))
440
+ def test_get(self):
441
+ from immlib import get, nestget
442
+ # get just extracts things from simple containers; nestget does so from
443
+ # nested containers.
444
+ x = {'a': [1, 2, 3], 'b': [{'x':0, 'y':1}, {'x':10, 'y':11}]}
445
+ self.assertEqual(get(x, 'a'), [1,2,3])
446
+ self.assertEqual(nestget(x, 'a'), [1,2,3])
447
+ self.assertEqual(nestget(x, 'a', 1), 2)
448
+ with self.assertRaises(KeyError):
449
+ get(x, 'q')
450
+ with self.assertRaises(KeyError):
451
+ get(x['a'], 'q')
452
+ with self.assertRaises(KeyError):
453
+ get(x['a'], 10)
454
+ with self.assertRaises(KeyError):
455
+ nestget(x, 'a', 5)
456
+ with self.assertRaises(TypeError):
457
+ nestget(x, 'b', 0, 'x', 10)
458
+ with self.assertRaises(KeyError):
459
+ nestget(x, 'b', 'q')
460
+ with self.assertRaises(TypeError):
461
+ get(None, 'q')
462
+ self.assertEqual(get(x, 'q', default=...), ...)
463
+ self.assertEqual(nestget(x, 'b', 4, default=...), ...)
464
+ # Other errors that can be caused:
465
+ with self.assertRaises(TypeError):
466
+ get(x, 'a', other=10)
467
+ with self.assertRaises(TypeError):
468
+ nestget(x, 'a', other=10)
469
+ def test_maps(self):
470
+ from immlib.util import (
471
+ lazyvalmap, valmap, lazykeymap, keymap, lazyitemmap, itemmap,
472
+ dictmap, pdictmap, ldictmap)
473
+ from pcollections import pdict, ldict, lazy
474
+ d = dict(a=1, b=2, c=3)
475
+ make_ld = lambda:ldict(a=lazy(lambda:1), b=lazy(lambda:2), c=3)
476
+ # lazyvalmap
477
+ md = lazyvalmap(lambda x: x+1, d)
478
+ self.assertIsInstance(md, ldict)
479
+ self.assertTrue(md.is_lazy('a'))
480
+ self.assertFalse(md.is_ready('a'))
481
+ self.assertEqual(md['a'], 2)
482
+ self.assertTrue(md.is_ready('a'))
483
+ mmd = lazyvalmap(lambda x: x+1, md)
484
+ self.assertIsInstance(mmd, ldict)
485
+ self.assertTrue(mmd.is_lazy('a'))
486
+ self.assertTrue(md.is_lazy('b'))
487
+ self.assertFalse(mmd.is_ready('a'))
488
+ self.assertFalse(md.is_ready('b'))
489
+ self.assertEqual(mmd['a'], 3)
490
+ self.assertEqual(md, dict(a=2, b=3, c=4))
491
+ self.assertEqual(mmd, dict(a=3, b=4, c=5))
492
+ # valmap
493
+ ld = make_ld()
494
+ md = valmap(lambda x: x+1, d)
495
+ mld = valmap(lambda x: x+1, ld)
496
+ mpd = valmap(lambda x: x+1, pdict(d))
497
+ self.assertIs(type(md), dict)
498
+ self.assertIs(type(mpd), pdict)
499
+ self.assertIs(type(mld), ldict)
500
+ self.assertTrue(mld.is_lazy('a'))
501
+ self.assertEqual(mld['a'], 2)
502
+ self.assertTrue(mld.is_ready('a'))
503
+ self.assertEqual(md, dict(a=2, b=3, c=4))
504
+ self.assertEqual(mpd, dict(a=2, b=3, c=4))
505
+ self.assertEqual(mld, dict(a=2, b=3, c=4))
506
+ # lazykeymap
507
+ md = lazykeymap(lambda x:x, d)
508
+ self.assertIsInstance(md, ldict)
509
+ self.assertTrue(md.is_lazy('a'))
510
+ self.assertFalse(md.is_ready('a'))
511
+ self.assertEqual(md['a'], 'a')
512
+ self.assertTrue(md.is_ready('a'))
513
+ self.assertEqual(md, dict(a='a', b='b', c='c'))
514
+ # keymap
515
+ ld = make_ld()
516
+ md = keymap(lambda x: x, d)
517
+ mld = keymap(lambda x: x, ld)
518
+ mpd = keymap(lambda x: x, pdict(d))
519
+ self.assertIs(type(md), dict)
520
+ self.assertIs(type(mpd), pdict)
521
+ self.assertIs(type(mld), pdict)
522
+ self.assertEqual(mld['a'], 'a')
523
+ self.assertEqual(md, dict(a='a', b='b', c='c'))
524
+ self.assertEqual(mpd, dict(a='a', b='b', c='c'))
525
+ self.assertEqual(mld, dict(a='a', b='b', c='c'))
526
+ # lazyitemmap
527
+ md = lazyitemmap(lambda x,y: x*y, d)
528
+ self.assertIsInstance(md, ldict)
529
+ self.assertTrue(md.is_lazy('a'))
530
+ self.assertFalse(md.is_ready('a'))
531
+ self.assertEqual(md['a'], 'a')
532
+ self.assertTrue(md.is_ready('a'))
533
+ mmd = lazyitemmap(lambda x,y: x*y, ldict(d))
534
+ self.assertIsInstance(mmd, ldict)
535
+ self.assertTrue(mmd.is_lazy('a'))
536
+ self.assertTrue(md.is_lazy('b'))
537
+ self.assertFalse(mmd.is_ready('a'))
538
+ self.assertFalse(md.is_ready('b'))
539
+ self.assertEqual(mmd['a'], 'a')
540
+ self.assertEqual(md, dict(a='a', b='bb', c='ccc'))
541
+ self.assertEqual(mmd, dict(a='a', b='bb', c='ccc'))
542
+ # itemmap
543
+ ld = make_ld()
544
+ md = itemmap(lambda x,y: x*y, d)
545
+ mld = itemmap(lambda x,y: x*y, ld)
546
+ mpd = itemmap(lambda x,y: x*y, pdict(d))
547
+ self.assertIs(type(md), dict)
548
+ self.assertIs(type(mpd), pdict)
549
+ self.assertIs(type(mld), ldict)
550
+ self.assertTrue(mld.is_lazy('a'))
551
+ self.assertEqual(mld['a'], 'a')
552
+ self.assertTrue(mld.is_ready('a'))
553
+ self.assertEqual(md, dict(a='a', b='bb', c='ccc'))
554
+ self.assertEqual(mpd, dict(a='a', b='bb', c='ccc'))
555
+ self.assertEqual(mld, dict(a='a', b='bb', c='ccc'))
556
+ # dictmap
557
+ ks = list('abcdefghij')
558
+ ref = dict(zip(ks, range(10)))
559
+ d = dictmap(lambda k: ref[k] + 1, ks)
560
+ pd = pdictmap(lambda k: ref[k] + 1, ks)
561
+ ld = ldictmap(lambda k: ref[k] + 1, ks)
562
+ self.assertIs(type(pd), pdict)
563
+ self.assertIs(type(ld), ldict)
564
+ self.assertEqual(valmap(lambda x:x+1, ref), d)
565
+ self.assertEqual(valmap(lambda x:x+1, ref), pd)
566
+ self.assertTrue(ld.is_lazy('a'))
567
+ self.assertFalse(ld.is_ready('a'))
568
+ self.assertEqual(ld['a'], 1)
569
+ self.assertTrue(ld.is_ready('a'))
570
+ self.assertEqual(valmap(lambda x:x+1, ref), ld)
571
+ def test_merge(self):
572
+ from immlib.util import merge, rmerge
573
+ from pcollections import ldict, lazy
574
+ d1 = dict(a=1, b=2, c=3)
575
+ d2 = dict(b=3, c=4, d=5)
576
+ d3 = ldict(c=lazy(lambda:5), d=6, e=lazy(lambda:7))
577
+ d = merge(d1, d2, d3, a=0)
578
+ self.assertIs(type(d), ldict)
579
+ self.assertTrue(d.is_lazy('c'))
580
+ self.assertTrue(d.is_lazy('e'))
581
+ self.assertFalse(d.is_ready('c'))
582
+ self.assertFalse(d.is_ready('e'))
583
+ self.assertFalse(d.is_lazy('d'))
584
+ self.assertEqual(d['c'], 5)
585
+ self.assertTrue(d.is_ready('c'))
586
+ self.assertFalse(d.is_ready('e'))
587
+ self.assertEqual(d, dict(a=0, b=3, c=5, d=6, e=7))
588
+ d3 = ldict(c=lazy(lambda:5), d=6, e=lazy(lambda:7))
589
+ d = rmerge(d1, d2, d3, a=0)
590
+ self.assertIs(type(d), ldict)
591
+ self.assertFalse(d.is_lazy('c'))
592
+ self.assertTrue(d.is_lazy('e'))
593
+ self.assertFalse(d.is_ready('e'))
594
+ self.assertEqual(d['c'], 3)
595
+ self.assertEqual(d['e'], 7)
596
+ self.assertTrue(d.is_ready('e'))
597
+ self.assertEqual(d, dict(a=1, b=2, c=3, d=5, e=7))
598
+ def test_assoc(self):
599
+ from immlib.util import assoc, dissoc
600
+ from pcollections import pdict
601
+ with self.assertRaises(ValueError):
602
+ assoc({}, 'a')
603
+ with self.assertRaises(TypeError):
604
+ assoc('abc', 'a', 1)
605
+ with self.assertRaises(TypeError):
606
+ dissoc('abc', 'a')
607
+ d = dict(a=1, b=2, c=3)
608
+ self.assertEqual(assoc(d, d=4), dict(d, d=4))
609
+ self.assertEqual(assoc(d, 'd', 4), dict(d, d=4))
610
+ self.assertEqual(assoc(d, 'd', 4, e=5), dict(d, d=4, e=5))
611
+ self.assertIsNot(assoc(d, 'd', 4), d)
612
+ self.assertEqual(dissoc(d, 'b'), dict(a=1, c=3))
613
+ self.assertEqual(dissoc(d, 'b', 'c'), dict(a=1))
614
+ self.assertIsNot(dissoc(d, 'b'), d)
615
+ d = pdict(a=1, b=2, c=3)
616
+ self.assertEqual(assoc(d, d=4), dict(d, d=4))
617
+ self.assertEqual(assoc(d, 'd', 4), dict(d, d=4))
618
+ self.assertEqual(assoc(d, 'd', 4, e=5), dict(d, d=4, e=5))
619
+ self.assertIsNot(assoc(d, 'd', 4), d)
620
+ self.assertEqual(dissoc(d, 'b'), dict(a=1, c=3))
621
+ self.assertEqual(dissoc(d, 'b', 'c'), dict(a=1))
622
+ self.assertIsNot(dissoc(d, 'b'), d)
623
+ def test_lambdadict(self):
624
+ from immlib.util import lambdadict
625
+ from pcollections import ldict
626
+ d = lambdadict(a=1, b=2, c=lambda a,b: a+b)
627
+ self.assertIsInstance(d, ldict)
628
+ self.assertTrue(d.is_lazy('c'))
629
+ self.assertFalse(d.is_ready('c'))
630
+ self.assertEqual(d['c'], 3)
631
+ self.assertTrue(d.is_ready('c'))
632
+ self.assertEqual(d, dict(a=1, b=2, c=3))
633
+ def test_args(self):
634
+ from immlib.util import args, argfilter
635
+ # First test the args type:
636
+ (a, kw) = args(1, 2, 3, a=1, b=2)
637
+ self.assertEqual(a, (1,2,3))
638
+ self.assertEqual(kw, dict(a=1, b=2))
639
+ aa = args(1, 2, 3, a=1, b=2)
640
+ self.assertIs(type(aa), args)
641
+ self.assertEqual(aa, ((1,2,3), {'a':1,'b':2}))
642
+ bb = aa.copy(args=(2,3,4))
643
+ self.assertEqual(bb, ((2,3,4), {'a':1,'b':2}))
644
+ cc = aa.copy(kwargs={'c':3})
645
+ self.assertEqual(cc, ((1,2,3), {'c':3}))
646
+ # Next test the argfilter:
647
+ @argfilter
648
+ def fix_angle(angle, *, unit):
649
+ angle = np.asarray(angle)
650
+ if unit == 'degrees':
651
+ angle = np.pi / 180 * angle
652
+ elif unit != 'radians':
653
+ raise ValueError(f'unrecognized unit: {unit}')
654
+ return (angle,)
655
+ @fix_angle
656
+ def cos_halfangle(angle, unit='radians'):
657
+ return np.cos(angle / 2)
658
+ self.assertEqual(cos_halfangle(0), 1.0)
659
+ self.assertEqual(cos_halfangle(0, unit='degrees'), 1.0)
660
+ self.assertTrue(np.abs(cos_halfangle(np.pi)) < 1e-9)
661
+ self.assertTrue(np.abs(cos_halfangle(180, unit='degrees')) < 1e-9)
662
+ def test_unitregistry(self):
663
+ from immlib.util import unitregistry
664
+ from immlib import unit, units, mag, quant, default_ureg
665
+ with default_ureg(units):
666
+ q = quant(10.5, 'mm')
667
+ p = quant(55, 's')
668
+ self.assertIs(units, unitregistry(units))
669
+ self.assertIs(units, unitregistry(...))
670
+ self.assertIs(units, unitregistry(q))
671
+ self.assertIs(units, unitregistry(p))
672
+ self.assertIs(units, unitregistry(q.u))
673
+ self.assertIs(units, unitregistry(p.u))
674
+ with self.assertRaises(TypeError):
675
+ unitregistry(units, None, 1)
676
+ with self.assertRaises(TypeError):
677
+ unitregistry()
678
+ with self.assertRaises(TypeError):
679
+ unitregistry(units, None, 1)
680
+
681
+