Level up to Apistar 0.5.4 without tests
							parent
							
								
									74def7032c
								
							
						
					
					
						commit
						1b77494769
					
				@ -0,0 +1,3 @@
 | 
			
		||||
[flake8]
 | 
			
		||||
max-line-length = 120
 | 
			
		||||
exclude = .git,__pycache__,htmlcov,.cache,.tox,env,dist,doc,*egg,build
 | 
			
		||||
@ -0,0 +1,5 @@
 | 
			
		||||
#History
 | 
			
		||||
 | 
			
		||||
0.2.0 Level up to Apistar 0.5.x
 | 
			
		||||
 | 
			
		||||
0.1.0 Initial app
 | 
			
		||||
@ -1,3 +1,6 @@
 | 
			
		||||
# news
 | 
			
		||||
 | 
			
		||||
A ReSTful api for storing and retrieving news articles
 | 
			
		||||
A ReSTful api for storing and retrieving news articles
 | 
			
		||||
 | 
			
		||||
## Pip tools
 | 
			
		||||
This project uses pip-tools for developement. Reference the [project page](https://github.com/jazzband/pip-tools) for usage instructions.
 | 
			
		||||
@ -0,0 +1,6 @@
 | 
			
		||||
pip-tools
 | 
			
		||||
pytest
 | 
			
		||||
tox
 | 
			
		||||
flake8
 | 
			
		||||
setuptools >= 38.6.0
 | 
			
		||||
wheel >= 0.31.0
 | 
			
		||||
@ -0,0 +1,29 @@
 | 
			
		||||
#
 | 
			
		||||
# This file is autogenerated by pip-compile
 | 
			
		||||
# To update, run:
 | 
			
		||||
#
 | 
			
		||||
#    pip-compile --output-file dev_requirements.txt dev_requirements.in
 | 
			
		||||
#
 | 
			
		||||
--trusted-host pypi.python.org
 | 
			
		||||
--trusted-host git.aigalatic.com
 | 
			
		||||
 | 
			
		||||
atomicwrites==1.1.5       # via pytest
 | 
			
		||||
attrs==18.1.0             # via pytest
 | 
			
		||||
click==6.7                # via pip-tools
 | 
			
		||||
first==2.0.1              # via pip-tools
 | 
			
		||||
flake8==3.5.0
 | 
			
		||||
mccabe==0.6.1             # via flake8
 | 
			
		||||
more-itertools==4.2.0     # via pytest
 | 
			
		||||
pip-tools==2.0.2
 | 
			
		||||
pluggy==0.6.0             # via pytest, tox
 | 
			
		||||
py==1.5.4                 # via pytest, tox
 | 
			
		||||
pycodestyle==2.3.1        # via flake8
 | 
			
		||||
pyflakes==1.6.0           # via flake8
 | 
			
		||||
pytest==3.6.2
 | 
			
		||||
six==1.11.0               # via more-itertools, pip-tools, pytest, tox
 | 
			
		||||
tox==3.0.0
 | 
			
		||||
virtualenv==16.0.0        # via tox
 | 
			
		||||
wheel==0.31.1
 | 
			
		||||
 | 
			
		||||
# The following packages are considered to be unsafe in a requirements file:
 | 
			
		||||
# setuptools
 | 
			
		||||
@ -1,2 +1 @@
 | 
			
		||||
from .app import application_factory
 | 
			
		||||
 | 
			
		||||
from .app import application_factory  # noqa: F401
 | 
			
		||||
 | 
			
		||||
@ -1,23 +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.timestamp()
 | 
			
		||||
    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')
 | 
			
		||||
@ -0,0 +1,38 @@
 | 
			
		||||
import inspect
 | 
			
		||||
import typing
 | 
			
		||||
from apistar import Component
 | 
			
		||||
from apistar.http import Response
 | 
			
		||||
from sqlalchemy.engine import Engine
 | 
			
		||||
from sqlalchemy.orm import sessionmaker, scoped_session
 | 
			
		||||
 | 
			
		||||
DBSession = scoped_session(sessionmaker())
 | 
			
		||||
 | 
			
		||||
Session = typing.TypeVar("Session")
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
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):
 | 
			
		||||
        return DBSession()
 | 
			
		||||
 | 
			
		||||
    def can_handle_parameter(self, parameter: inspect.Parameter) -> bool:
 | 
			
		||||
        return parameter.annotation is Session
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
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
 | 
			
		||||
@ -0,0 +1,5 @@
 | 
			
		||||
apistar
 | 
			
		||||
psycopg2
 | 
			
		||||
marshmallow
 | 
			
		||||
SQLAlchemy
 | 
			
		||||
 | 
			
		||||
@ -1,20 +1,24 @@
 | 
			
		||||
apistar==0.3.9
 | 
			
		||||
certifi==2017.11.5
 | 
			
		||||
chardet==3.0.4
 | 
			
		||||
colorama==0.3.9
 | 
			
		||||
coreapi==2.3.3
 | 
			
		||||
coreschema==0.0.4
 | 
			
		||||
idna==2.6
 | 
			
		||||
itypes==1.1.0
 | 
			
		||||
Jinja2==2.9.6
 | 
			
		||||
MarkupSafe==1.0
 | 
			
		||||
marshmallow==2.15.0
 | 
			
		||||
psycopg2==2.7.3.2
 | 
			
		||||
py==1.4.34
 | 
			
		||||
pytest==3.2.3
 | 
			
		||||
requests==2.18.4
 | 
			
		||||
SQLAlchemy==1.1.15
 | 
			
		||||
uritemplate==3.0.0
 | 
			
		||||
urllib3==1.22
 | 
			
		||||
Werkzeug==0.12.2
 | 
			
		||||
whitenoise==3.3.1
 | 
			
		||||
#
 | 
			
		||||
# This file is autogenerated by pip-compile
 | 
			
		||||
# To update, run:
 | 
			
		||||
#
 | 
			
		||||
#    pip-compile --output-file requirements.txt requirements.in
 | 
			
		||||
#
 | 
			
		||||
--trusted-host pypi.python.org
 | 
			
		||||
--trusted-host git.aigalatic.com
 | 
			
		||||
 | 
			
		||||
apistar==0.5.40
 | 
			
		||||
certifi==2018.4.16        # via requests
 | 
			
		||||
chardet==3.0.4            # via requests
 | 
			
		||||
click==6.7                # via apistar
 | 
			
		||||
idna==2.7                 # via requests
 | 
			
		||||
jinja2==2.10              # via apistar
 | 
			
		||||
markupsafe==1.0           # via jinja2
 | 
			
		||||
marshmallow==2.15.3
 | 
			
		||||
psycopg2==2.7.5
 | 
			
		||||
pyyaml==3.12              # via apistar
 | 
			
		||||
requests==2.19.1          # via apistar
 | 
			
		||||
sqlalchemy==1.2.9
 | 
			
		||||
urllib3==1.23             # via requests
 | 
			
		||||
werkzeug==0.14.1          # via apistar
 | 
			
		||||
whitenoise==3.3.1         # via apistar
 | 
			
		||||
 | 
			
		||||
@ -0,0 +1,11 @@
 | 
			
		||||
from news import application_factory
 | 
			
		||||
 | 
			
		||||
app = application_factory()
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def main():
 | 
			
		||||
    app.serve('0.0.0.0', 8080, debug=True)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
if __name__ == "__main__":
 | 
			
		||||
    main()
 | 
			
		||||
@ -0,0 +1,79 @@
 | 
			
		||||
from setuptools import setup, find_packages
 | 
			
		||||
 | 
			
		||||
with open('README.md') as readme_file:
 | 
			
		||||
    readme = readme_file.read()
 | 
			
		||||
 | 
			
		||||
with open('HISTORY.md') as history_file:
 | 
			
		||||
    history = history_file.read()
 | 
			
		||||
 | 
			
		||||
requirements = [
 | 
			
		||||
    'apistar==0.5.40',
 | 
			
		||||
    'certifi==2018.4.16',  # via requests
 | 
			
		||||
    'chardet==3.0.4',  # via requests
 | 
			
		||||
    'click==6.7',  # via apistar
 | 
			
		||||
    'idna==2.7',  # via requests
 | 
			
		||||
    'jinja2==2.10',  # via apistar
 | 
			
		||||
    'markupsafe==1.0',  # via jinja2
 | 
			
		||||
    'marshmallow==2.15.3',
 | 
			
		||||
    'psycopg2==2.7.5',
 | 
			
		||||
    'pyyaml==3.12',  # via apistar
 | 
			
		||||
    'requests==2.19.1',  # via apistar
 | 
			
		||||
    'sqlalchemy==1.2.9',
 | 
			
		||||
    'urllib3==1.23',  # via requests
 | 
			
		||||
    'werkzeug==0.14.1',  # via apistar
 | 
			
		||||
    'whitenoise==3.3.1',  # via apistar
 | 
			
		||||
]
 | 
			
		||||
 | 
			
		||||
dev_requirements = [
 | 
			
		||||
    'atomicwrites==1.1.5',  # via pytest
 | 
			
		||||
    'attrs==18.1.0',  # via pytest
 | 
			
		||||
    'click==6.7',  # via pip-tools
 | 
			
		||||
    'first==2.0.1',  # via pip-tools
 | 
			
		||||
    'flake8==3.5.0',
 | 
			
		||||
    'mccabe==0.6.1',  # via flake8
 | 
			
		||||
    'more-itertools==4.2.0',  # via pytest
 | 
			
		||||
    'pip-tools==2.0.2',
 | 
			
		||||
    'pluggy==0.6.0',  # via pytest, tox
 | 
			
		||||
    'py==1.5.4',  # via pytest, tox
 | 
			
		||||
    'pycodestyle==2.3.1',  # via flake8
 | 
			
		||||
    'pyflakes==1.6.0',  # via flake8
 | 
			
		||||
    'pytest==3.6.2',
 | 
			
		||||
    'six==1.11.0',  # via more-itertools, pip-tools, pytest, tox
 | 
			
		||||
    'tox==3.0.0',
 | 
			
		||||
    'virtualenv==16.0.0',  # via tox
 | 
			
		||||
    'wheel==0.31.1',
 | 
			
		||||
]
 | 
			
		||||
 | 
			
		||||
setup(
 | 
			
		||||
    name='news',
 | 
			
		||||
    version='0.2.0',
 | 
			
		||||
    description="A ReSTful api for storing and retrieving news articles",
 | 
			
		||||
    long_description=readme + '\n\n' + history,
 | 
			
		||||
    long_description_content_type='text/markdown',
 | 
			
		||||
    author="Drew Bednar",
 | 
			
		||||
    author_email='drew@androiddrew.com',
 | 
			
		||||
    url='https://git.aigalactic.com/Spyglass/news',
 | 
			
		||||
    packages=find_packages(include=['news', 'scripts']),
 | 
			
		||||
    include_package_data=True,
 | 
			
		||||
    install_requires=requirements,
 | 
			
		||||
    license='BSD',
 | 
			
		||||
    keywords='news spyglass',
 | 
			
		||||
    classifiers=[
 | 
			
		||||
        'Development Status :: 2 - Pre-Alpha',
 | 
			
		||||
        'Environment :: Backend',
 | 
			
		||||
        'Intended Audience :: Developers',
 | 
			
		||||
        'License :: OSI Approved :: MIT License',
 | 
			
		||||
        'Natural Language :: English',
 | 
			
		||||
        'Programming Language :: Python :: 3.5',
 | 
			
		||||
        'Programming Language :: Python :: 3.6',
 | 
			
		||||
    ],
 | 
			
		||||
    extras_require={
 | 
			
		||||
        'dev': dev_requirements,
 | 
			
		||||
    },
 | 
			
		||||
    entry_points={
 | 
			
		||||
        'console_scripts': [
 | 
			
		||||
            'wsgi_serve=scripts.wsgi_app:main'
 | 
			
		||||
        ]
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
)
 | 
			
		||||
@ -1,23 +0,0 @@
 | 
			
		||||
import datetime as dt
 | 
			
		||||
from decimal import Decimal
 | 
			
		||||
import json
 | 
			
		||||
 | 
			
		||||
from news.renders import extended_encoder, JSONRenderer
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def test_extended_encoder_date_parsing():
 | 
			
		||||
    test_date = dt.datetime(2017, 5, 10)
 | 
			
		||||
    assert test_date.timestamp() == extended_encoder(test_date)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def test_extended_encoder_decimal_casting():
 | 
			
		||||
    test_decimal = Decimal('1.0')
 | 
			
		||||
    assert 1.0 == extended_encoder(test_decimal)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def test_render_with_extended_encoder():
 | 
			
		||||
    test_date = dt.datetime(2017, 5, 10)
 | 
			
		||||
    test_decimal = Decimal('0.1')
 | 
			
		||||
    expected = dict(my_date=1494388800.0, my_float=0.1)
 | 
			
		||||
    test_response = dict(my_date=test_date, my_float=test_decimal)
 | 
			
		||||
    assert json.dumps(expected).encode('utf-8') == JSONRenderer().render(test_response)
 | 
			
		||||
@ -1,9 +0,0 @@
 | 
			
		||||
from news import application_factory
 | 
			
		||||
 | 
			
		||||
# Override base application settings here
 | 
			
		||||
settings = {}
 | 
			
		||||
 | 
			
		||||
app = application_factory(settings)
 | 
			
		||||
 | 
			
		||||
if __name__ == "__main__":
 | 
			
		||||
    app.main()
 | 
			
		||||
					Loading…
					
					
				
		Reference in New Issue