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