diff --git a/pype/avalon_apps/rest_api.py b/pype/avalon_apps/rest_api.py index dc74f17bd1..d58d080339 100644 --- a/pype/avalon_apps/rest_api.py +++ b/pype/avalon_apps/rest_api.py @@ -3,7 +3,7 @@ import re import json import bson import bson.json_util -from pype.services.rest_api import RestApi, abort, CallbackResult, Query +from pype.services.rest_api import RestApi, abort, CallbackResult from pype.ftrack.lib.custom_db_connector import DbConnector @@ -18,8 +18,8 @@ class AvalonRestApi(RestApi): self.dbcon.install() @RestApi.route("/projects/", url_prefix="/avalon", methods="GET") - def get_project(self, url_data): - project_name = url_data["project_name"] + def get_project(self, request): + project_name = request.url_data["project_name"] if not project_name: output = {} for project_name in self.dbcon.tables(): @@ -38,9 +38,9 @@ class AvalonRestApi(RestApi): )) @RestApi.route("/projects//assets/", url_prefix="/avalon", methods="GET") - def get_assets(self, url_data, query:Query): - _project_name = url_data["project_name"] - _asset = url_data["asset"] + def get_assets(self, request): + _project_name = request.url_data["project_name"] + _asset = request.url_data["asset"] if not self.dbcon.exist_table(_project_name): abort(404, "Project \"{}\" was not found in database".format( @@ -52,7 +52,7 @@ class AvalonRestApi(RestApi): output = self.result_to_json(assets) return CallbackResult(data=output) - identificator = query.get("identificator", "name") + identificator = request.query.get("identificator", "name") asset = self.dbcon[_project_name].find_one({ "type": "asset", diff --git a/pype/muster/muster.py b/pype/muster/muster.py index a4805369aa..e33caf40ca 100644 --- a/pype/muster/muster.py +++ b/pype/muster/muster.py @@ -38,8 +38,10 @@ class MusterModule: def process_modules(self, modules): if "RestApiServer" in modules: + def api_show_login(): + self.aShowLogin.trigger() modules["RestApiServer"].register_callback( - "muster/show_login", self.show_login, "post" + "/show_login", api_show_login, "muster", "post" ) # Definition of Tray menu diff --git a/pype/services/rest_api/__init__.py b/pype/services/rest_api/__init__.py index f0fddce0ee..fbeec00c88 100644 --- a/pype/services/rest_api/__init__.py +++ b/pype/services/rest_api/__init__.py @@ -1,15 +1,6 @@ from .rest_api import RestApiServer from .base_class import RestApi, abort, route, register_statics -from .lib import ( - RestMethods, - UrlData, - RequestData, - Query, - Fragment, - Params, - Handler, - CallbackResult -) +from .lib import RestMethods, CallbackResult def tray_init(tray_widget, main_widget): diff --git a/pype/services/rest_api/base_class.py b/pype/services/rest_api/base_class.py index a389ba517b..8d4f7cbaa5 100644 --- a/pype/services/rest_api/base_class.py +++ b/pype/services/rest_api/base_class.py @@ -4,7 +4,6 @@ from http import HTTPStatus from .lib import ( RestApiFactory, Splitter, ObjAlreadyExist, AbortException, - Params, UrlData, RequestData, Query, Fragment, Handler ) diff --git a/pype/services/rest_api/lib/__init__.py b/pype/services/rest_api/lib/__init__.py index 38d476050a..97fb232409 100644 --- a/pype/services/rest_api/lib/__init__.py +++ b/pype/services/rest_api/lib/__init__.py @@ -1,17 +1,7 @@ Splitter = "__splitter__" from .exceptions import ObjAlreadyExist, AbortException -from .lib import ( - RestMethods, - CustomNone, - UrlData, - RequestData, - Query, - Fragment, - Params, - CallbackResult -) - +from .lib import RestMethods, CustomNone, CallbackResult, RequestInfo from .factory import _RestApiFactory RestApiFactory = _RestApiFactory() diff --git a/pype/services/rest_api/lib/handler.py b/pype/services/rest_api/lib/handler.py index 71215c1f2c..de6b5a9a44 100644 --- a/pype/services/rest_api/lib/handler.py +++ b/pype/services/rest_api/lib/handler.py @@ -6,17 +6,13 @@ import http.server from http import HTTPStatus from urllib.parse import urlparse -from .lib import ( - RestMethods, CallbackResult, - UrlData, RequestData, Query, Fragment, Params -) +from .lib import RestMethods, CallbackResult, RequestInfo from .exceptions import AbortException -from . import RestApiFactory, CustomNone, Splitter +from . import RestApiFactory, Splitter from pypeapp import Logger log = Logger().get_logger("RestApiHandler") -NotSet = CustomNone("NotSet") class Handler(http.server.SimpleHTTPRequestHandler): @@ -115,7 +111,9 @@ class Handler(http.server.SimpleHTTPRequestHandler): try: log.debug("Triggering callback for path \"{}\"".format(path)) - result = self._handle_callback(matching_item, parsed_url) + result = self._handle_callback( + matching_item, parsed_url, rest_method + ) return self._handle_callback_result(result, rest_method) @@ -208,7 +206,7 @@ class Handler(http.server.SimpleHTTPRequestHandler): self.wfile.write(body.encode()) return body - def _handle_callback(self, item, parsed_url): + def _handle_callback(self, item, parsed_url, rest_method): regex = item["regex"] regex_keys = item["regex_keys"] @@ -228,11 +226,15 @@ class Handler(http.server.SimpleHTTPRequestHandler): if in_data_str: in_data = json.loads(in_data_str) - url_data = UrlData(url_data) - request_data = RequestData(in_data) - query = Query(parsed_url.query) - params = Params(parsed_url.params) - fragment = Fragment(parsed_url.fragment) + request_info = RequestInfo( + url_data=url_data, + request_data=in_data, + query=parsed_url.query, + fragment=parsed_url.fragment, + params=parsed_url.params, + method=rest_method, + handler=self + ) callback = item["callback"] callback_info = item["callback_info"] @@ -240,110 +242,20 @@ class Handler(http.server.SimpleHTTPRequestHandler): _args = callback_info["args"] _args_len = callback_info["args_len"] _defaults = callback_info["defaults"] - _defaults_len = callback_info["defaults_len"] _has_args = callback_info["hasargs"] _has_kwargs = callback_info["haskwargs"] - _annotations = callback_info["annotations"] - - arg_index = 0 - if type(callback).__name__ == "method": - arg_index = 1 - - _kwargs = {arg: NotSet for arg in _args[arg_index:]} - _available_kwargs = { - "url_data": url_data, - "request_data": request_data, - "query": query, - "params": params, - "fragment": fragment, - "handler": self - } - if not regex: - _available_kwargs.pop("url_data") - - available_len = len(_available_kwargs) - if available_len < (_args_len - _defaults_len): - raise Exception(( - "Callback expects {} required positional arguments but {} are" - " available {}<{}>" - ).format( - _args_len, available_len, callback.__qualname__, - callback.__globals__.get("__file__", "unknown file") - )) - elif available_len < _args_len: - log.warning(( - "Handler \"{}\" will never fill all args of callback {}<{}>" - ).format( - self.__class__.__name__, - callback.__qualname__, - callback.__globals__.get("__file__", "unknown file") - )) - + args = [] + kwargs = {} if _args_len == 0: if _has_args: - return callback(*_available_kwargs.values()) - if _has_kwargs: - return callback(**_available_kwargs) - else: - return callback() + args.append(request_info) + elif _has_kwargs: + kwargs["request_info"] = request_info + else: + args.append(request_info) - if _annotations: - for arg, argtype in _annotations.items(): - if argtype == Query: - key = "query" - elif argtype == Params: - key = "params" - elif argtype == Fragment: - key = "fragment" - elif argtype == Handler: - key = "handler" - elif argtype == UrlData: - key = "url_data" - elif argtype == RequestData: - key = "request_data" - else: - continue - - _kwargs[arg] = _available_kwargs[key] - _available_kwargs[key] = NotSet - - for key1, value1 in _kwargs.items(): - if value1 is not NotSet: - continue - has_values = False - for key2, value2 in _available_kwargs.items(): - if value2 is NotSet: - continue - has_values = True - _kwargs[key1] = value2 - _available_kwargs[key2] = NotSet - break - - if not has_values: - break - - _args = [] - kw_keys = [key for key in _kwargs.keys()] - for key in kw_keys: - value = _kwargs.pop(key) - if value is not NotSet: - _args.append(value) - continue - - if _has_args: - for key, value in _available_kwargs.items(): - if value is NotSet: - continue - _args.append(value) - - elif _has_kwargs: - for key, value in _available_kwargs.items(): - if value is NotSet: - continue - _kwargs[key] = value - - return callback(*_args, **_kwargs) + return callback(*args, **kwargs) def _handle_statics(self, dirpath, path): path = os.path.normpath(dirpath + path) diff --git a/pype/services/rest_api/lib/lib.py b/pype/services/rest_api/lib/lib.py index 4a9e41ce26..f8508ceea0 100644 --- a/pype/services/rest_api/lib/lib.py +++ b/pype/services/rest_api/lib/lib.py @@ -109,6 +109,32 @@ class Fragment(HandlerDict): ) return "&".join(items) +class RequestInfo: + def __init__( + self, url_data, request_data, query, fragment, params, method, handler + ): + self.url_data = UrlData(url_data) + self.request_data = RequestData(request_data) + self.query = Query(query) + self.fragment = Fragment(fragment) + self.params = Params(params) + self.method = method + self.handler = handler + + def __getitem__(self, key): + return self.__getattribute__(key) + + def __hash__(self): + return { + "url_data": self.url_data, + "request_data": self. request_data, + "query": self.query, + "fragment": self.fragment, + "params": self.params, + "method": self.method, + "handler": self.handler + } + class CallbackResult: _data = {} diff --git a/pype/services/rest_api/rest_api.py b/pype/services/rest_api/rest_api.py index 00e38b8102..994632a1e9 100644 --- a/pype/services/rest_api/rest_api.py +++ b/pype/services/rest_api/rest_api.py @@ -39,7 +39,6 @@ class RestApiServer: self.failed_icon = failed_icon def register_callback(self, path, callback, url_prefix="", methods=[]): - callback.restapi = True RestApiFactory.register_route(path, callback, url_prefix, methods) # route(path, url_prefix, methods)(callback)