Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Accurate python version support information & release to PyPI, works only on python 3.11+ unlike previously claimed #36

Merged
merged 21 commits into from
Sep 10, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 17 additions & 3 deletions .github/workflows/test-dev.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,15 +12,29 @@ on:

jobs:
test:
runs-on: ubuntu-latest
strategy:
matrix:
include:
# Define specific Python versions for each OS
- os: ubuntu-latest
python-version: 3.11
# - os: windows-latest
# python-version: 3.11
# - os: macos-latest
# python-version: 3.11
- os: ubuntu-latest
python-version: 3.12

runs-on: ${{ matrix.os }}

steps:
- name: Checkout code
uses: actions/checkout@v4

- name: Set up Python
- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v3
with:
python-version: 3.11
python-version: ${{ matrix.python-version }}

- name: Install dependencies
run: pip install -r tests/requirements.txt
Expand Down
21 changes: 18 additions & 3 deletions .github/workflows/test-release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,15 +9,30 @@ on:

jobs:
test:
runs-on: ubuntu-latest

strategy:
matrix:
include:
# Define specific Python versions for each OS
- os: ubuntu-latest
python-version: 3.11
# - os: windows-latest
# python-version: 3.11
# - os: macos-latest
# python-version: 3.11
- os: ubuntu-latest
python-version: 3.12

runs-on: ${{ matrix.os }}

steps:
- name: Checkout code
uses: actions/checkout@v4

- name: Set up Python
- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v3
with:
python-version: 3.11
python-version: ${{ matrix.python-version }}

- name: Install dependencies
run: |
Expand Down
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- image event handlers (develop branch) for streaming live video as JPEG and PNG ✓
- pydantic support for property models (develop branch) ✓

## [v0.2.4] - 2024-09-09

- added multiple versions of python for testing
- unlike claimed in previous versions, this package runs only on python 3.11 or higher

## [v0.2.3] - 2024-08-11

- HTTP SSE minor bug-fix/optimization - no difference to the user
Expand Down
20 changes: 9 additions & 11 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

[![Documentation Status](https://readthedocs.org/projects/hololinked/badge/?version=latest)](https://hololinked.readthedocs.io/en/latest/?badge=latest) [![PyPI](https://img.shields.io/pypi/v/hololinked?label=pypi%20package)](https://pypi.org/project/hololinked/) [![PyPI - Downloads](https://img.shields.io/pypi/dm/hololinked)](https://pypistats.org/packages/hololinked) [![codecov](https://codecov.io/gh/VigneshVSV/hololinked/graph/badge.svg?token=JF1928KTFE)](https://codecov.io/gh/VigneshVSV/hololinked)
<br>
[![email](https://img.shields.io/badge/email%20me-brown)](mailto:[email protected]) [![find me on discord](https://img.shields.io/badge/find_me_on_discord-brown)](https://discord.com/users/1178428338746966066)
[![email](https://img.shields.io/badge/email%20me-brown)](mailto:[email protected]) [![ways to contact me](https://img.shields.io/badge/ways_to_contact_me-brown)](https://hololinked.dev/contact)

### To Install

Expand Down Expand Up @@ -105,7 +105,7 @@ class OceanOpticsSpectrometer(Thing):

In this case, instead of generating a data container with an internal name, the setter method is called when `integration_time` property is set/written. One might add the hardware device driver (say, supplied by the manufacturer) logic here to apply the property onto the device. In the above example, there is not a way provided by lower level library to read the value from the device, so we store it in a variable after applying it and supply the variable back to the getter method. Normally, one would also want the getter to read from the device directly.

Those familiar with Web of Things (WoT) terminology may note that these properties generate the property affordance schema to become accessible by the [node-wot](https://github.com/eclipse-thingweb/node-wot) HTTP(s) client. An example of autogenerated property affordance for `integration_time` is as follows:
Those familiar with Web of Things (WoT) terminology may note that these properties generate the property affordance schema. An example of autogenerated property affordance for `integration_time` is as follows:

```JSON
"integration_time": {
Expand All @@ -127,9 +127,9 @@ Those familiar with Web of Things (WoT) terminology may note that these properti
"minimum": 0.001
},
```
If you are not familiar with Web of Things or the term "property affordance", consider the above JSON as a description of
If you are <span style="text-decoration: underline">not familiar</span> with Web of Things or the term "property affordance", consider the above JSON as a description of
what the property represents and how to interact with it from somewhere else. Such a JSON is both human-readable, yet consumable
by a client provider to create a client object to interact with the property.
by a client provider to create a client object to interact with the property. For example, the Eclipse ThingWeb [node-wot](https://github.com/eclipse-thingweb/node-wot) supports this feature to produce a HTTP(s) client that can issue `readProperty("integration_time")` and `writeProperty("integration_time", 1000)` to read and write this property.

The URL path segment `../spectrometer/..` in href field is taken from the `instance_name` which was specified in the `__init__`.
This is a mandatory key word argument to the parent class `Thing` to generate a unique name/id for the instance. One should use URI compatible strings.
Expand Down Expand Up @@ -305,14 +305,14 @@ See a list of currently supported possibilities while using this package [below]

> You may use a script deployment/automation tool to remote stop and start servers, in an attempt to remotely control your hardware scripts.

One may use the HTTP API according to one's beliefs (including letting the package auto-generate it), but it is mainly intended for web development and cross platform clients like the [node-wot](https://github.com/eclipse-thingweb/node-wot) HTTP(s) client. If your plan is to develop a truly networked system, it is recommended to learn more and use [Thing Descriptions](https://www.w3.org/TR/wot-thing-description11) to describe your hardware. A Thing Description will be automatically generated if absent as shown in JSON examples above or can be supplied manually. The node-wot HTTP(s) client will be able to consume such a description, validate it and abstract away the protocol level details so that one can invoke actions, read & write properties or subscribe to events in a technology agnostic manner. In this way, one can plugin code developed from this package to the rest of the IoT/data-acquisition tools, protocols & standardizations. To know more about client side scripting with node-wot, please look into the documentation [How-To](https://hololinked.readthedocs.io/en/latest/howto/clients.html#using-node-wot-http-s-client) section.
One may use the HTTP API according to one's beliefs (including letting the package auto-generate it), but it is mainly intended for web development and cross platform clients like the [node-wot](https://github.com/eclipse-thingweb/node-wot) HTTP(s) client. If your plan is to develop a truly networked system, it is recommended to learn more and use [Thing Descriptions](https://www.w3.org/TR/wot-thing-description11) to describe your hardware. A Thing Description will be automatically generated if absent as shown in JSON examples above or can be supplied manually.

### Currently Supported

- control method execution and property write with a custom finite state machine.
- database (Postgres, MySQL, SQLite - based on SQLAlchemy) support for storing and loading properties when the object dies and restarts.
- auto-generate Thing Description for Web of Things applications.
- use serializer of your choice (except for HTTP) - MessagePack, JSON, pickle etc. & extend serialization to suit your requirement. HTTP Server will support only JSON serializer to maintain compatibility with node-wot. Default is JSON serializer based on msgspec.
- use serializer of your choice (except for HTTP) - MessagePack, JSON, pickle etc. & extend serialization to suit your requirement. HTTP Server will support only JSON serializer to maintain comptibility with Javascript (MessagePack may be added later). Default is JSON serializer based on msgspec.
- asyncio compatible - async RPC server event-loop and async HTTP Server - write methods in async
- choose from multiple ZeroMQ transport methods which offers some possibilities like the following without changing the code:
- run HTTP Server & python object in separate processes or the same process
Expand All @@ -325,14 +325,12 @@ Again, please check examples or the code for explanations. Documentation is bein
### Currently being worked

- improving accuracy of Thing Descriptions
- cookie credentials for authentication - as a workaround until credentials are supported, use `allowed_clients` argument on HTTP server which restricts access based on remote IP supplied with the HTTP headers.
- separation of HTTP protocol specification like URL path and HTTP verbs from the API of properties, actions and events and move their customization completely to the HTTP server
- unit tests coverage
- cookie credentials for authentication - as a workaround until credentials are supported, use `allowed_clients` argument on HTTP server which restricts access based on remote IP supplied with the HTTP headers. This wont still help you in public networks or modified/non-standard HTTP clients.

### Internals

This package is an implementation of a ZeroMQ-based Object Oriented RPC with customizable HTTP end-points. A dual transport in both ZMQ and HTTP is provided to maximize flexibility in data type, serialization and speed, although HTTP is preferred for networked applications. If one is looking for an object oriented approach towards creating components within a control or data acquisition system, or an IoT device, one may consider this package.

### Some Day In Future

- mongo DB support for DB operations
- HTTP 2.0

5 changes: 5 additions & 0 deletions codecov.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
coverage:
status:
patch:
default:
enabled: false
2 changes: 1 addition & 1 deletion doc
Submodule doc updated from 84450d to c0c4a8
2 changes: 1 addition & 1 deletion examples
2 changes: 1 addition & 1 deletion hololinked/__init__.py
Original file line number Diff line number Diff line change
@@ -1 +1 @@
__version__ = "0.2.3"
__version__ = "0.2.4"
4 changes: 3 additions & 1 deletion hololinked/server/eventloop.py
Original file line number Diff line number Diff line change
Expand Up @@ -353,7 +353,9 @@ async def execute_once(cls, instance_name : str, instance : Thing, instruction_s
if action == "write":
if resource.state is None or (hasattr(instance, 'state_machine') and
instance.state_machine.current_state in resource.state):
return prop.__set__(owner_inst, arguments["value"])
if isinstance(arguments, dict) and len(arguments) == 1 and "value" in arguments:
return prop.__set__(owner_inst, arguments["value"])
return prop.__set__(owner_inst, arguments)
else:
raise StateMachineError("Thing {} is in `{}` state, however attribute can be written only in `{}` state".format(
instance_name, instance.state_machine.current_state, resource.state))
Expand Down
4 changes: 2 additions & 2 deletions hololinked/server/handlers.py
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,7 @@ def set_headers(self) -> None:
"""
sets default headers for RPC (property read-write and action execution). The general headers are listed as follows:

.. code-block:: http
.. code-block:: yaml

Content-Type: application/json
Access-Control-Allow-Credentials: true
Expand Down Expand Up @@ -220,7 +220,7 @@ def set_headers(self) -> None:
"""
sets default headers for event handling. The general headers are listed as follows:

.. code-block:: http
.. code-block:: yaml

Content-Type: text/event-stream
Cache-Control: no-cache
Expand Down
8 changes: 4 additions & 4 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,10 @@

setuptools.setup(
name="hololinked",
version="0.2.3",
author="Vigneh Vaidyanathan",
version="0.2.4",
author="Vignesh Vaidyanathan",
author_email="[email protected]",
description="A ZMQ-based Object Oriented RPC tool-kit with HTTP support for instrument control/data acquisition or controlling generic python objects.",
description="A ZMQ-based Object Oriented RPC tool-kit for instrument control/data acquisition or controlling generic python objects.",
long_description=long_description,
long_description_content_type="text/markdown",
url="https://hololinked.readthedocs.io/en/latest/index.html",
Expand Down Expand Up @@ -38,7 +38,7 @@
"Topic :: System :: Hardware",
"Development Status :: 4 - Beta"
],
python_requires='>=3.7',
python_requires='>=3.11',
install_requires=[
"argon2-cffi>=23.0.0",
"ifaddr>=0.2.0",
Expand Down
Loading