mirror of
https://github.com/RYGhub/royalnet.git
synced 2024-11-23 19:44:20 +00:00
A lot of progress on a lot of things
This commit is contained in:
parent
c3e77fa5e6
commit
353b94f1ba
13 changed files with 164 additions and 238 deletions
|
@ -1,19 +1 @@
|
||||||
"""A Pack that is imported by default by all Royalnet instances."""
|
"""A Pack that is imported by default by all Royalnet instances."""
|
||||||
|
|
||||||
from . import commands, tables, stars, events
|
|
||||||
from .commands import available_commands
|
|
||||||
from .tables import available_tables
|
|
||||||
from .stars import available_page_stars, available_exception_stars
|
|
||||||
from .events import available_events
|
|
||||||
|
|
||||||
__all__ = [
|
|
||||||
"commands",
|
|
||||||
"tables",
|
|
||||||
"stars",
|
|
||||||
"events",
|
|
||||||
"available_commands",
|
|
||||||
"available_tables",
|
|
||||||
"available_page_stars",
|
|
||||||
"available_exception_stars",
|
|
||||||
"available_events",
|
|
||||||
]
|
|
||||||
|
|
|
@ -7,10 +7,5 @@ available_page_stars = [
|
||||||
ApiRoyalnetVersionStar,
|
ApiRoyalnetVersionStar,
|
||||||
]
|
]
|
||||||
|
|
||||||
# Enter the ExceptionStars of your Pack here!
|
|
||||||
available_exception_stars = [
|
|
||||||
|
|
||||||
]
|
|
||||||
|
|
||||||
# Don't change this, it should automatically generate __all__
|
# Don't change this, it should automatically generate __all__
|
||||||
__all__ = [star.__name__ for star in [*available_page_stars, *available_exception_stars]]
|
__all__ = [star.__name__ for star in available_page_stars]
|
||||||
|
|
|
@ -1,15 +1,11 @@
|
||||||
import royalnet
|
import royalnet.version as rv
|
||||||
from starlette.requests import Request
|
from royalnet.constellation import ApiStar
|
||||||
from starlette.responses import *
|
|
||||||
from royalnet.constellation import PageStar
|
|
||||||
|
|
||||||
|
|
||||||
class ApiRoyalnetVersionStar(PageStar):
|
class ApiRoyalnetVersionStar(ApiStar):
|
||||||
path = "/api/royalnet/version"
|
path = "/api/royalnet/version"
|
||||||
|
|
||||||
async def page(self, request: Request) -> JSONResponse:
|
async def api(self, data: dict) -> dict:
|
||||||
return JSONResponse({
|
return {
|
||||||
"version": {
|
"semantic": rv.semantic
|
||||||
"semantic": royalnet.__version__,
|
|
||||||
}
|
}
|
||||||
})
|
|
||||||
|
|
28
royalnet/backpack/tables/tokens.py
Normal file
28
royalnet/backpack/tables/tokens.py
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
import datetime
|
||||||
|
from sqlalchemy import *
|
||||||
|
from sqlalchemy.orm import *
|
||||||
|
from sqlalchemy.ext.declarative import declared_attr
|
||||||
|
|
||||||
|
|
||||||
|
class Token:
|
||||||
|
__tablename__ = "tokens"
|
||||||
|
|
||||||
|
@declared_attr
|
||||||
|
def token(self):
|
||||||
|
return Column(String, primary_key=True)
|
||||||
|
|
||||||
|
@declared_attr
|
||||||
|
def user_id(self):
|
||||||
|
return Column(Integer, ForeignKey("users.uid"), nullable=False)
|
||||||
|
|
||||||
|
@declared_attr
|
||||||
|
def user(self):
|
||||||
|
return relationship("User", backref="tokens")
|
||||||
|
|
||||||
|
@declared_attr
|
||||||
|
def expiration(self):
|
||||||
|
return Column(DateTime, nullable=False)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def expired(self):
|
||||||
|
return datetime.datetime.now() > self.expiration
|
|
@ -15,13 +15,17 @@ You can install them with: ::
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from .constellation import Constellation
|
from .constellation import Constellation
|
||||||
from .star import Star, PageStar, ExceptionStar
|
from .star import Star
|
||||||
from .shoot import shoot
|
from .pagestar import PageStar
|
||||||
|
from .apistar import ApiStar
|
||||||
|
from .jsonapi import api_response, api_success, api_error
|
||||||
|
|
||||||
__all__ = [
|
__all__ = [
|
||||||
"Constellation",
|
"Constellation",
|
||||||
"Star",
|
"Star",
|
||||||
"PageStar",
|
"PageStar",
|
||||||
"ExceptionStar",
|
"ApiStar",
|
||||||
"shoot",
|
"api_response",
|
||||||
|
"api_success",
|
||||||
|
"api_error",
|
||||||
]
|
]
|
||||||
|
|
26
royalnet/constellation/apistar.py
Normal file
26
royalnet/constellation/apistar.py
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
from typing import *
|
||||||
|
from json import JSONDecodeError
|
||||||
|
from abc import *
|
||||||
|
from starlette.requests import Request
|
||||||
|
from starlette.responses import JSONResponse
|
||||||
|
from .pagestar import PageStar
|
||||||
|
from .jsonapi import api_error, api_success
|
||||||
|
|
||||||
|
|
||||||
|
class ApiStar(PageStar, ABC):
|
||||||
|
async def page(self, request: Request) -> JSONResponse:
|
||||||
|
if request.query_params:
|
||||||
|
data = request.query_params
|
||||||
|
else:
|
||||||
|
try:
|
||||||
|
data = await request.json()
|
||||||
|
except JSONDecodeError:
|
||||||
|
data = {}
|
||||||
|
try:
|
||||||
|
response = await self.api(data)
|
||||||
|
except Exception as e:
|
||||||
|
return api_error(e)
|
||||||
|
return api_success(response)
|
||||||
|
|
||||||
|
async def api(self, data: dict) -> dict:
|
||||||
|
raise NotImplementedError()
|
|
@ -8,7 +8,7 @@ import royalnet.alchemy as ra
|
||||||
import royalnet.herald as rh
|
import royalnet.herald as rh
|
||||||
import royalnet.utils as ru
|
import royalnet.utils as ru
|
||||||
import royalnet.commands as rc
|
import royalnet.commands as rc
|
||||||
from .star import PageStar, ExceptionStar
|
from .pagestar import PageStar
|
||||||
from ..utils import init_logging
|
from ..utils import init_logging
|
||||||
|
|
||||||
|
|
||||||
|
@ -42,7 +42,12 @@ class Constellation:
|
||||||
for pack_name in pack_names:
|
for pack_name in pack_names:
|
||||||
log.debug(f"Importing pack: {pack_name}")
|
log.debug(f"Importing pack: {pack_name}")
|
||||||
try:
|
try:
|
||||||
packs[pack_name] = importlib.import_module(pack_name)
|
packs[pack_name] = {
|
||||||
|
"commands": importlib.import_module(f"{pack_name}.commands"),
|
||||||
|
"events": importlib.import_module(f"{pack_name}.events"),
|
||||||
|
"stars": importlib.import_module(f"{pack_name}.stars"),
|
||||||
|
"tables": importlib.import_module(f"{pack_name}.tables"),
|
||||||
|
}
|
||||||
except ImportError as e:
|
except ImportError as e:
|
||||||
log.error(f"Error during the import of {pack_name}: {e}")
|
log.error(f"Error during the import of {pack_name}: {e}")
|
||||||
log.info(f"Packs: {len(packs)} imported")
|
log.info(f"Packs: {len(packs)} imported")
|
||||||
|
@ -60,7 +65,7 @@ class Constellation:
|
||||||
tables = set()
|
tables = set()
|
||||||
for pack in packs.values():
|
for pack in packs.values():
|
||||||
try:
|
try:
|
||||||
tables = tables.union(pack.available_tables)
|
tables = tables.union(pack["tables"].available_tables)
|
||||||
except AttributeError:
|
except AttributeError:
|
||||||
log.warning(f"Pack `{pack}` does not have the `available_tables` attribute.")
|
log.warning(f"Pack `{pack}` does not have the `available_tables` attribute.")
|
||||||
continue
|
continue
|
||||||
|
@ -99,7 +104,7 @@ class Constellation:
|
||||||
pack = packs[pack_name]
|
pack = packs[pack_name]
|
||||||
pack_cfg = packs_cfg.get(pack_name, {})
|
pack_cfg = packs_cfg.get(pack_name, {})
|
||||||
try:
|
try:
|
||||||
events = pack.available_events
|
events = pack["events"].available_events
|
||||||
except AttributeError:
|
except AttributeError:
|
||||||
log.warning(f"Pack `{pack}` does not have the `available_events` attribute.")
|
log.warning(f"Pack `{pack}` does not have the `available_events` attribute.")
|
||||||
else:
|
else:
|
||||||
|
@ -118,17 +123,11 @@ class Constellation:
|
||||||
pack = packs[pack_name]
|
pack = packs[pack_name]
|
||||||
pack_cfg = packs_cfg.get(pack_name, {})
|
pack_cfg = packs_cfg.get(pack_name, {})
|
||||||
try:
|
try:
|
||||||
page_stars = pack.available_page_stars
|
page_stars = pack["stars"].available_page_stars
|
||||||
except AttributeError:
|
except AttributeError:
|
||||||
log.warning(f"Pack `{pack}` does not have the `available_page_stars` attribute.")
|
log.warning(f"Pack `{pack}` does not have the `available_page_stars` attribute.")
|
||||||
else:
|
else:
|
||||||
self.register_page_stars(page_stars, pack_cfg)
|
self.register_page_stars(page_stars, pack_cfg)
|
||||||
try:
|
|
||||||
exc_stars = pack.available_exception_stars
|
|
||||||
except AttributeError:
|
|
||||||
log.warning(f"Pack `{pack}` does not have the `available_exception_stars` attribute.")
|
|
||||||
else:
|
|
||||||
self.register_exc_stars(exc_stars, pack_cfg)
|
|
||||||
log.info(f"PageStars: {len(self.starlette.routes)} stars")
|
log.info(f"PageStars: {len(self.starlette.routes)} stars")
|
||||||
log.info(f"ExceptionStars: {len(self.starlette.exception_handlers)} stars")
|
log.info(f"ExceptionStars: {len(self.starlette.exception_handlers)} stars")
|
||||||
|
|
||||||
|
@ -259,14 +258,6 @@ class Constellation:
|
||||||
|
|
||||||
return page_star.path, f, page_star.methods
|
return page_star.path, f, page_star.methods
|
||||||
|
|
||||||
def _exc_star_wrapper(self, exc_star: ExceptionStar):
|
|
||||||
async def f(request):
|
|
||||||
self._first_page_check()
|
|
||||||
log.info(f"Running {exc_star}")
|
|
||||||
return await exc_star.page(request)
|
|
||||||
|
|
||||||
return exc_star.error, f
|
|
||||||
|
|
||||||
def register_page_stars(self, page_stars: List[Type[PageStar]], pack_cfg: Dict[str, Any]):
|
def register_page_stars(self, page_stars: List[Type[PageStar]], pack_cfg: Dict[str, Any]):
|
||||||
for SelectedPageStar in page_stars:
|
for SelectedPageStar in page_stars:
|
||||||
log.debug(f"Registering: {SelectedPageStar.path} -> {SelectedPageStar.__qualname__}")
|
log.debug(f"Registering: {SelectedPageStar.path} -> {SelectedPageStar.__qualname__}")
|
||||||
|
@ -279,18 +270,6 @@ class Constellation:
|
||||||
continue
|
continue
|
||||||
self.starlette.add_route(*self._page_star_wrapper(page_star_instance))
|
self.starlette.add_route(*self._page_star_wrapper(page_star_instance))
|
||||||
|
|
||||||
def register_exc_stars(self, exc_stars: List[Type[ExceptionStar]], pack_cfg: Dict[str, Any]):
|
|
||||||
for SelectedExcStar in exc_stars:
|
|
||||||
log.debug(f"Registering: {SelectedExcStar.error} -> {SelectedExcStar.__qualname__}")
|
|
||||||
try:
|
|
||||||
exc_star_instance = SelectedExcStar(interface=self.Interface(pack_cfg))
|
|
||||||
except Exception as e:
|
|
||||||
log.error(f"Skipping: "
|
|
||||||
f"{SelectedExcStar.__qualname__} - {e.__class__.__qualname__} in the initialization.")
|
|
||||||
ru.sentry_exc(e)
|
|
||||||
continue
|
|
||||||
self.starlette.add_exception_handler(*self._exc_star_wrapper(exc_star_instance))
|
|
||||||
|
|
||||||
def run_blocking(self):
|
def run_blocking(self):
|
||||||
log.info(f"Running Constellation on https://{self.address}:{self.port}/...")
|
log.info(f"Running Constellation on https://{self.address}:{self.port}/...")
|
||||||
loop: aio.AbstractEventLoop = aio.get_event_loop()
|
loop: aio.AbstractEventLoop = aio.get_event_loop()
|
||||||
|
|
32
royalnet/constellation/jsonapi.py
Normal file
32
royalnet/constellation/jsonapi.py
Normal file
|
@ -0,0 +1,32 @@
|
||||||
|
from typing import *
|
||||||
|
try:
|
||||||
|
from starlette.responses import JSONResponse
|
||||||
|
except ImportError:
|
||||||
|
JSONResponse = None
|
||||||
|
|
||||||
|
|
||||||
|
def api_response(data: dict, code: int, headers: dict = None) -> JSONResponse:
|
||||||
|
if headers is None:
|
||||||
|
headers = {}
|
||||||
|
full_headers = {
|
||||||
|
**headers,
|
||||||
|
"Access-Control-Allow-Origin": "*",
|
||||||
|
}
|
||||||
|
return JSONResponse(data, status_code=code, headers=full_headers)
|
||||||
|
|
||||||
|
|
||||||
|
def api_success(data: dict) -> JSONResponse:
|
||||||
|
result = {
|
||||||
|
"success": True,
|
||||||
|
"data": data
|
||||||
|
}
|
||||||
|
return api_response(result, code=200)
|
||||||
|
|
||||||
|
|
||||||
|
def api_error(error: Exception, code: int = 500) -> JSONResponse:
|
||||||
|
result = {
|
||||||
|
"success": False,
|
||||||
|
"error_type": error.__class__.__qualname__,
|
||||||
|
"error_args": list(error.args)
|
||||||
|
}
|
||||||
|
return api_response(result, code=code)
|
34
royalnet/constellation/pagestar.py
Normal file
34
royalnet/constellation/pagestar.py
Normal file
|
@ -0,0 +1,34 @@
|
||||||
|
from typing import *
|
||||||
|
from .star import Star
|
||||||
|
|
||||||
|
|
||||||
|
class PageStar(Star):
|
||||||
|
"""A PageStar is a class representing a single route of the website (for example, ``/api/user/get``).
|
||||||
|
|
||||||
|
To create a new website route you should create a new class inheriting from this class with a function overriding
|
||||||
|
:meth:`.page`, :attr:`.path` and optionally :attr:`.methods`."""
|
||||||
|
|
||||||
|
path: str = NotImplemented
|
||||||
|
"""The route of the star.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
::
|
||||||
|
|
||||||
|
path: str = '/api/user/get'
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
methods: List[str] = ["GET"]
|
||||||
|
"""The HTTP methods supported by the Star, in form of a list.
|
||||||
|
|
||||||
|
By default, a Star only supports the ``GET`` method, but more can be added.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
::
|
||||||
|
|
||||||
|
methods: List[str] = ["GET", "POST", "PUT", "DELETE"]
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __repr__(self):
|
||||||
|
return f"<{self.__class__.__qualname__}: {self.path}>"
|
|
@ -1,13 +0,0 @@
|
||||||
try:
|
|
||||||
from starlette.responses import JSONResponse
|
|
||||||
except ImportError:
|
|
||||||
JSONResponse = None
|
|
||||||
|
|
||||||
|
|
||||||
def shoot(code: int, description: str) -> JSONResponse:
|
|
||||||
"""Create a error :class:`~starlette.response.JSONResponse` with the passed error code and description."""
|
|
||||||
if JSONResponse is None:
|
|
||||||
raise ImportError("'constellation' extra is not installed")
|
|
||||||
return JSONResponse({
|
|
||||||
"error": description
|
|
||||||
}, status_code=code)
|
|
|
@ -48,63 +48,3 @@ class Star:
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return f"<{self.__class__.__qualname__}>"
|
return f"<{self.__class__.__qualname__}>"
|
||||||
|
|
||||||
|
|
||||||
class PageStar(Star):
|
|
||||||
"""A PageStar is a class representing a single route of the website (for example, ``/api/user/get``).
|
|
||||||
|
|
||||||
To create a new website route you should create a new class inheriting from this class with a function overriding
|
|
||||||
:meth:`.page` and changing the values of :attr:`.path` and optionally :attr:`.methods`."""
|
|
||||||
path: str = NotImplemented
|
|
||||||
"""The route of the star.
|
|
||||||
|
|
||||||
Example:
|
|
||||||
::
|
|
||||||
|
|
||||||
path: str = '/api/user/get'
|
|
||||||
|
|
||||||
"""
|
|
||||||
|
|
||||||
methods: List[str] = ["GET"]
|
|
||||||
"""The HTTP methods supported by the Star, in form of a list.
|
|
||||||
|
|
||||||
By default, a Star only supports the ``GET`` method, but more can be added.
|
|
||||||
|
|
||||||
Example:
|
|
||||||
::
|
|
||||||
|
|
||||||
methods: List[str] = ["GET", "POST", "PUT", "DELETE"]
|
|
||||||
|
|
||||||
"""
|
|
||||||
|
|
||||||
def __repr__(self):
|
|
||||||
return f"<{self.__class__.__qualname__}: {self.path}>"
|
|
||||||
|
|
||||||
|
|
||||||
class ExceptionStar(Star):
|
|
||||||
"""An ExceptionStar is a class that handles an :class:`Exception` raised by another star by returning a different
|
|
||||||
response than the one originally intended.
|
|
||||||
|
|
||||||
The handled exception type is specified in the :attr:`.error`.
|
|
||||||
|
|
||||||
It can also handle standard webserver errors, such as ``404 Not Found``:
|
|
||||||
to handle them, set :attr:`.error` to an :class:`int` of the corresponding error code.
|
|
||||||
|
|
||||||
To create a new exception handler you should create a new class inheriting from this class with a function
|
|
||||||
overriding :meth:`.page` and changing the value of :attr:`.error`."""
|
|
||||||
error: Union[Type[Exception], int]
|
|
||||||
"""The error that should be handled by this star. It should be either a subclass of :exc:`Exception`,
|
|
||||||
or the :class:`int` of an HTTP error code.
|
|
||||||
|
|
||||||
Examples:
|
|
||||||
::
|
|
||||||
|
|
||||||
error: int = 404
|
|
||||||
|
|
||||||
::
|
|
||||||
|
|
||||||
error: Type[Exception] = ValueError
|
|
||||||
"""
|
|
||||||
|
|
||||||
def __repr__(self):
|
|
||||||
return f"<{self.__class__.__qualname__}: handles {self.error}>"
|
|
||||||
|
|
|
@ -19,7 +19,12 @@ def run(config_filename, file_format):
|
||||||
packs = {}
|
packs = {}
|
||||||
for pack_name in pack_names:
|
for pack_name in pack_names:
|
||||||
try:
|
try:
|
||||||
packs[pack_name] = importlib.import_module(pack_name)
|
packs[pack_name] = {
|
||||||
|
"commands": importlib.import_module(f"{pack_name}.commands"),
|
||||||
|
"events": importlib.import_module(f"{pack_name}.events"),
|
||||||
|
"stars": importlib.import_module(f"{pack_name}.stars"),
|
||||||
|
"tables": importlib.import_module(f"{pack_name}.tables"),
|
||||||
|
}
|
||||||
except ImportError as e:
|
except ImportError as e:
|
||||||
p(f"Skipping `{pack_name}`: {e}", err=True)
|
p(f"Skipping `{pack_name}`: {e}", err=True)
|
||||||
continue
|
continue
|
||||||
|
@ -30,7 +35,7 @@ def run(config_filename, file_format):
|
||||||
lines = []
|
lines = []
|
||||||
|
|
||||||
try:
|
try:
|
||||||
commands = pack.available_commands
|
commands = pack["commands"].available_commands
|
||||||
except AttributeError:
|
except AttributeError:
|
||||||
p(f"Pack `{pack}` does not have the `available_commands` attribute.", err=True)
|
p(f"Pack `{pack}` does not have the `available_commands` attribute.", err=True)
|
||||||
continue
|
continue
|
||||||
|
@ -41,93 +46,6 @@ def run(config_filename, file_format):
|
||||||
for line in lines:
|
for line in lines:
|
||||||
p(line)
|
p(line)
|
||||||
|
|
||||||
elif file_format == "markdown":
|
|
||||||
p("<!--This documentation was autogenerated with `python -m royalnet.generate -f markdown`.-->")
|
|
||||||
p("")
|
|
||||||
for pack_name in packs:
|
|
||||||
pack = packs[pack_name]
|
|
||||||
p(f"# `{pack_name}`")
|
|
||||||
p("")
|
|
||||||
if pack.__doc__:
|
|
||||||
p(f"{pack.__doc__}")
|
|
||||||
p("")
|
|
||||||
|
|
||||||
try:
|
|
||||||
commands = pack.available_commands
|
|
||||||
except AttributeError:
|
|
||||||
p(f"Pack `{pack}` does not have the `available_commands` attribute.", err=True)
|
|
||||||
else:
|
|
||||||
p(f"## Commands")
|
|
||||||
p("")
|
|
||||||
for command in commands:
|
|
||||||
p(f"### `{command.name}`")
|
|
||||||
p("")
|
|
||||||
p(f"{command.description}")
|
|
||||||
p("")
|
|
||||||
if command.__doc__:
|
|
||||||
p(f"{command.__doc__}")
|
|
||||||
p("")
|
|
||||||
if len(command.aliases) > 0:
|
|
||||||
p(f"> Aliases: {''.join(['`' + alias + '` ' for alias in command.aliases])}")
|
|
||||||
p("")
|
|
||||||
|
|
||||||
try:
|
|
||||||
events = pack.available_events
|
|
||||||
except AttributeError:
|
|
||||||
p(f"Pack `{pack}` does not have the `available_events` attribute.", err=True)
|
|
||||||
else:
|
|
||||||
p(f"## Events")
|
|
||||||
p("")
|
|
||||||
for event in events:
|
|
||||||
p(f"### `{event.name}`")
|
|
||||||
p("")
|
|
||||||
if event.__doc__:
|
|
||||||
p(f"{event.__doc__}")
|
|
||||||
p("")
|
|
||||||
|
|
||||||
try:
|
|
||||||
page_stars = pack.available_page_stars
|
|
||||||
except AttributeError:
|
|
||||||
p(f"Pack `{pack}` does not have the `available_page_stars` attribute.", err=True)
|
|
||||||
else:
|
|
||||||
p(f"## Page Stars")
|
|
||||||
p("")
|
|
||||||
for page_star in page_stars:
|
|
||||||
p(f"### `{page_star.path}`")
|
|
||||||
p("")
|
|
||||||
if page_star.__doc__:
|
|
||||||
p(f"{page_star.__doc__}")
|
|
||||||
p("")
|
|
||||||
|
|
||||||
try:
|
|
||||||
exc_stars = pack.available_exception_stars
|
|
||||||
except AttributeError:
|
|
||||||
p(f"Pack `{pack}` does not have the `available_exception_stars` attribute.", err=True)
|
|
||||||
else:
|
|
||||||
p(f"## Exception Stars")
|
|
||||||
p("")
|
|
||||||
for exc_star in exc_stars:
|
|
||||||
p(f"### `{exc_star.error}`")
|
|
||||||
p("")
|
|
||||||
if exc_star.__doc__:
|
|
||||||
p(f"{exc_star.__doc__}")
|
|
||||||
p("")
|
|
||||||
|
|
||||||
try:
|
|
||||||
tables = pack.available_tables
|
|
||||||
except AttributeError:
|
|
||||||
p(f"Pack `{pack}` does not have the `available_tables` attribute.", err=True)
|
|
||||||
else:
|
|
||||||
p(f"## Tables")
|
|
||||||
p("")
|
|
||||||
for table in tables:
|
|
||||||
p(f"### `{table.__tablename__}`")
|
|
||||||
p("")
|
|
||||||
# TODO: list columns
|
|
||||||
if table.__doc__:
|
|
||||||
p(f"{table.__doc__}")
|
|
||||||
p("")
|
|
||||||
|
|
||||||
else:
|
else:
|
||||||
raise click.ClickException("Unknown format")
|
raise click.ClickException("Unknown format")
|
||||||
|
|
||||||
|
|
|
@ -7,7 +7,7 @@ from sqlalchemy.schema import Table
|
||||||
from royalnet.commands import *
|
from royalnet.commands import *
|
||||||
import royalnet.utils as ru
|
import royalnet.utils as ru
|
||||||
import royalnet.alchemy as ra
|
import royalnet.alchemy as ra
|
||||||
import royalnet.backpack as rb
|
import royalnet.backpack.tables as rbt
|
||||||
import royalnet.herald as rh
|
import royalnet.herald as rh
|
||||||
import traceback
|
import traceback
|
||||||
|
|
||||||
|
@ -20,7 +20,7 @@ class Serf:
|
||||||
Discord)."""
|
Discord)."""
|
||||||
interface_name = NotImplemented
|
interface_name = NotImplemented
|
||||||
|
|
||||||
_master_table: type = rb.tables.User
|
_master_table: type = rbt.User
|
||||||
_identity_table: type = NotImplemented
|
_identity_table: type = NotImplemented
|
||||||
_identity_column: str = NotImplemented
|
_identity_column: str = NotImplemented
|
||||||
|
|
||||||
|
@ -39,7 +39,12 @@ class Serf:
|
||||||
for pack_name in pack_names:
|
for pack_name in pack_names:
|
||||||
log.debug(f"Importing pack: {pack_name}")
|
log.debug(f"Importing pack: {pack_name}")
|
||||||
try:
|
try:
|
||||||
packs[pack_name] = importlib.import_module(pack_name)
|
packs[pack_name] = {
|
||||||
|
"commands": importlib.import_module(f"{pack_name}.commands"),
|
||||||
|
"events": importlib.import_module(f"{pack_name}.events"),
|
||||||
|
"stars": importlib.import_module(f"{pack_name}.stars"),
|
||||||
|
"tables": importlib.import_module(f"{pack_name}.tables"),
|
||||||
|
}
|
||||||
except ImportError as e:
|
except ImportError as e:
|
||||||
log.error(f"{e.__class__.__name__} during the import of {pack_name}:\n"
|
log.error(f"{e.__class__.__name__} during the import of {pack_name}:\n"
|
||||||
f"{traceback.format_exception(*sys.exc_info())}")
|
f"{traceback.format_exception(*sys.exc_info())}")
|
||||||
|
@ -68,7 +73,7 @@ class Serf:
|
||||||
tables = set()
|
tables = set()
|
||||||
for pack in packs.values():
|
for pack in packs.values():
|
||||||
try:
|
try:
|
||||||
tables = tables.union(pack.available_tables)
|
tables = tables.union(pack["tables"].available_tables)
|
||||||
except AttributeError:
|
except AttributeError:
|
||||||
log.warning(f"Pack `{pack}` does not have the `available_tables` attribute.")
|
log.warning(f"Pack `{pack}` does not have the `available_tables` attribute.")
|
||||||
continue
|
continue
|
||||||
|
@ -95,13 +100,13 @@ class Serf:
|
||||||
pack = packs[pack_name]
|
pack = packs[pack_name]
|
||||||
pack_cfg = packs_cfg.get(pack_name, {})
|
pack_cfg = packs_cfg.get(pack_name, {})
|
||||||
try:
|
try:
|
||||||
events = pack.available_events
|
events = pack["events"].available_events
|
||||||
except AttributeError:
|
except AttributeError:
|
||||||
log.warning(f"Pack `{pack}` does not have the `available_events` attribute.")
|
log.warning(f"Pack `{pack}` does not have the `available_events` attribute.")
|
||||||
else:
|
else:
|
||||||
self.register_events(events, pack_cfg)
|
self.register_events(events, pack_cfg)
|
||||||
try:
|
try:
|
||||||
commands = pack.available_commands
|
commands = pack["commands"].available_commands
|
||||||
except AttributeError:
|
except AttributeError:
|
||||||
log.warning(f"Pack `{pack}` does not have the `available_commands` attribute.")
|
log.warning(f"Pack `{pack}` does not have the `available_commands` attribute.")
|
||||||
else:
|
else:
|
||||||
|
|
Loading…
Reference in a new issue