leveled up, minus auth
parent
7b23ad97d8
commit
d0a9b556c6
@ -1,3 +1 @@
|
|||||||
from cookie_api.renders import JSONRenderer
|
from cookie_api.app import application_factory
|
||||||
from cookie_api.app import application_factory
|
|
||||||
from cookie_api.models import Base
|
|
@ -1,16 +0,0 @@
|
|||||||
from apistar import Command
|
|
||||||
from apistar.backends.sqlalchemy_backend import Session
|
|
||||||
|
|
||||||
from cookie_api.models import User
|
|
||||||
|
|
||||||
|
|
||||||
def create_user(session: Session, email, password):
|
|
||||||
user = User(email, password)
|
|
||||||
session.add(user)
|
|
||||||
session.commit()
|
|
||||||
print('User added')
|
|
||||||
|
|
||||||
|
|
||||||
commands = [
|
|
||||||
Command('create_user', create_user)
|
|
||||||
]
|
|
@ -1,25 +0,0 @@
|
|||||||
import datetime as dt
|
|
||||||
import decimal
|
|
||||||
import json
|
|
||||||
|
|
||||||
from apistar import http
|
|
||||||
from apistar.renderers import Renderer
|
|
||||||
|
|
||||||
|
|
||||||
def extended_encoder(obj):
|
|
||||||
"""JSON encoder function with support for ISO 8601 datetime serialization and Decimal to float casting"""
|
|
||||||
if isinstance(obj, dt.datetime):
|
|
||||||
return obj.isoformat()
|
|
||||||
elif isinstance(obj, decimal.Decimal):
|
|
||||||
return float(obj)
|
|
||||||
|
|
||||||
|
|
||||||
class JSONRenderer(Renderer):
|
|
||||||
"""JSON Render with support for ISO 8601 datetime serialization and Decimal to float casting"""
|
|
||||||
media_type = 'application/json'
|
|
||||||
charset = None
|
|
||||||
|
|
||||||
def render(self, data: http.ResponseData) -> bytes:
|
|
||||||
return json.dumps(data, default=extended_encoder).encode('utf-8')
|
|
||||||
|
|
||||||
# TODO add an XML render
|
|
@ -1,48 +1,13 @@
|
|||||||
from apistar import typesystem
|
from apistar import types, validators
|
||||||
# from marshmallow import Schema, fields
|
from cookie_api.util import Decimal
|
||||||
|
|
||||||
from cookie_api.types import Datetime, Decimal
|
|
||||||
|
class CookieSchema(types.Type):
|
||||||
|
id = validators.Integer(allow_null=True)
|
||||||
# class CookieSchema(Schema):
|
created_date = validators.DateTime(allow_null=True)
|
||||||
# id = fields.Int()
|
modified_date = validators.DateTime(allow_null=True)
|
||||||
# created_date = fields.DateTime()
|
name = validators.String(max_length=50)
|
||||||
# modified_date = fields.DateTime()
|
recipe_url = validators.String(max_length=255)
|
||||||
# name = fields.Str(required=True)
|
sku = validators.String(max_length=55)
|
||||||
# recipe_url = fields.Str()
|
qoh = validators.Integer(minimum=0)
|
||||||
# sku = fields.Str(required=True)
|
unit_cost = Decimal(minimum=0.0)
|
||||||
# qoh = fields.Int(required=True)
|
|
||||||
# unit_cost = fields.Decimal(required=True)
|
|
||||||
|
|
||||||
|
|
||||||
class UserSchema(typesystem.Object):
|
|
||||||
description = 'A User respresentation'
|
|
||||||
properties = {
|
|
||||||
'id': typesystem.integer(),
|
|
||||||
'created_date': Datetime,
|
|
||||||
'modified_date': Datetime,
|
|
||||||
'email': typesystem.string(max_length=255),
|
|
||||||
'confirmed': typesystem.boolean(),
|
|
||||||
'admin': typesystem.boolean()
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
class UserCreateSchema(typesystem.Object):
|
|
||||||
description = 'A User respresentation for creating a user'
|
|
||||||
properties = {
|
|
||||||
'email': typesystem.string(max_length=255),
|
|
||||||
'password': typesystem.string(max_length=255)
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
class CookieSchema(typesystem.Object):
|
|
||||||
properties = {
|
|
||||||
'id': typesystem.integer(),
|
|
||||||
'created_date': Datetime,
|
|
||||||
'modified_date': Datetime,
|
|
||||||
'name': typesystem.string(),
|
|
||||||
'recipe_url': typesystem.string(),
|
|
||||||
'sku': typesystem.string(),
|
|
||||||
'qoh': typesystem.integer(),
|
|
||||||
'unit_cost': Decimal
|
|
||||||
}
|
|
||||||
|
@ -1,25 +0,0 @@
|
|||||||
import datetime
|
|
||||||
import decimal
|
|
||||||
|
|
||||||
import dateutil
|
|
||||||
from apistar import typesystem
|
|
||||||
|
|
||||||
|
|
||||||
class Datetime(datetime.datetime):
|
|
||||||
native_type = datetime.datetime
|
|
||||||
|
|
||||||
def __new__(cls, *args, **kwargs) -> datetime:
|
|
||||||
if args and isinstance(args[0], cls.native_type):
|
|
||||||
return args[0]
|
|
||||||
if args and isinstance(args[0], str):
|
|
||||||
try:
|
|
||||||
return dateutil.parser.parse(args[0])
|
|
||||||
except ValueError:
|
|
||||||
raise typesystem.TypeSystemError(cls=cls, code='type') from None
|
|
||||||
return cls.native_type(*args, **kwargs)
|
|
||||||
|
|
||||||
|
|
||||||
class Decimal(typesystem._NumericType, decimal.Decimal):
|
|
||||||
native_type = decimal.Decimal
|
|
||||||
|
|
||||||
|
|
@ -0,0 +1,106 @@
|
|||||||
|
import datetime as dt
|
||||||
|
import decimal
|
||||||
|
from math import isfinite
|
||||||
|
import typing
|
||||||
|
from apistar import types, validators
|
||||||
|
from apistar.http import JSONResponse, Response
|
||||||
|
from apistar.server.components import Component
|
||||||
|
from sqlalchemy.engine import Engine
|
||||||
|
from sqlalchemy.orm import sessionmaker, Session, scoped_session
|
||||||
|
|
||||||
|
|
||||||
|
class Decimal(validators.NumericType):
|
||||||
|
numeric_type = decimal.Decimal
|
||||||
|
|
||||||
|
def validate(self, value, definitions=None, allow_coerce=False):
|
||||||
|
if value is None and self.allow_null:
|
||||||
|
return None
|
||||||
|
elif value is None:
|
||||||
|
self.error('null')
|
||||||
|
elif isinstance(value, bool):
|
||||||
|
self.error('type')
|
||||||
|
elif self.numeric_type is int and isinstance(value, float) and not value.is_integer():
|
||||||
|
self.error('integer')
|
||||||
|
elif not isinstance(value, (int, float, decimal.Decimal)) and not allow_coerce:
|
||||||
|
self.error('type')
|
||||||
|
elif isinstance(value, float) and not isfinite(value):
|
||||||
|
self.error('finite')
|
||||||
|
|
||||||
|
try:
|
||||||
|
value = self.numeric_type(value)
|
||||||
|
except (TypeError, ValueError):
|
||||||
|
self.error('type')
|
||||||
|
|
||||||
|
if self.enum is not None:
|
||||||
|
if value not in self.enum:
|
||||||
|
if len(self.enum) == 1:
|
||||||
|
self.error('exact')
|
||||||
|
self.error('enum')
|
||||||
|
|
||||||
|
if self.minimum is not None:
|
||||||
|
if self.exclusive_minimum:
|
||||||
|
if value <= self.minimum:
|
||||||
|
self.error('exclusive_minimum')
|
||||||
|
else:
|
||||||
|
if value < self.minimum:
|
||||||
|
self.error('minimum')
|
||||||
|
|
||||||
|
if self.maximum is not None:
|
||||||
|
if self.exclusive_maximum:
|
||||||
|
if value >= self.maximum:
|
||||||
|
self.error('exclusive_maximum')
|
||||||
|
else:
|
||||||
|
if value > self.maximum:
|
||||||
|
self.error('maximum')
|
||||||
|
|
||||||
|
if self.multiple_of is not None:
|
||||||
|
if isinstance(self.multiple_of, float):
|
||||||
|
if not (value * (1 / self.multiple_of)).is_integer():
|
||||||
|
self.error('multiple_of')
|
||||||
|
else:
|
||||||
|
if value % self.multiple_of:
|
||||||
|
self.error('multiple_of')
|
||||||
|
|
||||||
|
return value
|
||||||
|
|
||||||
|
|
||||||
|
class ExtJSONResponse(JSONResponse):
|
||||||
|
"""JSON Response with support for ISO 8601 datetime serialization and Decimal to float casting"""
|
||||||
|
|
||||||
|
def default(self, obj: typing.Any) -> typing.Any:
|
||||||
|
if isinstance(obj, types.Type):
|
||||||
|
return dict(obj)
|
||||||
|
if isinstance(obj, dt.datetime):
|
||||||
|
return obj.isoformat()
|
||||||
|
elif isinstance(obj, decimal.Decimal):
|
||||||
|
return float(obj)
|
||||||
|
error = "Object of type '%s' is not JSON serializable."
|
||||||
|
return TypeError(error % type(obj).__name_)
|
||||||
|
|
||||||
|
|
||||||
|
DBSession = scoped_session(sessionmaker())
|
||||||
|
|
||||||
|
|
||||||
|
class SQLAlchemySession(Component):
|
||||||
|
def __init__(self, engine=None):
|
||||||
|
if not isinstance(engine, Engine):
|
||||||
|
raise ValueError('SQLAlchemySession must be instantiated with a sqlalchemy.engine.Engine object')
|
||||||
|
self.engine = engine
|
||||||
|
DBSession.configure(bind=self.engine)
|
||||||
|
|
||||||
|
def resolve(self) -> Session:
|
||||||
|
return DBSession()
|
||||||
|
|
||||||
|
|
||||||
|
class SQLAlchemyHook:
|
||||||
|
def on_request(self, session: Session):
|
||||||
|
return
|
||||||
|
|
||||||
|
def on_response(self, session: Session, response: Response):
|
||||||
|
DBSession.remove()
|
||||||
|
return response
|
||||||
|
|
||||||
|
def on_error(self, session: Session, response: Response):
|
||||||
|
session.rollback()
|
||||||
|
DBSession.remove()
|
||||||
|
return response
|
@ -1,66 +1,23 @@
|
|||||||
alembic==0.9.6
|
alembic==0.9.9
|
||||||
apistar==0.3.9
|
apistar==0.5.10
|
||||||
apistar-alembic-migrations==0.0.6
|
apistar-jwt==0.4.2
|
||||||
apistar-jwt==0.2.1
|
|
||||||
bcrypt==3.1.4
|
bcrypt==3.1.4
|
||||||
certifi==2017.7.27.1
|
certifi==2018.4.16
|
||||||
cffi==1.11.2
|
cffi==1.11.5
|
||||||
chardet==3.0.4
|
chardet==3.0.4
|
||||||
colorama==0.3.9
|
|
||||||
coreapi==2.3.3
|
|
||||||
coreschema==0.0.4
|
|
||||||
idna==2.6
|
idna==2.6
|
||||||
itypes==1.1.0
|
Jinja2==2.10
|
||||||
Jinja2==2.9.6
|
Logbook==1.3.3
|
||||||
Logbook==1.1.0
|
|
||||||
Mako==1.0.7
|
Mako==1.0.7
|
||||||
MarkupSafe==1.0
|
MarkupSafe==1.0
|
||||||
marshmallow==2.15.0
|
psycopg2==2.7.4
|
||||||
psycopg2==2.7.3.1
|
|
||||||
py==1.4.34
|
|
||||||
pycparser==2.18
|
pycparser==2.18
|
||||||
PyJWT==1.5.3
|
PyJWT==1.6.1
|
||||||
pytest==3.2.3
|
python-dateutil==2.7.2
|
||||||
python-dateutil==2.6.1
|
|
||||||
python-editor==1.0.3
|
python-editor==1.0.3
|
||||||
requests==2.18.4
|
requests==2.18.4
|
||||||
six==1.11.0
|
six==1.11.0
|
||||||
SQLAlchemy==1.1.14
|
SQLAlchemy==1.2.7
|
||||||
uritemplate==3.0.0
|
|
||||||
urllib3==1.22
|
urllib3==1.22
|
||||||
Werkzeug==0.12.2
|
Werkzeug==0.14.1
|
||||||
whitenoise==3.3.1
|
|
||||||
alembic==0.9.6
|
|
||||||
apistar==0.3.9
|
|
||||||
apistar-alembic-migrations==0.0.6
|
|
||||||
apistar-jwt==0.2.1
|
|
||||||
apistar-mail==0.2.0
|
|
||||||
bcrypt==3.1.4
|
|
||||||
certifi==2017.7.27.1
|
|
||||||
cffi==1.11.2
|
|
||||||
chardet==3.0.4
|
|
||||||
colorama==0.3.9
|
|
||||||
coreapi==2.3.3
|
|
||||||
coreschema==0.0.4
|
|
||||||
idna==2.6
|
|
||||||
itsdangerous==0.24
|
|
||||||
itypes==1.1.0
|
|
||||||
Jinja2==2.9.6
|
|
||||||
Logbook==1.1.0
|
|
||||||
Mako==1.0.7
|
|
||||||
MarkupSafe==1.0
|
|
||||||
marshmallow==2.15.0
|
|
||||||
psycopg2==2.7.3.1
|
|
||||||
py==1.4.34
|
|
||||||
pycparser==2.18
|
|
||||||
PyJWT==1.5.3
|
|
||||||
pytest==3.2.3
|
|
||||||
python-dateutil==2.6.1
|
|
||||||
python-editor==1.0.3
|
|
||||||
requests==2.18.4
|
|
||||||
six==1.11.0
|
|
||||||
SQLAlchemy==1.1.14
|
|
||||||
uritemplate==3.0.0
|
|
||||||
urllib3==1.22
|
|
||||||
Werkzeug==0.12.2
|
|
||||||
whitenoise==3.3.1
|
whitenoise==3.3.1
|
||||||
|
Loading…
Reference in New Issue