pumpwood_communication.microservice_abc.simple
Facilitate communication with Pumpowood backend.
This packages facilitates the communication with end-points with Pumpwood pattern and helps with authentication.
Source-code at Github:
https://github.com/Murabei-OpenSource-Codes/pumpwood-communication
1""" 2Facilitate communication with Pumpowood backend. 3 4This packages facilitates the communication with end-points with Pumpwood 5pattern and helps with authentication. 6 7Source-code at Github:<br> 8https://github.com/Murabei-OpenSource-Codes/pumpwood-communication 9""" 10 11__docformat__ = "google" 12from .batch import ABCSimpleBatchMicroservice 13from .permission import ABCPermissionMicroservice 14from .retrieve import ABCSimpleRetriveMicroservice 15from .delete import ABCSimpleDeleteMicroservice 16from .save import ABCSimpleSaveMicroservice 17 18__all__ = [ 19 ABCSimpleBatchMicroservice, ABCPermissionMicroservice, 20 ABCSimpleRetriveMicroservice, ABCSimpleDeleteMicroservice, 21 ABCSimpleSaveMicroservice]
10class ABCSimpleBatchMicroservice(ABC, PumpWoodMicroServiceBase): 11 """Abstract class for batch end-points.""" 12 13 @staticmethod 14 def _build_aggregate_url(model_class: str): 15 return "rest/%s/aggregate/" % (model_class.lower(),) 16 17 def aggregate(self, model_class: str, group_by: List[str], agg: dict, 18 filter_dict: dict = {}, exclude_dict: dict = {}, 19 order_by: List[str] = [], auth_header: dict = None, 20 limit: int = None) -> pd.DataFrame: 21 """Save a list of objects with one request. 22 23 Args: 24 model_class (str): 25 Model class of the end-point that will be aggregated. 26 group_by (List[str]): 27 List of the fields that will be used on aggregation as 28 group by. 29 agg (dict): 30 A dictionary with dictionary itens as `field` and `function` 31 specifing the field that will be aggregated using a function. 32 filter_dict (dict): 33 Filter that will be applied before the aggregation. 34 exclude_dict (dict): 35 Exclude clause that will be applied before the aggregation. 36 order_by (list): 37 Ordenation acording to grouping elements. It can be used 38 fields created as keys of agg dictinary. 39 auth_header (dict): 40 Authentication header used to impersonation of user. 41 limit (int): 42 Limit number of returned row at aggregation query. 43 44 Returns: 45 Return a DataFrame with aggregation results. 46 """ 47 url_str = self._build_aggregate_url(model_class=model_class) 48 data = { 49 'agg': agg, 'group_by': group_by, 'filter_dict': filter_dict, 50 'exclude_dict': exclude_dict, 'order_by': order_by, 51 'limit': limit} 52 return self.request_post( 53 url=url_str, data=data, auth_header=auth_header)
Abstract class for batch end-points.
17 def aggregate(self, model_class: str, group_by: List[str], agg: dict, 18 filter_dict: dict = {}, exclude_dict: dict = {}, 19 order_by: List[str] = [], auth_header: dict = None, 20 limit: int = None) -> pd.DataFrame: 21 """Save a list of objects with one request. 22 23 Args: 24 model_class (str): 25 Model class of the end-point that will be aggregated. 26 group_by (List[str]): 27 List of the fields that will be used on aggregation as 28 group by. 29 agg (dict): 30 A dictionary with dictionary itens as `field` and `function` 31 specifing the field that will be aggregated using a function. 32 filter_dict (dict): 33 Filter that will be applied before the aggregation. 34 exclude_dict (dict): 35 Exclude clause that will be applied before the aggregation. 36 order_by (list): 37 Ordenation acording to grouping elements. It can be used 38 fields created as keys of agg dictinary. 39 auth_header (dict): 40 Authentication header used to impersonation of user. 41 limit (int): 42 Limit number of returned row at aggregation query. 43 44 Returns: 45 Return a DataFrame with aggregation results. 46 """ 47 url_str = self._build_aggregate_url(model_class=model_class) 48 data = { 49 'agg': agg, 'group_by': group_by, 'filter_dict': filter_dict, 50 'exclude_dict': exclude_dict, 'order_by': order_by, 51 'limit': limit} 52 return self.request_post( 53 url=url_str, data=data, auth_header=auth_header)
Save a list of objects with one request.
Arguments:
- model_class (str): Model class of the end-point that will be aggregated.
- group_by (List[str]): List of the fields that will be used on aggregation as group by.
- agg (dict): A dictionary with dictionary itens as
field
andfunction
specifing the field that will be aggregated using a function. - filter_dict (dict): Filter that will be applied before the aggregation.
- exclude_dict (dict): Exclude clause that will be applied before the aggregation.
- order_by (list): Ordenation acording to grouping elements. It can be used fields created as keys of agg dictinary.
- auth_header (dict): Authentication header used to impersonation of user.
- limit (int): Limit number of returned row at aggregation query.
Returns:
Return a DataFrame with aggregation results.
9class ABCPermissionMicroservice(ABC, PumpWoodMicroServiceBase): 10 """Abstract class for permission checking at pumpwood.""" 11 12 def check_if_logged(self, auth_header: dict = None) -> bool: 13 """Check if user is logged. 14 15 Args: 16 auth_header (dict): = None 17 AuthHeader to substitute the microservice original at 18 request. If not passed, microservice object auth_header 19 will be used. 20 21 Returns: 22 Return True if auth_header is looged and False if not 23 """ 24 try: 25 check = self.request_get( 26 url="rest/registration/check/", 27 auth_header=auth_header) 28 except PumpWoodUnauthorized: 29 return False 30 return check 31 32 def get_user_info(self, auth_header: dict = None) -> dict: 33 """Get user info. 34 35 Args: 36 auth_header (dict): = None 37 AuthHeader to substitute the microservice original at 38 request. If not passed, microservice object auth_header 39 will be used. 40 41 Returns: 42 A serialized user object with information of the logged user. 43 """ 44 user_info = self.request_get( 45 url="rest/registration/retrieveauthenticateduser/", 46 auth_header=auth_header) 47 return user_info 48 49 def check_permission(self, model_class: str, end_point: str, 50 extra_arg: str = None, allow_service_user: str = None, 51 allow_external: str = None, auth_header: dict = None, 52 ) -> dict: 53 """Get user info. 54 55 Args: 56 model_class (str): 57 Model class associated to be checked for access. 58 end_point (str): 59 Name of the end-point that will be checked for permission. Ex.: 60 retrieve, save, list, list-without-pag, ... 61 extra_arg (str): 62 Used on some end-points. On action end-point it is reponsible 63 for setting the action associated with the call. 64 allow_service_user: str = None: 65 66 allow_external: str = None: 67 68 auth_header (dict): 69 AuthHeader to substitute the microservice original at 70 request. If not passed, microservice object auth_header 71 will be used. 72 73 Returns: 74 A serialized user object with information of the logged user. 75 """ 76 # user_info = self.request_post( 77 # url="rest/registration/check/", 78 # payload={ 79 # 'end_point': end_point, 80 # 'first_arg': first_arg, 81 # 'second_arg': second_arg, 82 # 'api_config_allow': api_config_allow, 83 # 'api_config_deny': api_config_deny}, 84 # auth_header=auth_header, timeout=self.default_timeout) 85 # return user_info 86 return True
Abstract class for permission checking at pumpwood.
12 def check_if_logged(self, auth_header: dict = None) -> bool: 13 """Check if user is logged. 14 15 Args: 16 auth_header (dict): = None 17 AuthHeader to substitute the microservice original at 18 request. If not passed, microservice object auth_header 19 will be used. 20 21 Returns: 22 Return True if auth_header is looged and False if not 23 """ 24 try: 25 check = self.request_get( 26 url="rest/registration/check/", 27 auth_header=auth_header) 28 except PumpWoodUnauthorized: 29 return False 30 return check
Check if user is logged.
Arguments:
- auth_header (dict): = None AuthHeader to substitute the microservice original at request. If not passed, microservice object auth_header will be used.
Returns:
Return True if auth_header is looged and False if not
32 def get_user_info(self, auth_header: dict = None) -> dict: 33 """Get user info. 34 35 Args: 36 auth_header (dict): = None 37 AuthHeader to substitute the microservice original at 38 request. If not passed, microservice object auth_header 39 will be used. 40 41 Returns: 42 A serialized user object with information of the logged user. 43 """ 44 user_info = self.request_get( 45 url="rest/registration/retrieveauthenticateduser/", 46 auth_header=auth_header) 47 return user_info
Get user info.
Arguments:
- auth_header (dict): = None AuthHeader to substitute the microservice original at request. If not passed, microservice object auth_header will be used.
Returns:
A serialized user object with information of the logged user.
49 def check_permission(self, model_class: str, end_point: str, 50 extra_arg: str = None, allow_service_user: str = None, 51 allow_external: str = None, auth_header: dict = None, 52 ) -> dict: 53 """Get user info. 54 55 Args: 56 model_class (str): 57 Model class associated to be checked for access. 58 end_point (str): 59 Name of the end-point that will be checked for permission. Ex.: 60 retrieve, save, list, list-without-pag, ... 61 extra_arg (str): 62 Used on some end-points. On action end-point it is reponsible 63 for setting the action associated with the call. 64 allow_service_user: str = None: 65 66 allow_external: str = None: 67 68 auth_header (dict): 69 AuthHeader to substitute the microservice original at 70 request. If not passed, microservice object auth_header 71 will be used. 72 73 Returns: 74 A serialized user object with information of the logged user. 75 """ 76 # user_info = self.request_post( 77 # url="rest/registration/check/", 78 # payload={ 79 # 'end_point': end_point, 80 # 'first_arg': first_arg, 81 # 'second_arg': second_arg, 82 # 'api_config_allow': api_config_allow, 83 # 'api_config_deny': api_config_deny}, 84 # auth_header=auth_header, timeout=self.default_timeout) 85 # return user_info 86 return True
Get user info.
Arguments:
- model_class (str): Model class associated to be checked for access.
- end_point (str): Name of the end-point that will be checked for permission. Ex.: retrieve, save, list, list-without-pag, ...
- extra_arg (str): Used on some end-points. On action end-point it is reponsible for setting the action associated with the call.
- allow_service_user: str = None:
- allow_external: str = None:
- auth_header (dict): AuthHeader to substitute the microservice original at request. If not passed, microservice object auth_header will be used.
Returns:
A serialized user object with information of the logged user.
12class ABCSimpleRetriveMicroservice(ABC, PumpWoodMicroServiceBase): 13 """Abstract class for parallel calls at Pumpwood end-points.""" 14 15 @staticmethod 16 def _build_list_one_url(model_class, pk): 17 return "rest/%s/retrieve/%s/" % (model_class.lower(), pk) 18 19 def list_one(self, model_class: str, pk: int, fields: list = None, 20 default_fields: bool = True, foreign_key_fields: bool = False, 21 related_fields: bool = False, auth_header: dict = None, 22 use_disk_cache: bool = False, 23 disk_cache_expire: int = None) -> dict: 24 """Retrieve an object using list serializer (simple). 25 26 **# DEPRECTED #** It is the same as retrieve using 27 `default_fields: bool = True`, if possible migrate to retrieve 28 function. 29 30 Args: 31 model_class: 32 Model class of the end-point 33 pk: 34 Object pk 35 auth_header: 36 Auth header to substitute the microservice original 37 at the request (user impersonation). 38 fields: 39 Set the fields to be returned by the list end-point. 40 default_fields: 41 Boolean, if true and fields arguments None will return the 42 default fields set for list by the backend. 43 foreign_key_fields: 44 Return forenging key objects. It will return the fk 45 corresponding object. Ex: `created_by_id` reference to 46 a user `model_class` the correspondent to User will be 47 returned at `created_by`. 48 related_fields: 49 Return related fields objects. Related field objects are 50 objects that have a forenging key associated with this 51 model_class, results will be returned as a list of 52 dictionaries usually in a field with `_set` at end. 53 Returning related_fields consume backend resorces, use 54 carefully. 55 use_disk_cache (bool): 56 If set true, get request will use local cache to reduce 57 the requests to the backend. 58 disk_cache_expire (int): 59 Time in seconds to expire the cache, it None it will 60 use de default set be PumpwoodCache. 61 62 Returns: 63 Return object with the correspondent pk. 64 65 Raises: 66 PumpWoodObjectDoesNotExist: 67 If pk not found on database. 68 """ 69 url_str = self._build_list_one_url(model_class, pk) 70 return self.request_get( 71 url=url_str, parameters={ 72 "fields": fields, "default_fields": default_fields, 73 "foreign_key_fields": foreign_key_fields, 74 "related_fields": related_fields}, 75 auth_header=auth_header, use_disk_cache=use_disk_cache, 76 disk_cache_expire=disk_cache_expire) 77 78 @staticmethod 79 def _build_retrieve_url(model_class: str, pk: int): 80 return "rest/%s/retrieve/%s/" % (model_class.lower(), pk) 81 82 def retrieve(self, model_class: str, pk: int, 83 default_fields: bool = False, 84 foreign_key_fields: bool = False, 85 related_fields: bool = False, 86 fields: list = None, 87 auth_header: dict = None, 88 use_disk_cache: bool = False, 89 disk_cache_expire: int = None) -> dict: 90 """Retrieve an object from PumpWood. 91 92 Function to get object serialized by retrieve end-point 93 (more detailed data). 94 95 Args: 96 model_class: 97 Model class of the end-point 98 pk: 99 Object pk 100 auth_header: 101 Auth header to substitute the microservice original 102 at the request (user impersonation). 103 fields: 104 Set the fields to be returned by the list end-point. 105 default_fields: 106 Boolean, if true and fields arguments None will return the 107 default fields set for list by the backend. 108 foreign_key_fields: 109 Return forenging key objects. It will return the fk 110 corresponding object. Ex: `created_by_id` reference to 111 a user `model_class` the correspondent to User will be 112 returned at `created_by`. 113 related_fields: 114 Return related fields objects. Related field objects are 115 objects that have a forenging key associated with this 116 model_class, results will be returned as a list of 117 dictionaries usually in a field with `_set` at end. 118 Returning related_fields consume backend resorces, use 119 carefully. 120 use_disk_cache (bool): 121 If set true, get request will use local cache to reduce 122 the requests to the backend. 123 disk_cache_expire (int): 124 Time in seconds to expire the cache, it None it will 125 use de default set be PumpwoodCache. 126 127 Returns: 128 Return object with the correspondent pk. 129 130 Raises: 131 PumpWoodObjectDoesNotExist: 132 If pk not found on database. 133 """ 134 url_str = self._build_retrieve_url(model_class=model_class, pk=pk) 135 return self.request_get( 136 url=url_str, parameters={ 137 "fields": fields, "default_fields": default_fields, 138 "foreign_key_fields": foreign_key_fields, 139 "related_fields": related_fields}, 140 auth_header=auth_header, use_disk_cache=use_disk_cache, 141 disk_cache_expire=disk_cache_expire) 142 143 @staticmethod 144 def _build_retrieve_file_url(model_class: str, pk: int): 145 return "rest/%s/retrieve-file/%s/" % (model_class.lower(), pk) 146 147 def retrieve_file(self, model_class: str, pk: int, file_field: str, 148 auth_header: dict = None, save_file: bool = True, 149 save_path: str = "./", file_name: str = None, 150 if_exists: str = "fail") -> any: 151 """Retrieve a file from PumpWood. 152 153 This function will retrieve file as a single request, depending on the 154 size of the files it would be preferred to use streaming end-point. 155 156 Args: 157 model_class: 158 Class of the model to retrieve file. 159 pk: 160 Pk of the object associeted file. 161 file_field: 162 Field of the file to be downloaded. 163 auth_header: 164 Dictionary containing the auth header. 165 save_file: 166 If data is to be saved as file or return get 167 response. 168 save_path: 169 Path of the directory to save file. 170 file_name: 171 Name of the file, if None it will have same name as 172 saved in PumpWood. 173 if_exists: 174 Values must be in {'fail', 'change_name', 'overwrite', 'skip'}. 175 Set what to do if there is a file with same name. Skip 176 will not download file if there is already with same 177 os.path.join(save_path, file_name), file_name must be set 178 for skip argument. 179 auth_header: 180 Auth header to substitute the microservice original 181 at the request (user impersonation). 182 183 Returns: 184 May return the file name if save_file=True; If false will return 185 a dictonary with keys `filename` with original file name and 186 `content` with binary data of file content. 187 188 Raises: 189 PumpWoodForbidden: 190 'storage_object attribute not set for view, file operations 191 are disable'. This indicates that storage for this backend 192 was not configured, so it is not possible to make storage 193 operations, 194 PumpWoodForbidden: 195 'file_field must be set on self.file_fields dictionary'. This 196 indicates that the `file_field` parameter is not listed as 197 a file field on the backend. 198 PumpWoodObjectDoesNotExist: 199 'field [{}] not found or null at object'. This indicates that 200 the file field requested is not present on object fields. 201 PumpWoodObjectDoesNotExist: 202 'Object not found in storage [{}]'. This indicates that the 203 file associated with file_field is not avaiable at the 204 storage. This should not ocorrur, it might have a manual 205 update at the model_class table or manual removal/rename of 206 files on storage. 207 """ 208 if if_exists not in ["fail", "change_name", "overwrite", "skip"]: 209 raise PumpWoodException( 210 "if_exists must be in ['fail', 'change_name', 'overwrite', " 211 "'skip']") 212 213 if file_name is not None and if_exists == 'skip': 214 file_path = os.path.join(save_path, file_name) 215 is_file_already = os.path.isfile(file_path) 216 if is_file_already: 217 print("skiping file already exists: ", file_path) 218 return file_path 219 220 url_str = self._build_retrieve_file_url(model_class=model_class, pk=pk) 221 file_response = self.request_get( 222 url=url_str, parameters={"file-field": file_field}, 223 auth_header=auth_header) 224 if not save_file: 225 return file_response 226 227 if not os.path.exists(save_path): 228 raise PumpWoodException( 229 "Path to save retrieved file [{}] does not exist".format( 230 save_path)) 231 232 file_name = secure_filename(file_name or file_response["filename"]) 233 file_path = os.path.join(save_path, file_name) 234 is_file_already = os.path.isfile(file_path) 235 if is_file_already: 236 if if_exists == "change_name": 237 filename, file_extension = os.path.splitext(file_path) 238 too_many_tries = True 239 for i in range(10): 240 new_path = "{filename}__{count}{extension}".format( 241 filename=filename, count=i, 242 extension=file_extension) 243 if not os.path.isfile(new_path): 244 file_path = new_path 245 too_many_tries = False 246 break 247 if too_many_tries: 248 raise PumpWoodException( 249 ("Too many tries to find a not used file name." + 250 " file_path[{}]".format(file_path))) 251 252 elif if_exists == "fail": 253 raise PumpWoodException( 254 ("if_exists set as 'fail' and there is a file with same" + 255 "name. file_path [{}]").format(file_path)) 256 257 with open(file_path, "wb") as file: 258 file.write(file_response["content"]) 259 return file_path 260 261 @staticmethod 262 def _build_retrieve_file_straming_url(model_class: str, pk: int): 263 return "rest/%s/retrieve-file-streaming/%s/" % ( 264 model_class.lower(), pk) 265 266 def retrieve_streaming_file(self, model_class: str, pk: int, 267 file_field: str, file_name: str, 268 auth_header: dict = None, 269 save_path: str = "./", 270 if_exists: str = "fail"): 271 """Retrieve a file from PumpWood using streaming to retrieve content. 272 273 This funcion uses file streaming to retrieve file content, it should be 274 prefered when dealing with large (bigger than 10Mb) files transfer. 275 Using this end-point the file is not loaded on backend memory content 276 is transfered by chucks that are read at the storage and transfered 277 to user. 278 279 It will necessarily save the content as a file, there is not the 280 possibility of retrieving the content directly from request. 281 282 Args: 283 model_class: 284 Class of the model to retrieve file. 285 pk: 286 Pk of the object associeted file. 287 file_field: 288 Field of the file to be downloaded. 289 auth_header: 290 Dictionary containing the auth header. 291 save_path: 292 Path of the directory to save file. 293 file_name: 294 Name of the file, if None it will have same name as 295 saved in PumpWood. 296 if_exists: 297 Values must be in {'fail', 'change_name', 'overwrite'}. 298 Set what to do if there is a file with same name. 299 auth_header: 300 Auth header to substitute the microservice original 301 at the request (user impersonation). 302 303 Returns: 304 Returns the file path that recived the file content. 305 306 Raises: 307 PumpWoodForbidden: 308 'storage_object attribute not set for view, file operations 309 are disable'. This indicates that storage for this backend 310 was not configured, so it is not possible to make storage 311 operations, 312 PumpWoodForbidden: 313 'file_field must be set on self.file_fields dictionary'. This 314 indicates that the `file_field` parameter is not listed as 315 a file field on the backend. 316 PumpWoodObjectDoesNotExist: 317 'field [{}] not found or null at object'. This indicates that 318 the file field requested is not present on object fields. 319 PumpWoodObjectDoesNotExist: 320 'Object not found in storage [{}]'. This indicates that the 321 file associated with file_field is not avaiable at the 322 storage. This should not ocorrur, it might have a manual 323 update at the model_class table or manual removal/rename of 324 files on storage. 325 """ 326 request_header = self._check__auth_header(auth_header) 327 328 # begin Args check 329 if if_exists not in ["fail", "change_name", "overwrite"]: 330 raise PumpWoodException( 331 "if_exists must be in ['fail', 'change_name', 'overwrite']") 332 333 if not os.path.exists(save_path): 334 raise PumpWoodException( 335 "Path to save retrieved file [{}] does not exist".format( 336 save_path)) 337 # end Args check 338 339 file_path = os.path.join(save_path, file_name) 340 if os.path.isfile(file_path) and if_exists == "change_name": 341 filename, file_extension = os.path.splitext(file_path) 342 too_many_tries = False 343 for i in range(10): 344 new_path = "{filename}__{count}{extension}".format( 345 filename=filename, count=i, 346 extension=file_extension) 347 if not os.path.isfile(new_path): 348 file_path = new_path 349 too_many_tries = True 350 break 351 if not too_many_tries: 352 raise PumpWoodException( 353 ("Too many tries to find a not used file name." + 354 " file_path[{}]".format(file_path))) 355 356 if os.path.isfile(file_path) and if_exists == "fail": 357 raise PumpWoodException( 358 ("if_exists set as 'fail' and there is a file with same" + 359 "name. file_path [{}]").format(file_path)) 360 361 url_str = self._build_retrieve_file_straming_url( 362 model_class=model_class, pk=pk) 363 364 get_url = self.server_url + url_str 365 with requests.get( 366 get_url, verify=self.verify_ssl, headers=request_header, 367 params={"file-field": file_field}, 368 timeout=self.default_timeout) as response: 369 self.error_handler(response) 370 with open(file_path, 'wb') as f: 371 for chunk in response.iter_content(chunk_size=8192): 372 if chunk: 373 f.write(chunk) 374 return file_path
Abstract class for parallel calls at Pumpwood end-points.
19 def list_one(self, model_class: str, pk: int, fields: list = None, 20 default_fields: bool = True, foreign_key_fields: bool = False, 21 related_fields: bool = False, auth_header: dict = None, 22 use_disk_cache: bool = False, 23 disk_cache_expire: int = None) -> dict: 24 """Retrieve an object using list serializer (simple). 25 26 **# DEPRECTED #** It is the same as retrieve using 27 `default_fields: bool = True`, if possible migrate to retrieve 28 function. 29 30 Args: 31 model_class: 32 Model class of the end-point 33 pk: 34 Object pk 35 auth_header: 36 Auth header to substitute the microservice original 37 at the request (user impersonation). 38 fields: 39 Set the fields to be returned by the list end-point. 40 default_fields: 41 Boolean, if true and fields arguments None will return the 42 default fields set for list by the backend. 43 foreign_key_fields: 44 Return forenging key objects. It will return the fk 45 corresponding object. Ex: `created_by_id` reference to 46 a user `model_class` the correspondent to User will be 47 returned at `created_by`. 48 related_fields: 49 Return related fields objects. Related field objects are 50 objects that have a forenging key associated with this 51 model_class, results will be returned as a list of 52 dictionaries usually in a field with `_set` at end. 53 Returning related_fields consume backend resorces, use 54 carefully. 55 use_disk_cache (bool): 56 If set true, get request will use local cache to reduce 57 the requests to the backend. 58 disk_cache_expire (int): 59 Time in seconds to expire the cache, it None it will 60 use de default set be PumpwoodCache. 61 62 Returns: 63 Return object with the correspondent pk. 64 65 Raises: 66 PumpWoodObjectDoesNotExist: 67 If pk not found on database. 68 """ 69 url_str = self._build_list_one_url(model_class, pk) 70 return self.request_get( 71 url=url_str, parameters={ 72 "fields": fields, "default_fields": default_fields, 73 "foreign_key_fields": foreign_key_fields, 74 "related_fields": related_fields}, 75 auth_header=auth_header, use_disk_cache=use_disk_cache, 76 disk_cache_expire=disk_cache_expire)
Retrieve an object using list serializer (simple).
# DEPRECTED # It is the same as retrieve using
default_fields: bool = True
, if possible migrate to retrieve
function.
Arguments:
- model_class: Model class of the end-point
- pk: Object pk
- auth_header: Auth header to substitute the microservice original at the request (user impersonation).
- fields: Set the fields to be returned by the list end-point.
- default_fields: Boolean, if true and fields arguments None will return the default fields set for list by the backend.
- foreign_key_fields: Return forenging key objects. It will return the fk
corresponding object. Ex:
created_by_id
reference to a usermodel_class
the correspondent to User will be returned atcreated_by
. - related_fields: Return related fields objects. Related field objects are
objects that have a forenging key associated with this
model_class, results will be returned as a list of
dictionaries usually in a field with
_set
at end. Returning related_fields consume backend resorces, use carefully. - use_disk_cache (bool): If set true, get request will use local cache to reduce the requests to the backend.
- disk_cache_expire (int): Time in seconds to expire the cache, it None it will use de default set be PumpwoodCache.
Returns:
Return object with the correspondent pk.
Raises:
- PumpWoodObjectDoesNotExist: If pk not found on database.
82 def retrieve(self, model_class: str, pk: int, 83 default_fields: bool = False, 84 foreign_key_fields: bool = False, 85 related_fields: bool = False, 86 fields: list = None, 87 auth_header: dict = None, 88 use_disk_cache: bool = False, 89 disk_cache_expire: int = None) -> dict: 90 """Retrieve an object from PumpWood. 91 92 Function to get object serialized by retrieve end-point 93 (more detailed data). 94 95 Args: 96 model_class: 97 Model class of the end-point 98 pk: 99 Object pk 100 auth_header: 101 Auth header to substitute the microservice original 102 at the request (user impersonation). 103 fields: 104 Set the fields to be returned by the list end-point. 105 default_fields: 106 Boolean, if true and fields arguments None will return the 107 default fields set for list by the backend. 108 foreign_key_fields: 109 Return forenging key objects. It will return the fk 110 corresponding object. Ex: `created_by_id` reference to 111 a user `model_class` the correspondent to User will be 112 returned at `created_by`. 113 related_fields: 114 Return related fields objects. Related field objects are 115 objects that have a forenging key associated with this 116 model_class, results will be returned as a list of 117 dictionaries usually in a field with `_set` at end. 118 Returning related_fields consume backend resorces, use 119 carefully. 120 use_disk_cache (bool): 121 If set true, get request will use local cache to reduce 122 the requests to the backend. 123 disk_cache_expire (int): 124 Time in seconds to expire the cache, it None it will 125 use de default set be PumpwoodCache. 126 127 Returns: 128 Return object with the correspondent pk. 129 130 Raises: 131 PumpWoodObjectDoesNotExist: 132 If pk not found on database. 133 """ 134 url_str = self._build_retrieve_url(model_class=model_class, pk=pk) 135 return self.request_get( 136 url=url_str, parameters={ 137 "fields": fields, "default_fields": default_fields, 138 "foreign_key_fields": foreign_key_fields, 139 "related_fields": related_fields}, 140 auth_header=auth_header, use_disk_cache=use_disk_cache, 141 disk_cache_expire=disk_cache_expire)
Retrieve an object from PumpWood.
Function to get object serialized by retrieve end-point (more detailed data).
Arguments:
- model_class: Model class of the end-point
- pk: Object pk
- auth_header: Auth header to substitute the microservice original at the request (user impersonation).
- fields: Set the fields to be returned by the list end-point.
- default_fields: Boolean, if true and fields arguments None will return the default fields set for list by the backend.
- foreign_key_fields: Return forenging key objects. It will return the fk
corresponding object. Ex:
created_by_id
reference to a usermodel_class
the correspondent to User will be returned atcreated_by
. - related_fields: Return related fields objects. Related field objects are
objects that have a forenging key associated with this
model_class, results will be returned as a list of
dictionaries usually in a field with
_set
at end. Returning related_fields consume backend resorces, use carefully. - use_disk_cache (bool): If set true, get request will use local cache to reduce the requests to the backend.
- disk_cache_expire (int): Time in seconds to expire the cache, it None it will use de default set be PumpwoodCache.
Returns:
Return object with the correspondent pk.
Raises:
- PumpWoodObjectDoesNotExist: If pk not found on database.
147 def retrieve_file(self, model_class: str, pk: int, file_field: str, 148 auth_header: dict = None, save_file: bool = True, 149 save_path: str = "./", file_name: str = None, 150 if_exists: str = "fail") -> any: 151 """Retrieve a file from PumpWood. 152 153 This function will retrieve file as a single request, depending on the 154 size of the files it would be preferred to use streaming end-point. 155 156 Args: 157 model_class: 158 Class of the model to retrieve file. 159 pk: 160 Pk of the object associeted file. 161 file_field: 162 Field of the file to be downloaded. 163 auth_header: 164 Dictionary containing the auth header. 165 save_file: 166 If data is to be saved as file or return get 167 response. 168 save_path: 169 Path of the directory to save file. 170 file_name: 171 Name of the file, if None it will have same name as 172 saved in PumpWood. 173 if_exists: 174 Values must be in {'fail', 'change_name', 'overwrite', 'skip'}. 175 Set what to do if there is a file with same name. Skip 176 will not download file if there is already with same 177 os.path.join(save_path, file_name), file_name must be set 178 for skip argument. 179 auth_header: 180 Auth header to substitute the microservice original 181 at the request (user impersonation). 182 183 Returns: 184 May return the file name if save_file=True; If false will return 185 a dictonary with keys `filename` with original file name and 186 `content` with binary data of file content. 187 188 Raises: 189 PumpWoodForbidden: 190 'storage_object attribute not set for view, file operations 191 are disable'. This indicates that storage for this backend 192 was not configured, so it is not possible to make storage 193 operations, 194 PumpWoodForbidden: 195 'file_field must be set on self.file_fields dictionary'. This 196 indicates that the `file_field` parameter is not listed as 197 a file field on the backend. 198 PumpWoodObjectDoesNotExist: 199 'field [{}] not found or null at object'. This indicates that 200 the file field requested is not present on object fields. 201 PumpWoodObjectDoesNotExist: 202 'Object not found in storage [{}]'. This indicates that the 203 file associated with file_field is not avaiable at the 204 storage. This should not ocorrur, it might have a manual 205 update at the model_class table or manual removal/rename of 206 files on storage. 207 """ 208 if if_exists not in ["fail", "change_name", "overwrite", "skip"]: 209 raise PumpWoodException( 210 "if_exists must be in ['fail', 'change_name', 'overwrite', " 211 "'skip']") 212 213 if file_name is not None and if_exists == 'skip': 214 file_path = os.path.join(save_path, file_name) 215 is_file_already = os.path.isfile(file_path) 216 if is_file_already: 217 print("skiping file already exists: ", file_path) 218 return file_path 219 220 url_str = self._build_retrieve_file_url(model_class=model_class, pk=pk) 221 file_response = self.request_get( 222 url=url_str, parameters={"file-field": file_field}, 223 auth_header=auth_header) 224 if not save_file: 225 return file_response 226 227 if not os.path.exists(save_path): 228 raise PumpWoodException( 229 "Path to save retrieved file [{}] does not exist".format( 230 save_path)) 231 232 file_name = secure_filename(file_name or file_response["filename"]) 233 file_path = os.path.join(save_path, file_name) 234 is_file_already = os.path.isfile(file_path) 235 if is_file_already: 236 if if_exists == "change_name": 237 filename, file_extension = os.path.splitext(file_path) 238 too_many_tries = True 239 for i in range(10): 240 new_path = "{filename}__{count}{extension}".format( 241 filename=filename, count=i, 242 extension=file_extension) 243 if not os.path.isfile(new_path): 244 file_path = new_path 245 too_many_tries = False 246 break 247 if too_many_tries: 248 raise PumpWoodException( 249 ("Too many tries to find a not used file name." + 250 " file_path[{}]".format(file_path))) 251 252 elif if_exists == "fail": 253 raise PumpWoodException( 254 ("if_exists set as 'fail' and there is a file with same" + 255 "name. file_path [{}]").format(file_path)) 256 257 with open(file_path, "wb") as file: 258 file.write(file_response["content"]) 259 return file_path
Retrieve a file from PumpWood.
This function will retrieve file as a single request, depending on the size of the files it would be preferred to use streaming end-point.
Arguments:
- model_class: Class of the model to retrieve file.
- pk: Pk of the object associeted file.
- file_field: Field of the file to be downloaded.
- auth_header: Dictionary containing the auth header.
- save_file: If data is to be saved as file or return get response.
- save_path: Path of the directory to save file.
- file_name: Name of the file, if None it will have same name as saved in PumpWood.
- if_exists: Values must be in {'fail', 'change_name', 'overwrite', 'skip'}. Set what to do if there is a file with same name. Skip will not download file if there is already with same os.path.join(save_path, file_name), file_name must be set for skip argument.
- auth_header: Auth header to substitute the microservice original at the request (user impersonation).
Returns:
May return the file name if save_file=True; If false will return a dictonary with keys
filename
with original file name andcontent
with binary data of file content.
Raises:
- PumpWoodForbidden: 'storage_object attribute not set for view, file operations are disable'. This indicates that storage for this backend was not configured, so it is not possible to make storage operations,
- PumpWoodForbidden: 'file_field must be set on self.file_fields dictionary'. This
indicates that the
file_field
parameter is not listed as a file field on the backend. - PumpWoodObjectDoesNotExist: 'field [{}] not found or null at object'. This indicates that the file field requested is not present on object fields.
- PumpWoodObjectDoesNotExist: 'Object not found in storage [{}]'. This indicates that the file associated with file_field is not avaiable at the storage. This should not ocorrur, it might have a manual update at the model_class table or manual removal/rename of files on storage.
266 def retrieve_streaming_file(self, model_class: str, pk: int, 267 file_field: str, file_name: str, 268 auth_header: dict = None, 269 save_path: str = "./", 270 if_exists: str = "fail"): 271 """Retrieve a file from PumpWood using streaming to retrieve content. 272 273 This funcion uses file streaming to retrieve file content, it should be 274 prefered when dealing with large (bigger than 10Mb) files transfer. 275 Using this end-point the file is not loaded on backend memory content 276 is transfered by chucks that are read at the storage and transfered 277 to user. 278 279 It will necessarily save the content as a file, there is not the 280 possibility of retrieving the content directly from request. 281 282 Args: 283 model_class: 284 Class of the model to retrieve file. 285 pk: 286 Pk of the object associeted file. 287 file_field: 288 Field of the file to be downloaded. 289 auth_header: 290 Dictionary containing the auth header. 291 save_path: 292 Path of the directory to save file. 293 file_name: 294 Name of the file, if None it will have same name as 295 saved in PumpWood. 296 if_exists: 297 Values must be in {'fail', 'change_name', 'overwrite'}. 298 Set what to do if there is a file with same name. 299 auth_header: 300 Auth header to substitute the microservice original 301 at the request (user impersonation). 302 303 Returns: 304 Returns the file path that recived the file content. 305 306 Raises: 307 PumpWoodForbidden: 308 'storage_object attribute not set for view, file operations 309 are disable'. This indicates that storage for this backend 310 was not configured, so it is not possible to make storage 311 operations, 312 PumpWoodForbidden: 313 'file_field must be set on self.file_fields dictionary'. This 314 indicates that the `file_field` parameter is not listed as 315 a file field on the backend. 316 PumpWoodObjectDoesNotExist: 317 'field [{}] not found or null at object'. This indicates that 318 the file field requested is not present on object fields. 319 PumpWoodObjectDoesNotExist: 320 'Object not found in storage [{}]'. This indicates that the 321 file associated with file_field is not avaiable at the 322 storage. This should not ocorrur, it might have a manual 323 update at the model_class table or manual removal/rename of 324 files on storage. 325 """ 326 request_header = self._check__auth_header(auth_header) 327 328 # begin Args check 329 if if_exists not in ["fail", "change_name", "overwrite"]: 330 raise PumpWoodException( 331 "if_exists must be in ['fail', 'change_name', 'overwrite']") 332 333 if not os.path.exists(save_path): 334 raise PumpWoodException( 335 "Path to save retrieved file [{}] does not exist".format( 336 save_path)) 337 # end Args check 338 339 file_path = os.path.join(save_path, file_name) 340 if os.path.isfile(file_path) and if_exists == "change_name": 341 filename, file_extension = os.path.splitext(file_path) 342 too_many_tries = False 343 for i in range(10): 344 new_path = "{filename}__{count}{extension}".format( 345 filename=filename, count=i, 346 extension=file_extension) 347 if not os.path.isfile(new_path): 348 file_path = new_path 349 too_many_tries = True 350 break 351 if not too_many_tries: 352 raise PumpWoodException( 353 ("Too many tries to find a not used file name." + 354 " file_path[{}]".format(file_path))) 355 356 if os.path.isfile(file_path) and if_exists == "fail": 357 raise PumpWoodException( 358 ("if_exists set as 'fail' and there is a file with same" + 359 "name. file_path [{}]").format(file_path)) 360 361 url_str = self._build_retrieve_file_straming_url( 362 model_class=model_class, pk=pk) 363 364 get_url = self.server_url + url_str 365 with requests.get( 366 get_url, verify=self.verify_ssl, headers=request_header, 367 params={"file-field": file_field}, 368 timeout=self.default_timeout) as response: 369 self.error_handler(response) 370 with open(file_path, 'wb') as f: 371 for chunk in response.iter_content(chunk_size=8192): 372 if chunk: 373 f.write(chunk) 374 return file_path
Retrieve a file from PumpWood using streaming to retrieve content.
This funcion uses file streaming to retrieve file content, it should be prefered when dealing with large (bigger than 10Mb) files transfer. Using this end-point the file is not loaded on backend memory content is transfered by chucks that are read at the storage and transfered to user.
It will necessarily save the content as a file, there is not the possibility of retrieving the content directly from request.
Arguments:
- model_class: Class of the model to retrieve file.
- pk: Pk of the object associeted file.
- file_field: Field of the file to be downloaded.
- auth_header: Dictionary containing the auth header.
- save_path: Path of the directory to save file.
- file_name: Name of the file, if None it will have same name as saved in PumpWood.
- if_exists: Values must be in {'fail', 'change_name', 'overwrite'}. Set what to do if there is a file with same name.
- auth_header: Auth header to substitute the microservice original at the request (user impersonation).
Returns:
Returns the file path that recived the file content.
Raises:
- PumpWoodForbidden: 'storage_object attribute not set for view, file operations are disable'. This indicates that storage for this backend was not configured, so it is not possible to make storage operations,
- PumpWoodForbidden: 'file_field must be set on self.file_fields dictionary'. This
indicates that the
file_field
parameter is not listed as a file field on the backend. - PumpWoodObjectDoesNotExist: 'field [{}] not found or null at object'. This indicates that the file field requested is not present on object fields.
- PumpWoodObjectDoesNotExist: 'Object not found in storage [{}]'. This indicates that the file associated with file_field is not avaiable at the storage. This should not ocorrur, it might have a manual update at the model_class table or manual removal/rename of files on storage.
8class ABCSimpleDeleteMicroservice(ABC, PumpWoodMicroServiceBase): 9 """Abstract class for calls at Pumpwood delete end-points.""" 10 11 @staticmethod 12 def _build_delete_request_url(model_class, pk): 13 return "rest/%s/delete/%s/" % (model_class.lower(), pk) 14 15 def delete(self, model_class: str, pk: int, 16 auth_header: dict = None) -> dict: 17 """Send delete request to a PumpWood object. 18 19 Delete (or whatever the PumpWood system have been implemented) the 20 object with the specified pk. 21 22 Args: 23 model_class: 24 Model class to delete the object 25 pk: 26 Object pk to be deleted (or whatever the PumpWood system 27 have been implemented). Some model_class with 'deleted' field 28 does not remove the entry, it will flag deleted=True at this 29 cases. Model class with delete=True will be not retrieved 30 by default on `list` and `list_without_pag` end-points. 31 auth_header: 32 Auth header to substitute the microservice original 33 at the request (user impersonation). 34 35 Returns: 36 Returns delete object. 37 38 Raises: 39 PumpWoodObjectDoesNotExist: 40 'Requested object {model_class}[{pk}] not found.' This 41 indicates that the pk was not found in database. 42 """ 43 url_str = self._build_delete_request_url(model_class, pk) 44 return self.request_delete(url=url_str, auth_header=auth_header) 45 46 @staticmethod 47 def _build_remove_file_field(model_class, pk): 48 return "rest/%s/remove-file-field/%s/" % (model_class.lower(), pk) 49 50 def delete_file(self, model_class: str, pk: int, file_field: str, 51 auth_header: dict = None) -> bool: 52 """Send delete request to a PumpWood object. 53 54 Delete (or whatever the PumpWood system have been implemented) the 55 object with the specified pk. 56 57 At previous versions this function was `remove_file_field`. An alias 58 is created for backward compatibility. 59 60 Args: 61 model_class: 62 Model class to delete the object 63 pk: 64 Object pk to be deleted (or whatever the PumpWood system 65 have been implemented). 66 file_field: 67 File field to be removed from storage. 68 auth_header: 69 Auth header to substitute the microservice original 70 at the request (user impersonation). 71 72 Returns: 73 Return True is file was successful removed 74 75 Raises: 76 PumpWoodForbidden: 77 'storage_object attribute not set for view, file operations 78 are disable'. This indicates that storage_object is not 79 associated with view, not allowing it to make storage 80 operations. 81 PumpWoodForbidden: 82 'file_field must be set on self.file_fields dictionary.'. 83 This indicates that the `file_field` was not set as a file 84 field on the backend. 85 PumpWoodObjectDoesNotExist: 86 'File does not exist. File field [{}] is set as None'. 87 This indicates that the object does not exists on storage, 88 it should not occur. It might have been some manual update 89 of the database or at the storage level. 90 """ 91 url_str = self._build_remove_file_field(model_class, pk) 92 return self.request_delete( 93 url=url_str, auth_header=auth_header, 94 parameters={"file-field": file_field}) 95 96 # Create an alias for backward compatibility. 97 remove_file_field = delete_file 98 99 @staticmethod 100 def _build_delete_many_request_url(model_class): 101 return "rest/%s/delete/" % (model_class.lower(), ) 102 103 def delete_many(self, model_class: str, filter_dict: dict = {}, 104 exclude_dict: dict = {}, auth_header: dict = None) -> bool: 105 """Remove many objects using query to retrict removal. 106 107 CAUTION It is not possible to undo this operation, model_class 108 this deleted field will be removed from database when using this 109 end-point, different from using delete end-point. 110 111 Args: 112 model_class: 113 Model class to delete the object 114 filter_dict: 115 Dictionary to make filter query. 116 exclude_dict: 117 Dictionary to make exclude query. 118 auth_header: 119 Auth header to substitute the microservice original 120 at the request (user impersonation). 121 122 Returns: 123 True if delete is ok. 124 125 Raises: 126 PumpWoodObjectDeleteException: 127 Raises error if there is any error when commiting object 128 deletion on database. 129 """ 130 url_str = self._build_delete_many_request_url(model_class) 131 return self.request_post( 132 url=url_str, 133 data={'filter_dict': filter_dict, 'exclude_dict': exclude_dict}, 134 auth_header=auth_header)
Abstract class for calls at Pumpwood delete end-points.
15 def delete(self, model_class: str, pk: int, 16 auth_header: dict = None) -> dict: 17 """Send delete request to a PumpWood object. 18 19 Delete (or whatever the PumpWood system have been implemented) the 20 object with the specified pk. 21 22 Args: 23 model_class: 24 Model class to delete the object 25 pk: 26 Object pk to be deleted (or whatever the PumpWood system 27 have been implemented). Some model_class with 'deleted' field 28 does not remove the entry, it will flag deleted=True at this 29 cases. Model class with delete=True will be not retrieved 30 by default on `list` and `list_without_pag` end-points. 31 auth_header: 32 Auth header to substitute the microservice original 33 at the request (user impersonation). 34 35 Returns: 36 Returns delete object. 37 38 Raises: 39 PumpWoodObjectDoesNotExist: 40 'Requested object {model_class}[{pk}] not found.' This 41 indicates that the pk was not found in database. 42 """ 43 url_str = self._build_delete_request_url(model_class, pk) 44 return self.request_delete(url=url_str, auth_header=auth_header)
Send delete request to a PumpWood object.
Delete (or whatever the PumpWood system have been implemented) the object with the specified pk.
Arguments:
- model_class: Model class to delete the object
- pk: Object pk to be deleted (or whatever the PumpWood system
have been implemented). Some model_class with 'deleted' field
does not remove the entry, it will flag deleted=True at this
cases. Model class with delete=True will be not retrieved
by default on
list
andlist_without_pag
end-points. - auth_header: Auth header to substitute the microservice original at the request (user impersonation).
Returns:
Returns delete object.
Raises:
- PumpWoodObjectDoesNotExist: 'Requested object {model_class}[{pk}] not found.' This indicates that the pk was not found in database.
50 def delete_file(self, model_class: str, pk: int, file_field: str, 51 auth_header: dict = None) -> bool: 52 """Send delete request to a PumpWood object. 53 54 Delete (or whatever the PumpWood system have been implemented) the 55 object with the specified pk. 56 57 At previous versions this function was `remove_file_field`. An alias 58 is created for backward compatibility. 59 60 Args: 61 model_class: 62 Model class to delete the object 63 pk: 64 Object pk to be deleted (or whatever the PumpWood system 65 have been implemented). 66 file_field: 67 File field to be removed from storage. 68 auth_header: 69 Auth header to substitute the microservice original 70 at the request (user impersonation). 71 72 Returns: 73 Return True is file was successful removed 74 75 Raises: 76 PumpWoodForbidden: 77 'storage_object attribute not set for view, file operations 78 are disable'. This indicates that storage_object is not 79 associated with view, not allowing it to make storage 80 operations. 81 PumpWoodForbidden: 82 'file_field must be set on self.file_fields dictionary.'. 83 This indicates that the `file_field` was not set as a file 84 field on the backend. 85 PumpWoodObjectDoesNotExist: 86 'File does not exist. File field [{}] is set as None'. 87 This indicates that the object does not exists on storage, 88 it should not occur. It might have been some manual update 89 of the database or at the storage level. 90 """ 91 url_str = self._build_remove_file_field(model_class, pk) 92 return self.request_delete( 93 url=url_str, auth_header=auth_header, 94 parameters={"file-field": file_field})
Send delete request to a PumpWood object.
Delete (or whatever the PumpWood system have been implemented) the object with the specified pk.
At previous versions this function was remove_file_field
. An alias
is created for backward compatibility.
Arguments:
- model_class: Model class to delete the object
- pk: Object pk to be deleted (or whatever the PumpWood system have been implemented).
- file_field: File field to be removed from storage.
- auth_header: Auth header to substitute the microservice original at the request (user impersonation).
Returns:
Return True is file was successful removed
Raises:
- PumpWoodForbidden: 'storage_object attribute not set for view, file operations are disable'. This indicates that storage_object is not associated with view, not allowing it to make storage operations.
- PumpWoodForbidden: 'file_field must be set on self.file_fields dictionary.'.
This indicates that the
file_field
was not set as a file field on the backend. - PumpWoodObjectDoesNotExist: 'File does not exist. File field [{}] is set as None'. This indicates that the object does not exists on storage, it should not occur. It might have been some manual update of the database or at the storage level.
50 def delete_file(self, model_class: str, pk: int, file_field: str, 51 auth_header: dict = None) -> bool: 52 """Send delete request to a PumpWood object. 53 54 Delete (or whatever the PumpWood system have been implemented) the 55 object with the specified pk. 56 57 At previous versions this function was `remove_file_field`. An alias 58 is created for backward compatibility. 59 60 Args: 61 model_class: 62 Model class to delete the object 63 pk: 64 Object pk to be deleted (or whatever the PumpWood system 65 have been implemented). 66 file_field: 67 File field to be removed from storage. 68 auth_header: 69 Auth header to substitute the microservice original 70 at the request (user impersonation). 71 72 Returns: 73 Return True is file was successful removed 74 75 Raises: 76 PumpWoodForbidden: 77 'storage_object attribute not set for view, file operations 78 are disable'. This indicates that storage_object is not 79 associated with view, not allowing it to make storage 80 operations. 81 PumpWoodForbidden: 82 'file_field must be set on self.file_fields dictionary.'. 83 This indicates that the `file_field` was not set as a file 84 field on the backend. 85 PumpWoodObjectDoesNotExist: 86 'File does not exist. File field [{}] is set as None'. 87 This indicates that the object does not exists on storage, 88 it should not occur. It might have been some manual update 89 of the database or at the storage level. 90 """ 91 url_str = self._build_remove_file_field(model_class, pk) 92 return self.request_delete( 93 url=url_str, auth_header=auth_header, 94 parameters={"file-field": file_field})
Send delete request to a PumpWood object.
Delete (or whatever the PumpWood system have been implemented) the object with the specified pk.
At previous versions this function was remove_file_field
. An alias
is created for backward compatibility.
Arguments:
- model_class: Model class to delete the object
- pk: Object pk to be deleted (or whatever the PumpWood system have been implemented).
- file_field: File field to be removed from storage.
- auth_header: Auth header to substitute the microservice original at the request (user impersonation).
Returns:
Return True is file was successful removed
Raises:
- PumpWoodForbidden: 'storage_object attribute not set for view, file operations are disable'. This indicates that storage_object is not associated with view, not allowing it to make storage operations.
- PumpWoodForbidden: 'file_field must be set on self.file_fields dictionary.'.
This indicates that the
file_field
was not set as a file field on the backend. - PumpWoodObjectDoesNotExist: 'File does not exist. File field [{}] is set as None'. This indicates that the object does not exists on storage, it should not occur. It might have been some manual update of the database or at the storage level.
103 def delete_many(self, model_class: str, filter_dict: dict = {}, 104 exclude_dict: dict = {}, auth_header: dict = None) -> bool: 105 """Remove many objects using query to retrict removal. 106 107 CAUTION It is not possible to undo this operation, model_class 108 this deleted field will be removed from database when using this 109 end-point, different from using delete end-point. 110 111 Args: 112 model_class: 113 Model class to delete the object 114 filter_dict: 115 Dictionary to make filter query. 116 exclude_dict: 117 Dictionary to make exclude query. 118 auth_header: 119 Auth header to substitute the microservice original 120 at the request (user impersonation). 121 122 Returns: 123 True if delete is ok. 124 125 Raises: 126 PumpWoodObjectDeleteException: 127 Raises error if there is any error when commiting object 128 deletion on database. 129 """ 130 url_str = self._build_delete_many_request_url(model_class) 131 return self.request_post( 132 url=url_str, 133 data={'filter_dict': filter_dict, 'exclude_dict': exclude_dict}, 134 auth_header=auth_header)
Remove many objects using query to retrict removal.
CAUTION It is not possible to undo this operation, model_class this deleted field will be removed from database when using this end-point, different from using delete end-point.
Arguments:
- model_class: Model class to delete the object
- filter_dict: Dictionary to make filter query.
- exclude_dict: Dictionary to make exclude query.
- auth_header: Auth header to substitute the microservice original at the request (user impersonation).
Returns:
True if delete is ok.
Raises:
- PumpWoodObjectDeleteException: Raises error if there is any error when commiting object deletion on database.
12class ABCSimpleSaveMicroservice(ABC, PumpWoodMicroServiceBase): 13 """Abstract class for parallel calls at Pumpwood end-points.""" 14 15 @staticmethod 16 def _build_save_url(model_class): 17 return "rest/%s/save/" % (model_class.lower()) 18 19 def save(self, obj_dict, files: dict = None, auth_header: dict = None, 20 fields: list = None, default_fields: bool = False, 21 foreign_key_fields: bool = False, 22 related_fields: bool = False) -> dict: 23 """Save or Update a new object. 24 25 Function to save or update a new model_class object. If obj_dict['pk'] 26 is None or not defined a new object will be created. The obj 27 model class is defided at obj_dict['model_class'] and if not defined an 28 PumpWoodObjectSavingException will be raised. 29 30 If files argument is set, request will be transfered using a multipart 31 request file files mapping file key to file field on backend. 32 33 Args: 34 obj_dict: 35 Model data dictionary. It must have 'model_class' 36 key and if 'pk' key is not defined a new object will 37 be created, else object with pk will be updated. 38 files: 39 A dictionary of files to be added to as a multi-part 40 post request. File must be passed as a file object with read 41 bytes. 42 auth_header: 43 Auth header to substitute the microservice original 44 at the request (user impersonation). 45 fields: 46 Set the fields to be returned by the list end-point. 47 default_fields: 48 Boolean, if true and fields arguments None will return the 49 default fields set for list by the backend. 50 foreign_key_fields: 51 Return forenging key objects. It will return the fk 52 corresponding object. Ex: `created_by_id` reference to 53 a user `model_class` the correspondent to User will be 54 returned at `created_by`. 55 related_fields: 56 Return related fields objects. Related field objects are 57 objects that have a forenging key associated with this 58 model_class, results will be returned as a list of 59 dictionaries usually in a field with `_set` at end. 60 Returning related_fields consume backend resorces, use 61 carefully. 62 63 Returns: 64 Return updated/created object data. 65 66 Raises: 67 PumpWoodObjectSavingException: 68 'To save an object obj_dict must have model_class defined.' 69 This indicates that the obj_dict must have key `model_class` 70 indicating model class of the object that will be 71 updated/created. 72 PumpWoodObjectDoesNotExist: 73 'Requested object {model_class}[{pk}] not found.'. This 74 indicates that the pk passed on obj_dict was not found on 75 backend database. 76 PumpWoodIntegrityError: 77 Error raised when IntegrityError is raised on database. This 78 might ocorrur when saving objects that does not respect 79 uniqueness restriction on database or other IntegrityError 80 like removal of foreign keys with related data. 81 PumpWoodObjectSavingException: 82 Return error at object validation on de-serializing the 83 object or files with unexpected extensions. 84 """ 85 model_class = obj_dict.get('model_class') 86 if model_class is None: 87 raise PumpWoodObjectSavingException( 88 'To save an object obj_dict must have model_class defined.') 89 90 url_str = self._build_save_url(model_class) 91 parameters = { 92 "fields": fields, "default_fields": default_fields, 93 "foreign_key_fields": foreign_key_fields, 94 "related_fields": related_fields} 95 return self.request_post( 96 url=url_str, data=obj_dict, parameters=parameters, files=files, 97 auth_header=auth_header) 98 99 @staticmethod 100 def _build_save_streaming_file_url(model_class, pk): 101 return "rest/{model_class}/save-file-streaming/{pk}/".format( 102 model_class=model_class.lower(), pk=pk) 103 104 def save_streaming_file(self, model_class: str, pk: int, file_field: str, 105 file: io.BufferedReader, file_name: str = None, 106 auth_header: dict = None, 107 fields: list = None, default_fields: bool = False, 108 foreign_key_fields: bool = False, 109 related_fields: bool = False) -> str: 110 """Stream file to PumpWood. 111 112 Use streaming to transfer a file content to Pumpwood storage, this 113 end-point is prefered when transmiting files bigger than 10Mb. It 114 is necessary to have the object created before the file transfer. 115 116 Args: 117 model_class: 118 Model class of the object. 119 pk: 120 pk of the object. 121 file_field: 122 File field that will receive file stream. 123 file: 124 File to upload as a file object with read bytes option. 125 auth_header: 126 Auth header to substitute the microservice original 127 at the request (user impersonation). 128 file_name: 129 Name of the file, if not set it will be saved as 130 {pk}__{file_field}.{extension at permited extension} 131 fields: 132 Set the fields to be returned by the list end-point. 133 default_fields: 134 Boolean, if true and fields arguments None will return the 135 default fields set for list by the backend. 136 foreign_key_fields: 137 Return forenging key objects. It will return the fk 138 corresponding object. Ex: `created_by_id` reference to 139 a user `model_class` the correspondent to User will be 140 returned at `created_by`. 141 related_fields: 142 Return related fields objects. Related field objects are 143 objects that have a forenging key associated with this 144 model_class, results will be returned as a list of 145 dictionaries usually in a field with `_set` at end. 146 Returning related_fields consume backend resorces, use 147 carefully. 148 149 Returns: 150 Return the file name associated with data at the storage. 151 152 Raises: 153 PumpWoodForbidden: 154 'file_field must be set on self.file_fields dictionary'. This 155 indicates that the `file_field` passed is not associated 156 with a file field on the backend. 157 PumpWoodException: 158 'Saved bytes in streaming [{}] differ from file bytes [{}].'. 159 This indicates that there was an error when transfering data 160 to storage, the file bytes and transfered bytes does not 161 match. 162 """ 163 request_header = self._check__auth_header(auth_header=auth_header) 164 request_header["Content-Type"] = "application/octet-stream" 165 post_url = self.server_url + self._build_save_streaming_file_url( 166 model_class=model_class, pk=pk) 167 168 parameters = { 169 "fields": fields, "default_fields": default_fields, 170 "foreign_key_fields": foreign_key_fields, 171 "related_fields": related_fields, "file_field": file_field} 172 if file_name is not None: 173 parameters["file_name"] = file_name 174 175 response = requests.post( 176 url=post_url, data=file, params=parameters, 177 verify=self.verify_ssl, headers=request_header, stream=True, 178 timeout=self.default_timeout) 179 180 file_last_bite = file.tell() 181 self.error_handler(response) 182 json_response = self.angular_json(response) 183 184 if file_last_bite != json_response["bytes_uploaded"]: 185 template = ( 186 "Saved bytes in streaming [{}] differ from file " + 187 "bites [{}].") 188 raise PumpWoodException( 189 template.format( 190 json_response["bytes_uploaded"], file_last_bite)) 191 return json_response["file_path"]
Abstract class for parallel calls at Pumpwood end-points.
19 def save(self, obj_dict, files: dict = None, auth_header: dict = None, 20 fields: list = None, default_fields: bool = False, 21 foreign_key_fields: bool = False, 22 related_fields: bool = False) -> dict: 23 """Save or Update a new object. 24 25 Function to save or update a new model_class object. If obj_dict['pk'] 26 is None or not defined a new object will be created. The obj 27 model class is defided at obj_dict['model_class'] and if not defined an 28 PumpWoodObjectSavingException will be raised. 29 30 If files argument is set, request will be transfered using a multipart 31 request file files mapping file key to file field on backend. 32 33 Args: 34 obj_dict: 35 Model data dictionary. It must have 'model_class' 36 key and if 'pk' key is not defined a new object will 37 be created, else object with pk will be updated. 38 files: 39 A dictionary of files to be added to as a multi-part 40 post request. File must be passed as a file object with read 41 bytes. 42 auth_header: 43 Auth header to substitute the microservice original 44 at the request (user impersonation). 45 fields: 46 Set the fields to be returned by the list end-point. 47 default_fields: 48 Boolean, if true and fields arguments None will return the 49 default fields set for list by the backend. 50 foreign_key_fields: 51 Return forenging key objects. It will return the fk 52 corresponding object. Ex: `created_by_id` reference to 53 a user `model_class` the correspondent to User will be 54 returned at `created_by`. 55 related_fields: 56 Return related fields objects. Related field objects are 57 objects that have a forenging key associated with this 58 model_class, results will be returned as a list of 59 dictionaries usually in a field with `_set` at end. 60 Returning related_fields consume backend resorces, use 61 carefully. 62 63 Returns: 64 Return updated/created object data. 65 66 Raises: 67 PumpWoodObjectSavingException: 68 'To save an object obj_dict must have model_class defined.' 69 This indicates that the obj_dict must have key `model_class` 70 indicating model class of the object that will be 71 updated/created. 72 PumpWoodObjectDoesNotExist: 73 'Requested object {model_class}[{pk}] not found.'. This 74 indicates that the pk passed on obj_dict was not found on 75 backend database. 76 PumpWoodIntegrityError: 77 Error raised when IntegrityError is raised on database. This 78 might ocorrur when saving objects that does not respect 79 uniqueness restriction on database or other IntegrityError 80 like removal of foreign keys with related data. 81 PumpWoodObjectSavingException: 82 Return error at object validation on de-serializing the 83 object or files with unexpected extensions. 84 """ 85 model_class = obj_dict.get('model_class') 86 if model_class is None: 87 raise PumpWoodObjectSavingException( 88 'To save an object obj_dict must have model_class defined.') 89 90 url_str = self._build_save_url(model_class) 91 parameters = { 92 "fields": fields, "default_fields": default_fields, 93 "foreign_key_fields": foreign_key_fields, 94 "related_fields": related_fields} 95 return self.request_post( 96 url=url_str, data=obj_dict, parameters=parameters, files=files, 97 auth_header=auth_header)
Save or Update a new object.
Function to save or update a new model_class object. If obj_dict['pk'] is None or not defined a new object will be created. The obj model class is defided at obj_dict['model_class'] and if not defined an PumpWoodObjectSavingException will be raised.
If files argument is set, request will be transfered using a multipart request file files mapping file key to file field on backend.
Arguments:
- obj_dict: Model data dictionary. It must have 'model_class' key and if 'pk' key is not defined a new object will be created, else object with pk will be updated.
- files: A dictionary of files to be added to as a multi-part post request. File must be passed as a file object with read bytes.
- auth_header: Auth header to substitute the microservice original at the request (user impersonation).
- fields: Set the fields to be returned by the list end-point.
- default_fields: Boolean, if true and fields arguments None will return the default fields set for list by the backend.
- foreign_key_fields: Return forenging key objects. It will return the fk
corresponding object. Ex:
created_by_id
reference to a usermodel_class
the correspondent to User will be returned atcreated_by
. - related_fields: Return related fields objects. Related field objects are
objects that have a forenging key associated with this
model_class, results will be returned as a list of
dictionaries usually in a field with
_set
at end. Returning related_fields consume backend resorces, use carefully.
Returns:
Return updated/created object data.
Raises:
- PumpWoodObjectSavingException: 'To save an object obj_dict must have model_class defined.'
This indicates that the obj_dict must have key
model_class
indicating model class of the object that will be updated/created. - PumpWoodObjectDoesNotExist: 'Requested object {model_class}[{pk}] not found.'. This indicates that the pk passed on obj_dict was not found on backend database.
- PumpWoodIntegrityError: Error raised when IntegrityError is raised on database. This might ocorrur when saving objects that does not respect uniqueness restriction on database or other IntegrityError like removal of foreign keys with related data.
- PumpWoodObjectSavingException: Return error at object validation on de-serializing the object or files with unexpected extensions.
104 def save_streaming_file(self, model_class: str, pk: int, file_field: str, 105 file: io.BufferedReader, file_name: str = None, 106 auth_header: dict = None, 107 fields: list = None, default_fields: bool = False, 108 foreign_key_fields: bool = False, 109 related_fields: bool = False) -> str: 110 """Stream file to PumpWood. 111 112 Use streaming to transfer a file content to Pumpwood storage, this 113 end-point is prefered when transmiting files bigger than 10Mb. It 114 is necessary to have the object created before the file transfer. 115 116 Args: 117 model_class: 118 Model class of the object. 119 pk: 120 pk of the object. 121 file_field: 122 File field that will receive file stream. 123 file: 124 File to upload as a file object with read bytes option. 125 auth_header: 126 Auth header to substitute the microservice original 127 at the request (user impersonation). 128 file_name: 129 Name of the file, if not set it will be saved as 130 {pk}__{file_field}.{extension at permited extension} 131 fields: 132 Set the fields to be returned by the list end-point. 133 default_fields: 134 Boolean, if true and fields arguments None will return the 135 default fields set for list by the backend. 136 foreign_key_fields: 137 Return forenging key objects. It will return the fk 138 corresponding object. Ex: `created_by_id` reference to 139 a user `model_class` the correspondent to User will be 140 returned at `created_by`. 141 related_fields: 142 Return related fields objects. Related field objects are 143 objects that have a forenging key associated with this 144 model_class, results will be returned as a list of 145 dictionaries usually in a field with `_set` at end. 146 Returning related_fields consume backend resorces, use 147 carefully. 148 149 Returns: 150 Return the file name associated with data at the storage. 151 152 Raises: 153 PumpWoodForbidden: 154 'file_field must be set on self.file_fields dictionary'. This 155 indicates that the `file_field` passed is not associated 156 with a file field on the backend. 157 PumpWoodException: 158 'Saved bytes in streaming [{}] differ from file bytes [{}].'. 159 This indicates that there was an error when transfering data 160 to storage, the file bytes and transfered bytes does not 161 match. 162 """ 163 request_header = self._check__auth_header(auth_header=auth_header) 164 request_header["Content-Type"] = "application/octet-stream" 165 post_url = self.server_url + self._build_save_streaming_file_url( 166 model_class=model_class, pk=pk) 167 168 parameters = { 169 "fields": fields, "default_fields": default_fields, 170 "foreign_key_fields": foreign_key_fields, 171 "related_fields": related_fields, "file_field": file_field} 172 if file_name is not None: 173 parameters["file_name"] = file_name 174 175 response = requests.post( 176 url=post_url, data=file, params=parameters, 177 verify=self.verify_ssl, headers=request_header, stream=True, 178 timeout=self.default_timeout) 179 180 file_last_bite = file.tell() 181 self.error_handler(response) 182 json_response = self.angular_json(response) 183 184 if file_last_bite != json_response["bytes_uploaded"]: 185 template = ( 186 "Saved bytes in streaming [{}] differ from file " + 187 "bites [{}].") 188 raise PumpWoodException( 189 template.format( 190 json_response["bytes_uploaded"], file_last_bite)) 191 return json_response["file_path"]
Stream file to PumpWood.
Use streaming to transfer a file content to Pumpwood storage, this end-point is prefered when transmiting files bigger than 10Mb. It is necessary to have the object created before the file transfer.
Arguments:
- model_class: Model class of the object.
- pk: pk of the object.
- file_field: File field that will receive file stream.
- file: File to upload as a file object with read bytes option.
- auth_header: Auth header to substitute the microservice original at the request (user impersonation).
- file_name: Name of the file, if not set it will be saved as {pk}__{file_field}.{extension at permited extension}
- fields: Set the fields to be returned by the list end-point.
- default_fields: Boolean, if true and fields arguments None will return the default fields set for list by the backend.
- foreign_key_fields: Return forenging key objects. It will return the fk
corresponding object. Ex:
created_by_id
reference to a usermodel_class
the correspondent to User will be returned atcreated_by
. - related_fields: Return related fields objects. Related field objects are
objects that have a forenging key associated with this
model_class, results will be returned as a list of
dictionaries usually in a field with
_set
at end. Returning related_fields consume backend resorces, use carefully.
Returns:
Return the file name associated with data at the storage.
Raises:
- PumpWoodForbidden: 'file_field must be set on self.file_fields dictionary'. This
indicates that the
file_field
passed is not associated with a file field on the backend. - PumpWoodException: 'Saved bytes in streaming [{}] differ from file bytes [{}].'. This indicates that there was an error when transfering data to storage, the file bytes and transfered bytes does not match.