Skip to content

Commit

Permalink
Start refactoring models and fields
Browse files Browse the repository at this point in the history
  • Loading branch information
noirbizarre committed Mar 25, 2015
1 parent 77f0770 commit 09a6c64
Show file tree
Hide file tree
Showing 9 changed files with 906 additions and 835 deletions.
100 changes: 76 additions & 24 deletions flask_restplus/fields.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,33 @@

from flask.ext.restful import fields as base_fields

from .utils import camel_to_dash
from .utils import camel_to_dash, not_none


class DetailsMixin(object):
class BaseField(object):
__schema_type__ = 'string'
__schema_format__ = None

def __init__(self, *args, **kwargs):
self.description = kwargs.pop('description', None)
self.title = kwargs.pop('title', None)
self.required = kwargs.pop('required', None)
self.readonly = kwargs.pop('readonly', None)
super(DetailsMixin, self).__init__(*args, **kwargs)
super(BaseField, self).__init__(*args, **kwargs)

@property
def __schema__(self):
return not_none(self.schema())

def schema(self):
return {
'type': self.__schema_type__,
'format': self.__schema_format__,
'title': self.title,
'description': self.description,
'readOnly': self.readonly,
'default': self.default,
}


class MinMaxMixin(object):
Expand All @@ -21,57 +38,92 @@ def __init__(self, *args, **kwargs):
self.maximum = kwargs.pop('max', None)
super(MinMaxMixin, self).__init__(*args, **kwargs)

def schema(self):
schema = super(MinMaxMixin, self).schema()
schema.update(minimum=self.minimum, maximum=self.maximum)
return schema

class String(DetailsMixin, base_fields.String):

class String(BaseField, base_fields.String):
def __init__(self, *args, **kwargs):
self.enum = kwargs.pop('enum', None)
self.discriminator = kwargs.pop('discriminator', None)
super(String, self).__init__(*args, **kwargs)
self.required = self.discriminator or self.required

def schema(self):
schema = super(String, self).schema()
schema.update(enum=self.enum)
return schema

class Integer(DetailsMixin, MinMaxMixin, base_fields.Integer):
pass

class Integer(MinMaxMixin, BaseField, base_fields.Integer):
__schema_type__ = 'integer'

class Float(DetailsMixin, MinMaxMixin, base_fields.Float):
pass
def __init__(self, default=None, **kwargs):
super(Integer, self).__init__(default=default, **kwargs)


class Arbitrary(DetailsMixin, MinMaxMixin, base_fields.Arbitrary):
pass
class Float(MinMaxMixin, BaseField, base_fields.Float):
__schema_type__ = 'number'


class Boolean(DetailsMixin, base_fields.Boolean):
pass
class Arbitrary(MinMaxMixin, BaseField, base_fields.Arbitrary):
__schema_type__ = 'number'


class DateTime(DetailsMixin, base_fields.DateTime):
pass
class Boolean(BaseField, base_fields.Boolean):
__schema_type__ = 'boolean'


class Raw(DetailsMixin, base_fields.Raw):
pass
class DateTime(BaseField, base_fields.DateTime):
__schema_format__ = 'date-time'


class Nested(DetailsMixin, base_fields.Nested):
def __init__(self, model, **kwargs):
class Raw(BaseField, base_fields.Raw):
__schema_type__ = 'object'


class Nested(BaseField, base_fields.Nested):
__schema_type__ = None

def __init__(self, model, as_list=False, **kwargs):
self.model = model
self.as_list = as_list
super(Nested, self).__init__(getattr(model, 'resolved', model), **kwargs)

def schema(self):
schema = super(Nested, self).schema()
ref = '#/definitions/{0}'.format(self.nested.name)

class List(DetailsMixin, base_fields.List):
pass
if self.as_list:
schema['type'] = 'array'
schema['items'] = {'$ref': ref}
else:
schema['$ref'] = ref
# if not self.allow_null and not self.readonly:
# schema['required'] = True

return schema

class Url(DetailsMixin, base_fields.Url):
pass

class List(BaseField, base_fields.List):
def schema(self):
schema = super(List, self).schema()
schema['type'] = 'array'
schema['items'] = self.container.__schema__
return schema


class Fixed(DetailsMixin, MinMaxMixin, base_fields.Fixed):
class Url(BaseField, base_fields.Url):
pass


class FormattedString(DetailsMixin, base_fields.FormattedString):
class Fixed(MinMaxMixin, BaseField, base_fields.Fixed):
__schema_type__ = 'number'


class FormattedString(BaseField, base_fields.FormattedString):
pass


Expand Down
37 changes: 37 additions & 0 deletions flask_restplus/model.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,14 @@

from collections import MutableMapping

from .utils import not_none


def instance(cls):
if isinstance(cls, type):
return cls()
return cls


class ApiModel(dict, MutableMapping):
'''A thin wrapper on dict to store API doc metadata'''
Expand Down Expand Up @@ -62,3 +70,32 @@ def get_parent(self, name):
return self.__parent__.get_parent(name)
else:
raise ValueError('Parent ' + name + ' not found')

@property
def __schema__(self):
properties = {}
required = set()
discriminator = None
for name, field in self.items():
field = instance(field)
properties[name] = field.__schema__
if field.required:
required.add(name)
if getattr(field, 'discriminator', False):
discriminator = name

schema = not_none({
'required': sorted(list(required)) or None,
'properties': properties,
'discriminator': discriminator,
})

if self.__parent__:
return {
'allOf': [
{'$ref': '#/definitions/{0}'.format(self.__parent__.name)},
schema
]
}
else:
return schema

0 comments on commit 09a6c64

Please sign in to comment.