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,81 @@
1
+ # -*- coding: utf-8 -*-
2
+ ################################################################################
3
+ # immlib/test/iolib/test_core.py
4
+
5
+ """Tests for the core iolib submodule in immlib: i.e., tests for the code in
6
+ the `immlib.iolib._core` module.
7
+ """
8
+
9
+
10
+ # Dependencies #################################################################
11
+
12
+ import gzip
13
+ from io import StringIO, BytesIO
14
+ from unittest import TestCase
15
+ from tempfile import TemporaryDirectory
16
+
17
+ from ...pathlib import *
18
+ from ...iolib import *
19
+ from ...util import is_str
20
+
21
+
22
+ # Tests ########################################################################
23
+
24
+ text_example = """
25
+ Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis molestie, nisl
26
+ eget volutpat interdum, ex tortor suscipit ipsum, at aliquam justo neque in
27
+ enim. In eu sollicitudin nunc. Integer egestas consequat nibh, ut pretium ex
28
+ accumsan ornare. Fusce et nisl laoreet, aliquet felis ac, fermentum
29
+ ipsum. Pellentesque at velit condimentum, auctor enim quis, ultrices
30
+ libero. Praesent efficitur posuere orci, id pretium nunc iaculis
31
+ id. Vestibulum varius massa in magna iaculis scelerisque. Etiam fermentum
32
+ condimentum orci, eget volutpat elit faucibus vestibulum. Mauris nec
33
+ imperdiet urna.
34
+ """
35
+ json_example = {
36
+ 'a': [1, 'test_2', {'b': 3, 'c': 4}, 5],
37
+ 'x': {'y': [10, 20.01, 30], 'z': [40, 50.01, 60]},
38
+ 'q': 100.5,
39
+ 'n': None,
40
+ 'bools': [True, False]
41
+ }
42
+
43
+ class TestIOLibCore(TestCase):
44
+ """Tests for the core module of the immlib.iolib subpackage.
45
+ """
46
+
47
+ def test_save(self):
48
+ """Tests the immlib.save interface."""
49
+ # We'll start by saving to StringIO and BytesIO objects.
50
+ s = save(StringIO(), text_example, "str")
51
+ self.assertEqual(s.getvalue(), text_example)
52
+ s = save(StringIO(), text_example, "text")
53
+ self.assertEqual(s.getvalue(), text_example)
54
+ # For JSON and YAML, easiest to check for equality after deserializing.
55
+ s = save(StringIO(), json_example, "json")
56
+ d = load(StringIO(s.getvalue()), "json")
57
+ self.assertEqual(json_example, d)
58
+ s = save(StringIO(), json_example, "yaml")
59
+ d = load(StringIO(s.getvalue()), "yaml")
60
+ self.assertEqual(json_example, d)
61
+ # We should also be able to save to a path.
62
+ with TemporaryDirectory() as tmpdir:
63
+ p = path(tmpdir) / "test.json"
64
+ # Should auto-detect the format from extension.
65
+ save(p, json_example)
66
+ d = load(p)
67
+ self.assertEqual(json_example, d)
68
+ # Also test the ability to load from CloudPaths.
69
+ p = osfpath("osf://bw9ec", local_cache_dir=tmpdir)
70
+ lns = load(p / "analysis.m", "text")
71
+ self.assertEqual(len(lns), 94)
72
+ self.assertTrue(all(is_str(ln) for ln in lns))
73
+ # Gzip objects should also work fine.
74
+ p_gz = path(tmpdir) / "test.json.gz"
75
+ save(p_gz, json_example)
76
+ d = load(p_gz)
77
+ self.assertEqual(json_example, d)
78
+ # We should be able to use the gzip module to load this also.
79
+ with gzip.open(p_gz, 'rt') as fl:
80
+ d = load(fl, "json")
81
+ self.assertEqual(json_example, d)
@@ -0,0 +1,11 @@
1
+ # -*- coding: utf-8 -*-
2
+ ################################################################################
3
+ # pimms/test/pathlib/__init__.py
4
+
5
+ """Test module for the pimms.pathlib submodule."""
6
+
7
+ # Import tests
8
+ from .test_core import TestPathlibCore
9
+ from .test_osf import TestPathlibOSF
10
+
11
+
@@ -0,0 +1,146 @@
1
+ # -*- coding: utf-8 -*-
2
+ ################################################################################
3
+ # immlib/test/pathlib/test_core.py
4
+
5
+ """Tests for the core pathlib submodule in immlib: i.e., tests for the code in
6
+ the `immlib.pathlib._core` module.
7
+ """
8
+
9
+
10
+ # Dependencies #################################################################
11
+
12
+ from unittest import TestCase
13
+ from tempfile import TemporaryDirectory
14
+ from pathlib import (Path, WindowsPath)
15
+
16
+ from cloudpathlib import (CloudPath, AzureBlobPath, S3Path, GSPath)
17
+
18
+ from ...pathlib import *
19
+
20
+
21
+ # Tests ########################################################################
22
+
23
+ # Some example path strings to use.
24
+ # Unfortunately, AzureBlobPaths require credentials, so we do not test these
25
+ # paths in the GitHub Actions automated testing (for now). These are tested by
26
+ # the cloudpathlib library, but the wrapper functions are not completely tested.
27
+ pathstrs = [
28
+ "/etc/ssh/",
29
+ "file://immlib/pathlib/__init__.py",
30
+ #"az://storageaccount.blob.core.windows.net/container/blob/path",
31
+ "osf://bw9ec/analysis.m",
32
+ "s3://openneuro.org/ds003787/derivatives/",
33
+ "gs://gcp-public-data-landsat/LC08/01/044/034/"]
34
+ pathtypes = [
35
+ Path,
36
+ Path,
37
+ #AzureBlobPath,
38
+ OSFPath,
39
+ S3Path,
40
+ GSPath]
41
+ pathfns = {
42
+ Path: (filepath, is_filepath, like_filepath),
43
+ AzureBlobPath: (None, is_azpath, like_azpath),
44
+ OSFPath: (osfpath, is_osfpath, like_osfpath),
45
+ S3Path: (s3path, is_s3path, like_s3path),
46
+ GSPath: (gspath, is_gspath, like_gspath)}
47
+
48
+ # The test class.
49
+ class TestPathlibCore(TestCase):
50
+ """Tests the immlib.pathlib._core module."""
51
+
52
+ def cleanup_cache(self, p):
53
+ """Given a path with a temporary directory, calls its cleanup routine.
54
+ """
55
+ if isinstance(p, CloudPath):
56
+ cl = p.client
57
+ if cl and cl._cache_tmp_dir:
58
+ cl._cache_tmp_dir.cleanup()
59
+ def test_pathstr(self):
60
+ """Tests the `path` and `pathstr` functions."""
61
+ # Path strings for basic strings should remain unchanged.
62
+ for p in pathstrs:
63
+ self.assertIs(p, pathstr(p))
64
+ # Path strings for path objects should equal the original strings.
65
+ paths = [path(p) for p in pathstrs]
66
+ for (p, tt) in zip(paths, pathtypes):
67
+ self.assertIsInstance(p, tt)
68
+ # Note that Path strips trailing slashes while CloudPath does not.
69
+ for (p,ps,pt) in zip(paths, pathstrs, pathtypes):
70
+ s = pathstr(p)
71
+ if isinstance(p, Path):
72
+ ps = ps.rstrip('/')
73
+ # if ps starts with file:// that will get stripped on a normal path.
74
+ if ps.startswith('file://'):
75
+ ps = ps[7:]
76
+ if isinstance(p, WindowsPath):
77
+ ps = ps.replace('/', '\\')
78
+ self.assertEqual(pathstr(p), ps)
79
+ # Adding to the path preserves a reasonable string:
80
+ correct_path = "/etc/ssh/sshd_config"
81
+ if isinstance(paths[0], WindowsPath):
82
+ correct_path = correct_path.replace('/', '\\')
83
+ self.assertEqual(pathstr(paths[0] / "sshd_config"), correct_path)
84
+ # The path and pathstr functions should fail for non-string inputs.
85
+ with self.assertRaises(TypeError):
86
+ path(10)
87
+ with self.assertRaises(TypeError):
88
+ pathstr(10)
89
+ # Before we exit, it's good form to cleanup the temporary directories
90
+ # that we created.
91
+ for p in paths:
92
+ self.cleanup_cache(p)
93
+ def test_pathfns(self):
94
+ """Tests the various path-related functions for each path type."""
95
+ from tempfile import TemporaryDirectory
96
+ # We make a single temporary directory for this whole test.
97
+ with TemporaryDirectory() as tempdir:
98
+ # We'll now go through each of the path types and check their
99
+ # functions using the pathstrs and pathtypes.
100
+ for (ps, pt) in zip(pathstrs, pathtypes):
101
+ (make, test, like) = pathfns[pt]
102
+ if make is None:
103
+ continue
104
+ if pt is Path:
105
+ p = make(ps)
106
+ pp = path(ps)
107
+ else:
108
+ p = make(ps, local_cache_dir=tempdir)
109
+ pp = path(ps, local_cache_dir=tempdir)
110
+ # The paths made with either method should be equivalent.
111
+ self.assertEqual(pathstr(p), pathstr(pp))
112
+ self.assertIs(type(p), type(pp))
113
+ self.assertTrue(test(p))
114
+ self.assertFalse(test(ps))
115
+ self.assertTrue(like(p))
116
+ self.assertTrue(like(ps))
117
+ # If we get the local cache paths, they should also be equal;
118
+ # (if p is a filepath, then this just returns their pathstrs).
119
+ self.assertEqual(pathstr(filepath(p)), pathstr(filepath(pp)))
120
+ # This path should be an instance of its own path type.
121
+ self.assertIsInstance(p, pt)
122
+ if '://' in ps:
123
+ # If there's a sheme at the beginning of the path, then it
124
+ # should fail to construct via other path functions.
125
+ for (k,(mk,tt,lk)) in pathfns.items():
126
+ if k is pt or k is Path:
127
+ continue
128
+ if mk is not None:
129
+ with self.assertRaises(Exception):
130
+ mk(ps, local_cache_dir=tempdir)
131
+ self.assertFalse(tt(p))
132
+ self.assertFalse(tt(ps))
133
+ self.assertFalse(lk(p))
134
+ self.assertFalse(lk(ps))
135
+ def test_misc(self):
136
+ from immlib.pathlib import (is_path, like_path, pathdict, path)
137
+ import immlib as il
138
+ p = path('osf://tery8/')
139
+ self.assertTrue(is_path(p))
140
+ self.assertTrue(like_path(p))
141
+ self.assertFalse(is_path(10))
142
+ self.assertFalse(like_path('blarg://nothing'))
143
+ d = pathdict(path(il.__file__).parent)
144
+ for k in ('util', 'doc', 'types', 'workflow'):
145
+ self.assertIn(k, d)
146
+ self.assertTrue(path(d['util']['__init__.py']).is_file())
@@ -0,0 +1,54 @@
1
+ # -*- coding: utf-8 -*-
2
+ ################################################################################
3
+ # immlib/test/pathlib/test_osf.py
4
+
5
+ """Tests for the OSF components of the pathlib submodule in immlib: i.e.,
6
+ tests for the code in the `immlib.pathlib._osf` module.
7
+ """
8
+
9
+
10
+ # Dependencies #################################################################
11
+
12
+ from unittest import TestCase
13
+ from tempfile import TemporaryDirectory
14
+
15
+ from ...pathlib import *
16
+
17
+
18
+ # Tests ########################################################################
19
+
20
+ class TestPathlibOSF(TestCase):
21
+ """Tests the immlib.pathlib._osf module."""
22
+
23
+ def test_osf(self):
24
+ """Tests the OSFPath type."""
25
+ # We'll do everything in a single temporary directory.
26
+ with TemporaryDirectory() as tmpdir:
27
+ # Create an OSFPath.
28
+ p0 = osfpath("osf://bw9ec/", local_cache_dir=tmpdir)
29
+ # Test out a few subpaths...
30
+ p = p0 / "analysis.m"
31
+ # This one is a file.
32
+ self.assertTrue(p.is_file())
33
+ # We should be able to read it.
34
+ with p.open('rt') as f:
35
+ lns = f.readlines()
36
+ # This particular file has 94 lines in it.
37
+ self.assertEqual(len(lns), 94)
38
+ # This is the first line:
39
+ self.assertEqual(
40
+ lns[0],
41
+ ('% This script shows how analyzePRF_HCP7TRET was used'
42
+ ' to analyze the\n'))
43
+ # Here's a directory.
44
+ p = p0 / "rotatingsurfaces"
45
+ self.assertTrue(p.is_dir())
46
+ # We should be able to list the contents.
47
+ ls = {fl.name: fl for fl in p.iterdir()}
48
+ # There are 12 files in this particular directory; here are a few
49
+ # of them:
50
+ self.assertEqual(len(ls), 12)
51
+ # Here's one example:
52
+ f = p / "rh-angle.mov"
53
+ self.assertEqual(f, ls["rh-angle.mov"])
54
+ self.assertTrue(f.is_file())
@@ -0,0 +1,5 @@
1
+ # -*- coding: utf-8 -*-
2
+ ################################################################################
3
+ # immlib/test/types/test_core.py
4
+
5
+ from .test_core import TestTypesCore
@@ -0,0 +1,110 @@
1
+ # -*- coding: utf-8 -*-
2
+ ################################################################################
3
+ # immlib/test/types/test_core.py
4
+
5
+ """Tests of the core types module in immlib: i.e., tests for the code in the
6
+ immlib.types._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 TestTypesCore(TestCase):
20
+ """Tests the immlib.types._core module."""
21
+
22
+ def test_metaobject(self):
23
+ "Tests the MetaObject class."
24
+ from ...types import MetaObject
25
+ from pcollections import ldict
26
+ # We can make objects with metadata (and the metadata get saved as
27
+ # persistent dictionaries).
28
+ o = MetaObject(metadata={'a': 1, 'b': 2})
29
+ self.assertIsInstance(o.metadata, ldict)
30
+ self.assertEqual(o.metadata, dict(a=1, b=2))
31
+ # We can add and subtract from these metadata maps.
32
+ oo = o.withmeta(c=3)
33
+ self.assertEqual(oo.metadata, dict(a=1, b=2, c=3))
34
+ ooo = oo.dropmeta('a')
35
+ self.assertEqual(ooo.metadata, dict(b=2, c=3))
36
+ # The original object must stay the same through all this.
37
+ self.assertEqual(o.metadata, dict(a=1, b=2))
38
+ self.assertEqual(oo.metadata, dict(a=1, b=2, c=3))
39
+ # We can also set the metadata directly.
40
+ oo = o.set_metadata(dict(e=5, f=6))
41
+ self.assertEqual(oo.metadata, dict(e=5, f=6))
42
+ self.assertIsInstance(oo.metadata, ldict)
43
+ # Finally we ca clear the metadata.
44
+ self.assertEqual(o.clear_metadata().metadata, dict())
45
+ def test_immutable(self):
46
+ "Test the Immutable type."
47
+ from ...types import Immutable
48
+ class immtest(Immutable):
49
+ __slots__ = ('a', 'b')
50
+ def __init__(self, a, b):
51
+ self.a = a
52
+ self.b = b
53
+ immobj = immtest(1, 2)
54
+ self.assertEqual(immobj.a, 1)
55
+ self.assertEqual(immobj.b, 2)
56
+ with self.assertRaises(TypeError):
57
+ immobj.a = 10
58
+ with self.assertRaises(TypeError):
59
+ immobj.b = 20
60
+ with self.assertRaises(TypeError):
61
+ del immobj.b
62
+ def test_array_index(self):
63
+ "Tests the ArrayIndex type."
64
+ from ...types import ArrayIndex
65
+ # Test with basic integers.
66
+ arr = np.reshape(np.arange(2*3*4), (2,3,4))
67
+ ai = ArrayIndex(arr)
68
+ for num in arr.flat:
69
+ self.assertEqual(arr[ai.find(num)], num)
70
+ # We can also find multiple elements at once:
71
+ els = [2,5,9]
72
+ self.assertTrue(np.array_equal(arr[ai.find(els)], els))
73
+ # Default values can be provided when not found:
74
+ self.assertEqual(ai.find(100, default=-1, ravel=True), -1)
75
+ # Otherwise, if we look for something not there, we get a KeyError:
76
+ with self.assertRaises(KeyError):
77
+ ai.find(100)
78
+ # The index freezes its array.
79
+ self.assertFalse(ai.array.flags['WRITEABLE'])
80
+ # But we can instruct the array to stay writeable if desired.
81
+ ai = ArrayIndex(arr, freeze=False)
82
+ self.assertTrue(ai.array.flags['WRITEABLE'])
83
+ # Tests with strings instead of integers.
84
+ lorem = '''Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed
85
+ do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut
86
+ enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi
87
+ ut aliquip ex ea commodo consequat. Duis aute irure dolor in
88
+ reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla
89
+ pariatur. Excepteur sint occaecat cupidatat non proident, sunt in
90
+ culpa qui officia deserunt mollit anim id est laborum.'''
91
+ words = lorem.split()[:24]
92
+ arr = np.reshape(words, (4,3,2))
93
+ ai = ArrayIndex(arr)
94
+ for word in words:
95
+ self.assertEqual(arr[ai.find(word)], word)
96
+ els = [words[k] for k in [2,5,9]]
97
+ self.assertTrue(np.array_equal(arr[ai.find(els)], els))
98
+ # ArrayIndex objects are immutable.
99
+ with self.assertRaises(TypeError):
100
+ del ai.flatdata
101
+ with self.assertRaises(TypeError):
102
+ del ai[0]
103
+ with self.assertRaises(TypeError):
104
+ ai.flatdata = ()
105
+ with self.assertRaises(TypeError):
106
+ ai[0] = 0
107
+ # They raise some other errors too:
108
+ with self.assertRaises(TypeError):
109
+ ai.find(0, xyz=10)
110
+
@@ -0,0 +1,11 @@
1
+ # -*- coding: utf-8 -*-
2
+ ################################################################################
3
+ # immlib/test/util/__init__.py
4
+
5
+ """Tests of the immlib.util module."""
6
+
7
+
8
+ from .test_core import TestUtilCore
9
+ from .test_numeric import TestUtilNumeric
10
+ from .test_quantity import TestUtilQuantity
11
+ from .test_url import TestUtilURL