Draft: Code generation for ThingClient subclasses #89
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Currently,
ThingClient
subclasses are generated on-the-fly from a Thing Description. This "gets the job done" and means it's always possible to have a client that's up to date with the server. However, it would be nice to support static analysis, e.g. type checking, autocompletion, etc. with importable client classes for specific instruments.Functionality
This PR implements client code generation, specifically:
ThingClient
and named as per thetitle
of the Thing Description.get_property
,set_property
as provided byThingClient
DataSchema
objects don't distinguish whether extra properties are allowed or not.invoke_action
....
is used to distinguish between explicitly setNone
values, and unspecified values (i.e. not included in the JSON). This allows for values or defaults that areNone
to be handled differently from properties that are optional but don't have a default.Schema conversion
Conversion from
DataSchema
to Python types is implemented partially. Types are converted recursively, with support for:integer
->int
number
->float
boolean
->bool
string
->str
anyOf
->Union
array
->List
(if an item type is specified, it's converted recursively)object
->dict[str, Any
Any
The major limitation here is that
object
gets converted to adict
so we don't get hints for each property. We'd need to use atypeddict
ordataclass
or similar to get that functionality, and for now I'm going to consider it out of scope. However, there's one exception, which is the input schema of an Action. That is currently required to be anobject
, and we map each of its propertiesStill to do
Before this is useful, we need to add a few things:
from_url
will overwrite the methods with generic ones.get_property
and friends and implementations of that roughly equivalent toDirectThingClient
andThingCilent
, and then providing a base client class with class methodsfrom_url
andfrom_thing
that create a subclass that mixes in eitherDirectThingClient
orHTTPThingClient
as appropriate.