def cast_value(self, field, value): if isinstance(field, ResourceListField): if not isinstance(value, dict): raise APIError.BadRequest( "Expected nested object in list for %s" % field) try: resource = field.resource_type() if isinstance(resource, DebugResource): return value.copy() new_object = {} for k, v in value.iteritems(): if not k in resource._fields and self.ignore_missing_fields: new_object[k] = v continue _field = resource._fields[k] if _field.property_name is not None: k = _field.property_name new_object[k] = self.cast_value(_field, v) if not getattr(resource, "_underlying_model", None): return new_object return resource._underlying_model(**new_object) except Exception: logging.exception( "Failed to cast value to _underlying_model of resource_type: %s" % getattr(field, 'resource_type', None)) raise # TODO: Use field to cast field back into a value, # if possible. return value
def apply_to_model(self, dt): for k, v in self.patch.iteritems(): field = self.get_field_from_resource(k) if field is None: setattr(dt, k, v) elif isinstance(v, dict): # Recursive application. resource = self.get_resource_from_field(field) patch = ResourcePatch( v, resource, ignore_missing_fields=self.ignore_missing_fields) patch.apply_to_model(getattr(dt, k, None)) elif isinstance(v, list): if (not isinstance(field, ResourceListField) and not isinstance(field, ListField)): raise APIError.BadRequest( "List not expected for field '%s'" % k) new_list = [] for itm in v: new_list.append(self.cast_value(field, itm)) setattr(dt, k, new_list) else: # Cast value and set setattr(dt, k, self.cast_value(field, v))
def get_field_from_resource(self, field): if isinstance(self.resource, DebugResource): # no fields defined in a DebugResource return None try: return self.resource._fields[field] except KeyError: if not self.ignore_missing_fields: raise APIError.BadRequest("Field '%s' is not expected." % field) return None