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.
Files changed (124) hide show
  1. {ipa_python_kit-0.1.3.dev1 → ipa_python_kit-1.0.0}/PKG-INFO +18 -7
  2. ipa_python_kit-1.0.0/README.md +55 -0
  3. {ipa_python_kit-0.1.3.dev1 → ipa_python_kit-1.0.0}/main.py +8 -1
  4. {ipa_python_kit-0.1.3.dev1 → ipa_python_kit-1.0.0}/main.spec +1 -1
  5. {ipa_python_kit-0.1.3.dev1 → ipa_python_kit-1.0.0}/pyproject.toml +3 -6
  6. {ipa_python_kit-0.1.3.dev1 → ipa_python_kit-1.0.0}/ruff.toml +5 -5
  7. {ipa_python_kit-0.1.3.dev1 → ipa_python_kit-1.0.0}/src/biz/__init__.py +2 -0
  8. ipa_python_kit-1.0.0/src/ipa/app/__init__.py +57 -0
  9. {ipa_python_kit-0.1.3.dev1 → ipa_python_kit-1.0.0}/src/ipa/data_type/unitable.py +3 -3
  10. {ipa_python_kit-0.1.3.dev1 → ipa_python_kit-1.0.0}/src/ipa/datetime/core.py +7 -7
  11. {ipa_python_kit-0.1.3.dev1 → ipa_python_kit-1.0.0}/src/ipa/func/dict.py +15 -6
  12. {ipa_python_kit-0.1.3.dev1 → ipa_python_kit-1.0.0}/src/ipa/network/__init__.py +23 -3
  13. ipa_python_kit-1.0.0/src/ipa/pkg/__init__.py +99 -0
  14. {ipa_python_kit-0.1.3.dev1 → ipa_python_kit-1.0.0}/src/ipa/pkg/hot_reload.py +4 -2
  15. {ipa_python_kit-0.1.3.dev1 → ipa_python_kit-1.0.0}/src/ipa/pydantic/core/__init__.py +1 -0
  16. ipa_python_kit-1.0.0/src/ipa/version.py +24 -0
  17. {ipa_python_kit-0.1.3.dev1 → ipa_python_kit-1.0.0}/src/ipa/websocket/core/__init__.py +10 -7
  18. {ipa_python_kit-0.1.3.dev1 → ipa_python_kit-1.0.0}/src/ipa_python_kit.egg-info/PKG-INFO +18 -7
  19. {ipa_python_kit-0.1.3.dev1 → ipa_python_kit-1.0.0}/src/ipa_python_kit.egg-info/SOURCES.txt +8 -10
  20. {ipa_python_kit-0.1.3.dev1 → ipa_python_kit-1.0.0}/tests/cli_test.py +2 -1
  21. {ipa_python_kit-0.1.3.dev1 → ipa_python_kit-1.0.0}/tests/decorator_test.py +1 -0
  22. {ipa_python_kit-0.1.3.dev1 → ipa_python_kit-1.0.0}/tests/logger_test.py +1 -1
  23. {ipa_python_kit-0.1.3.dev1 → ipa_python_kit-1.0.0}/tests/point_test.py +1 -0
  24. {ipa_python_kit-0.1.3.dev1 → ipa_python_kit-1.0.0}/tests/pydantic_test.py +2 -1
  25. {ipa_python_kit-0.1.3.dev1 → ipa_python_kit-1.0.0}/tests/python_test.py +1 -0
  26. ipa_python_kit-1.0.0/uv.lock +2875 -0
  27. ipa_python_kit-0.1.3.dev1/README.md +0 -44
  28. ipa_python_kit-0.1.3.dev1/src/ipa/extra/simpy/core.py +0 -288
  29. ipa_python_kit-0.1.3.dev1/src/ipa/func/app.py +0 -12
  30. ipa_python_kit-0.1.3.dev1/src/ipa/pkg/__init__.py +0 -43
  31. ipa_python_kit-0.1.3.dev1/src/ipa/version.py +0 -34
  32. ipa_python_kit-0.1.3.dev1/src/ipa/websocket/__init__.py +0 -1
  33. ipa_python_kit-0.1.3.dev1/uv.lock +0 -5283
  34. {ipa_python_kit-0.1.3.dev1 → ipa_python_kit-1.0.0}/.gitignore +0 -0
  35. {ipa_python_kit-0.1.3.dev1 → ipa_python_kit-1.0.0}/.pre-commit-config.yaml +0 -0
  36. {ipa_python_kit-0.1.3.dev1 → ipa_python_kit-1.0.0}/.pypirc.example +0 -0
  37. {ipa_python_kit-0.1.3.dev1 → ipa_python_kit-1.0.0}/.vscode/settings.json +0 -0
  38. {ipa_python_kit-0.1.3.dev1 → ipa_python_kit-1.0.0}/alembic/README +0 -0
  39. {ipa_python_kit-0.1.3.dev1 → ipa_python_kit-1.0.0}/alembic/env.py +0 -0
  40. {ipa_python_kit-0.1.3.dev1 → ipa_python_kit-1.0.0}/alembic/script.py.mako +0 -0
  41. {ipa_python_kit-0.1.3.dev1 → ipa_python_kit-1.0.0}/alembic/versions/5227325b977d_baseline.py +0 -0
  42. {ipa_python_kit-0.1.3.dev1 → ipa_python_kit-1.0.0}/alembic.ini +0 -0
  43. {ipa_python_kit-0.1.3.dev1 → ipa_python_kit-1.0.0}/docs/README.md +0 -0
  44. {ipa_python_kit-0.1.3.dev1 → ipa_python_kit-1.0.0}/pytest.ini +0 -0
  45. {ipa_python_kit-0.1.3.dev1 → ipa_python_kit-1.0.0}/scripts/build +0 -0
  46. {ipa_python_kit-0.1.3.dev1 → ipa_python_kit-1.0.0}/scripts/publish +0 -0
  47. {ipa_python_kit-0.1.3.dev1 → ipa_python_kit-1.0.0}/scripts/setup +0 -0
  48. {ipa_python_kit-0.1.3.dev1 → ipa_python_kit-1.0.0}/setup.cfg +0 -0
  49. {ipa_python_kit-0.1.3.dev1 → ipa_python_kit-1.0.0}/src/conf/__init__.py +0 -0
  50. {ipa_python_kit-0.1.3.dev1 → ipa_python_kit-1.0.0}/src/ipa/__init__.py +0 -0
  51. {ipa_python_kit-0.1.3.dev1 → ipa_python_kit-1.0.0}/src/ipa/cli/__init__.py +0 -0
  52. {ipa_python_kit-0.1.3.dev1 → ipa_python_kit-1.0.0}/src/ipa/cli/model.py +0 -0
  53. {ipa_python_kit-0.1.3.dev1 → ipa_python_kit-1.0.0}/src/ipa/cli/proxy.py +0 -0
  54. {ipa_python_kit-0.1.3.dev1 → ipa_python_kit-1.0.0}/src/ipa/cli/seaweedfs.py +0 -0
  55. {ipa_python_kit-0.1.3.dev1 → ipa_python_kit-1.0.0}/src/ipa/ctx/__init__.py +0 -0
  56. {ipa_python_kit-0.1.3.dev1 → ipa_python_kit-1.0.0}/src/ipa/data_type/__init__.py +0 -0
  57. {ipa_python_kit-0.1.3.dev1 → ipa_python_kit-1.0.0}/src/ipa/data_type/_math.py +0 -0
  58. {ipa_python_kit-0.1.3.dev1 → ipa_python_kit-1.0.0}/src/ipa/data_type/_queue.py +0 -0
  59. {ipa_python_kit-0.1.3.dev1 → ipa_python_kit-1.0.0}/src/ipa/data_type/base.py +0 -0
  60. {ipa_python_kit-0.1.3.dev1 → ipa_python_kit-1.0.0}/src/ipa/data_type/config.py +0 -0
  61. {ipa_python_kit-0.1.3.dev1 → ipa_python_kit-1.0.0}/src/ipa/data_type/container.py +0 -0
  62. {ipa_python_kit-0.1.3.dev1 → ipa_python_kit-1.0.0}/src/ipa/data_type/echarts.py +0 -0
  63. {ipa_python_kit-0.1.3.dev1 → ipa_python_kit-1.0.0}/src/ipa/data_type/exception.py +0 -0
  64. {ipa_python_kit-0.1.3.dev1 → ipa_python_kit-1.0.0}/src/ipa/data_type/handler.py +0 -0
  65. {ipa_python_kit-0.1.3.dev1 → ipa_python_kit-1.0.0}/src/ipa/data_type/lifecycle.py +0 -0
  66. {ipa_python_kit-0.1.3.dev1 → ipa_python_kit-1.0.0}/src/ipa/data_type/net.py +0 -0
  67. {ipa_python_kit-0.1.3.dev1 → ipa_python_kit-1.0.0}/src/ipa/data_type/notice.py +0 -0
  68. {ipa_python_kit-0.1.3.dev1 → ipa_python_kit-1.0.0}/src/ipa/data_type/page.py +0 -0
  69. {ipa_python_kit-0.1.3.dev1 → ipa_python_kit-1.0.0}/src/ipa/data_type/point.py +0 -0
  70. {ipa_python_kit-0.1.3.dev1 → ipa_python_kit-1.0.0}/src/ipa/data_type/process.py +0 -0
  71. {ipa_python_kit-0.1.3.dev1 → ipa_python_kit-1.0.0}/src/ipa/data_type/spatial.py +0 -0
  72. {ipa_python_kit-0.1.3.dev1 → ipa_python_kit-1.0.0}/src/ipa/datetime/__init__.py +0 -0
  73. {ipa_python_kit-0.1.3.dev1 → ipa_python_kit-1.0.0}/src/ipa/decorator/__init__.py +0 -0
  74. {ipa_python_kit-0.1.3.dev1 → ipa_python_kit-1.0.0}/src/ipa/decorator/exception.py +0 -0
  75. {ipa_python_kit-0.1.3.dev1 → ipa_python_kit-1.0.0}/src/ipa/echarts/__init__.py +0 -0
  76. {ipa_python_kit-0.1.3.dev1 → ipa_python_kit-1.0.0}/src/ipa/echarts/core/__init__.py +0 -0
  77. {ipa_python_kit-0.1.3.dev1/src/ipa/extra/simpy → ipa_python_kit-1.0.0/src/ipa/fastapi}/__init__.py +0 -0
  78. {ipa_python_kit-0.1.3.dev1 → ipa_python_kit-1.0.0}/src/ipa/fastapi/core/__init__.py +0 -0
  79. {ipa_python_kit-0.1.3.dev1 → ipa_python_kit-1.0.0}/src/ipa/func/__init__.py +0 -0
  80. {ipa_python_kit-0.1.3.dev1 → ipa_python_kit-1.0.0}/src/ipa/func/_async.py +0 -0
  81. {ipa_python_kit-0.1.3.dev1 → ipa_python_kit-1.0.0}/src/ipa/func/_lambda.py +0 -0
  82. {ipa_python_kit-0.1.3.dev1 → ipa_python_kit-1.0.0}/src/ipa/func/_object.py +0 -0
  83. {ipa_python_kit-0.1.3.dev1 → ipa_python_kit-1.0.0}/src/ipa/func/database.py +0 -0
  84. {ipa_python_kit-0.1.3.dev1 → ipa_python_kit-1.0.0}/src/ipa/func/num.py +0 -0
  85. {ipa_python_kit-0.1.3.dev1 → ipa_python_kit-1.0.0}/src/ipa/func/shortcut.py +0 -0
  86. {ipa_python_kit-0.1.3.dev1 → ipa_python_kit-1.0.0}/src/ipa/func/table.py +0 -0
  87. {ipa_python_kit-0.1.3.dev1 → ipa_python_kit-1.0.0}/src/ipa/i18n/__init__.py +0 -0
  88. {ipa_python_kit-0.1.3.dev1 → ipa_python_kit-1.0.0}/src/ipa/i18n/core.py +0 -0
  89. {ipa_python_kit-0.1.3.dev1 → ipa_python_kit-1.0.0}/src/ipa/i18n/locales/__init__.py +0 -0
  90. {ipa_python_kit-0.1.3.dev1 → ipa_python_kit-1.0.0}/src/ipa/io/__init__.py +0 -0
  91. {ipa_python_kit-0.1.3.dev1 → ipa_python_kit-1.0.0}/src/ipa/io/buffer.py +0 -0
  92. {ipa_python_kit-0.1.3.dev1/src/ipa/logger → ipa_python_kit-1.0.0/src/ipa/logging}/__init__.py +0 -0
  93. {ipa_python_kit-0.1.3.dev1/src/ipa/logger → ipa_python_kit-1.0.0/src/ipa/logging}/builder.py +0 -0
  94. {ipa_python_kit-0.1.3.dev1/src/ipa/logger → ipa_python_kit-1.0.0/src/ipa/logging}/fmt.py +0 -0
  95. {ipa_python_kit-0.1.3.dev1/src/ipa/logger → ipa_python_kit-1.0.0/src/ipa/logging}/handler.py +0 -0
  96. {ipa_python_kit-0.1.3.dev1/src/ipa/logger → ipa_python_kit-1.0.0/src/ipa/logging}/model/__init__.py +0 -0
  97. {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
  98. {ipa_python_kit-0.1.3.dev1/src/ipa/logger → ipa_python_kit-1.0.0/src/ipa/logging}/util.py +0 -0
  99. {ipa_python_kit-0.1.3.dev1 → ipa_python_kit-1.0.0}/src/ipa/math/__init__.py +0 -0
  100. {ipa_python_kit-0.1.3.dev1 → ipa_python_kit-1.0.0}/src/ipa/math/core.py +0 -0
  101. {ipa_python_kit-0.1.3.dev1/src/ipa/fastapi → ipa_python_kit-1.0.0/src/ipa/pydantic}/__init__.py +0 -0
  102. {ipa_python_kit-0.1.3.dev1 → ipa_python_kit-1.0.0}/src/ipa/system/__init__.py +0 -0
  103. {ipa_python_kit-0.1.3.dev1 → ipa_python_kit-1.0.0}/src/ipa/system/disk.py +0 -0
  104. {ipa_python_kit-0.1.3.dev1 → ipa_python_kit-1.0.0}/src/ipa/system/process.py +0 -0
  105. {ipa_python_kit-0.1.3.dev1 → ipa_python_kit-1.0.0}/src/ipa/visualization/__init__.py +0 -0
  106. {ipa_python_kit-0.1.3.dev1 → ipa_python_kit-1.0.0}/src/ipa/visualization/_networkx.py +0 -0
  107. {ipa_python_kit-0.1.3.dev1/src/ipa/pydantic → ipa_python_kit-1.0.0/src/ipa/websocket}/__init__.py +0 -0
  108. {ipa_python_kit-0.1.3.dev1 → ipa_python_kit-1.0.0}/src/ipa_python_kit.egg-info/dependency_links.txt +0 -0
  109. {ipa_python_kit-0.1.3.dev1 → ipa_python_kit-1.0.0}/src/ipa_python_kit.egg-info/requires.txt +0 -0
  110. {ipa_python_kit-0.1.3.dev1 → ipa_python_kit-1.0.0}/src/ipa_python_kit.egg-info/top_level.txt +0 -0
  111. {ipa_python_kit-0.1.3.dev1 → ipa_python_kit-1.0.0}/tests/ctx_test.py +0 -0
  112. {ipa_python_kit-0.1.3.dev1 → ipa_python_kit-1.0.0}/tests/data_type_test.py +0 -0
  113. {ipa_python_kit-0.1.3.dev1 → ipa_python_kit-1.0.0}/tests/datetime_test.py +0 -0
  114. {ipa_python_kit-0.1.3.dev1 → ipa_python_kit-1.0.0}/tests/echarts_test.py +0 -0
  115. {ipa_python_kit-0.1.3.dev1 → ipa_python_kit-1.0.0}/tests/fastapi_test.py +0 -0
  116. {ipa_python_kit-0.1.3.dev1 → ipa_python_kit-1.0.0}/tests/i18n_test.py +0 -0
  117. {ipa_python_kit-0.1.3.dev1 → ipa_python_kit-1.0.0}/tests/io_test.py +0 -0
  118. {ipa_python_kit-0.1.3.dev1 → ipa_python_kit-1.0.0}/tests/math_test.py +0 -0
  119. {ipa_python_kit-0.1.3.dev1 → ipa_python_kit-1.0.0}/tests/network_test.py +0 -0
  120. {ipa_python_kit-0.1.3.dev1 → ipa_python_kit-1.0.0}/tests/subprocess_test/child.py +0 -0
  121. {ipa_python_kit-0.1.3.dev1 → ipa_python_kit-1.0.0}/tests/subprocess_test/pipe_test.py +0 -0
  122. {ipa_python_kit-0.1.3.dev1 → ipa_python_kit-1.0.0}/tests/system_test.py +0 -0
  123. {ipa_python_kit-0.1.3.dev1 → ipa_python_kit-1.0.0}/tests/vis_test.py +0 -0
  124. {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: 0.1.3.dev1
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.8
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
- # pyproject-tmpl
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 `sdk` (for publish) and `biz` (for business logic).
62
- `sdk` is designed for publish and no need to rename, we use file/folder mapping `mylib=src/sdk` in `pyproject.toml`.
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. just replace `mylib` with `[the name you want]` in the whole project
70
- 1. remember to `uv pip install -e .[all]` to make sure `mylib` is available in development.
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()
@@ -2,7 +2,7 @@
2
2
 
3
3
  datas=[
4
4
  ("src/conf","conf"),
5
- ("src/sdk","ipa"),
5
+ ("src/ipa","ipa"),
6
6
  ("src/biz","biz"),
7
7
  ("alembic","alembic"),
8
8
  ("alembic.ini","."),
@@ -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.8"
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 level import
24
- "PLR0913", # 函数参数过多
25
- ]
23
+ "PLC0415", # top-level import
24
+ "PLR0913", # too many arguments
25
+ ]
@@ -1,5 +1,7 @@
1
+ from ipa.decorator import deprecated
1
2
  from ipa.math import add
2
3
 
3
4
 
5
+ @deprecated("use ipa.math.add instead")
4
6
  def demo_biz_add(a: int, b: int) -> int:
5
7
  return add(a, b)
@@ -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(l: Length, v: Speed):
199
+ def get_time(length: Length, v: Speed):
200
200
  """
201
201
  距离/速度=时间
202
202
  TODO:处理单位
203
203
  """
204
- assert l.value is not None, "length is not specified"
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(l.value / v.value)
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
- if pandas and isinstance(date_str, (pandas.Timestamp)):
39
- return date_str.to_pydatetime()
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, Callable, Dict, Iterable, Tuple, Union
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
- def get_the_first_existent_key(obj: dict, *keys, default=None) -> Tuple[Any, Any]:
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 (dict): 输入的字典,键名可能是中文或其他形式。
48
- keys (Iterable[Any]): 要查找的键名列表。
49
- default (Any, optional): 如果没有找到任何键,返回的默认值。默认值为None。
56
+ obj (Dict[K,V]): 输入的字典,键名可能是中文或其他形式。
57
+ keys (Iterable[K]): 要查找的键名列表。
58
+ default (V, optional): 如果没有找到任何键,返回的默认值。默认值为None。
50
59
 
51
60
  Returns:
52
- (Tuple[Any, Any]): 第一个存在的键值对,键为存在的键名,值为对应的值。如果没有找到任何键,返回(None, default)。
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 ..data_type import Point
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
- links.append(opts.GraphLink(source=str(u), target=str(v)))
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=opts.TooltipOpts(trigger="item", formatter="{b}"),
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)
@@ -45,6 +45,7 @@ def rename_keys_by_field_name(m: Type[BaseModel], data: dict):
45
45
  2. 如果有多个别名,以最后一个别名为准
46
46
  """
47
47
  for name, f in m.model_fields.items():
48
+ # TODO: 是否可能因为集合的无序性导致不一致问题
48
49
  aliases = collect_field_aliases(f)
49
50
  for alias in aliases:
50
51
  if alias in data:
@@ -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, fastapi.WebSocket, ClientConnection]
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, fastapi.WebSocket):
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, fastapi.WebSocket):
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, fastapi.WebSocket):
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, fastapi.WebSocket):
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