plesty-lib 0.2.2__tar.gz → 0.2.3__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.
- {plesty_lib-0.2.2 → plesty_lib-0.2.3}/.gitlab-ci.yml +15 -8
- {plesty_lib-0.2.2 → plesty_lib-0.2.3}/PKG-INFO +2 -2
- {plesty_lib-0.2.2 → plesty_lib-0.2.3}/README.md +1 -1
- plesty_lib-0.2.3/conftest.py +64 -0
- plesty_lib-0.2.3/docs/api_reference.md +16 -0
- {plesty_lib-0.2.2 → plesty_lib-0.2.3}/docs/device/base_device.md +34 -4
- {plesty_lib-0.2.2 → plesty_lib-0.2.3}/docs/device/cmd_solver.md +7 -7
- {plesty_lib-0.2.2 → plesty_lib-0.2.3}/docs/device/error_handling.md +8 -8
- {plesty_lib-0.2.2 → plesty_lib-0.2.3}/docs/device/func_system.md +5 -5
- {plesty_lib-0.2.2 → plesty_lib-0.2.3}/docs/device/index.md +2 -2
- {plesty_lib-0.2.2 → plesty_lib-0.2.3}/docs/device/logging_system.md +6 -6
- {plesty_lib-0.2.2 → plesty_lib-0.2.3}/docs/device/param_system.md +5 -5
- plesty_lib-0.2.3/docs/device/test_helper.md +320 -0
- {plesty_lib-0.2.2 → plesty_lib-0.2.3}/docs/device/traffic_manager.md +3 -3
- {plesty_lib-0.2.2 → plesty_lib-0.2.3}/docs/quickstart.md +4 -4
- {plesty_lib-0.2.2 → plesty_lib-0.2.3}/docs/toc.yaml +1 -1
- {plesty_lib-0.2.2/plestylib → plesty_lib-0.2.3/lib}/__init__.py +1 -1
- {plesty_lib-0.2.2/plestylib → plesty_lib-0.2.3/lib}/data/array.py +1 -1
- {plesty_lib-0.2.2/plestylib → plesty_lib-0.2.3/lib}/device/base_device_sync.py +6 -6
- {plesty_lib-0.2.2/plestylib → plesty_lib-0.2.3/lib}/device/base_tcp_scpi_device.py +4 -4
- {plesty_lib-0.2.2/plestylib → plesty_lib-0.2.3/lib}/device/base_visa_scpi_device.py +4 -4
- {plesty_lib-0.2.2/plestylib → plesty_lib-0.2.3/lib}/device/composite_device.py +2 -2
- {plesty_lib-0.2.2/plestylib → plesty_lib-0.2.3/lib}/device/funcs.py +2 -2
- {plesty_lib-0.2.2/plestylib → plesty_lib-0.2.3/lib}/device/params.py +3 -3
- {plesty_lib-0.2.2/plestylib → plesty_lib-0.2.3/lib}/service/__init__.py +3 -3
- {plesty_lib-0.2.2/plestylib → plesty_lib-0.2.3/lib}/service/tcp_ip_server.py +2 -2
- {plesty_lib-0.2.2/plestylib → plesty_lib-0.2.3/lib}/sim/data_generator.py +3 -3
- {plesty_lib-0.2.2/plestylib → plesty_lib-0.2.3/lib}/solver/__init__.py +1 -1
- {plesty_lib-0.2.2/plestylib → plesty_lib-0.2.3/lib}/solver/iceblock.py +1 -1
- {plesty_lib-0.2.2/plestylib → plesty_lib-0.2.3/lib}/solver/scpi.py +1 -1
- {plesty_lib-0.2.2/plestylib → plesty_lib-0.2.3/lib}/test/device_func_system.py +1 -1
- {plesty_lib-0.2.2/plestylib → plesty_lib-0.2.3/lib}/test/device_param_system.py +1 -1
- {plesty_lib-0.2.2/plestylib → plesty_lib-0.2.3/lib}/test/grouped_param_keys.py +1 -1
- {plesty_lib-0.2.2/plestylib → plesty_lib-0.2.3/lib}/test/resource_allocation.py +1 -1
- {plesty_lib-0.2.2/plestylib → plesty_lib-0.2.3/lib}/traffic/__init__.py +1 -1
- {plesty_lib-0.2.2/plestylib → plesty_lib-0.2.3/lib}/traffic/serial.py +2 -2
- {plesty_lib-0.2.2/plestylib → plesty_lib-0.2.3/lib}/traffic/tcp_ip.py +3 -3
- {plesty_lib-0.2.2/plestylib → plesty_lib-0.2.3/lib}/traffic/usb_utils.py +1 -1
- {plesty_lib-0.2.2/plestylib → plesty_lib-0.2.3/lib}/traffic/visa.py +3 -3
- plesty_lib-0.2.3/plesty_lib/__init__.py +3 -0
- plesty_lib-0.2.3/plestylib/__init__.py +55 -0
- {plesty_lib-0.2.2 → plesty_lib-0.2.3}/pyproject.toml +9 -0
- {plesty_lib-0.2.2 → plesty_lib-0.2.3}/tests/test_data_array.py +1 -1
- {plesty_lib-0.2.2 → plesty_lib-0.2.3}/tests/test_schema_params.py +5 -5
- {plesty_lib-0.2.2 → plesty_lib-0.2.3}/tests/test_tcp_ip_resources.py +3 -3
- {plesty_lib-0.2.2 → plesty_lib-0.2.3}/uv.lock +0 -1
- plesty_lib-0.2.2/docs/api_reference.md +0 -15
- plesty_lib-0.2.2/docs/device/auto_test.md +0 -168
- plesty_lib-0.2.2/plesty_lib/__init__.py +0 -3
- {plesty_lib-0.2.2 → plesty_lib-0.2.3}/.gitignore +0 -0
- {plesty_lib-0.2.2 → plesty_lib-0.2.3}/COPYING +0 -0
- {plesty_lib-0.2.2 → plesty_lib-0.2.3}/LICENSE +0 -0
- {plesty_lib-0.2.2 → plesty_lib-0.2.3}/LICENSES/GPL-3.0-or-later.txt +0 -0
- {plesty_lib-0.2.2 → plesty_lib-0.2.3}/LICENSES/LGPL-3.0-or-later.txt +0 -0
- {plesty_lib-0.2.2 → plesty_lib-0.2.3}/docs/contributing.md +0 -0
- {plesty_lib-0.2.2 → plesty_lib-0.2.3}/docs/imgs/device_layers.png +0 -0
- {plesty_lib-0.2.2 → plesty_lib-0.2.3}/docs/imgs/device_standard.png +0 -0
- {plesty_lib-0.2.2 → plesty_lib-0.2.3}/docs/imgs/plesty_framework.png +0 -0
- {plesty_lib-0.2.2 → plesty_lib-0.2.3}/docs/index.md +0 -0
- {plesty_lib-0.2.2/plestylib → plesty_lib-0.2.3/lib}/data/__init__.py +0 -0
- {plesty_lib-0.2.2/plestylib → plesty_lib-0.2.3/lib}/data/ctype_manager.py +0 -0
- {plesty_lib-0.2.2/plestylib → plesty_lib-0.2.3/lib}/data/table.py +0 -0
- {plesty_lib-0.2.2/plestylib → plesty_lib-0.2.3/lib}/data/types.py +0 -0
- {plesty_lib-0.2.2/plestylib → plesty_lib-0.2.3/lib}/data/units.py +0 -0
- {plesty_lib-0.2.2/plestylib → plesty_lib-0.2.3/lib}/device/__init__.py +0 -0
- {plesty_lib-0.2.2/plestylib → plesty_lib-0.2.3/lib}/device/async_wrapper.py +0 -0
- {plesty_lib-0.2.2/plestylib → plesty_lib-0.2.3/lib}/device/device_utils.py +0 -0
- {plesty_lib-0.2.2/plestylib → plesty_lib-0.2.3/lib}/service/resource_manager.py +0 -0
- {plesty_lib-0.2.2/plestylib → plesty_lib-0.2.3/lib}/service/tcp_ip_client.py +0 -0
- {plesty_lib-0.2.2/plestylib → plesty_lib-0.2.3/lib}/sim/__init__.py +0 -0
- {plesty_lib-0.2.2/plestylib → plesty_lib-0.2.3/lib}/test/schema_params.py +0 -0
- {plesty_lib-0.2.2/plestylib → plesty_lib-0.2.3/lib}/traffic/utils.py +0 -0
- {plesty_lib-0.2.2/plestylib → plesty_lib-0.2.3/lib}/utils/__init__.py +0 -0
- {plesty_lib-0.2.2/plestylib → plesty_lib-0.2.3/lib}/utils/dll_utils.py +0 -0
- {plesty_lib-0.2.2/plestylib → plesty_lib-0.2.3/lib}/utils/error_utils.py +0 -0
- {plesty_lib-0.2.2/plestylib → plesty_lib-0.2.3/lib}/utils/logger.py +0 -0
- {plesty_lib-0.2.2/plestylib → plesty_lib-0.2.3/lib}/utils/registry.py +0 -0
- {plesty_lib-0.2.2 → plesty_lib-0.2.3}/spdx.tmpl +0 -0
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
stages:
|
|
2
2
|
- check
|
|
3
|
+
- deploy
|
|
3
4
|
- test
|
|
4
5
|
- build
|
|
5
6
|
- release
|
|
6
|
-
- deploy
|
|
7
7
|
|
|
8
8
|
variables:
|
|
9
9
|
# Required for versioningit: the runner must fetch full Git history and tags.
|
|
@@ -14,24 +14,31 @@ include:
|
|
|
14
14
|
- component: $CI_SERVER_FQDN/plesty/plesty-ci/check-compliance@main
|
|
15
15
|
inputs:
|
|
16
16
|
stage: check
|
|
17
|
+
|
|
18
|
+
# Deploy documentation to dedicated documentation branch
|
|
19
|
+
- component: $CI_SERVER_FQDN/plesty/plesty-ci/deploy-docs@main
|
|
20
|
+
inputs:
|
|
21
|
+
stage: deploy
|
|
22
|
+
access_token: $CI_BOT_TOKEN
|
|
23
|
+
|
|
24
|
+
# Run tests
|
|
25
|
+
- component: $CI_SERVER_FQDN/plesty/plesty-ci/run-tests@main
|
|
26
|
+
inputs:
|
|
27
|
+
stage: test
|
|
28
|
+
job_name: run-tests
|
|
17
29
|
|
|
18
30
|
# Build Python package and expose dist/ as an artifact
|
|
19
|
-
- component: $CI_SERVER_FQDN/plesty/plesty-ci/build-pkg@
|
|
31
|
+
- component: $CI_SERVER_FQDN/plesty/plesty-ci/build-pkg@main
|
|
20
32
|
inputs:
|
|
21
33
|
stage: build
|
|
22
34
|
job_name: build-pkg
|
|
23
35
|
|
|
24
36
|
# Publish package to PyPI on release tags
|
|
25
|
-
- component: $CI_SERVER_FQDN/plesty/plesty-ci/publish-pypi@
|
|
37
|
+
- component: $CI_SERVER_FQDN/plesty/plesty-ci/publish-pypi@main
|
|
26
38
|
inputs:
|
|
27
39
|
stage: release
|
|
28
40
|
pypi_token: $PYPI_TOKEN
|
|
29
41
|
build_job_name: build-pkg
|
|
30
42
|
|
|
31
|
-
# Deploy documentation to dedicated documentation branch
|
|
32
|
-
- component: $CI_SERVER_FQDN/plesty/plesty-ci/deploy-docs@main
|
|
33
|
-
inputs:
|
|
34
|
-
stage: deploy
|
|
35
|
-
access_token: $CI_BOT_TOKEN
|
|
36
43
|
|
|
37
44
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: plesty-lib
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.3
|
|
4
4
|
Summary: A library for the Plesty ecosystem.
|
|
5
5
|
Author-email: Yunshuang Yuan <yunshuang.yuan@fkp.uni-hannover.de>
|
|
6
6
|
Maintainer-email: Plesty Development Team <yunshuang.yuan@fkp.uni-hannover.de>
|
|
@@ -57,7 +57,7 @@ pip install plesty-sdk
|
|
|
57
57
|
### 1. Create a device class from a base device
|
|
58
58
|
|
|
59
59
|
```python
|
|
60
|
-
from
|
|
60
|
+
from plesty.lib.device.base_visa_scpi_device import BaseVisaScpiDevice
|
|
61
61
|
|
|
62
62
|
|
|
63
63
|
class PowermeterDevice(BaseVisaScpiDevice):
|
|
@@ -39,7 +39,7 @@ pip install plesty-sdk
|
|
|
39
39
|
### 1. Create a device class from a base device
|
|
40
40
|
|
|
41
41
|
```python
|
|
42
|
-
from
|
|
42
|
+
from plesty.lib.device.base_visa_scpi_device import BaseVisaScpiDevice
|
|
43
43
|
|
|
44
44
|
|
|
45
45
|
class PowermeterDevice(BaseVisaScpiDevice):
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
"""Development import hook for editable installs.
|
|
2
|
+
|
|
3
|
+
Maps ``plesty`` → synthetic namespace package and ``plesty.lib.*`` → ``lib.*``
|
|
4
|
+
so that tests can use the canonical ``plesty.lib`` import path without
|
|
5
|
+
requiring a built wheel or extra directories in the project tree.
|
|
6
|
+
|
|
7
|
+
This file is loaded automatically by pytest and has no effect on installed
|
|
8
|
+
packages (the wheel's sources mapping handles that path).
|
|
9
|
+
"""
|
|
10
|
+
|
|
11
|
+
import sys
|
|
12
|
+
import types
|
|
13
|
+
import importlib
|
|
14
|
+
import importlib.abc
|
|
15
|
+
import importlib.machinery
|
|
16
|
+
import importlib.util
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
class _Loader(importlib.abc.Loader):
|
|
20
|
+
"""Return an already-imported module so Python uses it under the aliased name."""
|
|
21
|
+
|
|
22
|
+
def __init__(self, module):
|
|
23
|
+
self._module = module
|
|
24
|
+
|
|
25
|
+
def create_module(self, spec):
|
|
26
|
+
return self._module
|
|
27
|
+
|
|
28
|
+
def exec_module(self, module):
|
|
29
|
+
pass
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
class _PlestyLibDevFinder(importlib.abc.MetaPathFinder):
|
|
33
|
+
"""Redirect ``plesty.lib.*`` imports to ``lib.*`` for editable installs."""
|
|
34
|
+
|
|
35
|
+
def find_spec(self, fullname, path, target=None):
|
|
36
|
+
# Synthesize the ``plesty`` namespace package on demand.
|
|
37
|
+
if fullname == "plesty":
|
|
38
|
+
if "plesty" in sys.modules:
|
|
39
|
+
return sys.modules["plesty"].__spec__
|
|
40
|
+
ns = types.ModuleType("plesty")
|
|
41
|
+
ns.__path__ = []
|
|
42
|
+
ns.__package__ = "plesty"
|
|
43
|
+
spec = importlib.machinery.ModuleSpec("plesty", loader=None, is_package=True)
|
|
44
|
+
ns.__spec__ = spec
|
|
45
|
+
sys.modules["plesty"] = ns
|
|
46
|
+
return spec
|
|
47
|
+
|
|
48
|
+
if fullname == "plesty.lib" or fullname.startswith("plesty.lib."):
|
|
49
|
+
target_name = "lib" + fullname[len("plesty.lib"):]
|
|
50
|
+
if target_name in sys.modules:
|
|
51
|
+
sys.modules[fullname] = sys.modules[target_name]
|
|
52
|
+
return sys.modules[target_name].__spec__
|
|
53
|
+
try:
|
|
54
|
+
mod = importlib.import_module(target_name)
|
|
55
|
+
except ImportError:
|
|
56
|
+
return None
|
|
57
|
+
sys.modules[fullname] = mod
|
|
58
|
+
return importlib.util.spec_from_loader(fullname, _Loader(mod))
|
|
59
|
+
|
|
60
|
+
return None
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
if not any(isinstance(f, _PlestyLibDevFinder) for f in sys.meta_path):
|
|
64
|
+
sys.meta_path.insert(0, _PlestyLibDevFinder())
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
# API Reference
|
|
2
|
+
Entry page for [Full API](reference/index) documentation.
|
|
3
|
+
|
|
4
|
+
## Core Packages
|
|
5
|
+
|
|
6
|
+
| Package | Description |
|
|
7
|
+
| --- | --- |
|
|
8
|
+
| [`plesty.lib.data`](reference/plesty/lib/data/index) | Data containers, units, and type helpers
|
|
9
|
+
| [`plesty.lib.device`](reference/plesty/lib/device/index) | Base device model, parameter/function systems, async wrappers |
|
|
10
|
+
| [`plesty.lib.traffic`](reference/plesty/lib/traffic/index) | Transport backends (TCP/IP, VISA, Serial) |
|
|
11
|
+
| [`plesty.lib.solver`](reference/plesty/lib/solver/index) | Command and operation solvers |
|
|
12
|
+
| [`plesty.lib.service`](reference/plesty/lib/service/index) | TCP/IP server/client and service builders |
|
|
13
|
+
| [`plesty.lib.sim`](reference/plesty/lib/sim/index) | Synthetic data generation for testing |
|
|
14
|
+
| [`plesty.lib.utils`](reference/plesty/lib/utils/index) | Shared utilities (logging, errors, registry, DLL helpers) |
|
|
15
|
+
| [`plesty.lib.test`](reference/plesty/lib/test/index) | Test helpers |
|
|
16
|
+
|
|
@@ -19,6 +19,7 @@ When your device class inherits from `BaseDeviceSyncModel`, you get:
|
|
|
19
19
|
3. Built-in high-level methods such as `write`, `query`, `state`, and `summary`.
|
|
20
20
|
4. Context manager support (`with device:`) that calls `init`, `connect`, and `disconnect`.
|
|
21
21
|
5. Resource tracking through `ResourceRegistry` to avoid duplicate ownership.
|
|
22
|
+
6. Per-instance resource locking (`_locked_resources`, `_clients`) for multi-client access control.
|
|
22
23
|
|
|
23
24
|
## Typical Layering
|
|
24
25
|
|
|
@@ -73,9 +74,9 @@ with MyDevice("dev-id") as dev:
|
|
|
73
74
|
```python
|
|
74
75
|
from typing import Any
|
|
75
76
|
|
|
76
|
-
from
|
|
77
|
-
from
|
|
78
|
-
from
|
|
77
|
+
from plesty.lib.device.base_device_sync import BaseDeviceSyncModel
|
|
78
|
+
from plesty.lib.traffic.serial import SerialTrafficManager
|
|
79
|
+
from plesty.lib.solver.scpi import SCPISolver
|
|
79
80
|
|
|
80
81
|
|
|
81
82
|
class MyScpiSerialDevice(BaseDeviceSyncModel):
|
|
@@ -145,7 +146,7 @@ Example with `AsyncWrapperSafe`:
|
|
|
145
146
|
|
|
146
147
|
```python
|
|
147
148
|
import asyncio
|
|
148
|
-
from
|
|
149
|
+
from plesty.lib.device.async_wrapper import AsyncWrapperSafe
|
|
149
150
|
|
|
150
151
|
|
|
151
152
|
async def main():
|
|
@@ -157,6 +158,35 @@ async def main():
|
|
|
157
158
|
asyncio.run(main())
|
|
158
159
|
```
|
|
159
160
|
|
|
161
|
+
## Multi-Client Resource Control
|
|
162
|
+
|
|
163
|
+
`BaseDeviceSyncModel` carries three resource-tracking attributes that support exclusive access
|
|
164
|
+
control when a device is shared by multiple clients (for example, over a TCP/IP service):
|
|
165
|
+
|
|
166
|
+
| Attribute | Type | Purpose |
|
|
167
|
+
|---|---|---|
|
|
168
|
+
| `_resources` | `list` | Hardware resources registered for automatic release on disconnect |
|
|
169
|
+
| `_locked_resources` | `set` | Resources that are currently allocated to any client |
|
|
170
|
+
| `_clients` | `dict` | Maps `client_id → [allocated resources]` |
|
|
171
|
+
|
|
172
|
+
These attributes mirror the `ResourceManager` pattern from `plesty.lib.service.resource_manager`.
|
|
173
|
+
You can compose a `ResourceManager` inside your device subclass and delegate to its methods, or
|
|
174
|
+
override `_user_permission_check` to enforce access rules based on the per-instance state.
|
|
175
|
+
|
|
176
|
+
The default `_user_permission_check` always returns `True` (no restriction). Override it to
|
|
177
|
+
implement real guard logic:
|
|
178
|
+
|
|
179
|
+
```python
|
|
180
|
+
def _user_permission_check(self, user_resources: list, key: str) -> bool:
|
|
181
|
+
if not user_resources:
|
|
182
|
+
return True
|
|
183
|
+
return any(r in self._locked_resources for r in user_resources)
|
|
184
|
+
```
|
|
185
|
+
|
|
186
|
+
Both `write` and `query` pass a `resources` kwarg through to `_user_permission_check` when the
|
|
187
|
+
caller supplies it, so access control integrates transparently with the standard operation
|
|
188
|
+
interface.
|
|
189
|
+
|
|
160
190
|
## Best Practices
|
|
161
191
|
|
|
162
192
|
1. Keep transport logic in traffic managers, not in device classes.
|
|
@@ -21,7 +21,7 @@ A command solver typically handles:
|
|
|
21
21
|
|
|
22
22
|
## Solver Types in PlestyLib
|
|
23
23
|
|
|
24
|
-
The base interfaces are in `
|
|
24
|
+
The base interfaces are in `plesty.lib.solver`:
|
|
25
25
|
|
|
26
26
|
1. `CmdSolver`: parameter-centric command generation.
|
|
27
27
|
2. `OpSolver`: operation/message-centric translation.
|
|
@@ -45,7 +45,7 @@ Use this for protocol layers that operate on operation messages rather than dire
|
|
|
45
45
|
|
|
46
46
|
## Built-in Example: SCPISolver
|
|
47
47
|
|
|
48
|
-
`SCPISolver` (in `
|
|
48
|
+
`SCPISolver` (in `plesty.lib.solver.scpi`) is a `CmdSolver` implementation used by SCPI devices.
|
|
49
49
|
|
|
50
50
|
Behavior highlights:
|
|
51
51
|
|
|
@@ -66,8 +66,8 @@ This means your concrete device class usually only needs to register parameters
|
|
|
66
66
|
## Demo 1: Use SCPISolver Directly
|
|
67
67
|
|
|
68
68
|
```python
|
|
69
|
-
from
|
|
70
|
-
from
|
|
69
|
+
from plesty.lib.solver.scpi import SCPISolver
|
|
70
|
+
from plesty.lib.device.params import ConfigParameter
|
|
71
71
|
|
|
72
72
|
solver = SCPISolver()
|
|
73
73
|
|
|
@@ -95,8 +95,8 @@ Use a custom solver when your protocol syntax is not SCPI-compatible.
|
|
|
95
95
|
```python
|
|
96
96
|
from typing import Any
|
|
97
97
|
|
|
98
|
-
from
|
|
99
|
-
from
|
|
98
|
+
from plesty.lib.solver import CmdSolver
|
|
99
|
+
from plesty.lib.device.params import ConfigParameter
|
|
100
100
|
|
|
101
101
|
|
|
102
102
|
class KVTextSolver(CmdSolver):
|
|
@@ -118,7 +118,7 @@ class KVTextSolver(CmdSolver):
|
|
|
118
118
|
`ICEBLOCKSolver` is an operation-style solver that builds compact JSON messages with transmission IDs and includes helpers for response decoding and status checks.
|
|
119
119
|
|
|
120
120
|
```python
|
|
121
|
-
from
|
|
121
|
+
from plesty.lib.solver.iceblock import ICEBLOCKSolver
|
|
122
122
|
|
|
123
123
|
solver = ICEBLOCKSolver()
|
|
124
124
|
msg = solver.get_startLink_cmd("192.168.1.20")
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Error Handling
|
|
2
2
|
|
|
3
|
-
PlestyLib centralizes most runtime error behavior through `handle_error` in `
|
|
3
|
+
PlestyLib centralizes most runtime error behavior through `handle_error` in `plesty.lib.utils.error_utils`.
|
|
4
4
|
|
|
5
5
|
This utility standardizes logging and exception raising across device, traffic, and solver layers.
|
|
6
6
|
|
|
@@ -56,17 +56,17 @@ This project uses `handle_error` to:
|
|
|
56
56
|
|
|
57
57
|
You can see usage in:
|
|
58
58
|
|
|
59
|
-
1. Traffic managers (`
|
|
60
|
-
2. Base device classes (`
|
|
61
|
-
3. Solvers (`
|
|
62
|
-
4. Parameter system (`
|
|
59
|
+
1. Traffic managers (`plesty/lib/traffic`).
|
|
60
|
+
2. Base device classes (`plesty/lib/device/base_*`).
|
|
61
|
+
3. Solvers (`plesty/lib/solver`).
|
|
62
|
+
4. Parameter system (`plesty/lib/device/params.py`).
|
|
63
63
|
|
|
64
64
|
## Usage Examples
|
|
65
65
|
|
|
66
66
|
### Re-raise the original exception
|
|
67
67
|
|
|
68
68
|
```python
|
|
69
|
-
from
|
|
69
|
+
from plesty.lib.utils.error_utils import handle_error
|
|
70
70
|
|
|
71
71
|
try:
|
|
72
72
|
risky_call()
|
|
@@ -77,7 +77,7 @@ except Exception as e:
|
|
|
77
77
|
### Raise a contextual runtime error with chained cause
|
|
78
78
|
|
|
79
79
|
```python
|
|
80
|
-
from
|
|
80
|
+
from plesty.lib.utils.error_utils import handle_error
|
|
81
81
|
|
|
82
82
|
try:
|
|
83
83
|
device.connect()
|
|
@@ -88,7 +88,7 @@ except Exception as e:
|
|
|
88
88
|
### Warning-only mode (rare)
|
|
89
89
|
|
|
90
90
|
```python
|
|
91
|
-
from
|
|
91
|
+
from plesty.lib.utils.error_utils import handle_error
|
|
92
92
|
|
|
93
93
|
try:
|
|
94
94
|
optional_background_task()
|
|
@@ -4,7 +4,7 @@ The function system is the operation layer used by device APIs in PlestyLib.
|
|
|
4
4
|
|
|
5
5
|
It lets you define operation signatures with structured input and output metadata, then automatically exposes callable methods with validation, casting, and optional response parsing.
|
|
6
6
|
|
|
7
|
-
Core implementation: `FunctionSystem` in `
|
|
7
|
+
Core implementation: `FunctionSystem` in `plesty.lib.device.funcs`.
|
|
8
8
|
|
|
9
9
|
## What It Does
|
|
10
10
|
|
|
@@ -82,7 +82,7 @@ Registered operation methods support all three styles:
|
|
|
82
82
|
## Register Operations Programmatically
|
|
83
83
|
|
|
84
84
|
```python
|
|
85
|
-
from
|
|
85
|
+
from plesty.lib.device.funcs import FunctionSystem, FuncParam, FuncOutput
|
|
86
86
|
|
|
87
87
|
|
|
88
88
|
def fake_solver(request: dict) -> dict:
|
|
@@ -138,7 +138,7 @@ Example schema:
|
|
|
138
138
|
Load from file:
|
|
139
139
|
|
|
140
140
|
```python
|
|
141
|
-
from
|
|
141
|
+
from plesty.lib.device.funcs import FunctionSystem
|
|
142
142
|
|
|
143
143
|
fs = FunctionSystem(solver=my_solver)
|
|
144
144
|
registered = fs.register_from_op_schema("op_schema.json")
|
|
@@ -156,7 +156,7 @@ Notes:
|
|
|
156
156
|
Bind a parser when raw solver responses need custom transformation:
|
|
157
157
|
|
|
158
158
|
```python
|
|
159
|
-
from
|
|
159
|
+
from plesty.lib.device.device_utils import ResponseParser
|
|
160
160
|
|
|
161
161
|
|
|
162
162
|
class MyParser(ResponseParser):
|
|
@@ -206,7 +206,7 @@ fs.func_summary(style="md", filename="ops.md")
|
|
|
206
206
|
Example:
|
|
207
207
|
|
|
208
208
|
```python
|
|
209
|
-
from
|
|
209
|
+
from plesty.lib.device.base_device_sync import BaseDeviceSyncModel
|
|
210
210
|
|
|
211
211
|
|
|
212
212
|
class MyDevice(BaseDeviceSyncModel):
|
|
@@ -9,7 +9,7 @@ If you are building a new device API, read in this order:
|
|
|
9
9
|
5. [Traffic Manager](traffic_manager.md)
|
|
10
10
|
6. [Error Handling](error_handling.md)
|
|
11
11
|
7. [Logging System](logging_system.md)
|
|
12
|
-
8. [
|
|
12
|
+
8. [Test Helpers](test_helper.md)
|
|
13
13
|
|
|
14
14
|
## Topic Guide
|
|
15
15
|
|
|
@@ -28,5 +28,5 @@ If you are building a new device API, read in this order:
|
|
|
28
28
|
|
|
29
29
|
1. [Error Handling](error_handling.md): Standard error propagation and contextual wrapping.
|
|
30
30
|
2. [Logging System](logging_system.md): Process-level logging setup and usage patterns.
|
|
31
|
-
3. [
|
|
31
|
+
3. [Test Helpers](test_helper.md): Auto-test utilities for config parameters, operations, resource contention, and schema refresh.
|
|
32
32
|
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
PlestyLib uses Python built-in logging throughout device, traffic, service, and utility layers.
|
|
4
4
|
|
|
5
|
-
Central setup helper: `setup_logging` in `
|
|
5
|
+
Central setup helper: `setup_logging` in `plesty.lib.utils.logger`.
|
|
6
6
|
|
|
7
7
|
## Purpose
|
|
8
8
|
|
|
@@ -16,7 +16,7 @@ The logging system is used to:
|
|
|
16
16
|
## Setup API
|
|
17
17
|
|
|
18
18
|
```python
|
|
19
|
-
from
|
|
19
|
+
from plesty.lib.utils.logger import setup_logging
|
|
20
20
|
|
|
21
21
|
setup_logging(app_name="powermeter", level="INFO", console_print=True)
|
|
22
22
|
```
|
|
@@ -46,7 +46,7 @@ When `setup_logging` runs:
|
|
|
46
46
|
## Minimal Example
|
|
47
47
|
|
|
48
48
|
```python
|
|
49
|
-
from
|
|
49
|
+
from plesty.lib.utils.logger import setup_logging
|
|
50
50
|
|
|
51
51
|
setup_logging(app_name="pm100d", level="DEBUG", console_print=True)
|
|
52
52
|
|
|
@@ -59,7 +59,7 @@ Call setup once at process startup, before creating device instances:
|
|
|
59
59
|
|
|
60
60
|
```python
|
|
61
61
|
import logging
|
|
62
|
-
from
|
|
62
|
+
from plesty.lib.utils.logger import setup_logging
|
|
63
63
|
from powermeter_device import PowermeterDevice
|
|
64
64
|
|
|
65
65
|
setup_logging(app_name="powermeter_service", level="INFO", console_print=True)
|
|
@@ -76,7 +76,7 @@ Use this pattern when building or debugging a new device API implementation.
|
|
|
76
76
|
|
|
77
77
|
```python
|
|
78
78
|
import logging
|
|
79
|
-
from
|
|
79
|
+
from plesty.lib.device.base_tcp_scpi_device import BaseTCPScpiDevice
|
|
80
80
|
|
|
81
81
|
|
|
82
82
|
class DemoScpiDevice(BaseTCPScpiDevice):
|
|
@@ -107,7 +107,7 @@ Use this pattern in production-like scripts where operators mainly need status a
|
|
|
107
107
|
```python
|
|
108
108
|
import logging
|
|
109
109
|
|
|
110
|
-
from
|
|
110
|
+
from plesty.lib.utils.logger import setup_logging
|
|
111
111
|
from powermeter_device import PowermeterDevice
|
|
112
112
|
|
|
113
113
|
|
|
@@ -4,7 +4,7 @@ The parameter system is the metadata and validation layer used by device classes
|
|
|
4
4
|
|
|
5
5
|
It defines what can be queried or written, validates user input, stores cached values, and supports typed parsing of device responses.
|
|
6
6
|
|
|
7
|
-
Core implementation: `ConfigSystem` in `
|
|
7
|
+
Core implementation: `ConfigSystem` in `plesty.lib.device.params`.
|
|
8
8
|
|
|
9
9
|
## What It Does
|
|
10
10
|
|
|
@@ -59,7 +59,7 @@ Command metadata object used in grouped schemas:
|
|
|
59
59
|
## Register Parameters in Code
|
|
60
60
|
|
|
61
61
|
```python
|
|
62
|
-
from
|
|
62
|
+
from plesty.lib.device.base_visa_scpi_device import BaseVisaScpiDevice
|
|
63
63
|
|
|
64
64
|
|
|
65
65
|
class PowermeterDevice(BaseVisaScpiDevice):
|
|
@@ -95,7 +95,7 @@ class PowermeterDevice(BaseVisaScpiDevice):
|
|
|
95
95
|
Load schema from file path or dictionary:
|
|
96
96
|
|
|
97
97
|
```python
|
|
98
|
-
from
|
|
98
|
+
from plesty.lib.device.params import ConfigSystem
|
|
99
99
|
|
|
100
100
|
cfg = ConfigSystem(param_schema="param_schema.json")
|
|
101
101
|
# or
|
|
@@ -105,7 +105,7 @@ cfg = ConfigSystem(param_schema="param_schema.json")
|
|
|
105
105
|
Load schema directly in a base-device constructor (`BaseDeviceSyncModel`):
|
|
106
106
|
|
|
107
107
|
```python
|
|
108
|
-
from
|
|
108
|
+
from plesty.lib.device.base_device_sync import BaseDeviceSyncModel
|
|
109
109
|
|
|
110
110
|
|
|
111
111
|
class MyDevice(BaseDeviceSyncModel):
|
|
@@ -197,7 +197,7 @@ If needed, provide a custom parser in parameter metadata via `parser`.
|
|
|
197
197
|
## Minimal End-to-End Example
|
|
198
198
|
|
|
199
199
|
```python
|
|
200
|
-
from
|
|
200
|
+
from plesty.lib.device.params import ConfigSystem
|
|
201
201
|
|
|
202
202
|
system = ConfigSystem()
|
|
203
203
|
|