Coverage for /home/runner/work/viur-core/viur-core/viur/src/viur/core/prototypes/skelmodule.py: 0%

39 statements  

« prev     ^ index     » next       coverage.py v7.6.1, created at 2024-09-03 13:41 +0000

1import os 

2import yaml 

3import logging 

4from viur.core import Module, db 

5from viur.core.config import conf 

6from viur.core.skeleton import skeletonByKind, Skeleton, SkeletonInstance 

7import typing as t 

8 

9 

10SINGLE_ORDER_TYPE = str | tuple[str, db.SortOrder] 

11""" 

12Type for exactly one sort order definitions. 

13""" 

14 

15ORDER_TYPE = SINGLE_ORDER_TYPE | tuple[SINGLE_ORDER_TYPE] | list[SINGLE_ORDER_TYPE] | dict[str, str | int] | None 

16""" 

17Type for sort order definitions (any amount of single order definitions). 

18""" 

19 

20DEFAULT_ORDER_TYPE = ORDER_TYPE | t.Callable[[db.Query], ORDER_TYPE] 

21""" 

22Type for default sort order definitions. 

23""" 

24 

25 

26def __load_indexes_from_file() -> dict[str, list]: 

27 """ 

28 Loads all indexes from the index.yaml and stores it in a dictionary sorted by the module(kind) 

29 :return A dictionary of indexes per module 

30 """ 

31 indexes_dict = {} 

32 try: 

33 with open(os.path.join(conf.instance.project_base_path, "index.yaml"), "r") as file: 

34 indexes = yaml.safe_load(file) 

35 indexes = indexes.get("indexes", []) 

36 for index in indexes: 

37 index["properties"] = [_property["name"] for _property in index["properties"]] 

38 indexes_dict.setdefault(index["kind"], []).append(index) 

39 

40 except FileNotFoundError: 

41 logging.warning("index.yaml not found") 

42 return {} 

43 

44 return indexes_dict 

45 

46 

47DATASTORE_INDEXES = __load_indexes_from_file() 

48 

49 

50class SkelModule(Module): 

51 """ 

52 This is the extended module prototype used by any other ViUR module prototype. 

53 It a prototype which generally is bound to some database model abstracted by the ViUR skeleton system. 

54 """ 

55 

56 kindName: str = None 

57 """ 

58 Name of the datastore kind that is handled by this module. 

59 

60 This information is used to bind a specific :class:`viur.core.skeleton.Skeleton`-class to this 

61 prototype. By default, it is automatically determined from the module's class name, so a module named 

62 `Animal` refers to a Skeleton named `AnimalSkel` and its kindName is `animal`. 

63 

64 For more information, refer to the function :func:`~_resolveSkelCls`. 

65 """ 

66 

67 def __init__(self, *args, **kwargs): 

68 super().__init__(*args, **kwargs) 

69 

70 # automatically determine kindName when not set 

71 if self.kindName is None: 

72 self.kindName = str(type(self).__name__).lower() 

73 

74 # assign index descriptions from index.yaml 

75 self.indexes = DATASTORE_INDEXES.get(self.kindName, []) 

76 

77 def _resolveSkelCls(self, *args, **kwargs) -> t.Type[Skeleton]: 

78 """ 

79 Retrieve the generally associated :class:`viur.core.skeleton.Skeleton` that is used by 

80 the application. 

81 

82 This is either be defined by the member variable *kindName* or by a Skeleton named like the 

83 application class in lower-case order. 

84 

85 If this behavior is not wanted, it can be definitely overridden by defining module-specific 

86 :func:`~viewSkel`, :func:`~addSkel`, or :func:`~editSkel` functions, or by overriding this 

87 function in general. 

88 

89 :return: Returns a Skeleton class that matches the application. 

90 """ 

91 return skeletonByKind(self.kindName) 

92 

93 def baseSkel(self, *args, **kwargs) -> SkeletonInstance: 

94 """ 

95 Returns an instance of an unmodified base skeleton for this module. 

96 

97 This function should only be used in cases where a full, unmodified skeleton of the module is required, e.g. 

98 for administrative or maintenance purposes. 

99 

100 By default, baseSkel is used by :func:`~viewSkel`, :func:`~addSkel`, and :func:`~editSkel`. 

101 """ 

102 return self._resolveSkelCls(*args, **kwargs)()