[![PyPI version](https://img.shields.io/pypi/v/sila2?color=blue)](https://pypi.org/project/sila2)
[![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](https://opensource.org/licenses/MIT)
[![coverage report](https://img.shields.io/gitlab/coverage/sila2/sila_python/master?job_name=coverage)](https://gitlab.com/sila2/sila_python/)

> :warning: On 2021-11-15, this project replaced a legacy Python implementation of SiLA 2. That project can be found [here](https://gitlab.com/SiLA2/legacy/sila_python_20211115) and is still installable via [`pip install sila2lib`](https://pypi.org/project/sila2lib/).

# SiLA 2 Python Implementation

|||
| ---------------| ----------------------------------------------------------- |
| SiLA Homepage  | [https://sila-standard.com](https://sila-standard.com)      |
| Chat group     | [Join the group on Slack](https://join.slack.com/t/sila-standard/shared_invite/enQtNDI0ODcxMDg5NzkzLTBhOTU3N2I0NTc4NDcyMjg2ZDIwZDc1Yjg4N2FmYjZkMzljZDAyZjAwNTc5OTVjYjIwZWJjYjA0YTY0NTFiNDA)|
| Maintainer     | [Niklas Mertsch](mailto:niklas.mertsch@stud.uni-goettingen.de) ([@NMertsch](https://gitlab.com/NMertsch)) |
| Maintainer     | [Mark Doerr](mailto:mark.doerr@uni-greifswald.de) ([@markdoerr](https://gitlab.com/markdoerr)) |

## Getting started
### Installation
Use `pip install sila2` to install the library.

On Raspberry Pi systems, you might encounter `ImportError`s when using the library. Use the following commands to fix them:
- Error: `ImportError: libxslt.so.1: cannot open shared object file: No such file or directory`
  - Solution: Uninstall `lxml` and reinstall it with `apt`
    - `pip uninstall -y lxml`
    - `sudo apt install python3-lxml`
- Error: `ImportError: /home/pi/.local/.../cygrpc.cpython-39-arm-linux-gnueabihf.so: undefined symbol: __atomic_exchange_8`
  - Solution: Uninstall `grpcio` and `grpcio-tools` and reinstall them with `apt`
    - `pip uninstall -y grpcio grpcio-tools`
    - `sudo apt install python3-grpcio python3-grpc-tools`

### Documentation
A documentation on SiLA Server generation, feature implementation, and usage of SiLA Clients can be found in the [here](https://sila2.gitlab.io/sila_python/).

### Example
The directory [`example_server`](example_server/) contains an example SiLA Server application. [`example_client_scripts`](example_client_scripts/) contains multiple SiLA Client programs that interact with the example server.

## Implementation status
### Missing parts from SiLA 2 specification
- Lifetime handling for binary transfer
  - currently, large binaries are only deleted on request
- Lifetime handling for observable commands
  - currently, no lifetime is reported and execution UUIDs stay valid indefinitely
- Server-initiated connection (SiLA 2 v1.1)
  - currently, only client-initiated connections are supported

### Deviations from SiLA 2 specification
- [Duration](https://gitlab.com/SiLA2/sila_base/-/blob/master/protobuf/SiLAFramework.proto#L67) is rounded to microseconds, because [`datetime.timedelta`](https://docs.python.org/3.9/library/datetime.html#datetime.timedelta) does not support sub-microsecond precision
- Microseconds of [`datetime.time`](https://docs.python.org/3.9/library/datetime.html#datetime.time) and [`datetime.datetime`](https://docs.python.org/3.9/library/datetime.html#datetime.datetime) are ignored since [Time](https://gitlab.com/SiLA2/sila_base/-/blob/master/protobuf/SiLAFramework.proto#L38) and [Timestamp](https://gitlab.com/SiLA2/sila_base/-/blob/master/protobuf/SiLAFramework.proto#L45) don't support sub-second precision 

### Code generator
- Generates submodules from feature definitions (`.sila.xml` files)
  - feature implementation abstract base class
  - client typing stub (`.pyi` file)
- Does not yet support the Structure and Custom data types (fallback to `typing.Any`)
- Does not yet generate full docstrings (e.g. constraints are missing)

## Contributing
Contributions in the form of issues, feature requests and merge requests are welcome. To reduce duplicate work, please create an issue and state that you are working on it before you spend significant time on writing code for a merge request.

###  Development setup
Clone the repository, initialize the submodule and install it as editable, including the development requirements:
```shell
git clone https://gitlab.com/sila2/sila_python
cd sila2
git submodule update --init --recursive
pip install -e .[dev]
```

### Development environment
This project uses [black](https://black.readthedocs.io/) as code formatter and [isort](https://pycqa.github.io/isort/) for sorting imports.

[flake8](https://flake8.pycqa.org/) is used to check for various code problems.
[pytest](https://docs.pytest.org/) is used for testing, [pytest-cov](https://github.com/pytest-dev/pytest-cov) for measuring code coverage.

To apply formatting, the script [`run-formatting`](run-formatting) is provided with this repository.
For testing, use [`run-checks`](run-checks) afterwards.

To apply formatting and run a fast subset of the full test suite before each commit, link the script [`pre-commit`](pre-commit) to `.git/hooks/pre-commit`: `ln -s ./pre-commit ./.git/hooks/pre-commit`
