Skip to content

Commit

Permalink
added test for pydantic and JSON schema properties
Browse files Browse the repository at this point in the history
  • Loading branch information
VigneshVSV committed Dec 6, 2024
2 parents f4e947d + 54a3bcb commit 40bedc8
Show file tree
Hide file tree
Showing 2 changed files with 18 additions and 22 deletions.
14 changes: 4 additions & 10 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,7 @@ Those familiar with Web of Things (WoT) terminology may note that these properti
},
```
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 any application that may use the property, say a client provider to create a client object to interact with the property or a GUI application to autogenerate a suitable input field for this property.
what the property represents and how to interact with it from somewhere else. Such a JSON is both human-readable, yet consumable by any application that may use the property - say, a client provider to create a client object to interact with the property or a GUI application to autogenerate a suitable input field for this 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__`.
Expand Down Expand Up @@ -314,20 +314,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.
### Looking for sponsorships

Kindly read my message [in my GitHub profile](https://github.com/sponsors/VigneshVSV).

### A little more about Usage

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 interoperable [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
se [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 default end point to
fetch thing descriptions are: <br> `http(s)://<host name>/<instance name of the thing>/resources/wot-td` <br>
The HTTP API may be autogenerated or adjusted by the user. 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 (This is optional and one can still use a classic HTTP client). A Thing Description will be automatically generated if absent as shown in JSON examples above or can be supplied manually. The default end point to fetch thing descriptions are: <br> `http(s)://<host name>/<instance name of the thing>/resources/wot-td` <br>
If there are errors in generation of Thing Description
(mostly due to JSON non-complaint types), one could use: <br> `http(s)://<host name>/<instance name of the thing>/resources/wot-td?ignore_errors=true`

(client docs will be updated here next)
(client docs will be updated here next, also check official docs)

### Currently Supported

Expand Down
26 changes: 14 additions & 12 deletions hololinked/server/property.py
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ class Property(Parameter):
"""

__slots__ = ['db_persist', 'db_init', 'db_commit', 'metadata', 'model', '_json_validator', '_remote_info',
__slots__ = ['db_persist', 'db_init', 'db_commit', 'metadata', 'model', 'validator', '_remote_info',
'_observable', '_observable_event_descriptor', 'fcomparator', '_old_value_internal_name']

# RPC only init - no HTTP methods for those who dont like
Expand Down Expand Up @@ -187,12 +187,14 @@ def __init__(self, default: typing.Any = None, *,
isproperty=True
)
self.model = None
self._json_validator = None
self.validator = None
if model:
if isinstance(model, BaseModel):
self.model = wrap_plain_types_in_rootmodel(model)
elif issubclass(model, dict):
self._json_validator = JsonSchemaValidator(model)
if isinstance(model, dict):
self.model = model
self.validator = JsonSchemaValidator(model)
else:
self.model = wrap_plain_types_in_rootmodel(model) # type: BaseModel
self.validator = self.model.model_validate


def __set_name__(self, owner: typing.Any, attrib_name: str) -> None:
Expand Down Expand Up @@ -242,17 +244,17 @@ def _push_change_event_if_needed(self, obj, value : typing.Any) -> None:
event_dispatcher.push(value)


def validate_and_adapt(self, value):
def validate_and_adapt(self, value) -> typing.Any:
if value is None:
if self.allow_None:
return value
else:
raise ValueError(f"Property {self.name} does not allow None values")
elif self.model:
if isinstance(value, dict):
self._json_validator.validate(value)
else:
self.model(**value) # pydantic model validation, just try to create an instance
if self.model:
if isinstance(self.model, dict):
self.validator.validate(value)
elif issubklass(self.model, BaseModel):
self.validator(value)
return super().validate_and_adapt(value)


Expand Down

0 comments on commit 40bedc8

Please sign in to comment.