Initial commit
commit
3e2cf37921
@ -0,0 +1,62 @@
|
||||
# Pycharm
|
||||
.idea
|
||||
|
||||
# ---> Python
|
||||
# Byte-compiled / optimized / DLL files
|
||||
__pycache__/
|
||||
*.py[cod]
|
||||
*$py.class
|
||||
|
||||
# C extensions
|
||||
*.so
|
||||
|
||||
# Distribution / packaging
|
||||
.Python
|
||||
env/
|
||||
build/
|
||||
develop-eggs/
|
||||
dist/
|
||||
downloads/
|
||||
eggs/
|
||||
.eggs/
|
||||
lib/
|
||||
lib64/
|
||||
parts/
|
||||
sdist/
|
||||
var/
|
||||
*.egg-info/
|
||||
.installed.cfg
|
||||
*.egg
|
||||
|
||||
# PyInstaller
|
||||
# Usually these files are written by a python script from a template
|
||||
# before PyInstaller builds the exe, so as to inject date/other infos into it.
|
||||
*.manifest
|
||||
*.spec
|
||||
|
||||
# Installer logs
|
||||
pip-log.txt
|
||||
pip-delete-this-directory.txt
|
||||
|
||||
# Unit test / coverage reports
|
||||
htmlcov/
|
||||
.tox/
|
||||
.coverage
|
||||
.coverage.*
|
||||
.cache
|
||||
nosetests.xml
|
||||
coverage.xml
|
||||
*,cover
|
||||
|
||||
# Translations
|
||||
*.mo
|
||||
*.pot
|
||||
|
||||
# Django stuff:
|
||||
*.log
|
||||
|
||||
# Sphinx documentation
|
||||
docs/_build/
|
||||
|
||||
# PyBuilder
|
||||
target/
|
@ -0,0 +1,52 @@
|
||||
import json
|
||||
|
||||
from apistar import Include, Route, http, Response, annotate
|
||||
from apistar.frameworks.wsgi import WSGIApp as App
|
||||
from apistar.handlers import docs_urls, static_urls
|
||||
from apistar.backends import sqlalchemy_backend
|
||||
from apistar.backends.sqlalchemy_backend import Session
|
||||
|
||||
from models import Base, Cookie
|
||||
from model.util import alchemyencoder
|
||||
from render import JSONRenderer
|
||||
|
||||
|
||||
def welcome(name=None):
|
||||
if name is None:
|
||||
return {'message': 'Welcome to API Star!'}
|
||||
return {'message': 'Welcome to API Star, %s!' % name}
|
||||
|
||||
|
||||
@annotate(renderers=[JSONRenderer()])
|
||||
def get_cookies(session: Session):
|
||||
cookies = session.query(Cookie).all()
|
||||
result = [{"id": cookie.id,
|
||||
"created_date": cookie.created_date,
|
||||
"modified_date": cookie.modified_date,
|
||||
"name": cookie.name,
|
||||
"recipe_url": cookie.recipe_url,
|
||||
"sku": cookie.sku,
|
||||
"qoh": cookie.unit_cost}
|
||||
for cookie in cookies]
|
||||
|
||||
return result
|
||||
|
||||
routes = [
|
||||
Route('/', 'GET', welcome),
|
||||
Route('/cookies', 'GET', get_cookies),
|
||||
Include('/docs', docs_urls),
|
||||
Include('/static', static_urls)
|
||||
]
|
||||
|
||||
settings = {
|
||||
'DATABASE': {
|
||||
'URL': 'postgresql://:@localhost/apistar',
|
||||
'METADATA': Base.metadata
|
||||
}
|
||||
}
|
||||
|
||||
app = App(routes=routes,
|
||||
settings=settings,
|
||||
commands=sqlalchemy_backend.commands,
|
||||
components=sqlalchemy_backend.components
|
||||
)
|
@ -0,0 +1,9 @@
|
||||
import datetime as dt
|
||||
import decimal
|
||||
|
||||
def alchemyencoder(obj):
|
||||
"""JSON encoder function for SQLAlchemy special classes."""
|
||||
if isinstance(obj, dt.datetime):
|
||||
return obj.isoformat()
|
||||
elif isinstance(obj, decimal.Decimal):
|
||||
return float(obj)
|
@ -0,0 +1,70 @@
|
||||
from sqlalchemy.ext.declarative import declarative_base
|
||||
from sqlalchemy import Column, Integer, String, ForeignKey, DateTime, Boolean, Numeric
|
||||
from sqlalchemy.orm import relationship, backref
|
||||
from sqlalchemy.sql import expression
|
||||
from sqlalchemy.ext.compiler import compiles
|
||||
from sqlalchemy.types import DateTime as DateTimeType
|
||||
|
||||
# can be moved to models util
|
||||
class utcnow(expression.FunctionElement):
|
||||
type = DateTimeType()
|
||||
|
||||
# Can be moved to the models util dirp
|
||||
@compiles(utcnow, 'postgresql')
|
||||
def pg_utcnow(element, compiler, **kw):
|
||||
return "TIMEZONE('utc', CURRENT_TIMESTAMP)"
|
||||
|
||||
|
||||
Base = declarative_base()
|
||||
|
||||
|
||||
|
||||
class DBMixin:
|
||||
id = Column(Integer, primary_key=True)
|
||||
created_date = Column(DateTime, server_default=utcnow())
|
||||
modified_date = Column(DateTime, server_default=utcnow(), onupdate=utcnow())
|
||||
|
||||
|
||||
def ReferenceCol(tablename, nullable=False, **kw):
|
||||
return Column(ForeignKey('{}.id'.format(tablename)), nullable=nullable, **kw)
|
||||
|
||||
|
||||
class Cookie(Base, DBMixin):
|
||||
__tablename__ = 'cookies'
|
||||
|
||||
name = Column(String(50), index=True)
|
||||
recipe_url = Column(String(255))
|
||||
sku = Column(String(55))
|
||||
qoh = Column(Integer)
|
||||
unit_cost = Column(Numeric(12, 2))
|
||||
|
||||
|
||||
class User(DBMixin, Base):
|
||||
__tablename__ = 'users'
|
||||
|
||||
username = Column(String(255), nullable=False, unique=True)
|
||||
email_address = Column(String(255), nullable=False)
|
||||
phone = Column(String(20), nullable=False)
|
||||
password = Column(String(255))
|
||||
|
||||
|
||||
class Order(DBMixin, Base):
|
||||
__tablename__ = 'orders'
|
||||
|
||||
user_id = ReferenceCol('users')
|
||||
shipped = Column(Boolean, default=False)
|
||||
|
||||
user = relationship('User', backref=backref('orders'))
|
||||
|
||||
|
||||
class LineItem(DBMixin, Base):
|
||||
__tablename__ = 'line_items'
|
||||
|
||||
order_id = ReferenceCol('orders')
|
||||
cookie_id = ReferenceCol('cookies')
|
||||
quantity = Column(Integer)
|
||||
extended_cost = Column(Numeric(12, 2))
|
||||
|
||||
order = relationship('Order', backref=backref('line_items'))
|
||||
cookie = relationship('Cookie', uselist=False)
|
||||
|
@ -0,0 +1,13 @@
|
||||
import json
|
||||
from apistar import http
|
||||
from apistar.renderers import Renderer
|
||||
|
||||
from model.util import alchemyencoder
|
||||
|
||||
|
||||
class JSONRenderer(Renderer):
|
||||
media_type = 'application/json'
|
||||
charset = None
|
||||
|
||||
def render(self, data: http.ResponseData) -> bytes:
|
||||
return json.dumps(data, default=alchemyencoder).encode('utf-8')
|
@ -0,0 +1,17 @@
|
||||
apistar==0.3.6
|
||||
certifi==2017.7.27.1
|
||||
chardet==3.0.4
|
||||
coreapi==2.3.1
|
||||
coreschema==0.0.4
|
||||
idna==2.6
|
||||
itypes==1.1.0
|
||||
Jinja2==2.9.6
|
||||
MarkupSafe==1.0
|
||||
py==1.4.34
|
||||
pytest==3.2.2
|
||||
requests==2.18.4
|
||||
SQLAlchemy==1.1.14
|
||||
uritemplate==3.0.0
|
||||
urllib3==1.22
|
||||
Werkzeug==0.12.2
|
||||
whitenoise==3.3.1
|
@ -0,0 +1,20 @@
|
||||
from apistar.test import TestClient
|
||||
from app import welcome
|
||||
|
||||
|
||||
def test_welcome():
|
||||
"""
|
||||
Testing a view directly.
|
||||
"""
|
||||
data = welcome()
|
||||
assert data == {'message': 'Welcome to API Star!'}
|
||||
|
||||
|
||||
def test_http_request():
|
||||
"""
|
||||
Testing a view, using the test client.
|
||||
"""
|
||||
client = TestClient()
|
||||
response = client.get('http://localhost/')
|
||||
assert response.status_code == 200
|
||||
assert response.json() == {'message': 'Welcome to API Star!'}
|
Loading…
Reference in New Issue