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>
LINK =
<HttpMethods.LINK: 9>
UNLINK =
<HttpMethods.UNLINK: 10>
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
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