mirror of
https://github.com/ynput/ayon-core.git
synced 2026-01-01 08:24:53 +01:00
formatting fixes
This commit is contained in:
parent
4201ba173d
commit
343cdf55c1
5 changed files with 72 additions and 34 deletions
|
|
@ -1,4 +1,3 @@
|
||||||
from functools import wraps
|
|
||||||
from http import HTTPStatus
|
from http import HTTPStatus
|
||||||
|
|
||||||
from .lib import (
|
from .lib import (
|
||||||
|
|
@ -15,9 +14,12 @@ def route(path, url_prefix="", methods=[], strict_match=False):
|
||||||
:type path: str
|
:type path: str
|
||||||
:param url_prefix: Specify prefix of path, defaults to "/".
|
:param url_prefix: Specify prefix of path, defaults to "/".
|
||||||
:type url_prefix: str, list, optional
|
:type url_prefix: str, list, optional
|
||||||
:param methods: Specify request method (GET, POST, PUT, etc.) when callback will be triggered, defaults to ["GET"]
|
:param methods: Specify request method (GET, POST, PUT, etc.) when
|
||||||
|
callback will be triggered, defaults to ["GET"]
|
||||||
:type methods: list, str, optional
|
:type methods: list, str, optional
|
||||||
:param strict_match: Decides if callback can handle both single and multiple entities (~/projects/<project_name> && ~/projects/), defaults to False.
|
:param strict_match: Decides if callback can handle both single and
|
||||||
|
multiple entities (~/projects/<project_name> && ~/projects/),
|
||||||
|
defaults to False.
|
||||||
:type strict_match: bool
|
:type strict_match: bool
|
||||||
|
|
||||||
`path` may include dynamic keys that will be stored to object which can
|
`path` may include dynamic keys that will be stored to object which can
|
||||||
|
|
@ -36,6 +38,7 @@ def route(path, url_prefix="", methods=[], strict_match=False):
|
||||||
In this case request path must be "/avalon/projects" to trigger registered
|
In this case request path must be "/avalon/projects" to trigger registered
|
||||||
callback.
|
callback.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def decorator(callback):
|
def decorator(callback):
|
||||||
RestApiFactory.register_route(
|
RestApiFactory.register_route(
|
||||||
path, callback, url_prefix, methods, strict_match
|
path, callback, url_prefix, methods, strict_match
|
||||||
|
|
@ -49,26 +52,32 @@ def register_statics(url_prefix, dir_path):
|
||||||
"""Decorator that register callback and all its attributes.
|
"""Decorator that register callback and all its attributes.
|
||||||
Callback is registered to Singleton RestApiFactory.
|
Callback is registered to Singleton RestApiFactory.
|
||||||
|
|
||||||
:param url_prefix: Specify prefix of path, defaults to "/". (Example: "/resources")
|
:param url_prefix: Specify prefix of path, defaults to "/".
|
||||||
|
(Example: "/resources")
|
||||||
:type url_prefix: str
|
:type url_prefix: str
|
||||||
:param dir_path: Path to file folder where statics are located.
|
:param dir_path: Path to file folder where statics are located.
|
||||||
:type dir_path: str
|
:type dir_path: str
|
||||||
"""
|
"""
|
||||||
|
|
||||||
RestApiFactory.register_statics((url_prefix, dir_path))
|
RestApiFactory.register_statics((url_prefix, dir_path))
|
||||||
|
|
||||||
|
|
||||||
def abort(status_code=HTTPStatus.NOT_FOUND, message=None):
|
def abort(status_code=HTTPStatus.NOT_FOUND, message=None):
|
||||||
"""Should be used to stop registered callback
|
"""Should be used to stop registered callback.
|
||||||
`abort` raise AbortException that is handled with request Handler which
|
`abort` raise AbortException that is handled with request Handler which
|
||||||
returns entered status and may send optional message in body.
|
returns entered status and may send optional message in body.
|
||||||
|
|
||||||
:param status_code: Status that will be send in reply of request, defaults to 404
|
:param status_code: Status that will be send in reply of request,
|
||||||
|
defaults to 404
|
||||||
:type status_code: int
|
:type status_code: int
|
||||||
:param message: Message to send in body, default messages are based on statuc_code in Handler, defaults to None
|
:param message: Message to send in body, default messages are based on
|
||||||
|
statuc_code in Handler, defaults to None
|
||||||
:type message: str, optional
|
:type message: str, optional
|
||||||
...
|
...
|
||||||
:raises AbortException: This exception is handled in Handler to know about launched `abort`
|
:raises AbortException: This exception is handled in Handler to know
|
||||||
|
about launched `abort`
|
||||||
"""
|
"""
|
||||||
|
|
||||||
items = []
|
items = []
|
||||||
items.append(str(status_code))
|
items.append(str(status_code))
|
||||||
if not message:
|
if not message:
|
||||||
|
|
@ -85,9 +94,10 @@ class RestApi:
|
||||||
Use this class is required when it is necessary to have class for handling
|
Use this class is required when it is necessary to have class for handling
|
||||||
requests and want to use decorators for registering callbacks.
|
requests and want to use decorators for registering callbacks.
|
||||||
|
|
||||||
It is possible to use decorators in another class only when object, of class
|
It is possible to use decorators in another class only when object,
|
||||||
where decorators are, is registered to RestApiFactory.
|
of class where decorators are, is registered to RestApiFactory.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def route(path, url_prefix="", methods=[], strict_match=False):
|
def route(path, url_prefix="", methods=[], strict_match=False):
|
||||||
return route(path, url_prefix, methods, strict_match)
|
return route(path, url_prefix, methods, strict_match)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -8,4 +8,5 @@ class ObjAlreadyExist(Exception):
|
||||||
super().__init__(message)
|
super().__init__(message)
|
||||||
|
|
||||||
|
|
||||||
class AbortException(Exception): pass
|
class AbortException(Exception):
|
||||||
|
pass
|
||||||
|
|
|
||||||
|
|
@ -116,7 +116,8 @@ def prepare_methods(methods, callback=None):
|
||||||
|
|
||||||
:param methods: Contain rest api methods, when callback is called.
|
:param methods: Contain rest api methods, when callback is called.
|
||||||
:type methods: str, list
|
:type methods: str, list
|
||||||
:param callback: Registered callback, helps to identify where is invalid method.
|
:param callback: Registered callback, helps to identify where is
|
||||||
|
invalid method.
|
||||||
:type callback: function, method, optional
|
:type callback: function, method, optional
|
||||||
:return: Valid methods
|
:return: Valid methods
|
||||||
:rtype: list
|
:rtype: list
|
||||||
|
|
@ -138,7 +139,7 @@ def prepare_methods(methods, callback=None):
|
||||||
for method in methods:
|
for method in methods:
|
||||||
found = False
|
found = False
|
||||||
_method = RestMethods.get(method)
|
_method = RestMethods.get(method)
|
||||||
if _method == None:
|
if _method is None:
|
||||||
invalid_methods[methods].append(callback)
|
invalid_methods[methods].append(callback)
|
||||||
continue
|
continue
|
||||||
|
|
||||||
|
|
@ -169,6 +170,7 @@ def prepare_methods(methods, callback=None):
|
||||||
|
|
||||||
return _methods
|
return _methods
|
||||||
|
|
||||||
|
|
||||||
def prepare_callback_info(callback):
|
def prepare_callback_info(callback):
|
||||||
"""Prepare data for callback handling when should be triggered."""
|
"""Prepare data for callback handling when should be triggered."""
|
||||||
callback_info = inspect.getfullargspec(callback)
|
callback_info = inspect.getfullargspec(callback)
|
||||||
|
|
@ -228,7 +230,9 @@ class _RestApiFactory:
|
||||||
self.unprocessed_statics.index(item)
|
self.unprocessed_statics.index(item)
|
||||||
)
|
)
|
||||||
|
|
||||||
def register_route(self, path, callback, url_prefix, methods, strict_match):
|
def register_route(
|
||||||
|
self, path, callback, url_prefix, methods, strict_match
|
||||||
|
):
|
||||||
log.debug("Registering callback for item \"{}\"".format(
|
log.debug("Registering callback for item \"{}\"".format(
|
||||||
callback.__qualname__
|
callback.__qualname__
|
||||||
))
|
))
|
||||||
|
|
@ -242,7 +246,7 @@ class _RestApiFactory:
|
||||||
self.unprocessed_routes.append(route)
|
self.unprocessed_routes.append(route)
|
||||||
|
|
||||||
def register_obj(self, obj):
|
def register_obj(self, obj):
|
||||||
"""Register object for decorated methods in class definition"""
|
"""Register object for decorated methods in class definition."""
|
||||||
self.registered_objs.append(obj)
|
self.registered_objs.append(obj)
|
||||||
|
|
||||||
def register_statics(self, item):
|
def register_statics(self, item):
|
||||||
|
|
@ -255,7 +259,8 @@ class _RestApiFactory:
|
||||||
Registration info are prepared to easy filter during handling
|
Registration info are prepared to easy filter during handling
|
||||||
of requests.
|
of requests.
|
||||||
|
|
||||||
:param route: Contain all necessary info for filtering and handling callback for registered route.
|
:param route: Contain all necessary info for filtering and
|
||||||
|
handling callback for registered route.
|
||||||
:type route: dict
|
:type route: dict
|
||||||
"""
|
"""
|
||||||
callback = route["callback"]
|
callback = route["callback"]
|
||||||
|
|
@ -278,7 +283,7 @@ class _RestApiFactory:
|
||||||
})
|
})
|
||||||
|
|
||||||
def prepare_registered(self):
|
def prepare_registered(self):
|
||||||
"""Iterate through all registered callbacks and statics and prepare them
|
"""Iter through all registered callbacks and statics to prepare them.
|
||||||
|
|
||||||
First are processed callbacks registered with decorators in classes by
|
First are processed callbacks registered with decorators in classes by
|
||||||
registered objects. Remaining callbacks are filtered, it is checked if
|
registered objects. Remaining callbacks are filtered, it is checked if
|
||||||
|
|
@ -314,7 +319,9 @@ class _RestApiFactory:
|
||||||
if not (
|
if not (
|
||||||
callback.__qualname__ == method.__qualname__ and
|
callback.__qualname__ == method.__qualname__ and
|
||||||
callback.__module__ == method.__module__ and
|
callback.__module__ == method.__module__ and
|
||||||
callback.__globals__["__file__"] == method.__globals__["__file__"]
|
callback.__globals__["__file__"] == (
|
||||||
|
method.__globals__["__file__"]
|
||||||
|
)
|
||||||
):
|
):
|
||||||
continue
|
continue
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -32,6 +32,7 @@ class Handler(http.server.SimpleHTTPRequestHandler):
|
||||||
"NO_CONTENT": 204
|
"NO_CONTENT": 204
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
def do_GET(self):
|
def do_GET(self):
|
||||||
return self._handle_request(RestMethods.GET)
|
return self._handle_request(RestMethods.GET)
|
||||||
|
|
||||||
|
|
@ -156,7 +157,6 @@ class Handler(http.server.SimpleHTTPRequestHandler):
|
||||||
self.wfile.write(message.encode())
|
self.wfile.write(message.encode())
|
||||||
return message
|
return message
|
||||||
|
|
||||||
|
|
||||||
def _handle_callback_result(self, result, rest_method):
|
def _handle_callback_result(self, result, rest_method):
|
||||||
"""Send response to request based on result of callback.
|
"""Send response to request based on result of callback.
|
||||||
:param result: Result returned by callback.
|
:param result: Result returned by callback.
|
||||||
|
|
@ -232,7 +232,7 @@ class Handler(http.server.SimpleHTTPRequestHandler):
|
||||||
|
|
||||||
:param item: Item stored during callback registration with all info.
|
:param item: Item stored during callback registration with all info.
|
||||||
:type item: dict
|
:type item: dict
|
||||||
:param parsed_url: Url parsed with urllib (separated path, query, etc.).
|
:param parsed_url: Url parsed with urllib (separated path, query, etc).
|
||||||
:type parsed_url: ParseResult
|
:type parsed_url: ParseResult
|
||||||
:param rest_method: Rest api method (GET, POST, etc.).
|
:param rest_method: Rest api method (GET, POST, etc.).
|
||||||
:type rest_method: RestMethods
|
:type rest_method: RestMethods
|
||||||
|
|
@ -284,7 +284,7 @@ class Handler(http.server.SimpleHTTPRequestHandler):
|
||||||
return callback(*args, **kwargs)
|
return callback(*args, **kwargs)
|
||||||
|
|
||||||
def _handle_statics(self, dirpath, path):
|
def _handle_statics(self, dirpath, path):
|
||||||
"""Return static file in response when file exist in registered destination."""
|
"""Return static file in response when file exist in destination."""
|
||||||
path = os.path.normpath(dirpath + path)
|
path = os.path.normpath(dirpath + path)
|
||||||
|
|
||||||
ctype = self.guess_type(path)
|
ctype = self.guess_type(path)
|
||||||
|
|
@ -327,12 +327,17 @@ class Handler(http.server.SimpleHTTPRequestHandler):
|
||||||
self.send_response(HTTPStatus.OK)
|
self.send_response(HTTPStatus.OK)
|
||||||
self.send_header("Content-type", ctype)
|
self.send_header("Content-type", ctype)
|
||||||
self.send_header("Content-Length", str(file_stat[6]))
|
self.send_header("Content-Length", str(file_stat[6]))
|
||||||
self.send_header("Last-Modified",
|
self.send_header(
|
||||||
self.date_time_string(file_stat.st_mtime))
|
"Last-Modified",
|
||||||
|
self.date_time_string(file_stat.st_mtime)
|
||||||
|
)
|
||||||
self.end_headers()
|
self.end_headers()
|
||||||
self.wfile.write(file_obj.read())
|
self.wfile.write(file_obj.read())
|
||||||
return file_obj
|
return file_obj
|
||||||
except:
|
except Exception:
|
||||||
self.log.error("Failed to read data from file \"{}\"".format(path))
|
log.error(
|
||||||
|
"Failed to read data from file \"{}\"".format(path),
|
||||||
|
exc_info=True
|
||||||
|
)
|
||||||
finally:
|
finally:
|
||||||
file_obj.close()
|
file_obj.close()
|
||||||
|
|
|
||||||
|
|
@ -65,12 +65,22 @@ class HandlerDict(dict):
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return "<{}> {}".format(self.__class__.__name__, str(dict(self)))
|
return "<{}> {}".format(self.__class__.__name__, str(dict(self)))
|
||||||
|
|
||||||
class Params(HandlerDict): pass
|
|
||||||
class UrlData(HandlerDict): pass
|
class Params(HandlerDict):
|
||||||
class RequestData(HandlerDict): pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class UrlData(HandlerDict):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class RequestData(HandlerDict):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
class Query(HandlerDict):
|
class Query(HandlerDict):
|
||||||
"""Class for url query convert to dict and string"""
|
"""Class for url query convert to dict and string."""
|
||||||
|
|
||||||
def __init__(self, query):
|
def __init__(self, query):
|
||||||
if isinstance(query, dict):
|
if isinstance(query, dict):
|
||||||
pass
|
pass
|
||||||
|
|
@ -81,8 +91,10 @@ class Query(HandlerDict):
|
||||||
def get_string(self):
|
def get_string(self):
|
||||||
return urlencode(dict(self), doseq=True)
|
return urlencode(dict(self), doseq=True)
|
||||||
|
|
||||||
|
|
||||||
class Fragment(HandlerDict):
|
class Fragment(HandlerDict):
|
||||||
"""Class for url fragment convert to dict and string"""
|
"""Class for url fragment convert to dict and string."""
|
||||||
|
|
||||||
def __init__(self, fragment):
|
def __init__(self, fragment):
|
||||||
if isinstance(fragment, dict):
|
if isinstance(fragment, dict):
|
||||||
_fragment = fragment
|
_fragment = fragment
|
||||||
|
|
@ -112,13 +124,15 @@ class Fragment(HandlerDict):
|
||||||
)
|
)
|
||||||
return "&".join(items)
|
return "&".join(items)
|
||||||
|
|
||||||
|
|
||||||
class RequestInfo:
|
class RequestInfo:
|
||||||
"""Object that can be passed to callback as argument.
|
"""Object that can be passed to callback as argument.
|
||||||
|
|
||||||
Contain necessary data for handling request.
|
Contain necessary data for handling request.
|
||||||
Object is created to single use and can be used similar to dict.
|
Object is created to single use and can be used similar to dict.
|
||||||
|
|
||||||
:param url_data: Data collected from path when path with dynamic keys is matching.
|
:param url_data: Data collected from path when path with dynamic keys
|
||||||
|
is matching.
|
||||||
:type url_data: dict, None
|
:type url_data: dict, None
|
||||||
:param request_data: Data of body from request.
|
:param request_data: Data of body from request.
|
||||||
:type request_data: dict, None
|
:type request_data: dict, None
|
||||||
|
|
@ -166,14 +180,15 @@ class CallbackResult:
|
||||||
"""Can be used as return value of callback.
|
"""Can be used as return value of callback.
|
||||||
|
|
||||||
It is possible to specify status code, success boolean, message and data
|
It is possible to specify status code, success boolean, message and data
|
||||||
for specify head and body of request response. `abort` should be rather used
|
for specify head and body of request response. `abort` should be rather
|
||||||
when result is error.
|
used when result is error.
|
||||||
|
|
||||||
:param status_code: Status code of result.
|
:param status_code: Status code of result.
|
||||||
:type status_code: int
|
:type status_code: int
|
||||||
:param success: Success is key in body, may be used for handling response.
|
:param success: Success is key in body, may be used for handling response.
|
||||||
:type success: bool
|
:type success: bool
|
||||||
:param message: Similar to success, message is key in body and may be used for handling response.
|
:param message: Similar to success, message is key in body and may
|
||||||
|
be used for handling response.
|
||||||
:type message: str, None
|
:type message: str, None
|
||||||
:param data: Data is also key for body in response.
|
:param data: Data is also key for body in response.
|
||||||
:type data: dict, None
|
:type data: dict, None
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue