iker-python-common 1.0.56__tar.gz → 1.0.58__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.
- {iker_python_common-1.0.56 → iker_python_common-1.0.58}/.github/workflows/pr.yml +1 -1
- {iker_python_common-1.0.56 → iker_python_common-1.0.58}/.github/workflows/push.yml +1 -1
- {iker_python_common-1.0.56 → iker_python_common-1.0.58}/PKG-INFO +5 -7
- {iker_python_common-1.0.56 → iker_python_common-1.0.58}/README.md +1 -1
- {iker_python_common-1.0.56 → iker_python_common-1.0.58}/pyproject.toml +8 -12
- {iker_python_common-1.0.56 → iker_python_common-1.0.58}/src/iker/common/utils/funcutils.py +14 -21
- {iker_python_common-1.0.56 → iker_python_common-1.0.58}/src/iker/common/utils/jsonutils.py +11 -19
- {iker_python_common-1.0.56 → iker_python_common-1.0.58}/src/iker/common/utils/numutils.py +10 -18
- {iker_python_common-1.0.56 → iker_python_common-1.0.58}/src/iker/common/utils/randutils.py +16 -14
- {iker_python_common-1.0.56 → iker_python_common-1.0.58}/src/iker/common/utils/sequtils.py +95 -105
- {iker_python_common-1.0.56 → iker_python_common-1.0.58}/src/iker/common/utils/span.py +3 -6
- {iker_python_common-1.0.56 → iker_python_common-1.0.58}/src/iker_python_common.egg-info/PKG-INFO +5 -7
- {iker_python_common-1.0.56 → iker_python_common-1.0.58}/src/iker_python_common.egg-info/requires.txt +2 -6
- {iker_python_common-1.0.56 → iker_python_common-1.0.58}/test/iker_tests/common/utils/sequtils_test.py +1 -1
- {iker_python_common-1.0.56 → iker_python_common-1.0.58}/.editorconfig +0 -0
- {iker_python_common-1.0.56 → iker_python_common-1.0.58}/.gitignore +0 -0
- {iker_python_common-1.0.56 → iker_python_common-1.0.58}/MANIFEST.in +0 -0
- {iker_python_common-1.0.56 → iker_python_common-1.0.58}/VERSION +0 -0
- {iker_python_common-1.0.56 → iker_python_common-1.0.58}/resources/unittest/config/config.cfg +0 -0
- {iker_python_common-1.0.56 → iker_python_common-1.0.58}/resources/unittest/csv/data.csv +0 -0
- {iker_python_common-1.0.56 → iker_python_common-1.0.58}/resources/unittest/csv/data.tsv +0 -0
- {iker_python_common-1.0.56 → iker_python_common-1.0.58}/resources/unittest/s3utils/dir.baz/file.bar.baz +0 -0
- {iker_python_common-1.0.56 → iker_python_common-1.0.58}/resources/unittest/s3utils/dir.baz/file.foo.bar +0 -0
- {iker_python_common-1.0.56 → iker_python_common-1.0.58}/resources/unittest/s3utils/dir.baz/file.foo.baz +0 -0
- {iker_python_common-1.0.56 → iker_python_common-1.0.58}/resources/unittest/s3utils/dir.foo/dir.foo.bar/dir.foo.bar.baz/file.foo.bar.baz +0 -0
- {iker_python_common-1.0.56 → iker_python_common-1.0.58}/resources/unittest/s3utils/dir.foo/dir.foo.bar/file.bar.baz +0 -0
- {iker_python_common-1.0.56 → iker_python_common-1.0.58}/resources/unittest/s3utils/dir.foo/dir.foo.bar/file.foo.bar +0 -0
- {iker_python_common-1.0.56 → iker_python_common-1.0.58}/resources/unittest/s3utils/dir.foo/dir.foo.bar/file.foo.baz +0 -0
- {iker_python_common-1.0.56 → iker_python_common-1.0.58}/resources/unittest/s3utils/dir.foo/file.bar +0 -0
- {iker_python_common-1.0.56 → iker_python_common-1.0.58}/resources/unittest/s3utils/dir.foo/file.baz +0 -0
- {iker_python_common-1.0.56 → iker_python_common-1.0.58}/resources/unittest/s3utils/dir.foo/file.foo +0 -0
- {iker_python_common-1.0.56 → iker_python_common-1.0.58}/resources/unittest/shutils/dir.baz/file.bar.baz +0 -0
- {iker_python_common-1.0.56 → iker_python_common-1.0.58}/resources/unittest/shutils/dir.baz/file.foo.bar +0 -0
- {iker_python_common-1.0.56 → iker_python_common-1.0.58}/resources/unittest/shutils/dir.baz/file.foo.baz +0 -0
- {iker_python_common-1.0.56 → iker_python_common-1.0.58}/resources/unittest/shutils/dir.foo/dir.foo.bar/dir.foo.bar.baz/file.foo.bar.baz +0 -0
- {iker_python_common-1.0.56 → iker_python_common-1.0.58}/resources/unittest/shutils/dir.foo/dir.foo.bar/file.bar.baz +0 -0
- {iker_python_common-1.0.56 → iker_python_common-1.0.58}/resources/unittest/shutils/dir.foo/dir.foo.bar/file.foo.bar +0 -0
- {iker_python_common-1.0.56 → iker_python_common-1.0.58}/resources/unittest/shutils/dir.foo/dir.foo.bar/file.foo.baz +0 -0
- {iker_python_common-1.0.56 → iker_python_common-1.0.58}/resources/unittest/shutils/dir.foo/file.bar +0 -0
- {iker_python_common-1.0.56 → iker_python_common-1.0.58}/resources/unittest/shutils/dir.foo/file.baz +0 -0
- {iker_python_common-1.0.56 → iker_python_common-1.0.58}/resources/unittest/shutils/dir.foo/file.foo +0 -0
- {iker_python_common-1.0.56 → iker_python_common-1.0.58}/setup.cfg +0 -0
- {iker_python_common-1.0.56 → iker_python_common-1.0.58}/setup.py +0 -0
- {iker_python_common-1.0.56 → iker_python_common-1.0.58}/src/iker/common/__init__.py +0 -0
- {iker_python_common-1.0.56 → iker_python_common-1.0.58}/src/iker/common/utils/__init__.py +0 -0
- {iker_python_common-1.0.56 → iker_python_common-1.0.58}/src/iker/common/utils/argutils.py +0 -0
- {iker_python_common-1.0.56 → iker_python_common-1.0.58}/src/iker/common/utils/config.py +0 -0
- {iker_python_common-1.0.56 → iker_python_common-1.0.58}/src/iker/common/utils/csv.py +0 -0
- {iker_python_common-1.0.56 → iker_python_common-1.0.58}/src/iker/common/utils/dbutils.py +0 -0
- {iker_python_common-1.0.56 → iker_python_common-1.0.58}/src/iker/common/utils/dockerutils.py +0 -0
- {iker_python_common-1.0.56 → iker_python_common-1.0.58}/src/iker/common/utils/dtutils.py +0 -0
- {iker_python_common-1.0.56 → iker_python_common-1.0.58}/src/iker/common/utils/logger.py +0 -0
- {iker_python_common-1.0.56 → iker_python_common-1.0.58}/src/iker/common/utils/retry.py +0 -0
- {iker_python_common-1.0.56 → iker_python_common-1.0.58}/src/iker/common/utils/s3utils.py +0 -0
- {iker_python_common-1.0.56 → iker_python_common-1.0.58}/src/iker/common/utils/shutils.py +0 -0
- {iker_python_common-1.0.56 → iker_python_common-1.0.58}/src/iker/common/utils/strutils.py +0 -0
- {iker_python_common-1.0.56 → iker_python_common-1.0.58}/src/iker/common/utils/testutils.py +0 -0
- {iker_python_common-1.0.56 → iker_python_common-1.0.58}/src/iker/common/utils/typeutils.py +0 -0
- {iker_python_common-1.0.56 → iker_python_common-1.0.58}/src/iker_python_common.egg-info/SOURCES.txt +0 -0
- {iker_python_common-1.0.56 → iker_python_common-1.0.58}/src/iker_python_common.egg-info/dependency_links.txt +0 -0
- {iker_python_common-1.0.56 → iker_python_common-1.0.58}/src/iker_python_common.egg-info/not-zip-safe +0 -0
- {iker_python_common-1.0.56 → iker_python_common-1.0.58}/src/iker_python_common.egg-info/top_level.txt +0 -0
- {iker_python_common-1.0.56 → iker_python_common-1.0.58}/test/iker_test.py +0 -0
- {iker_python_common-1.0.56 → iker_python_common-1.0.58}/test/iker_tests/__init__.py +0 -0
- {iker_python_common-1.0.56 → iker_python_common-1.0.58}/test/iker_tests/common/utils/argutils_test.py +0 -0
- {iker_python_common-1.0.56 → iker_python_common-1.0.58}/test/iker_tests/common/utils/config_test.py +0 -0
- {iker_python_common-1.0.56 → iker_python_common-1.0.58}/test/iker_tests/common/utils/csv_test.py +0 -0
- {iker_python_common-1.0.56 → iker_python_common-1.0.58}/test/iker_tests/common/utils/dbutils_test.py +0 -0
- {iker_python_common-1.0.56 → iker_python_common-1.0.58}/test/iker_tests/common/utils/dockerutils_test.py +0 -0
- {iker_python_common-1.0.56 → iker_python_common-1.0.58}/test/iker_tests/common/utils/dtutils_test.py +0 -0
- {iker_python_common-1.0.56 → iker_python_common-1.0.58}/test/iker_tests/common/utils/funcutils_test.py +0 -0
- {iker_python_common-1.0.56 → iker_python_common-1.0.58}/test/iker_tests/common/utils/jsonutils_test.py +0 -0
- {iker_python_common-1.0.56 → iker_python_common-1.0.58}/test/iker_tests/common/utils/logger_test.py +0 -0
- {iker_python_common-1.0.56 → iker_python_common-1.0.58}/test/iker_tests/common/utils/numutils_test.py +0 -0
- {iker_python_common-1.0.56 → iker_python_common-1.0.58}/test/iker_tests/common/utils/randutils_test.py +0 -0
- {iker_python_common-1.0.56 → iker_python_common-1.0.58}/test/iker_tests/common/utils/retry_test.py +0 -0
- {iker_python_common-1.0.56 → iker_python_common-1.0.58}/test/iker_tests/common/utils/s3utils_test.py +0 -0
- {iker_python_common-1.0.56 → iker_python_common-1.0.58}/test/iker_tests/common/utils/shutils_test.py +0 -0
- {iker_python_common-1.0.56 → iker_python_common-1.0.58}/test/iker_tests/common/utils/span_test.py +0 -0
- {iker_python_common-1.0.56 → iker_python_common-1.0.58}/test/iker_tests/common/utils/strutils_test.py +0 -0
- {iker_python_common-1.0.56 → iker_python_common-1.0.58}/test/iker_tests/common/utils/testutils_test.py +0 -0
- {iker_python_common-1.0.56 → iker_python_common-1.0.58}/test/iker_tests/common/utils/typeutils_test.py +0 -0
- {iker_python_common-1.0.56 → iker_python_common-1.0.58}/test/iker_tests/docker_fixtures.py +0 -0
|
@@ -1,18 +1,17 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: iker-python-common
|
|
3
|
-
Version: 1.0.
|
|
3
|
+
Version: 1.0.58
|
|
4
4
|
Classifier: Programming Language :: Python :: 3
|
|
5
|
-
Classifier: Programming Language :: Python :: 3.11
|
|
6
5
|
Classifier: Programming Language :: Python :: 3.12
|
|
7
6
|
Classifier: Programming Language :: Python :: 3.13
|
|
8
|
-
|
|
7
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
8
|
+
Requires-Python: <3.15,>=3.12
|
|
9
9
|
Requires-Dist: boto3>=1.35
|
|
10
10
|
Requires-Dist: docker>=7.1
|
|
11
|
-
Requires-Dist: numpy>=
|
|
11
|
+
Requires-Dist: numpy>=2.3
|
|
12
12
|
Requires-Dist: psycopg>=3.2
|
|
13
13
|
Requires-Dist: pymysql>=1.1
|
|
14
|
-
Requires-Dist: sqlalchemy>=
|
|
15
|
-
Requires-Dist: typing-extensions; python_version < "3.12"
|
|
14
|
+
Requires-Dist: sqlalchemy>=2.0
|
|
16
15
|
Provides-Extra: all
|
|
17
16
|
Requires-Dist: iker-python-common; extra == "all"
|
|
18
17
|
Provides-Extra: test
|
|
@@ -23,4 +22,3 @@ Requires-Dist: pytest-mysql>=3.0; extra == "test"
|
|
|
23
22
|
Requires-Dist: pytest-order>=1.3; extra == "test"
|
|
24
23
|
Requires-Dist: pytest-postgresql>=6.1; extra == "test"
|
|
25
24
|
Requires-Dist: pytest>=8.3; extra == "test"
|
|
26
|
-
Requires-Dist: sqlalchemy>=2.0; extra == "test"
|
|
@@ -13,7 +13,7 @@ the [official site](https://www.anaconda.com/products/distribution)
|
|
|
13
13
|
Create a Conda environment and install the modules and their dependencies in it
|
|
14
14
|
|
|
15
15
|
```shell
|
|
16
|
-
conda create -n iker python=3.
|
|
16
|
+
conda create -n iker python=3.14
|
|
17
17
|
conda activate iker
|
|
18
18
|
|
|
19
19
|
pip install .
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
[build-system]
|
|
2
2
|
requires = [
|
|
3
|
-
"setuptools>=
|
|
4
|
-
"setuptools-scm>=
|
|
3
|
+
"setuptools>=80.0",
|
|
4
|
+
"setuptools-scm>=9.0",
|
|
5
5
|
"iker-python-setup>=1.0",
|
|
6
6
|
]
|
|
7
7
|
build-backend = "setuptools.build_meta"
|
|
@@ -10,11 +10,10 @@ build-backend = "setuptools.build_meta"
|
|
|
10
10
|
dev = [
|
|
11
11
|
"boto3>=1.35",
|
|
12
12
|
"docker>=7.1",
|
|
13
|
-
"numpy>=
|
|
13
|
+
"numpy>=2.3",
|
|
14
14
|
"psycopg>=3.2",
|
|
15
15
|
"pymysql>=1.1",
|
|
16
|
-
"sqlalchemy>=
|
|
17
|
-
"typing-extensions; python_version<'3.12'"
|
|
16
|
+
"sqlalchemy>=2.0",
|
|
18
17
|
]
|
|
19
18
|
test = [
|
|
20
19
|
"ddt>=1.7",
|
|
@@ -24,27 +23,25 @@ test = [
|
|
|
24
23
|
"pytest-order>=1.3",
|
|
25
24
|
"pytest-postgresql>=6.1",
|
|
26
25
|
"pytest>=8.3",
|
|
27
|
-
"sqlalchemy>=2.0",
|
|
28
26
|
]
|
|
29
27
|
|
|
30
28
|
[project]
|
|
31
29
|
name = "iker-python-common"
|
|
32
30
|
dynamic = ["version"]
|
|
33
|
-
requires-python = ">=3.
|
|
31
|
+
requires-python = ">=3.12,<3.15"
|
|
34
32
|
classifiers = [
|
|
35
33
|
"Programming Language :: Python :: 3",
|
|
36
|
-
"Programming Language :: Python :: 3.11",
|
|
37
34
|
"Programming Language :: Python :: 3.12",
|
|
38
35
|
"Programming Language :: Python :: 3.13",
|
|
36
|
+
"Programming Language :: Python :: 3.14",
|
|
39
37
|
]
|
|
40
38
|
dependencies = [
|
|
41
39
|
"boto3>=1.35",
|
|
42
40
|
"docker>=7.1",
|
|
43
|
-
"numpy>=
|
|
41
|
+
"numpy>=2.3",
|
|
44
42
|
"psycopg>=3.2",
|
|
45
43
|
"pymysql>=1.1",
|
|
46
|
-
"sqlalchemy>=
|
|
47
|
-
"typing-extensions; python_version<'3.12'"
|
|
44
|
+
"sqlalchemy>=2.0",
|
|
48
45
|
]
|
|
49
46
|
|
|
50
47
|
[project.optional-dependencies]
|
|
@@ -59,7 +56,6 @@ test = [
|
|
|
59
56
|
"pytest-order>=1.3",
|
|
60
57
|
"pytest-postgresql>=6.1",
|
|
61
58
|
"pytest>=8.3",
|
|
62
|
-
"sqlalchemy>=2.0",
|
|
63
59
|
]
|
|
64
60
|
|
|
65
61
|
[tool.setuptools]
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import functools
|
|
2
2
|
from collections.abc import Callable
|
|
3
|
-
from typing import Protocol
|
|
3
|
+
from typing import Protocol
|
|
4
4
|
|
|
5
5
|
__all__ = [
|
|
6
6
|
"identity",
|
|
@@ -11,12 +11,8 @@ __all__ = [
|
|
|
11
11
|
"unique_returns",
|
|
12
12
|
]
|
|
13
13
|
|
|
14
|
-
T = TypeVar("T")
|
|
15
|
-
U = TypeVar("U")
|
|
16
|
-
RT = TypeVar("RT")
|
|
17
14
|
|
|
18
|
-
|
|
19
|
-
def identity(instance: T) -> T:
|
|
15
|
+
def identity[T](instance: T) -> T:
|
|
20
16
|
"""
|
|
21
17
|
Returns the input ``instance`` unchanged. This is a utility function often used as a default or placeholder.
|
|
22
18
|
|
|
@@ -26,22 +22,19 @@ def identity(instance: T) -> T:
|
|
|
26
22
|
return instance
|
|
27
23
|
|
|
28
24
|
|
|
29
|
-
class Composable
|
|
25
|
+
class Composable[T, R](Protocol):
|
|
30
26
|
"""
|
|
31
27
|
Protocol for composable callables, supporting composition and chaining with other callables.
|
|
32
|
-
|
|
33
|
-
:param x: The input value for the callable.
|
|
34
|
-
:return: The result of the callable.
|
|
35
28
|
"""
|
|
36
29
|
|
|
37
|
-
def __call__(self, x: T) ->
|
|
30
|
+
def __call__(self, x: T) -> R: ...
|
|
38
31
|
|
|
39
|
-
def compose(self, func: "Callable[[U], T] | Composable[U, T]") -> "Composable[U,
|
|
32
|
+
def compose[U](self, func: "Callable[[U], T] | Composable[U, T]") -> "Composable[U, R]": ...
|
|
40
33
|
|
|
41
|
-
def and_then(self, func: "Callable[[
|
|
34
|
+
def and_then[U](self, func: "Callable[[R], U] | Composable[R, U]") -> "Composable[T, U]": ...
|
|
42
35
|
|
|
43
36
|
|
|
44
|
-
def composable(func: Callable[[T],
|
|
37
|
+
def composable[T, R](func: Callable[[T], R]) -> Composable[T, R]:
|
|
45
38
|
"""
|
|
46
39
|
Wraps a function to make it composable, allowing chaining with compose and and_then methods.
|
|
47
40
|
|
|
@@ -49,13 +42,13 @@ def composable(func: Callable[[T], RT]) -> Composable[T, RT]:
|
|
|
49
42
|
:return: A composable version of the function.
|
|
50
43
|
"""
|
|
51
44
|
|
|
52
|
-
def compose(another_func: Callable[[U], T] | Composable[U, T]) -> Composable[U,
|
|
53
|
-
def chained(x: U) ->
|
|
45
|
+
def compose[U](another_func: Callable[[U], T] | Composable[U, T]) -> Composable[U, R]:
|
|
46
|
+
def chained(x: U) -> R:
|
|
54
47
|
return func(another_func(x))
|
|
55
48
|
|
|
56
49
|
return composable(chained)
|
|
57
50
|
|
|
58
|
-
def and_then(another_func: Callable[[
|
|
51
|
+
def and_then[U](another_func: Callable[[R], U] | Composable[R, U]) -> Composable[T, U]:
|
|
59
52
|
def chained(x: T) -> U:
|
|
60
53
|
return another_func(func(x))
|
|
61
54
|
|
|
@@ -66,7 +59,7 @@ def composable(func: Callable[[T], RT]) -> Composable[T, RT]:
|
|
|
66
59
|
return func
|
|
67
60
|
|
|
68
61
|
|
|
69
|
-
def singleton(tar: Callable[...,
|
|
62
|
+
def singleton[R](tar: Callable[..., R] = None):
|
|
70
63
|
"""
|
|
71
64
|
Decorator to ensure a function or class is only instantiated once. Subsequent calls return the same instance.
|
|
72
65
|
|
|
@@ -91,7 +84,7 @@ def singleton(tar: Callable[..., RT] = None):
|
|
|
91
84
|
return decorator if tar is None else decorator(tar)
|
|
92
85
|
|
|
93
86
|
|
|
94
|
-
def memorized(tar: Callable[...,
|
|
87
|
+
def memorized[R](tar: Callable[..., R] = None, *, ordered: bool = False, typed: bool = False):
|
|
95
88
|
"""
|
|
96
89
|
Decorator to cache the results of a function based on its arguments. Supports options for argument order and type.
|
|
97
90
|
|
|
@@ -134,7 +127,7 @@ def memorized(tar: Callable[..., RT] = None, *, ordered: bool = False, typed: bo
|
|
|
134
127
|
return decorator if tar is None else decorator(tar)
|
|
135
128
|
|
|
136
129
|
|
|
137
|
-
def lazy(tar: Callable[...,
|
|
130
|
+
def lazy[R](tar: Callable[..., R] = None):
|
|
138
131
|
"""
|
|
139
132
|
Decorator to defer the execution of a function until its result is explicitly requested.
|
|
140
133
|
|
|
@@ -155,7 +148,7 @@ def lazy(tar: Callable[..., RT] = None):
|
|
|
155
148
|
return decorator if tar is None else decorator(tar)
|
|
156
149
|
|
|
157
150
|
|
|
158
|
-
def unique_returns(tar: Callable[...,
|
|
151
|
+
def unique_returns[R](tar: Callable[..., R] = None, *, max_trials: int | None = None):
|
|
159
152
|
"""
|
|
160
153
|
Decorator to ensure a function produces unique return values. If no unique value is found within max_trials,
|
|
161
154
|
raises an error.
|
|
@@ -1,12 +1,6 @@
|
|
|
1
1
|
import math
|
|
2
|
-
import sys
|
|
3
2
|
from collections.abc import Callable, Mapping, MutableMapping, MutableSequence, Sequence, Set
|
|
4
|
-
from typing import Any, SupportsFloat, SupportsInt
|
|
5
|
-
|
|
6
|
-
if sys.version_info < (3, 12):
|
|
7
|
-
from typing_extensions import TypeAliasType
|
|
8
|
-
else:
|
|
9
|
-
from typing import TypeAliasType
|
|
3
|
+
from typing import Any, SupportsFloat, SupportsInt
|
|
10
4
|
|
|
11
5
|
from iker.common.utils.numutils import is_normal_real
|
|
12
6
|
|
|
@@ -35,28 +29,26 @@ __all__ = [
|
|
|
35
29
|
|
|
36
30
|
JsonKey = str
|
|
37
31
|
JsonValue = str | bool | float | int | None
|
|
38
|
-
JsonObject
|
|
39
|
-
JsonArray
|
|
40
|
-
JsonType
|
|
32
|
+
type JsonObject = dict[JsonKey, JsonType]
|
|
33
|
+
type JsonArray = list[JsonType]
|
|
34
|
+
type JsonType = JsonValue | JsonObject | JsonArray
|
|
35
|
+
|
|
41
36
|
JsonKeyCompatible = str
|
|
42
37
|
JsonValueCompatible = str | bool | SupportsFloat | SupportsInt | None
|
|
43
|
-
JsonObjectCompatible
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
"Sequence[JsonTypeCompatible]")
|
|
47
|
-
JsonTypeCompatible: TypeAlias = TypeAliasType("JsonTypeCompatible",
|
|
48
|
-
"JsonValueCompatible | JsonObjectCompatible | JsonArrayCompatible")
|
|
38
|
+
type JsonObjectCompatible = Mapping[JsonKeyCompatible, JsonTypeCompatible]
|
|
39
|
+
type JsonArrayCompatible = Sequence[JsonTypeCompatible]
|
|
40
|
+
type JsonTypeCompatible = JsonValueCompatible | JsonObjectCompatible | JsonArrayCompatible
|
|
49
41
|
|
|
50
42
|
|
|
51
43
|
class NodeAsterisk(object):
|
|
52
44
|
pass
|
|
53
45
|
|
|
54
46
|
|
|
55
|
-
Node = str | int | NodeAsterisk
|
|
56
|
-
NodePath: TypeAlias = TypeAliasType("NodePath", "list[Node]")
|
|
57
|
-
|
|
58
47
|
asterisk = NodeAsterisk()
|
|
59
48
|
|
|
49
|
+
Node = str | int | NodeAsterisk
|
|
50
|
+
type NodePath = list[Node]
|
|
51
|
+
|
|
60
52
|
|
|
61
53
|
def json_get(
|
|
62
54
|
obj: JsonTypeCompatible,
|
|
@@ -2,7 +2,7 @@ import math
|
|
|
2
2
|
from collections.abc import Callable, Sequence
|
|
3
3
|
from decimal import Decimal
|
|
4
4
|
from numbers import Real
|
|
5
|
-
from typing import Any
|
|
5
|
+
from typing import Any
|
|
6
6
|
|
|
7
7
|
import numpy as np
|
|
8
8
|
|
|
@@ -26,8 +26,6 @@ __all__ = [
|
|
|
26
26
|
"real_nan_std",
|
|
27
27
|
]
|
|
28
28
|
|
|
29
|
-
RealT = TypeVar("RealT", bound=Real)
|
|
30
|
-
|
|
31
29
|
|
|
32
30
|
def to_decimal(x: float | str | None) -> Decimal | None:
|
|
33
31
|
"""
|
|
@@ -72,10 +70,7 @@ def is_normal_real(v: Any) -> bool:
|
|
|
72
70
|
return is_real(v) and not math.isnan(v) and not math.isinf(v)
|
|
73
71
|
|
|
74
72
|
|
|
75
|
-
def make_real_unary(
|
|
76
|
-
op: Callable[[RealT], RealT],
|
|
77
|
-
fb: RealT | None = None,
|
|
78
|
-
) -> Callable[[RealT], RealT | None]:
|
|
73
|
+
def make_real_unary[T: Real](op: Callable[[T], T], fb: T | None = None) -> Callable[[T], T | None]:
|
|
79
74
|
"""
|
|
80
75
|
Creates a unary function that applies the given operation to a real number, returning a fallback if not real.
|
|
81
76
|
|
|
@@ -84,7 +79,7 @@ def make_real_unary(
|
|
|
84
79
|
:return: A function that applies ``op`` to a real number or returns ``fb``.
|
|
85
80
|
"""
|
|
86
81
|
|
|
87
|
-
def func(x:
|
|
82
|
+
def func(x: T) -> T | None:
|
|
88
83
|
if not is_real(x):
|
|
89
84
|
return fb
|
|
90
85
|
return op(x)
|
|
@@ -92,10 +87,7 @@ def make_real_unary(
|
|
|
92
87
|
return func
|
|
93
88
|
|
|
94
89
|
|
|
95
|
-
def make_real_binary(
|
|
96
|
-
op: Callable[[RealT, RealT], RealT],
|
|
97
|
-
fb: RealT | None = None,
|
|
98
|
-
) -> Callable[[RealT, RealT], RealT | None]:
|
|
90
|
+
def make_real_binary[T: Real](op: Callable[[T, T], T], fb: T | None = None) -> Callable[[T, T], T | None]:
|
|
99
91
|
"""
|
|
100
92
|
Creates a binary function that applies the given operation to two real numbers, with fallback logic.
|
|
101
93
|
|
|
@@ -104,7 +96,7 @@ def make_real_binary(
|
|
|
104
96
|
:return: A function that applies ``op`` to two real numbers or returns ``fb``.
|
|
105
97
|
"""
|
|
106
98
|
|
|
107
|
-
def func(a:
|
|
99
|
+
def func(a: T, b: T) -> T | None:
|
|
108
100
|
if not is_real(a) and not is_real(b):
|
|
109
101
|
return fb
|
|
110
102
|
if not is_real(a):
|
|
@@ -116,10 +108,10 @@ def make_real_binary(
|
|
|
116
108
|
return func
|
|
117
109
|
|
|
118
110
|
|
|
119
|
-
def make_real_reducer(
|
|
120
|
-
op: Callable[[Sequence[
|
|
121
|
-
fb:
|
|
122
|
-
) -> Callable[[Sequence[
|
|
111
|
+
def make_real_reducer[T: Real](
|
|
112
|
+
op: Callable[[Sequence[T], ...], T],
|
|
113
|
+
fb: T | None = None,
|
|
114
|
+
) -> Callable[[Sequence[T], ...], T | None]:
|
|
123
115
|
"""
|
|
124
116
|
Creates a reducer function that applies the given operation to a sequence of real numbers, filtering out non-reals.
|
|
125
117
|
|
|
@@ -128,7 +120,7 @@ def make_real_reducer(
|
|
|
128
120
|
:return: A function that reduces a sequence of real numbers or returns ``fb``.
|
|
129
121
|
"""
|
|
130
122
|
|
|
131
|
-
def func(xs: Sequence[
|
|
123
|
+
def func(xs: Sequence[T], *args, **kwargs) -> T | None:
|
|
132
124
|
xs_new = list(filter(is_real, xs))
|
|
133
125
|
return op(xs_new, *args, **kwargs) if len(xs_new) > 0 else fb
|
|
134
126
|
|
|
@@ -4,7 +4,6 @@ import random
|
|
|
4
4
|
import string
|
|
5
5
|
import sys
|
|
6
6
|
from collections.abc import Callable, Sequence
|
|
7
|
-
from typing import TypeVar
|
|
8
7
|
from typing import overload
|
|
9
8
|
|
|
10
9
|
from iker.common.utils.dtutils import dt_utc_max, dt_utc_min
|
|
@@ -19,8 +18,6 @@ __all__ = [
|
|
|
19
18
|
"randomizer",
|
|
20
19
|
]
|
|
21
20
|
|
|
22
|
-
T = TypeVar("T")
|
|
23
|
-
|
|
24
21
|
|
|
25
22
|
@singleton
|
|
26
23
|
def max_int() -> int:
|
|
@@ -268,22 +265,22 @@ class Randomizer(object):
|
|
|
268
265
|
return generate_json_object(0)
|
|
269
266
|
|
|
270
267
|
@overload
|
|
271
|
-
def sample(self, population: Sequence[T], count_func: Callable[[T], int], k: int) -> list[T]:
|
|
268
|
+
def sample[T](self, population: Sequence[T], count_func: Callable[[T], int], k: int) -> list[T]:
|
|
272
269
|
...
|
|
273
270
|
|
|
274
271
|
@overload
|
|
275
|
-
def sample(self, population: Sequence[T], k: int) -> list[T]:
|
|
272
|
+
def sample[T](self, population: Sequence[T], k: int) -> list[T]:
|
|
276
273
|
...
|
|
277
274
|
|
|
278
275
|
@overload
|
|
279
|
-
def sample(self, population: Sequence[T], count_func: Callable[[T], int], k: None = None) -> T:
|
|
276
|
+
def sample[T](self, population: Sequence[T], count_func: Callable[[T], int], k: None = None) -> T:
|
|
280
277
|
...
|
|
281
278
|
|
|
282
279
|
@overload
|
|
283
|
-
def sample(self, population: Sequence[T], k: None = None) -> T:
|
|
280
|
+
def sample[T](self, population: Sequence[T], k: None = None) -> T:
|
|
284
281
|
...
|
|
285
282
|
|
|
286
|
-
def sample(self, population: Sequence[T], count_func: Callable[[T], int] = None, k: int = None) -> list[T] | T:
|
|
283
|
+
def sample[T](self, population: Sequence[T], count_func: Callable[[T], int] = None, k: int = None) -> list[T] | T:
|
|
287
284
|
"""
|
|
288
285
|
Returns a random sample from the population, optionally weighted by a count function.
|
|
289
286
|
|
|
@@ -297,22 +294,27 @@ class Randomizer(object):
|
|
|
297
294
|
return result if k is not None else head_or_none(result)
|
|
298
295
|
|
|
299
296
|
@overload
|
|
300
|
-
def choose(self, population: Sequence[T], weight_func: Callable[[T], float], k: int) -> list[T]:
|
|
297
|
+
def choose[T](self, population: Sequence[T], weight_func: Callable[[T], float], k: int) -> list[T]:
|
|
301
298
|
...
|
|
302
299
|
|
|
303
300
|
@overload
|
|
304
|
-
def choose(self, population: Sequence[T], k: int) -> list[T]:
|
|
301
|
+
def choose[T](self, population: Sequence[T], k: int) -> list[T]:
|
|
305
302
|
...
|
|
306
303
|
|
|
307
304
|
@overload
|
|
308
|
-
def choose(self, population: Sequence[T], weight_func: Callable[[T], float], k: None = None) -> T:
|
|
305
|
+
def choose[T](self, population: Sequence[T], weight_func: Callable[[T], float], k: None = None) -> T:
|
|
309
306
|
...
|
|
310
307
|
|
|
311
308
|
@overload
|
|
312
|
-
def choose(self, population: Sequence[T], k: None = None) -> T:
|
|
309
|
+
def choose[T](self, population: Sequence[T], k: None = None) -> T:
|
|
313
310
|
...
|
|
314
311
|
|
|
315
|
-
def choose
|
|
312
|
+
def choose[T](
|
|
313
|
+
self,
|
|
314
|
+
population: Sequence[T],
|
|
315
|
+
weight_func: Callable[[T], float] = None,
|
|
316
|
+
k: int = None,
|
|
317
|
+
) -> list[T] | T:
|
|
316
318
|
"""
|
|
317
319
|
Returns a random selection from the population, optionally weighted by a weight function.
|
|
318
320
|
|
|
@@ -325,7 +327,7 @@ class Randomizer(object):
|
|
|
325
327
|
result = self.random.choices(population, weights=weights, k=k or 1)
|
|
326
328
|
return result if k is not None else head_or_none(result)
|
|
327
329
|
|
|
328
|
-
def shuffle(self, data: Sequence[T]) -> list[T]:
|
|
330
|
+
def shuffle[T](self, data: Sequence[T]) -> list[T]:
|
|
329
331
|
"""
|
|
330
332
|
Returns a shuffled copy of the input ``data`` sequence.
|
|
331
333
|
|