Skip to content

Instantly share code, notes, and snippets.

View jfhbrook's full-sized avatar
💭
KNEE DEEP IN THE HOOPLA

Josh Holbrook jfhbrook

💭
KNEE DEEP IN THE HOOPLA
View GitHub Profile
@jfhbrook
jfhbrook / kinja-service-to-json-helper.py
Created April 19, 2019 21:03
A snippet from the data team's API framework used to JSON-serialize results
# Used to implement the same pretty-printing behavior as flask:jsonify
# Also calls cattr.unstructure on data
def _to_json(error, warnings, data):
indent = None
separators = (',', ':')
if current_app.config['JSONIFY_PRETTYPRINT_REGULAR'] or current_app.debug:
indent = 2
separators = (', ', ': ')
@jfhbrook
jfhbrook / kinja-service-create-response-helper.py
Created April 19, 2019 21:02
A snippet from the data team's API framework used to generate responses
def create_response(
*,
error,
warnings,
data,
status,
headers
):
return current_app.response_class(
response=_to_json(
@jfhbrook
jfhbrook / kinja-service-success-helper.py
Created April 19, 2019 21:01
A snippet from the data team's API framework used to generate success responses
def success(
response,
*,
warnings=None,
status=200,
headers=None
):
warnings = warnings if warnings else get_warnings()
return create_response(
@jfhbrook
jfhbrook / kinja-service-make-response-snippet.py
Created April 19, 2019 21:00
A snippet from the Kinja data team's implementation of make_response in our subclass of Flask
# In the default handler for flask, they don't allow None. We however
# allow anything that's json serializable. :)
if not isinstance(rv, self.response_class):
if isinstance(rv, (bytes, bytearray)):
# For now, treat bytes as raw data and don't attempt to
# JSON-serialize
rv = self.response_class(rv, status=status, headers=headers)
status = headers = None
# Try to coerce things that are Responses or wsgi callables already
@jfhbrook
jfhbrook / flask-make-response-docstring.py
Created April 19, 2019 20:58
A copy of the docstring in Flask's "make_response" app method
"""
:attr:`response_class`.
:param rv: the return value from the view function. The view function
must return a response. Returning ``None``, or the view ending
without returning, is not allowed. The following types are allowed
for ``view_rv``:
``str`` (``unicode`` in Python 2)
A response object is created with the string encoded to UTF-8
as the body.
``bytes`` (``str`` in Python 2)
@jfhbrook
jfhbrook / kinja-api-controller-flask-example.py
Last active April 26, 2019 16:39
A completely fake example of what a controller might look like using our Flask-based python API framework
import cattrs
from flask import Blueprint, request
from flask_sqlalchemy import SQLAlchemy
from kinja_service import create_app
# Our framework's app factory
app = create_app('my_app')
# This is what setting up sqlalchemy models looks like with Flask
db = SQLAlchemy(app)
@jfhbrook
jfhbrook / kinja-api-model-example-attrs.py
Last active April 19, 2019 21:10
A completely fake example of what an attrs-based model might look like in a hypothetical python API app
@attr.s
class Person:
first_name = attr.ib()
last_name = attr.ib()
bio = attr.ib()
user_id = attr.ib()
@jfhbrook
jfhbrook / kinja-api-controller-async-example.py
Last active April 19, 2019 21:09
A completely fake example of what a controller might look like in a world where our python API apps used asyncio
@authenticated
async def create(request):
body = await request.json()
first_name = body['firstName']
last_name = body['lastName']
bio = body.get('bio', '')
saved = await person_logic.create(
first_name,
@jfhbrook
jfhbrook / kinja-api-model-example.scala
Last active April 26, 2019 16:02
A completely fake example of what a model might look like in one of our Scala API apps
case class Person(
id: Option[Id[Person]],
firstName: String,
lastName: String,
bio: String)
@jfhbrook
jfhbrook / kinja-api-controller-example.scala
Last active April 19, 2019 21:09
A completely fake example of what a controller might look like in one of our Scala API apps
def create: Action[JsValue] = Authenticated.json { request =>
for {
firstName <- request.body.required[String]("firstName").toAcc
lastName <- request.body.required[String]("lastName").toAcc
bio <- request.body.optional[String]("bio").map(_.getOrElse("")).toAcc
saved <- personLogic.create(firstName, lastName, bio, request.userId)
} yield saved
}.withNoCaching