Stupeflask Documentation

Numberly

Jan 20, 2020

Contents

1 Install 3

2 Comparison 5

3 Tests 7

4 License 9

5 Documentation 11 5.1 Better application defaults...... 11 5.2 Easier collection of configuration values...... 13 5.3 Native ObjectId support...... 13 5.4 API Reference...... 14 5.5 Cursor support...... 18

6 Indices and tables 19

Python Module Index 21

Index 23

i ii Stupeflask Documentation

a.k.a. « Flask on steroids » An opinionated Flask extension designed by and for web developers to reduce boilerplate code when working with Marshmallow, MongoDB and/or JSON. Documentation: https://flask-stupe.readthedocs.io • Return any object type in views, and it will be coerced to a flask.Response • Validate payloads through Marshmallow schemas • Easily add JSON converters for any custom type • Fetch all the blueprints from a whole module in one line • Native ObjectId support for both Flask and Marshmallow • Powerful configuration management • Decorators to handle authentication, permissions, and pagination • 100% coverage and no dependency

Contents 1 Stupeflask Documentation

2 Contents CHAPTER 1

Install

$ pip install flask-stupe

3 Stupeflask Documentation

4 Chapter 1. Install CHAPTER 2

Comparison

Here is a comparison of a bare Flask application and its equivalent Stupeflask version. They both rely on MongoDB, handle input and output in JSON, and allow to create a user and retrieve one or more.

5 Stupeflask Documentation

Bare Flask With Stupeflask

from bson import ObjectId from flask import request from flask import abort, Flask, jsonify, from flask_stupe import paginate, schema_

˓→request ˓→required from marshmallow import Schema from flask_stupe. import Stupeflask from marshmallow.fields import String from marshmallow import Schema from pymongo import MongoClient from marshmallow.fields import String from pymongo import MongoClient app= Flask(__name__) users= MongoClient().database.users app= Stupeflask(__name__) users= MongoClient().database.users

class UserSchema(Schema): username= String(required=True) class UserSchema(Schema): password= String() username= String(required=True) password= String()

@app.route("/user", methods=["POST"]) def post_user(): @app.route("/user", methods=["POST"]) json= request.get_json(force=True) @schema_required(UserSchema()) validation_result= UserSchema(). def post_user():

˓→load(json) result= users.insert_one(request.

if validation_result.errors: ˓→schema) abort(400, validation_result. request.schema.update(_id=result.

˓→errors) ˓→inserted_id) result= users.insert_one(validation_ return request.schema

˓→result.data) inserted_id= str(result.inserted_id) validation_result.data.update(_ @app.route("/user/")

˓→id=inserted_id) def get_user(id): return jsonify(validation_result. return users.find_one({"_id": id})

˓→data)

@app.route("/users") @app.route("/user/") @paginate(limit=100) def get_user(id): def get_users(): try: return users.find() id= ObjectId(id) except ValueError: abort(404) user= users.find_one({"_id": id}) user["_id"]= str(user["_id"]) return jsonify(user)

@app.route("/users") def get_users(): limit= request.args.get("limit",

˓→100, type=int) skip= request.args.get("skip",0,

˓→type=int) cursor= users.find().limit(limit).

˓→skip(skip) return jsonify(list(cursor))

6 Chapter 2. Comparison CHAPTER 3

Tests

To run Flask-Stupe tests: • install developers requirements with pip install -r requirements.txt; • run pytest.

7 Stupeflask Documentation

8 Chapter 3. Tests CHAPTER 4

License

MIT

9 Stupeflask Documentation

10 Chapter 4. License CHAPTER 5

Documentation

5.1 Better application defaults

Stupeflask makes it easy to use JSON to build APIs. A perfect example is the flask_stupe.json.Stupeflask application.

5.1.1 Better support for JSON based APIs

Automatic conversion to JSON

By using the JSON version of Stupeflask, every Python object your views returns that is not a Response object will be JSON serialized. With that in mind, you can do that kind of things:

@app.route("/foo") def foo(): return {"foo":"bar"}

This will be rendered as the equivalent JSON and sent to the client.

Add JSON encoding for objects

If you want to add serialization methods for other custom types, you can! You’ll need to call JSONEncoder. add_rule().

import uuid app.json_encoder.add_rule(uuid.UUID, lambda uuid: str(uuid))

This snippet shows how to add a serializer for UUIDs.

11 Stupeflask Documentation

5.1.2 Import all blueprints from a package

You can easily add a bunch of blueprints by passing a package to the Stupeflask.register_blueprints(). It will search through all the package’s modules and import a variable named like the module. If this is a blueprint, it will be registered into the application. For example, this snippet:

from application.views.user import user from application.views.pets import pets from application.views.family import family app.register_blueprint(user) app.register_blueprint(pets) app.register_blueprint(family)

Becomes:

from application import views app.register_blueprints(views)

Metadata wrapping

By default, returning {"foo": "bar"} from a route would produce such a response:

{ "code": 200, "data":{ "foo": "bar" } }

As you can see, the data is wrapped within another JSON object containing the status code. You can add more metadata to that outter JSON object by modifying the metadata dictionary of the current flask. request. For example, this snippet will make all responses have a version field added to them:

from flask import request

@app.before_request def before_request(response): request.metadata.update(version="v1")

The produced output will thus look like this:

{ "code": 200, "data":{ "foo": "bar" }, "version": "v1" }

If, on the opposite, you don’t want any sort of metadata wrapping, and rather return a plain {"foo": "bar"} JSON object, just set the METADATA_WRAPPING configuration value to False.

12 Chapter 5. Documentation Stupeflask Documentation

5.1.3 Add path converters

With Stupeflask, you can add path converters with Stupeflask.register_converter(). Please head towards werkzeug’s documentation about converters if you want to learn more.

5.2 Easier collection of configuration values

Stupeflask makes it easier to collect configuration variables from different sources.

5.2.1 config.py

If a file named config.py is present in the working directory, it will be imported and used as the configuration file for your application.

5.2.2 $CONFIG

If an environment variable named CONFIG exists, its value will be imported as a Python configuration file.

5.2.3 Environment

Any key present in the configuration at this point will be checked in the environment. If a corresponding variable is found in the environment, its value will override the current configuration. Since all environment variables are strings, the value will be cast in the type of the value present in the configuration in the first place. Let’s say you have a variable like so in the config.py file:

DEBUG= True

You can override it by putting that in the environment:

DEBUG=1

In your code, it will not be treated a string or an integer, but as True, because Stupeflask will have detected that it was a boolean and cast it. If you want to invoke this behavior at another moment, use the from_env method.

5.3 Native ObjectId support

The bson.ObjectId type is natively supported by Stupeflask.

5.3.1 Path parameter

Stupeflask recognizes ObjectIds in path parameters. You can use it like this:

@app.route("/user/")

5.2. Easier collection of configuration values 13 Stupeflask Documentation

5.3.2 JSON

Any ObjectIds a in JSON response will be coerced to string automaticaly.

5.3.3 Marshmallow field

Stupeflask features a field (ObjectId) for ObjectIds. If the bson module exists (for example if you’re using MongoDB), you can use it with schema_required(). It allows to automaticaly cast indicated fields from string to ObjectId.

5.4 API Reference

5.4.1 App class flask_stupe.app.Stupeflask(*args, **kwargs)

config_class alias of flask_stupe.config.Config register_blueprints(package, **options) Auto-discover blueprints and register them It will look recursively in every module of the package to find a variable that has the same name as its module. It means that if a file called foo.py has an exportable variable called foo, it will try to register that variable as a blueprint. register_converter(converter, name=None) Register a new converter that can be used in endpoints URLs A converter is a Werkzeug class that transforms a part of an URL to a Python object, passed as an argument to the endpoint function. Stupeflask currently implements the following converters: • // with ::ObjectIdConverter See Werkzeug documentation about custom converters if you want to implement your own converter. register_converters(converter_list) Register multiple converters at once. See register_converter(). request_class alias of flask_stupe.request.Request

5.4.2 Auth

flask_stupe.auth.auth_required(function) Decorator checking that the request is made by an authenticated user. If you want to use that function, you should set a before_request handler that authenticate requests when possi- ble. It must then expose a user attribute on the flask.request object.

14 Chapter 5. Documentation Stupeflask Documentation

@app.before_request def get_user(): token= request.args.get("token") if verify_token(token): request.user={"username":"toto"}

A view decorated with auth_required() will be aborted with a status code 401 if the user making the request is not authenticated. flask_stupe.auth.permission_required(*permissions) Decorator checking that the request is made by a user with adequate privileges. This decorator also decorates the function with the auth_required() doecorator, thus the same constraints apply here. If the flask.request.user is a dictionnary, it must contains a “permissions” key. If it is an object, it must have “permissions” attribute. These permissions must be a list of strings. They will be checked against the strings passed as parameter to this decorator. At least one must match. You can apply this decorator multiple times if you need several permissions at once to access a view.

5.4.3 Config class flask_stupe.config.Config(root_path, defaults=None)

from_env() Try to overload the config with the environment. Take each key in the config and, if it is present as an environment variable, replace the current value with the environment one, casting it in the appropriate type.

5.4.4 Converters class flask_stupe.converters.ObjectIdConverter(map)

regex = '[A-Fa-f0-9]{24}' to_python(value) to_url(value)

5.4.5 Fields

5.4.6 Inputs flask_stupe.inputs.boolean(value) Parse the string "true" or "false" as a boolean (case insensitive). Also accepts "1" and "0" as True/False (respectively). If the input is from the request JSON body, the type is already a native python boolean, and will be passed through without further parsing. This function belongs to https://github.com/flask-restful/flask-restful It is licensed under the BSD 3-clause “New” or “Revised” License https://github.com/flask-restful/flask-restful/blob/master/LICENSE

5.4. API Reference 15 Stupeflask Documentation flask_stupe.inputs.int_list(value) Convert a numeric comma separated string to an int list. flask_stupe.inputs.str_list(value) Convert a literal comma separated string to a string list. flask_stupe.inputs.objectid_list(value) Convert a hexadecimal comma separated string to an ObjectId list. flask_stupe.inputs.datetime(value) Convert a string to a datetime flask_stupe.inputs.date(value) Convert a string to a date

5.4.7 JSON flask_stupe.json.encode(o, silent=True) Recursively encode a Python object in a JSON serializable format. objects natively supported by json’s library are obviously supported, but so are datetimes, and ObjectId (if bson is installed). If you want to add such encoding for custom types, see JSONEncoder.add_rule(). class flask_stupe.json.JSONEncoder(skipkeys=False, ensure_ascii=True, check_circular=True, allow_nan=True, sort_keys=False, indent=None, separa- tors=None, encoding=’utf-8’, default=None) Stupeflask extensible JSON encoder The JSONEncoder is used by flask.jsonify() to convert a Python dictionary into a real JSON string. If the JSONEncoder receive a dict containing unknown type, a TypeError exception will be raised. Default supported types are Python built-in types (int, list, etc.), datetime.date and datetime.date, as well as bson.ObjectId if bson module is present. To make the JSONEncoder support more types, see add_rule(). add_rule(function) Add a new serializing rule A rule is defined by one or multiple types, and a function to execute in order to serialize this or those types. Dumb example:

>>> app= flask.ext.stupe.json.Stupeflask(__name__) >>> app.json_encoder.add_rule(int, lambda i: str(i))

default(o) Implement this method in a subclass such that it returns a serializable object for o, or calls the base implementation (to raise a TypeError). For example, to support arbitrary iterators, you could implement default like this:

def default(self, o): try: iterable= iter(o) except TypeError: pass else: (continues on next page)

16 Chapter 5. Documentation Stupeflask Documentation

(continued from previous page) return list(iterable) return JSONEncoder.default(self, o) flask_stupe.json.handle_error(e) Convert any exception into a JSON message, with a proper HTTP code The JSON message will have the following form:

{ "code": 403, "message": "You don't have the permission to access the requested resource. It is either read-protected or not readable by the server." } class flask_stupe.json.Stupeflask(*args, **kwargs)

json_encoder alias of JSONEncoder make_response(rv) Convert the return value from a view function to an instance of response_class. Parameters rv – the return value from the view function. The view function must return a re- sponse. Returning None, or the view ending without returning, is not allowed. The following types are allowed for view_rv: str ( in Python 2) A response object is created with the string encoded to UTF-8 as the body. bytes (str in Python 2) A response object is created with the bytes as the body. dict A dictionary that will be jsonify’ before being returned. tuple Either (body, status, headers), (body, status), or (body, headers), where body is any of the other types allowed here, status is a string or an integer, and headers is a dictionary or a list of (key, value) tuples. If body is a response_class instance, status overwrites the exiting value and headers are extended. response_class The object is returned unchanged. other Response class The object is coerced to response_class. callable() The function is called as a WSGI application. The result is used to create a response object. Changed in version 0.9: Previously a tuple was interpreted as the arguments for the response object. response_class alias of Response

5.4.8 Pagination flask_stupe.pagination.paginate(function_or_cursor=None, skip=None, limit=None, sort=None, count=True, collation=False) Apply pagination to the given MongoDB cursor or function

5.4. API Reference 17 Stupeflask Documentation

5.4.9 Request

class flask_stupe.request.Request(*args, **kwargs)

metadata = None Store additionnal data about the request.

5.4.10 Validation

flask_stupe.validation.schema_required(schema) Validate body of the request against the schema. Abort with a status code 400 if the schema yields errors.

5.5 Cursor support

5.5.1 Pagination

Views that returns a MongoDB cursor can be easily paginated using the paginate decorator. See the following example:

@app.route("/news") @paginate def get_news(): return db.news.find()

With this setting, elements from the news collection will be returned. You can control the pagination with the skip and limit query parameters.

5.5.2 Sorting

You also get sorting using the same decorator. With the example from the previous section, you can use the sort query parameter to sort on one of the MongoDB fields. You can prefix the field with a minus sign to sort in descending order.

18 Chapter 5. Documentation CHAPTER 6

Indices and tables

• genindex • modindex • search

19 Stupeflask Documentation

20 Chapter 6. Indices and tables Python Module Index

f flask_stupe.app, 14 flask_stupe.auth, 14 flask_stupe.config, 15 flask_stupe.converters, 15 flask_stupe.inputs, 15 flask_stupe.json, 16 flask_stupe.pagination, 17 flask_stupe.request, 18 flask_stupe.validation, 18

21 Stupeflask Documentation

22 Python Module Index Index

A J add_rule() (flask_stupe.json.JSONEncoder method), json_encoder (flask_stupe.json.Stupeflask attribute), 16 17 auth_required() (in module flask_stupe.auth), 14 JSONEncoder (class in flask_stupe.json), 16 B M boolean() (in module flask_stupe.inputs), 15 make_response() (flask_stupe.json.Stupeflask method), 17 metadata (flask_stupe.request.Request attribute), 18 Config (class in flask_stupe.config), 15 config_class (flask_stupe.app.Stupeflask attribute), O 14 objectid_list() (in module flask_stupe.inputs), 16 ObjectIdConverter (class in D flask_stupe.converters), 15 date() (in module flask_stupe.inputs), 16 datetime() (in module flask_stupe.inputs), 16 P default() (flask_stupe.json.JSONEncoder method), paginate() (in module flask_stupe.pagination), 17 16 permission_required() (in module E flask_stupe.auth), 15 encode() (in module flask_stupe.json), 16 R regex (flask_stupe.converters.ObjectIdConverter F attribute), 15 flask_stupe.app (module), 14 register_blueprints() flask_stupe.auth (module), 14 (flask_stupe.app.Stupeflask method), 14 flask_stupe.config (module), 15 register_converter() flask_stupe.converters (module), 15 (flask_stupe.app.Stupeflask method), 14 flask_stupe.inputs (module), 15 register_converters() flask_stupe.json (module), 16 (flask_stupe.app.Stupeflask method), 14 flask_stupe.pagination (module), 17 Request (class in flask_stupe.request), 18 flask_stupe.request (module), 18 request_class (flask_stupe.app.Stupeflask at- flask_stupe.validation (module), 18 tribute), 14 from_env() (flask_stupe.config.Config method), 15 response_class (flask_stupe.json.Stupeflask at- tribute), 17 H handle_error() (in module flask_stupe.json), 17 S schema_required() (in module I flask_stupe.validation), 18 int_list() (in module flask_stupe.inputs), 15 str_list() (in module flask_stupe.inputs), 16

23 Stupeflask Documentation

Stupeflask (class in flask_stupe.app), 14 Stupeflask (class in flask_stupe.json), 17 T to_python() (flask_stupe.converters.ObjectIdConverter method), 15 to_url() (flask_stupe.converters.ObjectIdConverter method), 15

24 Index