Wsgi_15Watt.Route

  1from enum import Enum
  2from importlib import import_module
  3import re
  4from .Exceptions import NotAllowedHttpMethod, InvalidData
  5
  6
  7class HttpMethods(Enum):
  8    """
  9        Die erlaubten HTTP-Methoden
 10    """
 11    GET      = 1
 12    POST     = 2
 13    PUT      = 3
 14    PATCH    = 4
 15    DELETE   = 5
 16    COPY     = 6
 17    HEAD     = 7
 18    OPTIONS  = 8
 19    LINK     = 9
 20    UNLINK   = 10
 21    PURGE    = 11
 22    LOCK     = 12
 23    PROPFIND = 13
 24    VIEW     = 14
 25
 26
 27class Route(object):
 28    """
 29    The route is the connection between the path and the called controller method
 30    """
 31    def __init__(
 32            self,
 33            path: str,
 34            nameController: str,
 35            nameMethod: str,
 36            httpMethod: HttpMethods,
 37            paramsDef: dict = None
 38    ):
 39
 40        if httpMethod not in HttpMethods:
 41            raise NotAllowedHttpMethod(returnMsg=httpMethod.name)
 42
 43        self.__path                = path
 44        self.__nameControllerParts = nameController.split('.')
 45        self.__nameMethod          = nameMethod
 46        self.__methodToCall        = None
 47        self.__httpMethod          = httpMethod
 48        self.__dictParamsDef       = paramsDef
 49        self.__pathRegEx           = self.__buildPathRegEx()
 50
 51        if paramsDef is None:
 52            self.__dictParamsDef = {}
 53        else:
 54            self.__config = paramsDef
 55
 56
 57    @property
 58    def path(self) -> str:
 59        """
 60        Returns the path defined in the route.
 61        """
 62        return self.__path
 63
 64
 65    @property
 66    def methodToCall(self):
 67        """
 68        Returns the method to call.
 69        """
 70        if self.__methodToCall is None:
 71            self.__methodToCall = self.__buildMethod()
 72
 73        return self.__methodToCall
 74
 75
 76    @property
 77    def httpMethod(self) -> HttpMethods:
 78        """
 79        Returns the HTTP-method
 80        """
 81        return self.__httpMethod
 82
 83
 84    @property
 85    def pathRegEx(self) -> str:
 86        """
 87        Returns the RegEx-String to match the route
 88        """
 89        return self.__pathRegEx
 90
 91
 92    def setConfig(self, config: dict):
 93        """
 94        Set the configuration from project root config.py for the route
 95        """
 96        self.__config = config
 97
 98
 99    def match(self, path: str, httpMethod: HttpMethods) -> bool:
100        """
101        Checks if the route matches path and httpMethod
102        """
103        if httpMethod != self.__httpMethod:
104            return False
105
106        path = path.rstrip('/')
107        if '' == path:
108            path = '/'
109        
110        return re.match(f'^{self.__pathRegEx}$', path) is not None
111
112
113    def getParamsFromPath(self, path: str) -> dict:
114        """
115            Returns the parameters from the path
116        """
117        matches = re.match(self.__pathRegEx, path)
118        if matches is None:
119            return {}
120
121        paramsFromPath = {}
122        for placeHolder in self.__dictParamsDef:
123            if 'str' == self.__dictParamsDef[placeHolder]:
124                paramsFromPath[placeHolder] = matches.group(placeHolder)
125            elif 'int' == self.__dictParamsDef[placeHolder]:
126                paramsFromPath[placeHolder] = int(matches.group(placeHolder))
127
128        return paramsFromPath
129
130
131    def __buildMethod(self):
132        """
133        Build the callable method, that will be call for the route
134        """
135        nameModule = '.'.join(self.__nameControllerParts[:-1])
136        nameClass  = self.__nameControllerParts[-1]
137        module     = import_module(name=nameModule)
138        inst       = getattr(module, nameClass)(config=self.__config)
139
140        return getattr(inst, self.__nameMethod)
141
142
143    def __buildPathRegEx(self):
144        """
145        Build the RegEx-String to match the route
146        """
147        strPathRegEx = self.__path
148
149        for placeHolder in re.findall(r'\{[\w]{1,}\}', strPathRegEx):
150            placeHolderPlain = placeHolder.strip('{}')
151
152            if placeHolderPlain not in self.__dictParamsDef:
153                raise InvalidData(returnMsg=f'Parameter "{placeHolderPlain}" not defined in paramsDef. Route = {self.__path}')
154
155            if 'str' == self.__dictParamsDef[placeHolderPlain]:
156                to = "(?P<{n}>[\w\/\-\.]{{1,}})".format(n=placeHolderPlain)
157            elif 'int' == self.__dictParamsDef[placeHolderPlain]:
158                to = "(?P<{n}>[0-9]{{1,}})".format(n=placeHolderPlain)
159            else:
160                raise InvalidData(returnMsg=f'Not allowed data type: {self.__dictParamsDef[placeHolderPlain]}')
161
162            strPathRegEx = strPathRegEx.replace(placeHolder, to)
163        return strPathRegEx
164
165
166    def __str__(self):
167        return f'Route - Path={self.__path} {self.__httpMethod.name} {".".join(self.__nameControllerParts)}.{self.__nameMethod}'
class HttpMethods(enum.Enum):
 8class HttpMethods(Enum):
 9    """
10        Die erlaubten HTTP-Methoden
11    """
12    GET      = 1
13    POST     = 2
14    PUT      = 3
15    PATCH    = 4
16    DELETE   = 5
17    COPY     = 6
18    HEAD     = 7
19    OPTIONS  = 8
20    LINK     = 9
21    UNLINK   = 10
22    PURGE    = 11
23    LOCK     = 12
24    PROPFIND = 13
25    VIEW     = 14

Die erlaubten HTTP-Methoden

GET = <HttpMethods.GET: 1>
POST = <HttpMethods.POST: 2>
PUT = <HttpMethods.PUT: 3>
PATCH = <HttpMethods.PATCH: 4>
DELETE = <HttpMethods.DELETE: 5>
COPY = <HttpMethods.COPY: 6>
HEAD = <HttpMethods.HEAD: 7>
OPTIONS = <HttpMethods.OPTIONS: 8>
PURGE = <HttpMethods.PURGE: 11>
LOCK = <HttpMethods.LOCK: 12>
PROPFIND = <HttpMethods.PROPFIND: 13>
VIEW = <HttpMethods.VIEW: 14>
class Route:
 28class Route(object):
 29    """
 30    The route is the connection between the path and the called controller method
 31    """
 32    def __init__(
 33            self,
 34            path: str,
 35            nameController: str,
 36            nameMethod: str,
 37            httpMethod: HttpMethods,
 38            paramsDef: dict = None
 39    ):
 40
 41        if httpMethod not in HttpMethods:
 42            raise NotAllowedHttpMethod(returnMsg=httpMethod.name)
 43
 44        self.__path                = path
 45        self.__nameControllerParts = nameController.split('.')
 46        self.__nameMethod          = nameMethod
 47        self.__methodToCall        = None
 48        self.__httpMethod          = httpMethod
 49        self.__dictParamsDef       = paramsDef
 50        self.__pathRegEx           = self.__buildPathRegEx()
 51
 52        if paramsDef is None:
 53            self.__dictParamsDef = {}
 54        else:
 55            self.__config = paramsDef
 56
 57
 58    @property
 59    def path(self) -> str:
 60        """
 61        Returns the path defined in the route.
 62        """
 63        return self.__path
 64
 65
 66    @property
 67    def methodToCall(self):
 68        """
 69        Returns the method to call.
 70        """
 71        if self.__methodToCall is None:
 72            self.__methodToCall = self.__buildMethod()
 73
 74        return self.__methodToCall
 75
 76
 77    @property
 78    def httpMethod(self) -> HttpMethods:
 79        """
 80        Returns the HTTP-method
 81        """
 82        return self.__httpMethod
 83
 84
 85    @property
 86    def pathRegEx(self) -> str:
 87        """
 88        Returns the RegEx-String to match the route
 89        """
 90        return self.__pathRegEx
 91
 92
 93    def setConfig(self, config: dict):
 94        """
 95        Set the configuration from project root config.py for the route
 96        """
 97        self.__config = config
 98
 99
100    def match(self, path: str, httpMethod: HttpMethods) -> bool:
101        """
102        Checks if the route matches path and httpMethod
103        """
104        if httpMethod != self.__httpMethod:
105            return False
106
107        path = path.rstrip('/')
108        if '' == path:
109            path = '/'
110        
111        return re.match(f'^{self.__pathRegEx}$', path) is not None
112
113
114    def getParamsFromPath(self, path: str) -> dict:
115        """
116            Returns the parameters from the path
117        """
118        matches = re.match(self.__pathRegEx, path)
119        if matches is None:
120            return {}
121
122        paramsFromPath = {}
123        for placeHolder in self.__dictParamsDef:
124            if 'str' == self.__dictParamsDef[placeHolder]:
125                paramsFromPath[placeHolder] = matches.group(placeHolder)
126            elif 'int' == self.__dictParamsDef[placeHolder]:
127                paramsFromPath[placeHolder] = int(matches.group(placeHolder))
128
129        return paramsFromPath
130
131
132    def __buildMethod(self):
133        """
134        Build the callable method, that will be call for the route
135        """
136        nameModule = '.'.join(self.__nameControllerParts[:-1])
137        nameClass  = self.__nameControllerParts[-1]
138        module     = import_module(name=nameModule)
139        inst       = getattr(module, nameClass)(config=self.__config)
140
141        return getattr(inst, self.__nameMethod)
142
143
144    def __buildPathRegEx(self):
145        """
146        Build the RegEx-String to match the route
147        """
148        strPathRegEx = self.__path
149
150        for placeHolder in re.findall(r'\{[\w]{1,}\}', strPathRegEx):
151            placeHolderPlain = placeHolder.strip('{}')
152
153            if placeHolderPlain not in self.__dictParamsDef:
154                raise InvalidData(returnMsg=f'Parameter "{placeHolderPlain}" not defined in paramsDef. Route = {self.__path}')
155
156            if 'str' == self.__dictParamsDef[placeHolderPlain]:
157                to = "(?P<{n}>[\w\/\-\.]{{1,}})".format(n=placeHolderPlain)
158            elif 'int' == self.__dictParamsDef[placeHolderPlain]:
159                to = "(?P<{n}>[0-9]{{1,}})".format(n=placeHolderPlain)
160            else:
161                raise InvalidData(returnMsg=f'Not allowed data type: {self.__dictParamsDef[placeHolderPlain]}')
162
163            strPathRegEx = strPathRegEx.replace(placeHolder, to)
164        return strPathRegEx
165
166
167    def __str__(self):
168        return f'Route - Path={self.__path} {self.__httpMethod.name} {".".join(self.__nameControllerParts)}.{self.__nameMethod}'

The route is the connection between the path and the called controller method

Route( path: str, nameController: str, nameMethod: str, httpMethod: HttpMethods, paramsDef: dict = None)
32    def __init__(
33            self,
34            path: str,
35            nameController: str,
36            nameMethod: str,
37            httpMethod: HttpMethods,
38            paramsDef: dict = None
39    ):
40
41        if httpMethod not in HttpMethods:
42            raise NotAllowedHttpMethod(returnMsg=httpMethod.name)
43
44        self.__path                = path
45        self.__nameControllerParts = nameController.split('.')
46        self.__nameMethod          = nameMethod
47        self.__methodToCall        = None
48        self.__httpMethod          = httpMethod
49        self.__dictParamsDef       = paramsDef
50        self.__pathRegEx           = self.__buildPathRegEx()
51
52        if paramsDef is None:
53            self.__dictParamsDef = {}
54        else:
55            self.__config = paramsDef
path: str
58    @property
59    def path(self) -> str:
60        """
61        Returns the path defined in the route.
62        """
63        return self.__path

Returns the path defined in the route.

methodToCall
66    @property
67    def methodToCall(self):
68        """
69        Returns the method to call.
70        """
71        if self.__methodToCall is None:
72            self.__methodToCall = self.__buildMethod()
73
74        return self.__methodToCall

Returns the method to call.

httpMethod: HttpMethods
77    @property
78    def httpMethod(self) -> HttpMethods:
79        """
80        Returns the HTTP-method
81        """
82        return self.__httpMethod

Returns the HTTP-method

pathRegEx: str
85    @property
86    def pathRegEx(self) -> str:
87        """
88        Returns the RegEx-String to match the route
89        """
90        return self.__pathRegEx

Returns the RegEx-String to match the route

def setConfig(self, config: dict):
93    def setConfig(self, config: dict):
94        """
95        Set the configuration from project root config.py for the route
96        """
97        self.__config = config

Set the configuration from project root config.py for the route

def match(self, path: str, httpMethod: HttpMethods) -> bool:
100    def match(self, path: str, httpMethod: HttpMethods) -> bool:
101        """
102        Checks if the route matches path and httpMethod
103        """
104        if httpMethod != self.__httpMethod:
105            return False
106
107        path = path.rstrip('/')
108        if '' == path:
109            path = '/'
110        
111        return re.match(f'^{self.__pathRegEx}$', path) is not None

Checks if the route matches path and httpMethod

def getParamsFromPath(self, path: str) -> dict:
114    def getParamsFromPath(self, path: str) -> dict:
115        """
116            Returns the parameters from the path
117        """
118        matches = re.match(self.__pathRegEx, path)
119        if matches is None:
120            return {}
121
122        paramsFromPath = {}
123        for placeHolder in self.__dictParamsDef:
124            if 'str' == self.__dictParamsDef[placeHolder]:
125                paramsFromPath[placeHolder] = matches.group(placeHolder)
126            elif 'int' == self.__dictParamsDef[placeHolder]:
127                paramsFromPath[placeHolder] = int(matches.group(placeHolder))
128
129        return paramsFromPath

Returns the parameters from the path