From ddb130bf873e67186532205bd02bdf105562625b Mon Sep 17 00:00:00 2001 From: Joel Collins Date: Fri, 6 Mar 2020 16:59:52 +0000 Subject: [PATCH] Added basic support for dictionary PUT generation --- examples/builder.py | 56 ++++++++++++++++++++++------ examples/components/pdf_component.py | 8 ++++ 2 files changed, 53 insertions(+), 11 deletions(-) diff --git a/examples/builder.py b/examples/builder.py index fee4a6f7..79618d53 100644 --- a/examples/builder.py +++ b/examples/builder.py @@ -1,4 +1,6 @@ import uuid +import types +import functools from labthings.server.quick import create_app from labthings.server.view import View @@ -8,11 +10,25 @@ use_args, ) -from labthings.server.types import value_to_field +from labthings.server.types import value_to_field, data_dict_to_schema from components.pdf_component import PdfComponent +def copy_func(f): + """Based on http://stackoverflow.com/a/6528148/190597 (Glenn Maynard)""" + g = types.FunctionType( + f.__code__, + f.__globals__, + name=f.__name__, + argdefs=f.__defaults__, + closure=f.__closure__, + ) + g = functools.update_wrapper(g, f) + g.__kwdefaults__ = f.__kwdefaults__ + return g + + class BasePropertyResource(View): def __init__(self): super().__init__() @@ -22,13 +38,19 @@ def __init__(self): property_name: String name of property of object """ - def get(self): + def _get(self): return getattr(self.property_object, self.property_name) - def post(self, args): + def _post(self, args): setattr(self.property_object, self.property_name, args) return getattr(self.property_object, self.property_name) + def _put(self, args): + if type(getattr(self.property_object, self.property_name)) != dict: + raise TypeError("Cannot PUT to a property that isn't an object/dictionary") + getattr(self.property_object, self.property_name).update(args) + return getattr(self.property_object, self.property_name) + def gen_property(property_object, property_name, name: str = None, post=True): @@ -40,18 +62,29 @@ def gen_property(property_object, property_name, name: str = None, post=True): generated_class = type( name, (BasePropertyResource, object), - {"property_object": property_object, "property_name": property_name,}, + { + "property_object": property_object, + "property_name": property_name, + "get": copy_func(BasePropertyResource._get), + }, ) + # Enable PUT requests for dictionaries + if type(getattr(property_object, property_name)) == dict: + generated_class.put = copy_func(BasePropertyResource._put) + # Override read-write capabilities - if not post: - generated_class.post = None + if post: + generated_class.post = copy_func(BasePropertyResource._post) # Add decorators for arguments etc initial_property_value = getattr(property_object, property_name) - generated_class = PropertySchema(value_to_field(initial_property_value))( - generated_class - ) + if type(initial_property_value) == dict: + property_schema = data_dict_to_schema(initial_property_value) + else: + property_schema = value_to_field(initial_property_value) + + generated_class = PropertySchema(property_schema)(generated_class) generated_class = ThingProperty(generated_class) return generated_class @@ -72,7 +105,8 @@ def gen_property(property_object, property_name, name: str = None, post=True): # Add routes for the API views we created labthing.add_view(gen_property(my_component, "magic_denoise"), "/denoise") +labthing.add_view(gen_property(my_component, "magic_dictionary"), "/dictionary") # Start the app -if __name__ == "__main__": - app.run(host="0.0.0.0", port="5000", threaded=True, debug=True, use_reloader=False) +# if __name__ == "__main__": +# app.run(host="0.0.0.0", port="5000", threaded=True, debug=True, use_reloader=False) diff --git a/examples/components/pdf_component.py b/examples/components/pdf_component.py index 3d96b154..f4af40a8 100644 --- a/examples/components/pdf_component.py +++ b/examples/components/pdf_component.py @@ -13,6 +13,14 @@ def __init__(self): self.x_range = range(-100, 100) self.magic_denoise = 200 + self.magic_dictionary = { + "voltage": 5, + "volume": [5, 10], + "mode": "spectrum", + "light_on": True, + "user": {"name": "Squidward", "id": 1}, + } + def noisy_pdf(self, x, mu=0.0, sigma=25.0): """ Generate a noisy gaussian function (to act as some pretend data)