schema: Continue

Signed-off-by: Jan Lindemann <jan@janware.com>
This commit is contained in:
Jan Lindemann 2025-02-04 10:27:38 +01:00
commit 173ff0ef5a
2 changed files with 70 additions and 27 deletions

View file

@ -4,8 +4,10 @@ from typing import Optional, Iterable, Any # TODO: Need any for many things, as
import abc
from collections import OrderedDict
from urllib.parse import quote_plus
from ...log import *
from ...misc import load_class
from .ColumnSet import ColumnSet
from .DataType import DataType
@ -32,10 +34,11 @@ class Table(abc.ABC): # export
self.__log_columns: Optional[Iterable[str]] = None
self.__display_columns: Optional[Iterable[str]] = None
self.__column_default: Optional[dict[str, Any]] = None
self.__base_location: Optional[Iterable[str]] = None
self.__location: Optional[Iterable[str]] = None
self.__row_location: Optional[Iterable[str]] = None
self.__base_location_rule: Optional[Iterable[str]] = None
self.__location_rule: Optional[Iterable[str]] = None
self.__row_location_rule: Optional[Iterable[str]] = None
self.__foreign_keys_to_parent_table: Optional[OrderedDict[str, Any]] = None
self.__model_class: Optional[Any] = None
@property
def __columns(self) -> OrderedDict[str, Any]:
@ -101,7 +104,8 @@ class Table(abc.ABC): # export
@abc.abstractmethod
def _display_columns(self) -> Iterable[str]:
return self._primary_keys()
return None
#return self._primary_keys()
@abc.abstractmethod
def _nullable_columns(self) -> Iterable[str]:
@ -123,29 +127,31 @@ class Table(abc.ABC): # export
slog(WARNING, f'Returning None model name for table {self.name}')
return None
def _model_class(self) -> Optional[Any]:
slog(WARNING, f'Returning None model class for table {self.name}')
throw(ERR, "Not implemented")
return None
def _model_module_search_paths(self) -> list[tuple[str, type]]:
return self.schema.model_module_search_paths # Fall back to Schema-global default
@abc.abstractmethod
def _query_name(self) -> str:
return self.__name
return 'tbl/' + self.__name
@abc.abstractmethod
def _row_query_name(self) -> str:
return 'row/' + self.__name
# -- common URL schema for all data
def _base_location(self) -> Optional[str]:
def _base_location_rule(self) -> Optional[str]:
return f'/{self.name}'
def _location(self) -> Optional[str]:
def _location_rule(self) -> Optional[str]:
ret = ''
for col in self.__schema.access_defining_columns:
if col in self.primary_keys:
ret += f'/<{col}>'
ret += '/' + self.base_location
ret += self.base_location_rule
return ret
def _row_location(self) -> Optional[str]:
ret = self._location()
def _row_location_rule(self) -> Optional[str]:
ret = self._location_rule()
if ret is not None:
for col in self.primary_keys:
if col not in self.__schema.access_defining_columns:
@ -185,26 +191,55 @@ class Table(abc.ABC): # export
def model_name(self) -> Optional[str]:
return self._model_name()
@property
def model_class(self) -> Any:
if self.__model_class is None:
pattern = r'^' + self.model_name + '$'
for module_path, base_class in self._model_module_search_paths():
ret = load_class(module_path, base_class, class_name_filter=pattern)
if ret is not None:
self.__model_class = ret
break
else:
throw(ERR, f'No model class found for model {self.model_name}')
return self.__model_class
def query_name(self) -> str:
return self._query_name()
@property
def base_location(self):
if self.__base_location is None:
self.__base_location = self._base_location()
return self.__base_location
def row_query_name(self) -> str:
return self._row_query_name()
@property
def location(self):
if self.__location is None:
self.__location = self._base_location()
return self.__location
def base_location_rule(self):
if self.__base_location_rule is None:
self.__base_location_rule = self._base_location_rule()
return self.__base_location_rule
@property
def row_location(self):
if self.__row_location is None:
self.__row_location = self._row_location()
return self.__row_location
def location_rule(self):
if self.__location_rule is None:
self.__location_rule = self._location_rule()
return self.__location_rule
def location(self, *args, **kwargs):
ret = self.location_rule
for token, val in kwargs.items(): # FIXME: Poor man's row location assembly
ret = re.sub(f'<{token}>', quote_plus(quote_plus(str(val))), ret)
return ret
@property
def row_location_rule(self):
if self.__row_location_rule is None:
self.__row_location_rule = self._row_location_rule()
return self.__row_location_rule
def row_location(self, *args, **kwargs):
ret = self.row_location_rule
for col in self.primary_keys:
if col in kwargs: # FIXME: Poor man's row location assembly
ret = re.sub(f'<{col}>', quote_plus(quote_plus(str(kwargs[col]))), ret)
return ret
@property
def primary_keys(self) -> Iterable[str]: