immlib 1.0.0.dev1__tar.gz
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.
- immlib-1.0.0.dev1/LICENSE +21 -0
- immlib-1.0.0.dev1/PKG-INFO +61 -0
- immlib-1.0.0.dev1/README.md +17 -0
- immlib-1.0.0.dev1/pyproject.toml +44 -0
- immlib-1.0.0.dev1/setup.cfg +4 -0
- immlib-1.0.0.dev1/src/immlib/__init__.py +88 -0
- immlib-1.0.0.dev1/src/immlib/_version.py +94 -0
- immlib-1.0.0.dev1/src/immlib/doc/__init__.py +22 -0
- immlib-1.0.0.dev1/src/immlib/doc/_core.py +103 -0
- immlib-1.0.0.dev1/src/immlib/iolib/__init__.py +31 -0
- immlib-1.0.0.dev1/src/immlib/iolib/_core.py +720 -0
- immlib-1.0.0.dev1/src/immlib/pathlib/__init__.py +77 -0
- immlib-1.0.0.dev1/src/immlib/pathlib/_cache.py +152 -0
- immlib-1.0.0.dev1/src/immlib/pathlib/_core.py +840 -0
- immlib-1.0.0.dev1/src/immlib/pathlib/_osf.py +529 -0
- immlib-1.0.0.dev1/src/immlib/test/__init__.py +15 -0
- immlib-1.0.0.dev1/src/immlib/test/__main__.py +10 -0
- immlib-1.0.0.dev1/src/immlib/test/doc/__init__.py +6 -0
- immlib-1.0.0.dev1/src/immlib/test/doc/test_core.py +90 -0
- immlib-1.0.0.dev1/src/immlib/test/iolib/__init__.py +7 -0
- immlib-1.0.0.dev1/src/immlib/test/iolib/test_core.py +81 -0
- immlib-1.0.0.dev1/src/immlib/test/pathlib/__init__.py +11 -0
- immlib-1.0.0.dev1/src/immlib/test/pathlib/test_core.py +134 -0
- immlib-1.0.0.dev1/src/immlib/test/pathlib/test_osf.py +59 -0
- immlib-1.0.0.dev1/src/immlib/test/util/__init__.py +10 -0
- immlib-1.0.0.dev1/src/immlib/test/util/test_core.py +208 -0
- immlib-1.0.0.dev1/src/immlib/test/util/test_numeric.py +853 -0
- immlib-1.0.0.dev1/src/immlib/test/util/test_quantity.py +218 -0
- immlib-1.0.0.dev1/src/immlib/test/workflow/__init__.py +9 -0
- immlib-1.0.0.dev1/src/immlib/test/workflow/test_core.py +219 -0
- immlib-1.0.0.dev1/src/immlib/test/workflow/test_plantype.py +105 -0
- immlib-1.0.0.dev1/src/immlib/util/__init__.py +252 -0
- immlib-1.0.0.dev1/src/immlib/util/_core.py +1943 -0
- immlib-1.0.0.dev1/src/immlib/util/_numeric.py +1686 -0
- immlib-1.0.0.dev1/src/immlib/util/_quantity.py +496 -0
- immlib-1.0.0.dev1/src/immlib/util/_url.py +98 -0
- immlib-1.0.0.dev1/src/immlib/workflow/__init__.py +49 -0
- immlib-1.0.0.dev1/src/immlib/workflow/_core.py +1104 -0
- immlib-1.0.0.dev1/src/immlib/workflow/_plantype.py +258 -0
- immlib-1.0.0.dev1/src/immlib.egg-info/PKG-INFO +61 -0
- immlib-1.0.0.dev1/src/immlib.egg-info/SOURCES.txt +42 -0
- immlib-1.0.0.dev1/src/immlib.egg-info/dependency_links.txt +1 -0
- immlib-1.0.0.dev1/src/immlib.egg-info/requires.txt +15 -0
- immlib-1.0.0.dev1/src/immlib.egg-info/top_level.txt +1 -0
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2024 Noah C. Benson
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
Metadata-Version: 2.1
|
|
2
|
+
Name: immlib
|
|
3
|
+
Version: 1.0.0.dev1
|
|
4
|
+
Summary: A library of utilites for immutable scientific data.
|
|
5
|
+
Author-email: "Noah C. Benson" <nben@uw.edu>
|
|
6
|
+
License: MIT
|
|
7
|
+
Project-URL: homepage, https://github.com/noahbenson/immlib
|
|
8
|
+
Project-URL: documentation, https://github.com/noahbenson/immlib
|
|
9
|
+
Project-URL: repository, https://github.com/noahbenson/immlib
|
|
10
|
+
Keywords: persistent,immutable,functional,scientific,workflow
|
|
11
|
+
Classifier: Intended Audience :: Science/Research
|
|
12
|
+
Classifier: Intended Audience :: Developers
|
|
13
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
14
|
+
Classifier: Programming Language :: Python :: 3
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.8
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
19
|
+
Classifier: Topic :: Software Development
|
|
20
|
+
Classifier: Topic :: Software Development :: Libraries
|
|
21
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
22
|
+
Classifier: Topic :: Scientific/Engineering
|
|
23
|
+
Classifier: Topic :: Scientific/Engineering :: Information Analysis
|
|
24
|
+
Classifier: Operating System :: Microsoft :: Windows
|
|
25
|
+
Classifier: Operating System :: POSIX
|
|
26
|
+
Classifier: Operating System :: Unix
|
|
27
|
+
Classifier: Operating System :: MacOS
|
|
28
|
+
Requires-Python: >=3.8
|
|
29
|
+
Description-Content-Type: text/markdown
|
|
30
|
+
License-File: LICENSE
|
|
31
|
+
Requires-Dist: pcollections>=0.2.7
|
|
32
|
+
Requires-Dist: numpy>=1.24.0
|
|
33
|
+
Requires-Dist: scipy>=1.7.0
|
|
34
|
+
Requires-Dist: pint>=0.18.0
|
|
35
|
+
Requires-Dist: docrep>=0.3.2
|
|
36
|
+
Requires-Dist: joblib>=1.3.0
|
|
37
|
+
Requires-Dist: cloudpathlib[azure,gs,s3]>=0.18.0
|
|
38
|
+
Provides-Extra: dev
|
|
39
|
+
Requires-Dist: torch>=2.2.0; extra == "dev"
|
|
40
|
+
Requires-Dist: pyyaml; extra == "dev"
|
|
41
|
+
Provides-Extra: test
|
|
42
|
+
Requires-Dist: torch>=2.2.0; extra == "test"
|
|
43
|
+
Requires-Dist: pyyaml; extra == "test"
|
|
44
|
+
|
|
45
|
+
# immlib
|
|
46
|
+
|
|
47
|
+

|
|
48
|
+
[](https://codecov.io/gh/noahbenson/immlib)
|
|
49
|
+
[](https://badge.fury.io/py/immlib)
|
|
50
|
+
|
|
51
|
+
`immlib` is a library of utilities for managing and manipulating immutable
|
|
52
|
+
scientific data with a focus on lazy calculations and workflows. It is based on
|
|
53
|
+
a prototype library [`pimms`](https://github.com/noahbenson/pimms).
|
|
54
|
+
|
|
55
|
+
---
|
|
56
|
+
|
|
57
|
+
**Author**: Noah C. Benson <[nben@uw.edu](mailto:nben@uw.edu)>
|
|
58
|
+
**License**: MIT
|
|
59
|
+
|
|
60
|
+
---
|
|
61
|
+
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
# immlib
|
|
2
|
+
|
|
3
|
+

|
|
4
|
+
[](https://codecov.io/gh/noahbenson/immlib)
|
|
5
|
+
[](https://badge.fury.io/py/immlib)
|
|
6
|
+
|
|
7
|
+
`immlib` is a library of utilities for managing and manipulating immutable
|
|
8
|
+
scientific data with a focus on lazy calculations and workflows. It is based on
|
|
9
|
+
a prototype library [`pimms`](https://github.com/noahbenson/pimms).
|
|
10
|
+
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
**Author**: Noah C. Benson <[nben@uw.edu](mailto:nben@uw.edu)>
|
|
14
|
+
**License**: MIT
|
|
15
|
+
|
|
16
|
+
---
|
|
17
|
+
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
[project]
|
|
2
|
+
name = "immlib"
|
|
3
|
+
version = "1.0.0.dev1"
|
|
4
|
+
description = """A library of utilites for immutable scientific data."""
|
|
5
|
+
authors = [{name="Noah C. Benson", email="nben@uw.edu"}]
|
|
6
|
+
license = {"text"="MIT"}
|
|
7
|
+
readme = "README.md"
|
|
8
|
+
requires-python = ">=3.8"
|
|
9
|
+
keywords = ["persistent", "immutable", "functional", "scientific", "workflow"]
|
|
10
|
+
classifiers = [
|
|
11
|
+
'Intended Audience :: Science/Research',
|
|
12
|
+
'Intended Audience :: Developers',
|
|
13
|
+
'License :: OSI Approved :: MIT License',
|
|
14
|
+
'Programming Language :: Python :: 3',
|
|
15
|
+
'Programming Language :: Python :: 3.8',
|
|
16
|
+
'Programming Language :: Python :: 3.9',
|
|
17
|
+
'Programming Language :: Python :: 3.10',
|
|
18
|
+
'Programming Language :: Python :: 3.11',
|
|
19
|
+
'Topic :: Software Development',
|
|
20
|
+
'Topic :: Software Development :: Libraries',
|
|
21
|
+
'Topic :: Software Development :: Libraries :: Python Modules',
|
|
22
|
+
'Topic :: Scientific/Engineering',
|
|
23
|
+
'Topic :: Scientific/Engineering :: Information Analysis',
|
|
24
|
+
'Operating System :: Microsoft :: Windows',
|
|
25
|
+
'Operating System :: POSIX',
|
|
26
|
+
'Operating System :: Unix',
|
|
27
|
+
'Operating System :: MacOS']
|
|
28
|
+
dependencies = [
|
|
29
|
+
'pcollections >= 0.2.7',
|
|
30
|
+
'numpy >= 1.24.0',
|
|
31
|
+
'scipy >= 1.7.0',
|
|
32
|
+
'pint >= 0.18.0',
|
|
33
|
+
'docrep >= 0.3.2',
|
|
34
|
+
'joblib >= 1.3.0',
|
|
35
|
+
'cloudpathlib[s3,gs,azure] >= 0.18.0']
|
|
36
|
+
|
|
37
|
+
[project.optional-dependencies]
|
|
38
|
+
dev = ["torch >= 2.2.0", "pyyaml"]
|
|
39
|
+
test = ["torch >= 2.2.0", "pyyaml"]
|
|
40
|
+
|
|
41
|
+
[project.urls]
|
|
42
|
+
homepage = "https://github.com/noahbenson/immlib"
|
|
43
|
+
documentation = "https://github.com/noahbenson/immlib"
|
|
44
|
+
repository = "https://github.com/noahbenson/immlib"
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
################################################################################
|
|
3
|
+
# immlib/__init__.py
|
|
4
|
+
|
|
5
|
+
'''`immlib` is a library of tools for manipulating immutable scientific data.
|
|
6
|
+
|
|
7
|
+
The `immlib` library is designed to enable immutable data structures and lazy
|
|
8
|
+
computation in a scientific context, and it works primarily via a collection of
|
|
9
|
+
utility functions and through the use of decorators, which are generally applied
|
|
10
|
+
to classes and their members to declare how an immutable data-structure's
|
|
11
|
+
members are related. Taken together, these utilities form a DSL-like system for
|
|
12
|
+
declaring workflows and immutable data-structures with full inheritance support.
|
|
13
|
+
'''
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
# Imports ######################################################################
|
|
17
|
+
|
|
18
|
+
from .doc import *
|
|
19
|
+
from .util import *
|
|
20
|
+
from .pathlib import *
|
|
21
|
+
from .iolib import *
|
|
22
|
+
from .workflow import *
|
|
23
|
+
# We want the version object from the ._version namespace.
|
|
24
|
+
from ._version import version
|
|
25
|
+
# Import the Global UnitRegistry object to the global immlib scope. This is the
|
|
26
|
+
# value that gets updated when one runs `immlib.default_ureg()`, and this is the
|
|
27
|
+
# UnitRegistry that is used as the default registry for all `immlib` functions.
|
|
28
|
+
from .util._quantity import _initial_global_ureg as units
|
|
29
|
+
"""UnitRegistry: the registry for units tracked by immlib.
|
|
30
|
+
|
|
31
|
+
`immlib.units` is a global `pint`-module unit registry that can be used as a
|
|
32
|
+
single global place for tracking units. Immlib functions that interact with
|
|
33
|
+
units generally take an argument `ureg` that can be used to modify this
|
|
34
|
+
registry. Additionally, the default registry (this object, `immlib.units`) can
|
|
35
|
+
be temporarily changed in a local block using `with immlib.default_ureg(ureg):
|
|
36
|
+
...`.
|
|
37
|
+
"""
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
# Modules/Reloading ############################################################
|
|
41
|
+
|
|
42
|
+
submodules = (
|
|
43
|
+
'immlib.doc._core',
|
|
44
|
+
'immlib.doc',
|
|
45
|
+
'immlib.util._core',
|
|
46
|
+
'immlib.util._numeric',
|
|
47
|
+
'immlib.util._quantity',
|
|
48
|
+
'immlib.util',
|
|
49
|
+
'immlib.pathlib._osf',
|
|
50
|
+
'immlib.pathlib._cache',
|
|
51
|
+
'immlib.pathlib._core',
|
|
52
|
+
'immlib.pathlib',
|
|
53
|
+
'immlib.iolib._core',
|
|
54
|
+
'immlib.iolib',
|
|
55
|
+
'immlib.workflow._core',
|
|
56
|
+
'immlib.workflow._plantype',
|
|
57
|
+
'immlib.workflow',
|
|
58
|
+
'immlib._version')
|
|
59
|
+
"""tuple: a list of all immlib subpackage names in load-order.
|
|
60
|
+
|
|
61
|
+
`immlib.submodules` is a tuple of strings, each of which is the name of one of
|
|
62
|
+
the sub-submodules in `immlib`. The modules are listed in load-order and all
|
|
63
|
+
`immlib` submodules are included.
|
|
64
|
+
"""
|
|
65
|
+
def reload_immlib():
|
|
66
|
+
"""Reload and return the entire `immlib` package.
|
|
67
|
+
|
|
68
|
+
`immlib.reload_immlib()` reloads every submodule in the `immlib` package
|
|
69
|
+
then reloads `immlib` itself, and returns the reloaded package.
|
|
70
|
+
|
|
71
|
+
This function exists primarily for debugging purposes; its use is not
|
|
72
|
+
generally needed or advised.
|
|
73
|
+
"""
|
|
74
|
+
import sys, importlib
|
|
75
|
+
for mod in submodules:
|
|
76
|
+
importlib.reload(sys.modules[mod])
|
|
77
|
+
return importlib.reload(sys.modules['immlib'])
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
# Package Meta-Code ############################################################
|
|
81
|
+
|
|
82
|
+
__version__ = version.string
|
|
83
|
+
__all__ = tuple(
|
|
84
|
+
[k for k in locals()
|
|
85
|
+
if k[0] != '_'
|
|
86
|
+
if k != 'reload_immlib'
|
|
87
|
+
if k != 'submodules'
|
|
88
|
+
if ('immlib.' + k) not in submodules])
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
################################################################################
|
|
3
|
+
# immlib/_version.py
|
|
4
|
+
#
|
|
5
|
+
# Loads the version and splits it into meaningful pieces.
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
import os, re
|
|
9
|
+
from collections import namedtuple
|
|
10
|
+
|
|
11
|
+
try:
|
|
12
|
+
from importlib.metadata import version as get_version
|
|
13
|
+
from importlib.metadata import PackageNotFoundError
|
|
14
|
+
except ModuleNotFoundError:
|
|
15
|
+
try:
|
|
16
|
+
from importlib_metadata import version as get_version
|
|
17
|
+
from importlib_metadata import PackageNotFoundError
|
|
18
|
+
except ModuleNotFoundError:
|
|
19
|
+
pass
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
# ImmLibVersion Type ###########################################################
|
|
23
|
+
|
|
24
|
+
_ImmLibVersionBase = namedtuple(
|
|
25
|
+
'_ImmLibVersionBase',
|
|
26
|
+
['string', 'major', 'minor', 'micro', 'stage', 'tuple'])
|
|
27
|
+
class ImmLibVersion(_ImmLibVersionBase):
|
|
28
|
+
"""The type that manages the version information for the immlib package."""
|
|
29
|
+
__slots__ = ()
|
|
30
|
+
def __new__(cls, string=None):
|
|
31
|
+
if string is None:
|
|
32
|
+
# Try to deduce the version string.
|
|
33
|
+
try:
|
|
34
|
+
string = get_version(__package__)
|
|
35
|
+
except PackageNotFoundError:
|
|
36
|
+
# Probably immlib isn't installed via pip or poetry so it
|
|
37
|
+
# doesn't show up as a registered module. As a backup, we can
|
|
38
|
+
# grab it from the pyproject.toml file.
|
|
39
|
+
base_path = os.path.join(os.path.split(__file__)[0], '..', '..')
|
|
40
|
+
pyproject_toml_path = os.path.join(base_path, 'pyproject.toml')
|
|
41
|
+
with open(pyproject_toml_path, 'r') as fl:
|
|
42
|
+
pyproject_toml_lines = fl.read().split('\n')
|
|
43
|
+
for ln in pyproject_toml_lines:
|
|
44
|
+
ln = ln.strip()
|
|
45
|
+
if ln.startswith('version = '):
|
|
46
|
+
string = ln.split('"')[1]
|
|
47
|
+
break
|
|
48
|
+
if string is None:
|
|
49
|
+
from warnings import warn
|
|
50
|
+
warn("immlib could not detect its version number")
|
|
51
|
+
(major, minor, micro, stage) = (None, None, None, None)
|
|
52
|
+
else:
|
|
53
|
+
s = string
|
|
54
|
+
ss = s.split('.')
|
|
55
|
+
if len(ss) == 4:
|
|
56
|
+
(major, minor, micro, stage) = ss
|
|
57
|
+
else:
|
|
58
|
+
if len(ss) == 3:
|
|
59
|
+
(major, minor, micro) = ss
|
|
60
|
+
elif len(ss) == 2:
|
|
61
|
+
(major, minor) = ss
|
|
62
|
+
micro = '0'
|
|
63
|
+
stage = None
|
|
64
|
+
for tag in ('rc', 'a', 'b'):
|
|
65
|
+
if tag in micro:
|
|
66
|
+
(micro, stage) = micro.split(tag)
|
|
67
|
+
stage = tag + stage
|
|
68
|
+
break
|
|
69
|
+
major = int(major)
|
|
70
|
+
minor = int(minor)
|
|
71
|
+
micro = int(micro)
|
|
72
|
+
tup = tuple(u for u in (major, minor, micro, stage) if u is not None)
|
|
73
|
+
return super(ImmLibVersion, cls).__new__(
|
|
74
|
+
cls,
|
|
75
|
+
string=string,
|
|
76
|
+
major=major, minor=minor, micro=micro,
|
|
77
|
+
stage=stage,
|
|
78
|
+
tuple=tup)
|
|
79
|
+
def __str__(self):
|
|
80
|
+
return self.string
|
|
81
|
+
def __repr__(self):
|
|
82
|
+
return f"ImmLibVersion({repr(self.string)})"
|
|
83
|
+
def __iter__(self):
|
|
84
|
+
return iter(self.tuple)
|
|
85
|
+
def __reversed__(self):
|
|
86
|
+
return reversed(self.tuple)
|
|
87
|
+
def __contains__(self, k):
|
|
88
|
+
if isinstance(k, str):
|
|
89
|
+
return k in self.string
|
|
90
|
+
else:
|
|
91
|
+
return k in self.tuple
|
|
92
|
+
|
|
93
|
+
# Declare the version object; this will automatically detect the version.
|
|
94
|
+
version = ImmLibVersion()
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
################################################################################
|
|
3
|
+
# immlib/doc/__init__.py
|
|
4
|
+
|
|
5
|
+
"""Documentation tools that operate via decorators.
|
|
6
|
+
|
|
7
|
+
The module `immlib.doc` primarily contains a decorator, `docwrap`, which can be
|
|
8
|
+
used to parse the inputs, outputs, parameters, and return values in a function's
|
|
9
|
+
docstring and to save them in a global cache of all such docstring
|
|
10
|
+
components. These components can then be referenced in the docstring of another
|
|
11
|
+
function decorated with `@docwrap` such that the text needn't be repeated in
|
|
12
|
+
every related function.
|
|
13
|
+
"""
|
|
14
|
+
|
|
15
|
+
from ._core import (docwrap, docproc, make_docproc)
|
|
16
|
+
|
|
17
|
+
# For each of the above we transfer it to this (non-private) subpackage.
|
|
18
|
+
docwrap.__module__ = __name__
|
|
19
|
+
docproc.__module__ = __name__
|
|
20
|
+
make_docproc.__module__ = __name__
|
|
21
|
+
|
|
22
|
+
__all__ = ("docwrap", "docproc")
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
################################################################################
|
|
3
|
+
# immlib/doc/_core.py
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
# Dependencies #################################################################
|
|
7
|
+
|
|
8
|
+
from re import compile as _re_compile
|
|
9
|
+
from functools import wraps as _wraps
|
|
10
|
+
from docrep import DocstringProcessor as _DocstringProcessor
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
# The Document Processor #######################################################
|
|
14
|
+
def make_docproc():
|
|
15
|
+
"""Creates and returns a document preprocessor."""
|
|
16
|
+
docproc = _DocstringProcessor()
|
|
17
|
+
# We need to add a few features to the docproc's members so that we can
|
|
18
|
+
# process the Inputs and Outputs sections when present.
|
|
19
|
+
docproc.param_like_sections = \
|
|
20
|
+
docproc.param_like_sections + ['Inputs','Outputs']
|
|
21
|
+
docproc.patterns['Inputs'] = _re_compile(
|
|
22
|
+
docproc.patterns['Parameters'].pattern
|
|
23
|
+
.replace('Parameters', 'Inputs')
|
|
24
|
+
.replace('----------', '------'))
|
|
25
|
+
docproc.patterns['Outputs'] = _re_compile(
|
|
26
|
+
docproc.patterns['Parameters'].pattern
|
|
27
|
+
.replace('Parameters', 'Outputs')
|
|
28
|
+
.replace('----------', '-------'))
|
|
29
|
+
return docproc
|
|
30
|
+
docproc = make_docproc()
|
|
31
|
+
"""The `docrep.DocstringProcessor` object used by `immlib`.
|
|
32
|
+
|
|
33
|
+
This object is used to process all of the doc-strings in the `immlib` library;
|
|
34
|
+
it should be used only with the `immlib.docwrap` decorator, which can safely be
|
|
35
|
+
applied anywhere in a sequence of decorators and which correctly applies the
|
|
36
|
+
`wraps` decorator to its argument. Function documentation is always processed
|
|
37
|
+
using the `sections=('Parameters', 'Returns', 'Raises', 'Examples', 'Inputs',
|
|
38
|
+
'Outputs')` parameter and the `with_indent(4)` decorator. The base-name for the
|
|
39
|
+
function `f` is `f.__module__ + '.' + f.__name__`.
|
|
40
|
+
"""
|
|
41
|
+
|
|
42
|
+
# The docwrap Decorator ########################################################
|
|
43
|
+
def _docwrap_helper(f, fnname, indent=None, proc=docproc):
|
|
44
|
+
# If no ident number was provided, deduce it.
|
|
45
|
+
if indent is None:
|
|
46
|
+
if not hasattr(f, '__doc__') or f.__doc__ is None:
|
|
47
|
+
# Doesn't matter, no documentation.
|
|
48
|
+
indent = 0
|
|
49
|
+
else:
|
|
50
|
+
lines = f.__doc__.split('\n')
|
|
51
|
+
# We always skip the first line (the one that starts with """).
|
|
52
|
+
lines = lines[1:]
|
|
53
|
+
# Strip the lines.
|
|
54
|
+
striplines = [s.lstrip() for s in lines]
|
|
55
|
+
# Pick out the ones with text in them and calculate the indentation.
|
|
56
|
+
indents = [
|
|
57
|
+
len(ws_s) - len(s)
|
|
58
|
+
for (ws_s,s) in zip(lines, striplines)
|
|
59
|
+
if len(s) > 0]
|
|
60
|
+
# The minimum is the one we want.
|
|
61
|
+
indent = min(indents) if len(indents) > 0 else 0
|
|
62
|
+
ff = f
|
|
63
|
+
ff = proc.with_indent(indent)(ff)
|
|
64
|
+
fd = proc.get_sections(base=fnname, sections=proc.param_like_sections)
|
|
65
|
+
ff = fd(ff)
|
|
66
|
+
ff = _wraps(f)(ff)
|
|
67
|
+
# Post-process the documentation sections.
|
|
68
|
+
for section in ['parameters', 'other_parameters', 'inputs', 'outputs']:
|
|
69
|
+
k = fnname + '.' + section
|
|
70
|
+
v = proc.params.get(k, '')
|
|
71
|
+
if len(v) == 0: continue
|
|
72
|
+
for ln in v.split('\n'):
|
|
73
|
+
# Skip lines that start with whitespace.
|
|
74
|
+
if ln[0].strip() == '': continue
|
|
75
|
+
pname = ln.split(':')[0].strip()
|
|
76
|
+
proc.keep_params(k, pname)
|
|
77
|
+
return ff
|
|
78
|
+
def docwrap(f=None, indent=None, proc=docproc):
|
|
79
|
+
"""Applies standard doc-string processing to the decorated function.
|
|
80
|
+
|
|
81
|
+
The `immlib.docwrap` decorator applies a standard set of pre-processing to
|
|
82
|
+
the docstring of the function that follows it. This processing amounts to
|
|
83
|
+
using the `docrep` module's `DocstringProcessor` as a filter on the
|
|
84
|
+
documentation of the function. The function's documentation is always placed
|
|
85
|
+
in the base-name equal to its fully-qualified namespace name.
|
|
86
|
+
|
|
87
|
+
When called as `@docwrap(name)` for a string `name`, the documentation for
|
|
88
|
+
the decorated function is instead placed under the base-name `name`.
|
|
89
|
+
"""
|
|
90
|
+
# If we've been given a string, then we've been called as @docwrap(name)
|
|
91
|
+
# instead of @docwrap.
|
|
92
|
+
if f is None:
|
|
93
|
+
return lambda fn: _docwrap_helper(
|
|
94
|
+
fn, fn.__module__ + '.' + fn.__name__,
|
|
95
|
+
indent=indent,
|
|
96
|
+
proc=proc)
|
|
97
|
+
if isinstance(f, str):
|
|
98
|
+
return lambda fn: _docwrap_helper(fn, f, indent=indent, proc=proc)
|
|
99
|
+
else:
|
|
100
|
+
return _docwrap_helper(
|
|
101
|
+
f, f.__module__ + '.' + f.__name__,
|
|
102
|
+
indent=indent,
|
|
103
|
+
proc=proc)
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
################################################################################
|
|
3
|
+
# pimms/iolib/__init__.py
|
|
4
|
+
|
|
5
|
+
"""Input/output tools managed by pimms; primarily the save and load functions.
|
|
6
|
+
|
|
7
|
+
The `pimms.iolib` module contains tools for saving and loading data to/from
|
|
8
|
+
paths or streams. This functionality is primarily supported via the `save` and
|
|
9
|
+
`load` objects that behave as general (de)serializers to which formats can be
|
|
10
|
+
registered.
|
|
11
|
+
"""
|
|
12
|
+
|
|
13
|
+
from ._core import (
|
|
14
|
+
Save,
|
|
15
|
+
save,
|
|
16
|
+
Load,
|
|
17
|
+
load,
|
|
18
|
+
)
|
|
19
|
+
|
|
20
|
+
__all__ = (
|
|
21
|
+
'Save',
|
|
22
|
+
'save',
|
|
23
|
+
'Load',
|
|
24
|
+
'load',
|
|
25
|
+
)
|
|
26
|
+
|
|
27
|
+
# Mark these as native to this module.
|
|
28
|
+
Save.__module__ = __name__
|
|
29
|
+
save.__module__ = __name__
|
|
30
|
+
Load.__module__ = __name__
|
|
31
|
+
load.__module__ = __name__
|