def extract_files(self, data): """ This functions checks if data which are going to be sent to request include files and it extract them. Then it performs two checks: a) It checks that the location of files is not nested. b) If files were detected, then it checks that request data does not include nested data. When uploading files, the `Content-Type` header of request is set to `multipart/form-data`. :param data: Dictionary of data which are going to be sent to request. :returns: A dictionary keyed by the name of the field and it includes all files to be uploaded. """ paths = [ path for path, val in doc.doc_iter(data) if isinstance(val, file) ] error_msg = ('Content-Type `application/json is not supported when' ' uploading files`') if any(len(path) > 1 for path in paths): raise ex.ApimasClientException(error_msg) if paths and any( isinstance(v, (list, dict)) for _, v in data.iteritems()): raise ex.ApimasClientException(error_msg) return {path[-1]: doc.doc_pop(data, path) for path in paths}
def partial_validate(self, data, raise_exception=True, schema=None): """ Validates data that are going to be sent for a partial update of a resource. Construct a cerberus schema validator by taking into consideration only the fields that are included in the request. :param raise_exception: True if an exception should be raised when validation fails. """ schema = schema or self.validation_schema cerberus_paths = to_cerberus_paths(data) validated_subdocs = self._validate_subdata(data, schema, raise_exception) partial_schema_paths = { path: doc.doc_get(schema, path.split('/')) for path in cerberus_paths } partial_schema = doc.doc_from_ns(partial_schema_paths) validator = ApimasValidator(partial_schema) is_valid = validator.validate(data) if raise_exception and not is_valid: raise ex.ApimasClientException(validator.errors) for k, v in validated_subdocs.iteritems(): doc.doc_set(validator.document, k, v) return validator.document
def wrapper(*args, **kwargs): try: r = func(*args, **kwargs) if kwargs.pop('raise_exception', True): r.raise_for_status() return r except HTTPError as e: raise ex.ApimasClientException(e.message, response=e.response, request=e.request)
def validate(self, data, raise_exception=True): """ Validates data that are going to be sent using a cerberus validation schema. :param raise_exception: True if an exception should be raised when validation fails. """ is_valid = self.api_validator.validate(data) if raise_exception and not is_valid: raise ex.ApimasClientException(self.api_validator.errors) return self.api_validator.document
def _validate_subdata(self, data, schema, raise_exception): """ This function partially validates subdata of request. Subdata are considered nested data which are elements of lists. Example: data = { 'foo': [ {'foo': 'value'}, {'bar': 'value'}, ] } This function partial validates them according to their specified fields. :returns: A dictionary of validated subdata, with the path of their location to the parent document as keys. """ subdocs = get_subdocuments(data) validated = {} for k, v in subdocs.iteritems(): path = k.split('/') cerberus_path = [] for u in path: cerberus_path.extend([u, 'schema']) subdata = doc.doc_pop(data, path) subschema = doc.doc_pop(schema, cerberus_path[:-1]) or {} subschema = subschema.get('schema', {}).get('schema', {}) if not subschema: raise ex.ApimasClientException( 'Field `%s` cannot be validated' % (str(tuple(path)))) validated_docs = [] for subdoc in subdata: validated_docs.append( self.partial_validate(subdoc, raise_exception, subschema)) validated[tuple(path)] = validated_docs return validated