server.py
ofrak.gui.server
AiohttpOFRAKServer
start(self)
async
Start the server then return.
Source code in ofrak/gui/server.py
async def start(self): # pragma: no cover
"""
Start the server then return.
"""
self.runner = web.AppRunner(self._app)
await self.runner.setup()
server = web.TCPSite(self.runner, host=self._host, port=self._port)
await server.start()
stop(self)
async
Stop the server.
Source code in ofrak/gui/server.py
async def stop(self): # pragma: no cover
"""
Stop the server.
"""
await self.runner.server.shutdown()
await self.runner.cleanup()
run_until_cancelled(self)
async
To be run after start_server
, within an asyncio Task.
cancel() that task to shutdown the server.
Source code in ofrak/gui/server.py
async def run_until_cancelled(self): # pragma: no cover
"""
To be run after `start_server`, within an asyncio Task.
cancel() that task to shutdown the server.
"""
try:
while True:
await asyncio.sleep(1)
except asyncio.CancelledError:
pass
finally:
await self.runner.cleanup()
add_comment(self, request)
async
Expected POST body is a comment in the form Tuple[Optional[Range], str] (serialized to JSON).
Source code in ofrak/gui/server.py
async def add_comment(self, request: Request) -> Response:
"""
Expected POST body is a comment in the form Tuple[Optional[Range], str] (serialized to JSON).
"""
resource = await self._get_resource_for_request(request)
comment = self._serializer.from_pjson(await request.json(), Tuple[Optional[Range], str])
script_str = (
"""
await {resource}.run"""
f"""(AddCommentModifier, AddCommentModifierConfig({comment}))
"""
)
await self.script_builder.add_action(resource, script_str, ActionType.MOD)
try:
result = await resource.run(AddCommentModifier, AddCommentModifierConfig(comment))
await self.script_builder.commit_to_script(resource)
except Exception as e:
await self.script_builder.clear_script_queue(resource)
raise e
return json_response(await self._serialize_component_result(result))
_serialize_resource_model(self, resource_model)
private
Serialize the resource model, stripped of information irrelevant to the frontend.
Source code in ofrak/gui/server.py
def _serialize_resource_model(self, resource_model: ResourceModel) -> PJSONType:
"""
Serialize the resource model, stripped of information irrelevant to the frontend.
"""
result = {
"id": resource_model.id.hex(),
"data_id": resource_model.data_id.hex() if resource_model.data_id else None,
"parent_id": resource_model.parent_id.hex() if resource_model.parent_id else None,
"tags": [tag.__module__ + "." + tag.__qualname__ for tag in resource_model.tags],
"attributes": self._serializer.to_pjson(
resource_model.attributes, Dict[Type[ResourceAttributes], ResourceAttributes]
),
"caption": resource_model.caption,
}
return result
_serialize_resource(self, resource)
private
Serialize the resource as a serialized model, stripped of information irrelevant to the frontend.
Source code in ofrak/gui/server.py
def _serialize_resource(self, resource: Resource) -> PJSONType:
"""
Serialize the resource as a serialized model, stripped of information irrelevant to the
frontend.
"""
return self._serialize_resource_model(resource.get_model())
_serialize_multi_resource(self, resources)
private
Serialize the resources as serialized models, stripped of information irrelevant to the frontend.
Source code in ofrak/gui/server.py
def _serialize_multi_resource(self, resources: Iterable[Resource]) -> PJSONType:
"""
Serialize the resources as serialized models, stripped of information irrelevant to the
frontend.
"""
return list(map(self._serialize_resource, resources))
exceptions_to_http(error_class)
Decorator for a server function that attempts to do some work, and forwards the exception, if any, to the client over HTTP.
Usage:
@exceptions_to_http(MyErrorClass) async def handle_some_request(self, request...): ...
Source code in ofrak/gui/server.py
def exceptions_to_http(error_class: Type[SerializedError]):
"""
Decorator for a server function that attempts to do some work, and
forwards the exception, if any, to the client over HTTP.
Usage:
@exceptions_to_http(MyErrorClass)
async def handle_some_request(self, request...):
...
"""
def exceptions_to_http_decorator(func: Callable):
@functools.wraps(func)
async def wrapper(*args, **kwargs):
try:
return await func(*args, **kwargs)
except Exception as error:
LOGGER.exception("Exception raised in aiohttp endpoint")
return respond_with_error(error, error_class)
return wrapper
return exceptions_to_http_decorator
get_query_string_as_pjson(request)
URL-encoded GET parameters are all strings. For example, None is encoded as 'None',
or 1 as '1', which isn't valid PJSON. We fix this by applying json.loads
on each parameter.
Source code in ofrak/gui/server.py
def get_query_string_as_pjson(request: Request) -> Dict[str, PJSONType]:
"""
URL-encoded GET parameters are all strings. For example, None is encoded as 'None',
or 1 as '1', which isn't valid PJSON. We fix this by applying `json.loads` on each parameter.
"""
return {key: json.loads(value) for key, value in request.query.items()}