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

13 statements  

« prev     ^ index     » next       coverage.py v7.6.3, created at 2024-10-16 22:16 +0000

1import copy 

2 

3from viur.core import Module 

4 

5 

6class InstancedModule: 

7 """InstancedModule is a base class for modules, which can be passed as instance to the viur-core. 

8 

9 Normally, the viur-core expects classes from modules and instantiates them during setup. 

10 However, there are cases where you want to pass already instantiated 

11 classes, i.e. module instances, to the core. For example, to integrate 

12 plugins. This is where this base class comes into play. If it is included 

13 as an ADDITIONAL base class to the module class, the viur-core accepts an 

14 instance of this class. The class itself is then no longer 

15 instantiated in the core. 

16 

17 In order to preserve the well-known ViUR module concept, this class 

18 overwrites the __init__ method so that it behaves like a classic object 

19 constructor. The __call__ method then takes on the role of the 

20 conventional __init__ module. 

21 However, as each render requires its own module instance, as the render 

22 itself is then referenced to this instance via the "render" attribute, 

23 several instances are required. Therefore, a copy of the module instance 

24 is created using the internal method `_viur_clone`. This can be changed 

25 if necessary. A shadow-copy is created here by default. 

26 

27 Here an example: 

28 

29 .. code-block:: python 

30 

31 from viur.core.prototypes import List 

32 from viur.core.prototypes.instanced_module import InstancedModule 

33 

34 

35 class MyModule(InstancedModule, List): 

36 def __init__(self, configuration): 

37 self.configuration = configuration 

38 

39 

40 my_module = MyModule( 

41 configuration=... 

42 ) 

43 

44 As you can see, the configuration parameter is set from outside and not 

45 in the class. This may seem a bit strange here, but now imagine that the 

46 class definition `MyModule` is not within the same file but in an imported 

47 pip package. Then this instantiation is much easier than using a subclass. 

48 """ 

49 

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

51 """Overwrite the Module.__init__ and do nothing 

52 

53 Can be overwritten as needed, e.g. to assign instance attributes. 

54 """ 

55 object.__init__(self) 

56 

57 def __call__(self, moduleName: str, modulePath: str, *args, **kwargs) -> "InstancedModule": 

58 """Do the instance initialisation 

59 

60 Take the role of Module.__init__ (and call it). 

61 """ 

62 if modulePath == f"/{moduleName}": 

63 # For the default renderer we use the original instance 

64 instance = self 

65 else: 

66 # For other renderer we use a copy 

67 instance = self._viur_clone() 

68 Module.__init__(instance, moduleName, modulePath, *args, **kwargs) 

69 return instance 

70 

71 def _viur_clone(self): 

72 """Creates a copy for non-standard renderers. 

73 

74 Since viur keeps one instance per render. Can be overwritten if desired. 

75 """ 

76 return copy.copy(self)