mirror of
https://github.com/tiqi-group/pydase.git
synced 2025-04-20 00:10:03 +02:00
moves state persistence section into docs, restructuring docs
This commit is contained in:
parent
ca19fcc63f
commit
c7ec929d05
63
README.md
63
README.md
@ -1,3 +1,4 @@
|
|||||||
|
<!--introduction-start-->
|
||||||
# pydase <!-- omit from toc -->
|
# pydase <!-- omit from toc -->
|
||||||
|
|
||||||
[](https://pypi.org/project/pydase/)
|
[](https://pypi.org/project/pydase/)
|
||||||
@ -17,15 +18,18 @@ Whether you're managing lab sensors, network devices, or any abstract data entit
|
|||||||
- [Auto-generated web interface for interactive access and control of your service](#accessing-the-web-interface)
|
- [Auto-generated web interface for interactive access and control of your service](#accessing-the-web-interface)
|
||||||
- [Python RPC client](#connecting-to-the-service-via-python-rpc-client)
|
- [Python RPC client](#connecting-to-the-service-via-python-rpc-client)
|
||||||
- [Customizable web interface](#customizing-the-web-interface)
|
- [Customizable web interface](#customizing-the-web-interface)
|
||||||
- [Saving and restoring the service state](#understanding-service-persistence)
|
- [Saving and restoring the service state](https://pydase.readthedocs.io/en/latest/user-guide/Service_Persistence)
|
||||||
- [Automated task management with built-in start/stop controls and optional autostart](#understanding-tasks-in-pydase)
|
- [Automated task management with built-in start/stop controls and optional autostart](#understanding-tasks-in-pydase)
|
||||||
- [Support for units](#understanding-units-in-pydase)
|
- [Support for units](#understanding-units-in-pydase)
|
||||||
- [Validating Property Setters](#using-validate_set-to-validate-property-setters)
|
- [Validating Property Setters](#using-validate_set-to-validate-property-setters)
|
||||||
<!-- Support for additional servers for specific use-cases -->
|
<!-- Support for additional servers for specific use-cases -->
|
||||||
|
|
||||||
|
<!--introduction-end-->
|
||||||
|
|
||||||
|
<!--getting-started-start-->
|
||||||
|
|
||||||
## Installation
|
## Installation
|
||||||
|
|
||||||
<!--installation-start-->
|
|
||||||
|
|
||||||
Install `pydase` using [`poetry`](https://python-poetry.org/):
|
Install `pydase` using [`poetry`](https://python-poetry.org/):
|
||||||
|
|
||||||
@ -39,13 +43,11 @@ or `pip`:
|
|||||||
pip install pydase
|
pip install pydase
|
||||||
```
|
```
|
||||||
|
|
||||||
<!--installation-end-->
|
|
||||||
|
|
||||||
## Usage
|
## Usage
|
||||||
|
|
||||||
<!--usage-start-->
|
|
||||||
|
|
||||||
Using `pydase` involves three main steps: defining a `DataService` subclass, running the server, and then connecting to the service either programmatically using `pydase.Client` or through the web interface.
|
Using `pydase` involves three main steps: defining a `pydase.DataService` subclass, running the server, and then connecting to the service either programmatically using `pydase.Client` or through the web interface.
|
||||||
|
|
||||||
### Defining a DataService
|
### Defining a DataService
|
||||||
|
|
||||||
@ -176,56 +178,7 @@ serialized_value = json.loads(response.text)
|
|||||||
|
|
||||||
For more information, see [here](https://pydase.readthedocs.io/en/stable/user-guide/interaction/main/#restful-api).
|
For more information, see [here](https://pydase.readthedocs.io/en/stable/user-guide/interaction/main/#restful-api).
|
||||||
|
|
||||||
<!--usage-end-->
|
<!--getting-started-end-->
|
||||||
|
|
||||||
## Understanding Service Persistence
|
|
||||||
|
|
||||||
`pydase` allows you to easily persist the state of your service by saving it to a file. This is especially useful when you want to maintain the service's state across different runs.
|
|
||||||
|
|
||||||
To save the state of your service, pass a `filename` keyword argument to the constructor of the `pydase.Server` class. If the file specified by `filename` does not exist, the state manager will create this file and store its state in it when the service is shut down. If the file already exists, the state manager will load the state from this file, setting the values of its attributes to the values stored in the file.
|
|
||||||
|
|
||||||
Here's an example:
|
|
||||||
|
|
||||||
```python
|
|
||||||
from pydase import DataService, Server
|
|
||||||
|
|
||||||
class Device(DataService):
|
|
||||||
# ... defining the Device class ...
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
service = Device()
|
|
||||||
Server(service, filename="device_state.json").run()
|
|
||||||
```
|
|
||||||
|
|
||||||
In this example, the state of the `Device` service will be saved to `device_state.json` when the service is shut down. If `device_state.json` exists when the server is started, the state manager will restore the state of the service from this file.
|
|
||||||
|
|
||||||
### Controlling Property State Loading with `@load_state`
|
|
||||||
|
|
||||||
By default, the state manager only restores values for public attributes of your service. If you have properties that you want to control the loading for, you can use the `@load_state` decorator on your property setters. This indicates to the state manager that the value of the property should be loaded from the state file.
|
|
||||||
|
|
||||||
Here is how you can apply the `@load_state` decorator:
|
|
||||||
|
|
||||||
```python
|
|
||||||
from pydase import DataService
|
|
||||||
from pydase.data_service.state_manager import load_state
|
|
||||||
|
|
||||||
class Device(DataService):
|
|
||||||
_name = "Default Device Name"
|
|
||||||
|
|
||||||
@property
|
|
||||||
def name(self) -> str:
|
|
||||||
return self._name
|
|
||||||
|
|
||||||
@name.setter
|
|
||||||
@load_state
|
|
||||||
def name(self, value: str) -> None:
|
|
||||||
self._name = value
|
|
||||||
```
|
|
||||||
|
|
||||||
With the `@load_state` decorator applied to the `name` property setter, the state manager will load and apply the `name` property's value from the file storing the state upon server startup, assuming it exists.
|
|
||||||
|
|
||||||
Note: If the service class structure has changed since the last time its state was saved, only the attributes and properties decorated with `@load_state` that have remained the same will be restored from the settings file.
|
|
||||||
|
|
||||||
## Understanding Tasks in pydase
|
## Understanding Tasks in pydase
|
||||||
|
|
||||||
|
@ -1,14 +1,6 @@
|
|||||||
# Getting Started
|
# Getting Started
|
||||||
## Installation
|
|
||||||
{%
|
{%
|
||||||
include-markdown "../README.md"
|
include-markdown "../README.md"
|
||||||
start="<!--installation-start-->"
|
start="<!--getting-started-start-->"
|
||||||
end="<!--installation-end-->"
|
end="<!--getting-started-end-->"
|
||||||
%}
|
%}
|
||||||
|
|
||||||
## Usage
|
|
||||||
{%
|
|
||||||
include-markdown "../README.md"
|
|
||||||
start="<!--usage-start-->"
|
|
||||||
end="<!--usage-end-->"
|
|
||||||
%}
|
|
@ -1 +1,5 @@
|
|||||||
{% include-markdown "../README.md" %}
|
{%
|
||||||
|
include-markdown "../README.md"
|
||||||
|
start="<!--introduction-start-->"
|
||||||
|
end="<!--introduction-end-->"
|
||||||
|
%}
|
||||||
|
@ -36,7 +36,7 @@ class MyService(pydase.DataService):
|
|||||||
# ...
|
# ...
|
||||||
```
|
```
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
You can still define synchronous tasks with arguments and call them using a python client. However, decorating them with the `@frontend` decorator will raise a `FunctionDefinitionError`. Defining a task with arguments will raise a `TaskDefinitionError`.
|
You can still define synchronous tasks with arguments and call them using a python client. However, decorating them with the `@frontend` decorator will raise a `FunctionDefinitionError`. Defining a task with arguments will raise a `TaskDefinitionError`.
|
||||||
I decided against supporting function arguments for functions rendered in the frontend due to the following reasons:
|
I decided against supporting function arguments for functions rendered in the frontend due to the following reasons:
|
||||||
@ -83,7 +83,7 @@ if __name__ == "__main__":
|
|||||||
Server(service).run()
|
Server(service).run()
|
||||||
```
|
```
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
**Note** that defining classes within `DataService` classes is not supported (see [this issue](https://github.com/tiqi-group/pydase/issues/16)).
|
**Note** that defining classes within `DataService` classes is not supported (see [this issue](https://github.com/tiqi-group/pydase/issues/16)).
|
||||||
|
|
||||||
@ -132,7 +132,7 @@ if __name__ == "__main__":
|
|||||||
pydase.Server(service_instance).run()
|
pydase.Server(service_instance).run()
|
||||||
```
|
```
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
#### Customizing Connection Logic
|
#### Customizing Connection Logic
|
||||||
|
|
||||||
@ -214,7 +214,7 @@ if __name__ == "__main__":
|
|||||||
pydase.Server(service).run()
|
pydase.Server(service).run()
|
||||||
```
|
```
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
### `NumberSlider`
|
### `NumberSlider`
|
||||||
|
|
||||||
@ -291,7 +291,7 @@ if __name__ == "__main__":
|
|||||||
|
|
||||||
In this example, `MySlider` overrides the `min`, `max`, `step_size`, and `value` properties. Users can make any of these properties read-only by omitting the corresponding setter method.
|
In this example, `MySlider` overrides the `min`, `max`, `step_size`, and `value` properties. Users can make any of these properties read-only by omitting the corresponding setter method.
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
- Accessing parent class resources in `NumberSlider`
|
- Accessing parent class resources in `NumberSlider`
|
||||||
|
|
||||||
@ -424,7 +424,7 @@ my_service = StatusExample()
|
|||||||
my_service.status = MyStatus.FAILED
|
my_service.status = MyStatus.FAILED
|
||||||
```
|
```
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
**Note** that each enumeration name and value must be unique.
|
**Note** that each enumeration name and value must be unique.
|
||||||
This means that you should use different colour formats when you want to use a colour multiple times.
|
This means that you should use different colour formats when you want to use a colour multiple times.
|
||||||
|
49
docs/user-guide/Service_Persistence.md
Normal file
49
docs/user-guide/Service_Persistence.md
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
# Understanding Service Persistence
|
||||||
|
|
||||||
|
`pydase` allows you to easily persist the state of your service by saving it to a file. This is especially useful when you want to maintain the service's state across different runs.
|
||||||
|
|
||||||
|
To save the state of your service, pass a `filename` keyword argument to the constructor of the `pydase.Server` class. If the file specified by `filename` does not exist, the state manager will create this file and store its state in it when the service is shut down. If the file already exists, the state manager will load the state from this file, setting the values of its attributes to the values stored in the file.
|
||||||
|
|
||||||
|
Here's an example:
|
||||||
|
|
||||||
|
```python
|
||||||
|
import pydase
|
||||||
|
|
||||||
|
class Device(pydase.DataService):
|
||||||
|
# ... defining the Device class ...
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
service = Device()
|
||||||
|
pydase.Server(service=service, filename="device_state.json").run()
|
||||||
|
```
|
||||||
|
|
||||||
|
In this example, the state of the `Device` service will be saved to `device_state.json` when the service is shut down. If `device_state.json` exists when the server is started, the state manager will restore the state of the service from this file.
|
||||||
|
|
||||||
|
## Controlling Property State Loading with `@load_state`
|
||||||
|
|
||||||
|
By default, the state manager only restores values for public attributes of your service. If you have properties that you want to control the loading for, you can use the `@load_state` decorator on your property setters. This indicates to the state manager that the value of the property should be loaded from the state file.
|
||||||
|
|
||||||
|
Here is how you can apply the `@load_state` decorator:
|
||||||
|
|
||||||
|
```python
|
||||||
|
import pydase
|
||||||
|
from pydase.data_service.state_manager import load_state
|
||||||
|
|
||||||
|
class Device(pydase.DataService):
|
||||||
|
_name = "Default Device Name"
|
||||||
|
|
||||||
|
@property
|
||||||
|
def name(self) -> str:
|
||||||
|
return self._name
|
||||||
|
|
||||||
|
@name.setter
|
||||||
|
@load_state
|
||||||
|
def name(self, value: str) -> None:
|
||||||
|
self._name = value
|
||||||
|
```
|
||||||
|
|
||||||
|
With the `@load_state` decorator applied to the `name` property setter, the state manager will load and apply the `name` property's value from the file storing the state upon server startup, assuming it exists.
|
||||||
|
|
||||||
|
Note: If the service class structure has changed since the last time its state was saved, only the attributes and properties decorated with `@load_state` that have remained the same will be restored from the settings file.
|
||||||
|
|
Loading…
x
Reference in New Issue
Block a user