From dc99a12985e85b3136965080270db4b4fb618c45 Mon Sep 17 00:00:00 2001 From: Joel Collins Date: Thu, 21 Nov 2019 15:53:22 +0000 Subject: [PATCH] Status and settings members can be accessed via URI --- .../api/v2/blueprints/actions/stage.py | 4 +- .../api/v2/blueprints/settings.py | 44 ++++++++++++++++++- .../api/v2/blueprints/status.py | 21 ++++++++- openflexure_microscope/utilities.py | 17 +++++++ 4 files changed, 80 insertions(+), 6 deletions(-) diff --git a/openflexure_microscope/api/v2/blueprints/actions/stage.py b/openflexure_microscope/api/v2/blueprints/actions/stage.py index 7e8af1d3..efd69964 100644 --- a/openflexure_microscope/api/v2/blueprints/actions/stage.py +++ b/openflexure_microscope/api/v2/blueprints/actions/stage.py @@ -53,6 +53,4 @@ class MoveStageAPI(MicroscopeView): with self.microscope.stage.lock: self.microscope.stage.move_rel(position) - out = filter_dict(self.microscope.state, ["stage", "position"]) - - return jsonify(out) + return jsonify(self.microscope.status["stage"]["position"]) diff --git a/openflexure_microscope/api/v2/blueprints/settings.py b/openflexure_microscope/api/v2/blueprints/settings.py index 4d14fd13..83be2985 100644 --- a/openflexure_microscope/api/v2/blueprints/settings.py +++ b/openflexure_microscope/api/v2/blueprints/settings.py @@ -6,7 +6,9 @@ from openflexure_microscope.api.utilities import gen, JsonResponse from openflexure_microscope.api.views import MicroscopeView from openflexure_microscope.api.utilities import blueprint_for_module -from flask import Blueprint, jsonify, request +from openflexure_microscope.utilities import get_by_path, set_by_path, create_from_path + +from flask import Blueprint, jsonify, request, abort import logging @@ -144,7 +146,38 @@ class SettingsAPI(MicroscopeView): self.microscope.apply_settings(payload.json) self.microscope.save_settings() - return jsonify(self.microscope.read_settings(json_safe=True)) + return jsonify(self.microscope.read_settings()) + + +class NestedSettingsAPI(MicroscopeView): + def get(self, route): + + keys = route.split("/") + + try: + value = get_by_path(self.microscope.read_settings(), keys) + except KeyError: + return abort(404) + + return jsonify(value) + + def put(self, route): + keys = route.split("/") + + payload = JsonResponse(request) + + logging.debug("Updating settings from PUT request:") + logging.debug(payload.json) + + dictionary = create_from_path(keys) + set_by_path(dictionary, keys, payload.json) + + logging.debug(f"Applying settings: {dictionary}") + + self.microscope.apply_settings(dictionary) + self.microscope.save_settings() + + return self.get(route) def construct_blueprint(microscope_obj): @@ -155,4 +188,11 @@ def construct_blueprint(microscope_obj): "/", view_func=SettingsAPI.as_view("settings", microscope=microscope_obj) ) + blueprint.add_url_rule( + "/", + view_func=NestedSettingsAPI.as_view( + "nested_settings", microscope=microscope_obj + ), + ) + return blueprint diff --git a/openflexure_microscope/api/v2/blueprints/status.py b/openflexure_microscope/api/v2/blueprints/status.py index 6344cb42..846a594f 100644 --- a/openflexure_microscope/api/v2/blueprints/status.py +++ b/openflexure_microscope/api/v2/blueprints/status.py @@ -4,8 +4,9 @@ Read-only status of the microscope, and attached hardware info from openflexure_microscope.api.views import MicroscopeView from openflexure_microscope.api.utilities import blueprint_for_module +from openflexure_microscope.utilities import get_by_path -from flask import Blueprint, jsonify +from flask import Blueprint, jsonify, abort class StatusAPI(MicroscopeView): @@ -58,6 +59,19 @@ class StatusAPI(MicroscopeView): return jsonify(self.microscope.status) +class NestedStatusAPI(MicroscopeView): + def get(self, route): + + keys = route.split("/") + + try: + value = get_by_path(self.microscope.status, keys) + except KeyError: + return abort(404) + + return jsonify(value) + + def construct_blueprint(microscope_obj): blueprint = blueprint_for_module(__name__) @@ -66,4 +80,9 @@ def construct_blueprint(microscope_obj): "/", view_func=StatusAPI.as_view("status", microscope=microscope_obj) ) + blueprint.add_url_rule( + "/", + view_func=NestedStatusAPI.as_view("nested_status", microscope=microscope_obj), + ) + return blueprint diff --git a/openflexure_microscope/utilities.py b/openflexure_microscope/utilities.py index 27e5734d..0551790e 100644 --- a/openflexure_microscope/utilities.py +++ b/openflexure_microscope/utilities.py @@ -6,6 +6,23 @@ from functools import reduce from contextlib import contextmanager +def get_by_path(root, items): + """Access a nested object in root by item sequence.""" + return reduce(operator.getitem, items, root) + + +def set_by_path(root, items, value): + """Set a value in a nested object in root by item sequence.""" + get_by_path(root, items[:-1])[items[-1]] = value + + +def create_from_path(items): + tree_dict = {} + for key in reversed(items): + tree_dict = {key: tree_dict} + return tree_dict + + def bottom_level_name(obj): return obj.__name__.split(".")[-1]