Source code for snow.resource.schema
import warnings
from typing import Tuple, Iterable
import marshmallow
import ujson
from .fields import BaseField
class SchemaOpts(marshmallow.schema.SchemaOpts):
def __init__(self, meta, **kwargs):
self.load_only = []
self.dump_only = []
super(SchemaOpts, self).__init__(meta, **kwargs)
self.render_module = ujson
self.unknown = marshmallow.EXCLUDE
class SchemaMeta(marshmallow.schema.SchemaMeta):
def __new__(mcs, name, bases, attrs):
fields = {}
for key, value in attrs.items():
if isinstance(value, BaseField):
fields[key] = value
cls = super().__new__(mcs, name, bases, attrs)
for name, field in fields.items():
field.name = name
# Register queryable BaseField with the class.
setattr(cls, name, field)
return cls
[docs]class Schema(marshmallow.Schema, metaclass=SchemaMeta):
"""Resource schema
Attributes:
__location__: API path
"""
OPTIONS_CLASS = SchemaOpts
def __init__(self, *args, **kwargs):
super(Schema, self).__init__(*args, **kwargs)
def __transform(self, data: dict) -> Iterable[Tuple[str, str]]:
for key, value in data.items():
name = key.name if isinstance(key, BaseField) else key
if isinstance(value, dict):
field = getattr(self, name, None)
if not field:
warnings.warn(f"Unexpected field in response content: {name}, skipping...")
continue
yield name, value[field.joined.value]
else:
yield name, value
@marshmallow.pre_load
def _transform(self, data, **_):
"""Normalize the given data
Args:
data: Dictionary of fields to load
Returns:
dict(field_name=field_value, ...)
"""
return dict(self.__transform(data))
@property
def __location__(self):
raise NotImplementedError