ipa-python-kit 0.1.3.dev1__tar.gz → 1.0.0__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.
- {ipa_python_kit-0.1.3.dev1 → ipa_python_kit-1.0.0}/PKG-INFO +18 -7
- ipa_python_kit-1.0.0/README.md +55 -0
- {ipa_python_kit-0.1.3.dev1 → ipa_python_kit-1.0.0}/main.py +8 -1
- {ipa_python_kit-0.1.3.dev1 → ipa_python_kit-1.0.0}/main.spec +1 -1
- {ipa_python_kit-0.1.3.dev1 → ipa_python_kit-1.0.0}/pyproject.toml +3 -6
- {ipa_python_kit-0.1.3.dev1 → ipa_python_kit-1.0.0}/ruff.toml +5 -5
- {ipa_python_kit-0.1.3.dev1 → ipa_python_kit-1.0.0}/src/biz/__init__.py +2 -0
- ipa_python_kit-1.0.0/src/ipa/app/__init__.py +57 -0
- {ipa_python_kit-0.1.3.dev1 → ipa_python_kit-1.0.0}/src/ipa/data_type/unitable.py +3 -3
- {ipa_python_kit-0.1.3.dev1 → ipa_python_kit-1.0.0}/src/ipa/datetime/core.py +7 -7
- {ipa_python_kit-0.1.3.dev1 → ipa_python_kit-1.0.0}/src/ipa/func/dict.py +15 -6
- {ipa_python_kit-0.1.3.dev1 → ipa_python_kit-1.0.0}/src/ipa/network/__init__.py +23 -3
- ipa_python_kit-1.0.0/src/ipa/pkg/__init__.py +99 -0
- {ipa_python_kit-0.1.3.dev1 → ipa_python_kit-1.0.0}/src/ipa/pkg/hot_reload.py +4 -2
- {ipa_python_kit-0.1.3.dev1 → ipa_python_kit-1.0.0}/src/ipa/pydantic/core/__init__.py +1 -0
- ipa_python_kit-1.0.0/src/ipa/version.py +24 -0
- {ipa_python_kit-0.1.3.dev1 → ipa_python_kit-1.0.0}/src/ipa/websocket/core/__init__.py +10 -7
- {ipa_python_kit-0.1.3.dev1 → ipa_python_kit-1.0.0}/src/ipa_python_kit.egg-info/PKG-INFO +18 -7
- {ipa_python_kit-0.1.3.dev1 → ipa_python_kit-1.0.0}/src/ipa_python_kit.egg-info/SOURCES.txt +8 -10
- {ipa_python_kit-0.1.3.dev1 → ipa_python_kit-1.0.0}/tests/cli_test.py +2 -1
- {ipa_python_kit-0.1.3.dev1 → ipa_python_kit-1.0.0}/tests/decorator_test.py +1 -0
- {ipa_python_kit-0.1.3.dev1 → ipa_python_kit-1.0.0}/tests/logger_test.py +1 -1
- {ipa_python_kit-0.1.3.dev1 → ipa_python_kit-1.0.0}/tests/point_test.py +1 -0
- {ipa_python_kit-0.1.3.dev1 → ipa_python_kit-1.0.0}/tests/pydantic_test.py +2 -1
- {ipa_python_kit-0.1.3.dev1 → ipa_python_kit-1.0.0}/tests/python_test.py +1 -0
- ipa_python_kit-1.0.0/uv.lock +2875 -0
- ipa_python_kit-0.1.3.dev1/README.md +0 -44
- ipa_python_kit-0.1.3.dev1/src/ipa/extra/simpy/core.py +0 -288
- ipa_python_kit-0.1.3.dev1/src/ipa/func/app.py +0 -12
- ipa_python_kit-0.1.3.dev1/src/ipa/pkg/__init__.py +0 -43
- ipa_python_kit-0.1.3.dev1/src/ipa/version.py +0 -34
- ipa_python_kit-0.1.3.dev1/src/ipa/websocket/__init__.py +0 -1
- ipa_python_kit-0.1.3.dev1/uv.lock +0 -5283
- {ipa_python_kit-0.1.3.dev1 → ipa_python_kit-1.0.0}/.gitignore +0 -0
- {ipa_python_kit-0.1.3.dev1 → ipa_python_kit-1.0.0}/.pre-commit-config.yaml +0 -0
- {ipa_python_kit-0.1.3.dev1 → ipa_python_kit-1.0.0}/.pypirc.example +0 -0
- {ipa_python_kit-0.1.3.dev1 → ipa_python_kit-1.0.0}/.vscode/settings.json +0 -0
- {ipa_python_kit-0.1.3.dev1 → ipa_python_kit-1.0.0}/alembic/README +0 -0
- {ipa_python_kit-0.1.3.dev1 → ipa_python_kit-1.0.0}/alembic/env.py +0 -0
- {ipa_python_kit-0.1.3.dev1 → ipa_python_kit-1.0.0}/alembic/script.py.mako +0 -0
- {ipa_python_kit-0.1.3.dev1 → ipa_python_kit-1.0.0}/alembic/versions/5227325b977d_baseline.py +0 -0
- {ipa_python_kit-0.1.3.dev1 → ipa_python_kit-1.0.0}/alembic.ini +0 -0
- {ipa_python_kit-0.1.3.dev1 → ipa_python_kit-1.0.0}/docs/README.md +0 -0
- {ipa_python_kit-0.1.3.dev1 → ipa_python_kit-1.0.0}/pytest.ini +0 -0
- {ipa_python_kit-0.1.3.dev1 → ipa_python_kit-1.0.0}/scripts/build +0 -0
- {ipa_python_kit-0.1.3.dev1 → ipa_python_kit-1.0.0}/scripts/publish +0 -0
- {ipa_python_kit-0.1.3.dev1 → ipa_python_kit-1.0.0}/scripts/setup +0 -0
- {ipa_python_kit-0.1.3.dev1 → ipa_python_kit-1.0.0}/setup.cfg +0 -0
- {ipa_python_kit-0.1.3.dev1 → ipa_python_kit-1.0.0}/src/conf/__init__.py +0 -0
- {ipa_python_kit-0.1.3.dev1 → ipa_python_kit-1.0.0}/src/ipa/__init__.py +0 -0
- {ipa_python_kit-0.1.3.dev1 → ipa_python_kit-1.0.0}/src/ipa/cli/__init__.py +0 -0
- {ipa_python_kit-0.1.3.dev1 → ipa_python_kit-1.0.0}/src/ipa/cli/model.py +0 -0
- {ipa_python_kit-0.1.3.dev1 → ipa_python_kit-1.0.0}/src/ipa/cli/proxy.py +0 -0
- {ipa_python_kit-0.1.3.dev1 → ipa_python_kit-1.0.0}/src/ipa/cli/seaweedfs.py +0 -0
- {ipa_python_kit-0.1.3.dev1 → ipa_python_kit-1.0.0}/src/ipa/ctx/__init__.py +0 -0
- {ipa_python_kit-0.1.3.dev1 → ipa_python_kit-1.0.0}/src/ipa/data_type/__init__.py +0 -0
- {ipa_python_kit-0.1.3.dev1 → ipa_python_kit-1.0.0}/src/ipa/data_type/_math.py +0 -0
- {ipa_python_kit-0.1.3.dev1 → ipa_python_kit-1.0.0}/src/ipa/data_type/_queue.py +0 -0
- {ipa_python_kit-0.1.3.dev1 → ipa_python_kit-1.0.0}/src/ipa/data_type/base.py +0 -0
- {ipa_python_kit-0.1.3.dev1 → ipa_python_kit-1.0.0}/src/ipa/data_type/config.py +0 -0
- {ipa_python_kit-0.1.3.dev1 → ipa_python_kit-1.0.0}/src/ipa/data_type/container.py +0 -0
- {ipa_python_kit-0.1.3.dev1 → ipa_python_kit-1.0.0}/src/ipa/data_type/echarts.py +0 -0
- {ipa_python_kit-0.1.3.dev1 → ipa_python_kit-1.0.0}/src/ipa/data_type/exception.py +0 -0
- {ipa_python_kit-0.1.3.dev1 → ipa_python_kit-1.0.0}/src/ipa/data_type/handler.py +0 -0
- {ipa_python_kit-0.1.3.dev1 → ipa_python_kit-1.0.0}/src/ipa/data_type/lifecycle.py +0 -0
- {ipa_python_kit-0.1.3.dev1 → ipa_python_kit-1.0.0}/src/ipa/data_type/net.py +0 -0
- {ipa_python_kit-0.1.3.dev1 → ipa_python_kit-1.0.0}/src/ipa/data_type/notice.py +0 -0
- {ipa_python_kit-0.1.3.dev1 → ipa_python_kit-1.0.0}/src/ipa/data_type/page.py +0 -0
- {ipa_python_kit-0.1.3.dev1 → ipa_python_kit-1.0.0}/src/ipa/data_type/point.py +0 -0
- {ipa_python_kit-0.1.3.dev1 → ipa_python_kit-1.0.0}/src/ipa/data_type/process.py +0 -0
- {ipa_python_kit-0.1.3.dev1 → ipa_python_kit-1.0.0}/src/ipa/data_type/spatial.py +0 -0
- {ipa_python_kit-0.1.3.dev1 → ipa_python_kit-1.0.0}/src/ipa/datetime/__init__.py +0 -0
- {ipa_python_kit-0.1.3.dev1 → ipa_python_kit-1.0.0}/src/ipa/decorator/__init__.py +0 -0
- {ipa_python_kit-0.1.3.dev1 → ipa_python_kit-1.0.0}/src/ipa/decorator/exception.py +0 -0
- {ipa_python_kit-0.1.3.dev1 → ipa_python_kit-1.0.0}/src/ipa/echarts/__init__.py +0 -0
- {ipa_python_kit-0.1.3.dev1 → ipa_python_kit-1.0.0}/src/ipa/echarts/core/__init__.py +0 -0
- {ipa_python_kit-0.1.3.dev1/src/ipa/extra/simpy → ipa_python_kit-1.0.0/src/ipa/fastapi}/__init__.py +0 -0
- {ipa_python_kit-0.1.3.dev1 → ipa_python_kit-1.0.0}/src/ipa/fastapi/core/__init__.py +0 -0
- {ipa_python_kit-0.1.3.dev1 → ipa_python_kit-1.0.0}/src/ipa/func/__init__.py +0 -0
- {ipa_python_kit-0.1.3.dev1 → ipa_python_kit-1.0.0}/src/ipa/func/_async.py +0 -0
- {ipa_python_kit-0.1.3.dev1 → ipa_python_kit-1.0.0}/src/ipa/func/_lambda.py +0 -0
- {ipa_python_kit-0.1.3.dev1 → ipa_python_kit-1.0.0}/src/ipa/func/_object.py +0 -0
- {ipa_python_kit-0.1.3.dev1 → ipa_python_kit-1.0.0}/src/ipa/func/database.py +0 -0
- {ipa_python_kit-0.1.3.dev1 → ipa_python_kit-1.0.0}/src/ipa/func/num.py +0 -0
- {ipa_python_kit-0.1.3.dev1 → ipa_python_kit-1.0.0}/src/ipa/func/shortcut.py +0 -0
- {ipa_python_kit-0.1.3.dev1 → ipa_python_kit-1.0.0}/src/ipa/func/table.py +0 -0
- {ipa_python_kit-0.1.3.dev1 → ipa_python_kit-1.0.0}/src/ipa/i18n/__init__.py +0 -0
- {ipa_python_kit-0.1.3.dev1 → ipa_python_kit-1.0.0}/src/ipa/i18n/core.py +0 -0
- {ipa_python_kit-0.1.3.dev1 → ipa_python_kit-1.0.0}/src/ipa/i18n/locales/__init__.py +0 -0
- {ipa_python_kit-0.1.3.dev1 → ipa_python_kit-1.0.0}/src/ipa/io/__init__.py +0 -0
- {ipa_python_kit-0.1.3.dev1 → ipa_python_kit-1.0.0}/src/ipa/io/buffer.py +0 -0
- {ipa_python_kit-0.1.3.dev1/src/ipa/logger → ipa_python_kit-1.0.0/src/ipa/logging}/__init__.py +0 -0
- {ipa_python_kit-0.1.3.dev1/src/ipa/logger → ipa_python_kit-1.0.0/src/ipa/logging}/builder.py +0 -0
- {ipa_python_kit-0.1.3.dev1/src/ipa/logger → ipa_python_kit-1.0.0/src/ipa/logging}/fmt.py +0 -0
- {ipa_python_kit-0.1.3.dev1/src/ipa/logger → ipa_python_kit-1.0.0/src/ipa/logging}/handler.py +0 -0
- {ipa_python_kit-0.1.3.dev1/src/ipa/logger → ipa_python_kit-1.0.0/src/ipa/logging}/model/__init__.py +0 -0
- {ipa_python_kit-0.1.3.dev1/src/ipa/logger → ipa_python_kit-1.0.0/src/ipa/logging}/model/dict_config.py +0 -0
- {ipa_python_kit-0.1.3.dev1/src/ipa/logger → ipa_python_kit-1.0.0/src/ipa/logging}/util.py +0 -0
- {ipa_python_kit-0.1.3.dev1 → ipa_python_kit-1.0.0}/src/ipa/math/__init__.py +0 -0
- {ipa_python_kit-0.1.3.dev1 → ipa_python_kit-1.0.0}/src/ipa/math/core.py +0 -0
- {ipa_python_kit-0.1.3.dev1/src/ipa/fastapi → ipa_python_kit-1.0.0/src/ipa/pydantic}/__init__.py +0 -0
- {ipa_python_kit-0.1.3.dev1 → ipa_python_kit-1.0.0}/src/ipa/system/__init__.py +0 -0
- {ipa_python_kit-0.1.3.dev1 → ipa_python_kit-1.0.0}/src/ipa/system/disk.py +0 -0
- {ipa_python_kit-0.1.3.dev1 → ipa_python_kit-1.0.0}/src/ipa/system/process.py +0 -0
- {ipa_python_kit-0.1.3.dev1 → ipa_python_kit-1.0.0}/src/ipa/visualization/__init__.py +0 -0
- {ipa_python_kit-0.1.3.dev1 → ipa_python_kit-1.0.0}/src/ipa/visualization/_networkx.py +0 -0
- {ipa_python_kit-0.1.3.dev1/src/ipa/pydantic → ipa_python_kit-1.0.0/src/ipa/websocket}/__init__.py +0 -0
- {ipa_python_kit-0.1.3.dev1 → ipa_python_kit-1.0.0}/src/ipa_python_kit.egg-info/dependency_links.txt +0 -0
- {ipa_python_kit-0.1.3.dev1 → ipa_python_kit-1.0.0}/src/ipa_python_kit.egg-info/requires.txt +0 -0
- {ipa_python_kit-0.1.3.dev1 → ipa_python_kit-1.0.0}/src/ipa_python_kit.egg-info/top_level.txt +0 -0
- {ipa_python_kit-0.1.3.dev1 → ipa_python_kit-1.0.0}/tests/ctx_test.py +0 -0
- {ipa_python_kit-0.1.3.dev1 → ipa_python_kit-1.0.0}/tests/data_type_test.py +0 -0
- {ipa_python_kit-0.1.3.dev1 → ipa_python_kit-1.0.0}/tests/datetime_test.py +0 -0
- {ipa_python_kit-0.1.3.dev1 → ipa_python_kit-1.0.0}/tests/echarts_test.py +0 -0
- {ipa_python_kit-0.1.3.dev1 → ipa_python_kit-1.0.0}/tests/fastapi_test.py +0 -0
- {ipa_python_kit-0.1.3.dev1 → ipa_python_kit-1.0.0}/tests/i18n_test.py +0 -0
- {ipa_python_kit-0.1.3.dev1 → ipa_python_kit-1.0.0}/tests/io_test.py +0 -0
- {ipa_python_kit-0.1.3.dev1 → ipa_python_kit-1.0.0}/tests/math_test.py +0 -0
- {ipa_python_kit-0.1.3.dev1 → ipa_python_kit-1.0.0}/tests/network_test.py +0 -0
- {ipa_python_kit-0.1.3.dev1 → ipa_python_kit-1.0.0}/tests/subprocess_test/child.py +0 -0
- {ipa_python_kit-0.1.3.dev1 → ipa_python_kit-1.0.0}/tests/subprocess_test/pipe_test.py +0 -0
- {ipa_python_kit-0.1.3.dev1 → ipa_python_kit-1.0.0}/tests/system_test.py +0 -0
- {ipa_python_kit-0.1.3.dev1 → ipa_python_kit-1.0.0}/tests/vis_test.py +0 -0
- {ipa_python_kit-0.1.3.dev1 → ipa_python_kit-1.0.0}/tests/websocket_test.py +0 -0
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: ipa-python-kit
|
|
3
|
-
Version:
|
|
3
|
+
Version: 1.0.0
|
|
4
4
|
Summary: kit for python
|
|
5
5
|
Author-email: xdewx <present150608@sina.com>
|
|
6
6
|
Keywords: python,kit,lib,util
|
|
7
|
-
Requires-Python: >=3.
|
|
7
|
+
Requires-Python: >=3.10
|
|
8
8
|
Description-Content-Type: text/markdown
|
|
9
9
|
Requires-Dist: deprecated>=1.3.1
|
|
10
10
|
Requires-Dist: pint>=0.21.1
|
|
@@ -43,7 +43,15 @@ Requires-Dist: ipa-python-kit[visualization]; extra == "all"
|
|
|
43
43
|
Provides-Extra: des
|
|
44
44
|
Requires-Dist: simpy>=4.1.1; extra == "des"
|
|
45
45
|
|
|
46
|
-
#
|
|
46
|
+
# ipa-python-kit
|
|
47
|
+
|
|
48
|
+
## usage
|
|
49
|
+
|
|
50
|
+
`import ipa`
|
|
51
|
+
|
|
52
|
+
or
|
|
53
|
+
|
|
54
|
+
`from ipa.xx import yy`
|
|
47
55
|
|
|
48
56
|
## features
|
|
49
57
|
|
|
@@ -58,16 +66,19 @@ Requires-Dist: simpy>=4.1.1; extra == "des"
|
|
|
58
66
|
|
|
59
67
|
## introduction
|
|
60
68
|
|
|
61
|
-
the project uses `src-layout`, includes `
|
|
62
|
-
|
|
69
|
+
the project uses `src-layout`, includes `my_sdk` (for publish) and `biz` (for business logic).
|
|
70
|
+
|
|
71
|
+
~~`sdk` is designed for publish and no need to rename, we use file/folder mapping `my_sdk=src/sdk` in `pyproject.toml`.~~
|
|
72
|
+
|
|
73
|
+
feel free to rename `my_sdk` to `[the name you want]` in the whole project for your own use or publish.
|
|
63
74
|
|
|
64
75
|
### dev
|
|
65
76
|
|
|
66
77
|
before you start:
|
|
67
78
|
|
|
68
79
|
1. must run `./scripts/setup`
|
|
69
|
-
1.
|
|
70
|
-
1. remember to `uv pip install -e .[all]` to make sure `
|
|
80
|
+
1. replace `my_sdk` with `[the name you want]` in the whole project
|
|
81
|
+
1. ~~remember to `uv pip install -e .[all]` to make sure `my_sdk` is available in development.~~
|
|
71
82
|
|
|
72
83
|
### unit test
|
|
73
84
|
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
# ipa-python-kit
|
|
2
|
+
|
|
3
|
+
## usage
|
|
4
|
+
|
|
5
|
+
`import ipa`
|
|
6
|
+
|
|
7
|
+
or
|
|
8
|
+
|
|
9
|
+
`from ipa.xx import yy`
|
|
10
|
+
|
|
11
|
+
## features
|
|
12
|
+
|
|
13
|
+
1. pytest
|
|
14
|
+
2. pre-commit
|
|
15
|
+
3. darker for code format
|
|
16
|
+
4. ruff for lint
|
|
17
|
+
5. commitlint for commit message format
|
|
18
|
+
6. typer for cli
|
|
19
|
+
7. sqlmodel for database ORM
|
|
20
|
+
8. alembic for database migration
|
|
21
|
+
|
|
22
|
+
## introduction
|
|
23
|
+
|
|
24
|
+
the project uses `src-layout`, includes `my_sdk` (for publish) and `biz` (for business logic).
|
|
25
|
+
|
|
26
|
+
~~`sdk` is designed for publish and no need to rename, we use file/folder mapping `my_sdk=src/sdk` in `pyproject.toml`.~~
|
|
27
|
+
|
|
28
|
+
feel free to rename `my_sdk` to `[the name you want]` in the whole project for your own use or publish.
|
|
29
|
+
|
|
30
|
+
### dev
|
|
31
|
+
|
|
32
|
+
before you start:
|
|
33
|
+
|
|
34
|
+
1. must run `./scripts/setup`
|
|
35
|
+
1. replace `my_sdk` with `[the name you want]` in the whole project
|
|
36
|
+
1. ~~remember to `uv pip install -e .[all]` to make sure `my_sdk` is available in development.~~
|
|
37
|
+
|
|
38
|
+
### unit test
|
|
39
|
+
|
|
40
|
+
`uv run -m pytest`
|
|
41
|
+
|
|
42
|
+
### run cli
|
|
43
|
+
|
|
44
|
+
`uv run main.py --help`
|
|
45
|
+
|
|
46
|
+
### release sdk
|
|
47
|
+
|
|
48
|
+
1. `cp .pypirc.example .pypirc`
|
|
49
|
+
2. replace your token in `.pypirc`
|
|
50
|
+
3. `git tag vx.y.z`
|
|
51
|
+
4. `./scripts/publish`
|
|
52
|
+
|
|
53
|
+
### build executable file
|
|
54
|
+
|
|
55
|
+
`./scripts/build`
|
|
@@ -6,7 +6,7 @@ from typer import Typer
|
|
|
6
6
|
# TODO: i don't want to add this manually, but i have no idea how to do it automatically at present
|
|
7
7
|
sys.path.append(str(Path(__file__).parent / "src"))
|
|
8
8
|
|
|
9
|
-
print(sys.path)
|
|
9
|
+
# print(sys.path)
|
|
10
10
|
|
|
11
11
|
cmd = Typer()
|
|
12
12
|
|
|
@@ -26,5 +26,12 @@ def setup_db():
|
|
|
26
26
|
setup_database()
|
|
27
27
|
|
|
28
28
|
|
|
29
|
+
@cmd.command()
|
|
30
|
+
def version():
|
|
31
|
+
from ipa.version import __version__
|
|
32
|
+
|
|
33
|
+
print(__version__)
|
|
34
|
+
|
|
35
|
+
|
|
29
36
|
if __name__ == "__main__":
|
|
30
37
|
cmd()
|
|
@@ -8,7 +8,7 @@ description = "kit for python"
|
|
|
8
8
|
authors = [{ name = "xdewx", email = "present150608@sina.com" }]
|
|
9
9
|
keywords = ["python", "kit", "lib", "util"]
|
|
10
10
|
readme = "README.md"
|
|
11
|
-
requires-python = ">=3.
|
|
11
|
+
requires-python = ">=3.10"
|
|
12
12
|
|
|
13
13
|
dependencies = [
|
|
14
14
|
"deprecated>=1.3.1",
|
|
@@ -26,10 +26,7 @@ hmr = ["python-hmr>=0.3.0", "watchfiles>=0.24.0"]
|
|
|
26
26
|
date = ["python-dateutil>=2.9.0.post0"]
|
|
27
27
|
websocket = ["websockets>=13.1"]
|
|
28
28
|
visualization = ["matplotlib>=3.7.5", "pyecharts>=2.0.9"]
|
|
29
|
-
orm = [
|
|
30
|
-
"alembic>=1.14.1",
|
|
31
|
-
"sqlmodel>=0.0.29",
|
|
32
|
-
]
|
|
29
|
+
orm = ["alembic>=1.14.1", "sqlmodel>=0.0.29"]
|
|
33
30
|
network = ["networkx>=3.1"]
|
|
34
31
|
|
|
35
32
|
all = [
|
|
@@ -75,7 +72,7 @@ local_scheme = "no-local-version"
|
|
|
75
72
|
|
|
76
73
|
# SDK实现方式2:通过自动发现打包模块,结合sdk重命名,可以支持代码提示
|
|
77
74
|
[tool.setuptools.packages]
|
|
78
|
-
find = {where = ["src"], include = ["ipa"]}
|
|
75
|
+
find = { where = ["src"], include = ["ipa"] }
|
|
79
76
|
|
|
80
77
|
[tool.uv]
|
|
81
78
|
index = [
|
|
@@ -12,14 +12,14 @@ ignore = [
|
|
|
12
12
|
"F401",
|
|
13
13
|
"F403",
|
|
14
14
|
"F405",
|
|
15
|
-
"F841", # 未使用的变量
|
|
16
|
-
"E741", # 变量名有歧义
|
|
15
|
+
# "F841", # 未使用的变量
|
|
16
|
+
# "E741", # 变量名有歧义
|
|
17
17
|
"E722", # except
|
|
18
18
|
"E501", # 行长度太长
|
|
19
19
|
"E402", # import不在顶部
|
|
20
20
|
"PLR2004", # 魔法值
|
|
21
21
|
"PLW1641", # 未实现hash方法
|
|
22
22
|
"RUF012", # docs必须前缀加个r
|
|
23
|
-
"PLC0415", # top
|
|
24
|
-
"PLR0913", #
|
|
25
|
-
]
|
|
23
|
+
"PLC0415", # top-level import
|
|
24
|
+
"PLR0913", # too many arguments
|
|
25
|
+
]
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
__doc__ = """
|
|
2
|
+
配置模块
|
|
3
|
+
包含一些全局配置
|
|
4
|
+
"""
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
import logging
|
|
8
|
+
from abc import ABC, abstractmethod
|
|
9
|
+
from pathlib import Path
|
|
10
|
+
from typing import Optional
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class IAppConfig(ABC):
|
|
14
|
+
"""
|
|
15
|
+
应用配置接口
|
|
16
|
+
"""
|
|
17
|
+
|
|
18
|
+
@abstractmethod
|
|
19
|
+
def get_runtime_root_dir(self, *args, **kwargs) -> Optional[Path]:
|
|
20
|
+
pass
|
|
21
|
+
|
|
22
|
+
def get_root_dir(self, *args, **kwargs) -> Optional[Path]:
|
|
23
|
+
"""
|
|
24
|
+
此方法只是一个别名,返回与get_runtime_root_dir相同的结果
|
|
25
|
+
"""
|
|
26
|
+
return self.get_runtime_root_dir(*args, **kwargs)
|
|
27
|
+
|
|
28
|
+
# @abstractmethod
|
|
29
|
+
# def get_user_data_root_dir(self, *args, **kwargs) -> Optional[Path]:
|
|
30
|
+
# pass
|
|
31
|
+
|
|
32
|
+
@abstractmethod
|
|
33
|
+
def get_logs_dir(self, *args, **kwargs) -> Optional[Path]:
|
|
34
|
+
pass
|
|
35
|
+
|
|
36
|
+
@abstractmethod
|
|
37
|
+
def get_config_dir(self, *args, **kwargs) -> Optional[Path]:
|
|
38
|
+
pass
|
|
39
|
+
|
|
40
|
+
@abstractmethod
|
|
41
|
+
def get_data_dir(self, *args, **kwargs) -> Optional[Path]:
|
|
42
|
+
pass
|
|
43
|
+
|
|
44
|
+
def get_temp_dir(self, *args, **kwargs) -> Optional[Path]:
|
|
45
|
+
raise NotImplementedError()
|
|
46
|
+
|
|
47
|
+
def get_middleware_dir(self, *args, **kwargs) -> Optional[Path]:
|
|
48
|
+
raise NotImplementedError()
|
|
49
|
+
|
|
50
|
+
def get_extension_dir(self, *args, **kwargs) -> Optional[Path]:
|
|
51
|
+
raise NotImplementedError()
|
|
52
|
+
|
|
53
|
+
def get_app_logger(self, *args, **kwargs) -> logging.Logger:
|
|
54
|
+
raise NotImplementedError()
|
|
55
|
+
|
|
56
|
+
def get_sidecar_dir(self, *args, **kwargs) -> Optional[Path]:
|
|
57
|
+
raise NotImplementedError()
|
|
@@ -196,15 +196,15 @@ class Time(QuantifiedValue):
|
|
|
196
196
|
pass
|
|
197
197
|
|
|
198
198
|
|
|
199
|
-
def get_time(
|
|
199
|
+
def get_time(length: Length, v: Speed):
|
|
200
200
|
"""
|
|
201
201
|
距离/速度=时间
|
|
202
202
|
TODO:处理单位
|
|
203
203
|
"""
|
|
204
|
-
assert
|
|
204
|
+
assert length.value is not None, "length is not specified"
|
|
205
205
|
assert v.value is not None, "speed is not specified"
|
|
206
206
|
assert v.value != 0, "speed cannot be zero"
|
|
207
|
-
return abs(
|
|
207
|
+
return abs(length.value / v.value)
|
|
208
208
|
|
|
209
209
|
|
|
210
210
|
def get_time_3d(delta_distance: Point, v: ThreeDimensionalVelocity):
|
|
@@ -2,11 +2,6 @@ from datetime import datetime
|
|
|
2
2
|
from enum import Enum
|
|
3
3
|
from typing import Union
|
|
4
4
|
|
|
5
|
-
try:
|
|
6
|
-
import pandas
|
|
7
|
-
except ImportError:
|
|
8
|
-
pandas = None
|
|
9
|
-
|
|
10
5
|
from dateutil.parser import parse
|
|
11
6
|
|
|
12
7
|
|
|
@@ -35,8 +30,13 @@ def parse_datetime(date_str: str):
|
|
|
35
30
|
if not date_str: # 处理空值
|
|
36
31
|
return None
|
|
37
32
|
|
|
38
|
-
|
|
39
|
-
|
|
33
|
+
try:
|
|
34
|
+
import pandas as pd
|
|
35
|
+
|
|
36
|
+
if isinstance(date_str, (pd.Timestamp)):
|
|
37
|
+
return date_str.to_pydatetime()
|
|
38
|
+
except ImportError:
|
|
39
|
+
pass
|
|
40
40
|
|
|
41
41
|
if isinstance(date_str, (datetime)):
|
|
42
42
|
return date_str
|
|
@@ -2,7 +2,7 @@ __doc__ = """
|
|
|
2
2
|
字典工具类
|
|
3
3
|
"""
|
|
4
4
|
|
|
5
|
-
from typing import Any,
|
|
5
|
+
from typing import Any, Dict, Iterable, Optional, Tuple, TypeVar, Union
|
|
6
6
|
|
|
7
7
|
cn_en_dict = dict(
|
|
8
8
|
半径="radius",
|
|
@@ -32,24 +32,33 @@ def remove_key_not_in(dc: dict, keys: Iterable[Any], delete_value: bool = False)
|
|
|
32
32
|
Args:
|
|
33
33
|
delete_value: 是否同时del value
|
|
34
34
|
"""
|
|
35
|
+
keys_removed = []
|
|
35
36
|
for key in list(dc.keys()):
|
|
36
37
|
if key not in keys:
|
|
37
38
|
v = dc.pop(key, None)
|
|
38
39
|
if delete_value and v is not None:
|
|
39
40
|
del v
|
|
41
|
+
keys_removed.append(key)
|
|
42
|
+
return keys_removed
|
|
40
43
|
|
|
41
44
|
|
|
42
|
-
|
|
45
|
+
K = TypeVar("K")
|
|
46
|
+
V = TypeVar("V")
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
def get_the_first_existent_key(
|
|
50
|
+
obj: Dict[K, V], *keys: K, default: Optional[V] = None
|
|
51
|
+
) -> Tuple[Optional[K], Optional[V]]:
|
|
43
52
|
"""
|
|
44
53
|
获取第一个存在的key的值
|
|
45
54
|
|
|
46
55
|
Args:
|
|
47
|
-
obj (
|
|
48
|
-
keys (Iterable[
|
|
49
|
-
default (
|
|
56
|
+
obj (Dict[K,V]): 输入的字典,键名可能是中文或其他形式。
|
|
57
|
+
keys (Iterable[K]): 要查找的键名列表。
|
|
58
|
+
default (V, optional): 如果没有找到任何键,返回的默认值。默认值为None。
|
|
50
59
|
|
|
51
60
|
Returns:
|
|
52
|
-
(Tuple[
|
|
61
|
+
(Tuple[K, V]): 第一个存在的键值对,键为存在的键名,值为对应的值。如果没有找到任何键,返回(None, default)。
|
|
53
62
|
"""
|
|
54
63
|
for key in keys:
|
|
55
64
|
if key in obj:
|
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
from typing import Any, Dict, List, Literal, Optional, Union
|
|
2
2
|
|
|
3
|
-
from
|
|
3
|
+
from ipa.data_type import Point
|
|
4
4
|
|
|
5
5
|
Grid2 = List[List[Point]]
|
|
6
6
|
Grid3 = List[Grid2]
|
|
7
7
|
|
|
8
|
+
from ipa.func import get_the_first_existent_key
|
|
9
|
+
|
|
8
10
|
|
|
9
11
|
def to_grid(
|
|
10
12
|
points: List[Point], include_x=True, include_y=True, include_z=False, **kwargs
|
|
@@ -133,7 +135,20 @@ def nx_digraph_to_graph(
|
|
|
133
135
|
|
|
134
136
|
links = []
|
|
135
137
|
for u, v, attrs in G.edges(data=True):
|
|
136
|
-
|
|
138
|
+
_, label = get_the_first_existent_key(attrs, "label", "name", "id")
|
|
139
|
+
links.append(
|
|
140
|
+
opts.GraphLink(
|
|
141
|
+
source=str(u),
|
|
142
|
+
target=str(v),
|
|
143
|
+
label_opts=opts.LabelOpts(
|
|
144
|
+
is_show=False, position="middle", formatter=label, font_size=15
|
|
145
|
+
),
|
|
146
|
+
emphasis_label_opts=opts.LabelOpts(
|
|
147
|
+
is_show=True,
|
|
148
|
+
),
|
|
149
|
+
linestyle_opts=opts.LineStyleOpts(),
|
|
150
|
+
)
|
|
151
|
+
)
|
|
137
152
|
|
|
138
153
|
graph = (
|
|
139
154
|
Graph()
|
|
@@ -143,6 +158,7 @@ def nx_digraph_to_graph(
|
|
|
143
158
|
links=links,
|
|
144
159
|
layout=layout,
|
|
145
160
|
is_draggable=True,
|
|
161
|
+
edge_symbol=graph_opts.pop("edge_symbol", ["circle", "arrow"]),
|
|
146
162
|
**graph_opts,
|
|
147
163
|
)
|
|
148
164
|
.set_global_opts(
|
|
@@ -164,6 +180,8 @@ def nx_digraph_to_tree(
|
|
|
164
180
|
color_key: str = "color",
|
|
165
181
|
default_name: str = "node",
|
|
166
182
|
virtual_root_id: Optional[str] = None,
|
|
183
|
+
initial_tree_depth: int | None = None,
|
|
184
|
+
tooltip_opts=opts.TooltipOpts(trigger="item", formatter="{b}"),
|
|
167
185
|
) -> Tree:
|
|
168
186
|
"""
|
|
169
187
|
将树状结构的 networkx.DiGraph 转换为 Pyecharts Tree 图表
|
|
@@ -196,6 +214,7 @@ def nx_digraph_to_tree(
|
|
|
196
214
|
def build_node(current: Any) -> Dict[str, Any]:
|
|
197
215
|
attrs = G.nodes.get(current, {})
|
|
198
216
|
node = {
|
|
217
|
+
"nodeAttrs": attrs,
|
|
199
218
|
"name": attrs.get(name_key, str(current) or default_name),
|
|
200
219
|
"itemStyle": {"color": attrs[color_key]} if color_key in attrs else {},
|
|
201
220
|
}
|
|
@@ -207,7 +226,7 @@ def nx_digraph_to_tree(
|
|
|
207
226
|
tree = Tree().set_global_opts(
|
|
208
227
|
# datazoom_opts=opts.DataZoomOpts(orient="vertical"),# not work
|
|
209
228
|
title_opts=opts.TitleOpts(title=title),
|
|
210
|
-
tooltip_opts=
|
|
229
|
+
tooltip_opts=tooltip_opts,
|
|
211
230
|
)
|
|
212
231
|
for root in roots:
|
|
213
232
|
tree_data = [build_node(root)]
|
|
@@ -221,6 +240,7 @@ def nx_digraph_to_tree(
|
|
|
221
240
|
vertical_align="middle",
|
|
222
241
|
horizontal_align="right",
|
|
223
242
|
),
|
|
243
|
+
initial_tree_depth=initial_tree_depth,
|
|
224
244
|
)
|
|
225
245
|
|
|
226
246
|
return tree
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
import inspect
|
|
2
|
+
import logging
|
|
3
|
+
from importlib import import_module
|
|
4
|
+
from types import ModuleType
|
|
5
|
+
from typing import Callable, List, Optional, Set, Tuple, Type, TypeVar
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
def try_import(path: str):
|
|
9
|
+
"""
|
|
10
|
+
支持以x.y.z的方式导入模块或模块内的属性
|
|
11
|
+
Args:
|
|
12
|
+
path: 模块路径或属性路径
|
|
13
|
+
Returns:
|
|
14
|
+
导入的模块或属性, 如果导入失败则返回None
|
|
15
|
+
"""
|
|
16
|
+
try:
|
|
17
|
+
return import_module(path)
|
|
18
|
+
except ModuleNotFoundError:
|
|
19
|
+
tmps = path.split(".")
|
|
20
|
+
assert len(tmps) > 1, f"unexpected path: {path}"
|
|
21
|
+
module = try_import(".".join(tmps[0:-1]))
|
|
22
|
+
return getattr(module, tmps[-1], None)
|
|
23
|
+
except Exception as e:
|
|
24
|
+
logging.warning("failed to import %s: %s", path, e)
|
|
25
|
+
return None
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
def try_import(path: str):
|
|
29
|
+
"""
|
|
30
|
+
支持以x.y.z的方式导入模块或模块内的属性
|
|
31
|
+
Args:
|
|
32
|
+
path: 模块路径或属性路径
|
|
33
|
+
Returns:
|
|
34
|
+
导入的模块或属性, 如果导入失败则返回None
|
|
35
|
+
"""
|
|
36
|
+
try:
|
|
37
|
+
return import_module(path)
|
|
38
|
+
except ModuleNotFoundError:
|
|
39
|
+
tmps = path.split(".")
|
|
40
|
+
assert len(tmps) > 1, f"unexpected path: {path}"
|
|
41
|
+
module = try_import(".".join(tmps[0:-1]))
|
|
42
|
+
return getattr(module, tmps[-1], None)
|
|
43
|
+
except Exception as e:
|
|
44
|
+
logging.warning("failed to import %s: %s", path, e)
|
|
45
|
+
return None
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
T = TypeVar("T")
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
def is_subclass_of(
|
|
52
|
+
child: Type[T], parent: Type[T], include_parent: bool = True
|
|
53
|
+
) -> bool:
|
|
54
|
+
"""
|
|
55
|
+
判断child是否是parent的子类
|
|
56
|
+
Args:
|
|
57
|
+
child: 子类
|
|
58
|
+
parent: 父类
|
|
59
|
+
include_parent: 父类本身是否视为子类
|
|
60
|
+
Returns:
|
|
61
|
+
是否是子类
|
|
62
|
+
"""
|
|
63
|
+
if (not include_parent) and (child is parent):
|
|
64
|
+
return False
|
|
65
|
+
return inspect.isclass(child) and issubclass(child, parent)
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
def collect_subclass_of(
|
|
69
|
+
parent: Type[T], _from: ModuleType, include_parent: bool = False
|
|
70
|
+
):
|
|
71
|
+
"""
|
|
72
|
+
收集所有子类
|
|
73
|
+
Args:
|
|
74
|
+
parent: 父类
|
|
75
|
+
_from: 模块
|
|
76
|
+
include_parent: 父类本身是否视为子类
|
|
77
|
+
Returns:
|
|
78
|
+
所有子类的(名称,类,全路径)元组
|
|
79
|
+
"""
|
|
80
|
+
|
|
81
|
+
def predicate(child):
|
|
82
|
+
return is_subclass_of(child=child, parent=parent, include_parent=include_parent)
|
|
83
|
+
|
|
84
|
+
name_class_map: List[Tuple[str, T]] = inspect.getmembers(_from, predicate=predicate)
|
|
85
|
+
return name_class_map
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
def get_class_full_path(cls) -> str:
|
|
89
|
+
"""
|
|
90
|
+
获取类的全路径表示(模块路径.类名)
|
|
91
|
+
|
|
92
|
+
参数:
|
|
93
|
+
cls: 目标类(需传入类本身,而非实例)
|
|
94
|
+
|
|
95
|
+
返回:
|
|
96
|
+
str: 类的全路径,格式为 "模块路径.类名"
|
|
97
|
+
"""
|
|
98
|
+
# __qualname__ 获取类的限定名(含嵌套关系,如 "OuterClass.InnerClass")
|
|
99
|
+
return f"{cls.__module__}.{cls.__qualname__}"
|
|
@@ -2,7 +2,6 @@ import logging
|
|
|
2
2
|
from importlib import import_module
|
|
3
3
|
from typing import Callable, Optional, Set, Tuple
|
|
4
4
|
|
|
5
|
-
import hmr
|
|
6
5
|
from watchfiles import Change, PythonFilter, awatch
|
|
7
6
|
|
|
8
7
|
|
|
@@ -13,10 +12,13 @@ def try_hot_reload(name, package: Optional[str] = None):
|
|
|
13
12
|
name: 模块名
|
|
14
13
|
package: 包名
|
|
15
14
|
"""
|
|
16
|
-
|
|
17
15
|
try:
|
|
18
16
|
hmlib = import_module(name=name, package=package)
|
|
17
|
+
assert hmlib, f"failed to import module: {package}.{name}"
|
|
19
18
|
logging.info("shall reload: %s", hmlib)
|
|
19
|
+
# TODO: exclude怎么用
|
|
20
|
+
import hmr
|
|
21
|
+
|
|
20
22
|
hmr.reload(hmlib)
|
|
21
23
|
except Exception as e:
|
|
22
24
|
logging.warning("failed to reload: %s", e)
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
# file generated by vcs-versioning
|
|
2
|
+
# don't change, don't track in version control
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
__all__ = [
|
|
6
|
+
"__version__",
|
|
7
|
+
"__version_tuple__",
|
|
8
|
+
"version",
|
|
9
|
+
"version_tuple",
|
|
10
|
+
"__commit_id__",
|
|
11
|
+
"commit_id",
|
|
12
|
+
]
|
|
13
|
+
|
|
14
|
+
version: str
|
|
15
|
+
__version__: str
|
|
16
|
+
__version_tuple__: tuple[int | str, ...]
|
|
17
|
+
version_tuple: tuple[int | str, ...]
|
|
18
|
+
commit_id: str | None
|
|
19
|
+
__commit_id__: str | None
|
|
20
|
+
|
|
21
|
+
__version__ = version = '1.0.0'
|
|
22
|
+
__version_tuple__ = version_tuple = (1, 0, 0)
|
|
23
|
+
|
|
24
|
+
__commit_id__ = commit_id = 'g33579e931'
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import asyncio
|
|
2
|
-
from typing import Union
|
|
2
|
+
from typing import TypeAlias, Union
|
|
3
3
|
|
|
4
|
-
import fastapi
|
|
5
4
|
import websockets
|
|
6
5
|
from websockets.asyncio.client import connect
|
|
7
6
|
|
|
@@ -11,15 +10,19 @@ try:
|
|
|
11
10
|
except:
|
|
12
11
|
from websockets import ClientConnection, ServerConnection
|
|
13
12
|
|
|
13
|
+
try:
|
|
14
|
+
from fastapi import WebSocket
|
|
15
|
+
except:
|
|
16
|
+
WebSocket: TypeAlias = None
|
|
14
17
|
|
|
15
|
-
WebSocketConnection = Union[ServerConnection,
|
|
18
|
+
WebSocketConnection = Union[ServerConnection, WebSocket, ClientConnection]
|
|
16
19
|
|
|
17
20
|
|
|
18
21
|
def is_websocket_closed(conn: WebSocketConnection):
|
|
19
22
|
"""
|
|
20
23
|
判断WebSocket连接是否已关闭
|
|
21
24
|
"""
|
|
22
|
-
if isinstance(conn,
|
|
25
|
+
if isinstance(conn, WebSocket):
|
|
23
26
|
from starlette.websockets import WebSocketState
|
|
24
27
|
|
|
25
28
|
return conn.client_state == WebSocketState.DISCONNECTED
|
|
@@ -34,7 +37,7 @@ def is_websocket_closed(conn: WebSocketConnection):
|
|
|
34
37
|
async def send_text(conn: WebSocketConnection, data: str):
|
|
35
38
|
if isinstance(conn, ServerConnection):
|
|
36
39
|
await conn.send(data)
|
|
37
|
-
elif isinstance(conn,
|
|
40
|
+
elif isinstance(conn, WebSocket):
|
|
38
41
|
await conn.send_text(data)
|
|
39
42
|
else:
|
|
40
43
|
raise NotImplementedError(
|
|
@@ -45,7 +48,7 @@ async def send_text(conn: WebSocketConnection, data: str):
|
|
|
45
48
|
def get_close_code(conn: WebSocketConnection):
|
|
46
49
|
if isinstance(conn, ServerConnection):
|
|
47
50
|
return conn.close_code
|
|
48
|
-
elif isinstance(conn,
|
|
51
|
+
elif isinstance(conn, WebSocket):
|
|
49
52
|
return None
|
|
50
53
|
|
|
51
54
|
|
|
@@ -55,7 +58,7 @@ def parse_client_info(connection: WebSocketConnection):
|
|
|
55
58
|
"""
|
|
56
59
|
if isinstance(connection, ServerConnection):
|
|
57
60
|
client_ip, client_port = connection.transport.get_extra_info("peername")
|
|
58
|
-
elif isinstance(connection,
|
|
61
|
+
elif isinstance(connection, WebSocket):
|
|
59
62
|
client_ip, client_port = connection.client.host, connection.client.port
|
|
60
63
|
else:
|
|
61
64
|
client_ip, client_port = None, None
|