From 30ccdcd52827a38314da61505403f6122975b3fd Mon Sep 17 00:00:00 2001 From: Jace Browning Date: Tue, 11 Apr 2017 20:12:07 -0400 Subject: [PATCH 01/87] Customize automatic API return types --- docs/about/release-notes.md | 4 ++++ flask_api/__init__.py | 2 +- flask_api/app.py | 3 ++- flask_api/response.py | 5 ++++- 4 files changed, 11 insertions(+), 3 deletions(-) diff --git a/docs/about/release-notes.md b/docs/about/release-notes.md index ccaa010..e2480ee 100644 --- a/docs/about/release-notes.md +++ b/docs/about/release-notes.md @@ -2,6 +2,10 @@ This project is currently in beta. It is functional and well tested but you are advised to pay close attention to the release notes when upgrading to future versions. +## Version 0.7.1 (unreleased) + +* Added customization of automatic API return types (`app.response_class.api_return_types`). + ## Version 0.7 * Disabled rendering of text responses as API views. diff --git a/flask_api/__init__.py b/flask_api/__init__.py index 55cd723..c4b6f47 100644 --- a/flask_api/__init__.py +++ b/flask_api/__init__.py @@ -1,3 +1,3 @@ from flask_api.app import FlaskAPI -__version__ = '0.7' +__version__ = '0.7.1b2' diff --git a/flask_api/app.py b/flask_api/app.py index 9744cf0..fbffd20 100644 --- a/flask_api/app.py +++ b/flask_api/app.py @@ -56,7 +56,8 @@ def make_response(self, rv): if not isinstance(rv, self.response_class): if isinstance(rv, (text_type, bytes, bytearray, list, dict)): - rv = self.response_class(rv, headers=headers, status=status_or_headers) + status = status_or_headers + rv = self.response_class(rv, headers=headers, status=status) headers = status_or_headers = None else: rv = self.response_class.force_type(rv, request.environ) diff --git a/flask_api/response.py b/flask_api/response.py index 3272b45..3551158 100644 --- a/flask_api/response.py +++ b/flask_api/response.py @@ -5,11 +5,14 @@ class APIResponse(Response): + + api_return_types = (list, dict) + def __init__(self, content=None, *args, **kwargs): super(APIResponse, self).__init__(None, *args, **kwargs) media_type = None - if isinstance(content, (list, dict)) or content == '': + if isinstance(content, self.api_return_types) or content == '': renderer = request.accepted_renderer if content != '' or renderer.handles_empty_responses: media_type = request.accepted_media_type From a0b0b34758d3b09316675f5cb7eec3bc22f53446 Mon Sep 17 00:00:00 2001 From: Jace Browning Date: Wed, 12 Apr 2017 21:12:24 -0400 Subject: [PATCH 02/87] Bump version to 0.7.1 --- docs/about/release-notes.md | 2 +- flask_api/__init__.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/about/release-notes.md b/docs/about/release-notes.md index e2480ee..d47df7d 100644 --- a/docs/about/release-notes.md +++ b/docs/about/release-notes.md @@ -2,7 +2,7 @@ This project is currently in beta. It is functional and well tested but you are advised to pay close attention to the release notes when upgrading to future versions. -## Version 0.7.1 (unreleased) +## Version 0.7.1 * Added customization of automatic API return types (`app.response_class.api_return_types`). diff --git a/flask_api/__init__.py b/flask_api/__init__.py index c4b6f47..9202151 100644 --- a/flask_api/__init__.py +++ b/flask_api/__init__.py @@ -1,3 +1,3 @@ from flask_api.app import FlaskAPI -__version__ = '0.7.1b2' +__version__ = '0.7.1' From 9874a2f72ae163391b189b4611d03ca5d340c9a5 Mon Sep 17 00:00:00 2001 From: Jace Browning Date: Tue, 11 Apr 2017 20:12:07 -0400 Subject: [PATCH 03/87] Customize automatic API return types --- flask_api/app.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/flask_api/app.py b/flask_api/app.py index fbffd20..91fcde7 100644 --- a/flask_api/app.py +++ b/flask_api/app.py @@ -1,7 +1,7 @@ # coding: utf8 from __future__ import unicode_literals from flask import request, Flask, Blueprint -from flask._compat import reraise, string_types, text_type +from flask._compat import reraise, string_types from flask_api.exceptions import APIException from flask_api.request import APIRequest from flask_api.response import APIResponse @@ -55,13 +55,15 @@ def make_response(self, rv): headers, status_or_headers = status_or_headers, None if not isinstance(rv, self.response_class): - if isinstance(rv, (text_type, bytes, bytearray, list, dict)): + if isinstance(rv, self.response_class.api_return_types): status = status_or_headers rv = self.response_class(rv, headers=headers, status=status) headers = status_or_headers = None else: rv = self.response_class.force_type(rv, request.environ) + if status_or_headers is not None: + if isinstance( if status_or_headers is not None: if isinstance(status_or_headers, string_types): rv.status = status_or_headers From f2880950b5013f3cbede4d22fe0c7557d8bfc2d2 Mon Sep 17 00:00:00 2001 From: Jace Browning Date: Tue, 11 Apr 2017 22:46:16 -0400 Subject: [PATCH 04/87] Add initial support for pipenv --- .gitignore | 1 + .travis.yml | 5 ++- Makefile | 34 +++++++++++++++ Pipfile | 13 ++++++ Pipfile.lock | 114 +++++++++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 166 insertions(+), 1 deletion(-) create mode 100644 Makefile create mode 100644 Pipfile create mode 100644 Pipfile.lock diff --git a/.gitignore b/.gitignore index fc77599..08865de 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,5 @@ .env/ +.venv/ env/ dist/ htmlcov/ diff --git a/.travis.yml b/.travis.yml index 337f200..ba831a8 100644 --- a/.travis.yml +++ b/.travis.yml @@ -15,8 +15,11 @@ env: # - FLASK_VERSION=0.10.2 - FLASK_VERSION=0.11.0 +before_install: +- pip install pipenv + install: -- pip install -r requirements.txt +- pipenv install --dev --system - pip install flask==${FLASK_VERSION} # override version for the build matrix - pip install coverage==3.6 - pip install python-coveralls==2.4.0 diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..83ef839 --- /dev/null +++ b/Makefile @@ -0,0 +1,34 @@ +.PHONY: all +all: install + +# PROJECT DEPENDENCIES ######################################################### + +export PIPENV_SHELL_COMPAT=true +export PIPENV_VENV_IN_PROJECT=true + +ENV := .venv +DEPENDENCIES := $(ENV)/.installed +PIP := $(ENV)/bin/pip + +.PHONY: install +install: $(DEPENDENCIES) + +$(DEPENDENCIES): $(PIP) Pipfile* + pipenv install --dev --ignore-hashes + @ touch $@ + +$(PIP): + pipenv --python=python3.6 + +# VALIDATION TARGETS ########################################################### + +.PHONY: test +test: install ## Run tests and linters + pipenv run nosetests flask_api + pipenv run flake8 flask_api --ignore=E128,E501 --exclude=__init__.py + +# CLEANUP ###################################################################### + +.PHONY: clean +clean: + rm -rf $(ENV) diff --git a/Pipfile b/Pipfile new file mode 100644 index 0000000..c2d31ca --- /dev/null +++ b/Pipfile @@ -0,0 +1,13 @@ +[[source]] +url = "https://pypi.python.org/simple" +verify_ssl = true + +[packages] +Flask = "~=0.10.1" + +[dev-packages] +nose = "*" +coverage = "~=3.7.1" +flake8 = "~=2.1" +mkdocs = "~=0.12" +tox = "~=2.0" diff --git a/Pipfile.lock b/Pipfile.lock new file mode 100644 index 0000000..6c1bd73 --- /dev/null +++ b/Pipfile.lock @@ -0,0 +1,114 @@ +{ + "_meta": { + "hash": { + "sha256": "a0439b121de7a82ce054bdc5d2dde15abc519eae516a6efef81d8bcef577220f" + }, + "requires": {}, + "sources": [ + { + "url": "https://pypi.python.org/simple", + "verify_ssl": true + } + ] + }, + "default": { + "Flask": { + "hash": "sha256:4c83829ff83d408b5e1d4995472265411d2c414112298f2eb4b359d9e4563373", + "version": "==0.10.1" + }, + "Jinja2": { + "hash": "sha256:2231bace0dfd8d2bf1e5d7e41239c06c9e0ded46e70cc1094a0aa64b0afeb054", + "version": "==2.9.6" + }, + "MarkupSafe": { + "hash": "sha256:a6be69091dac236ea9c6bc7d012beab42010fa914c459791d627dad4910eb665", + "version": "==1.0" + }, + "Werkzeug": { + "hash": "sha256:918322630c58fa52b89e14c45de3ad78514e18928dac726060bb89cd647f6b83", + "version": "==0.12.1" + }, + "itsdangerous": { + "hash": "sha256:cbb3fcf8d3e33df861709ecaf89d9e6629cff0a217bc2848f1b41cd30d360519", + "version": "==0.24" + } + }, + "develop": { + "Jinja2": { + "hash": "sha256:2231bace0dfd8d2bf1e5d7e41239c06c9e0ded46e70cc1094a0aa64b0afeb054", + "version": "==2.9.6" + }, + "Markdown": { + "hash": "sha256:0ac8a81e658167da95d063a9279c9c1b2699f37c7c4153256a458b3a43860e33", + "version": "==2.6.8" + }, + "MarkupSafe": { + "hash": "sha256:a6be69091dac236ea9c6bc7d012beab42010fa914c459791d627dad4910eb665", + "version": "==1.0" + }, + "PyYAML": { + "hash": "sha256:592766c6303207a20efc445587778322d7f73b161bd994f227adaa341ba212ab", + "version": "==3.12" + }, + "click": { + "hash": "sha256:29f99fc6125fbc931b758dc053b3114e55c77a6e4c6c3a2674a2dc986016381d", + "version": "==6.7" + }, + "coverage": { + "hash": "sha256:d1aea1c4aa61b8366d6a42dd3650622fbf9c634ed24eaf7f379c8b970e5ed44e", + "version": "==3.7.1" + }, + "flake8": { + "hash": "sha256:7ac3bbaac27174d95bc4734ed23a07de567ffbcf4fc7e316854b4f3015d4fd15", + "version": "==2.6.2" + }, + "livereload": { + "hash": "sha256:422de10d7ea9467a1ba27cbaffa84c74b809d96fb1598d9de4b9b676adf35e2c", + "version": "==2.5.1" + }, + "mccabe": { + "hash": "sha256:f9b58bf366c1506dcd6117b33e5c4874746f0de859c9c7cab8b516cb6be1d22e", + "version": "==0.5.3" + }, + "mkdocs": { + "hash": "sha256:005b87441084aacd67ada15843c4ed2746bf324103a5bd94c02d36d9b307310f", + "version": "==0.16.3" + }, + "nose": { + "hash": "sha256:9ff7c6cc443f8c51994b34a667bbcf45afd6d945be7477b52e97516fd17c53ac", + "version": "==1.3.7" + }, + "pluggy": { + "hash": "sha256:d2766caddfbbc8ef641d47da556d2ae3056860ce4d553aa04009e42b76a09951", + "version": "==0.4.0" + }, + "py": { + "hash": "sha256:81b5e37db3cc1052de438375605fb5d3b3e97f950f415f9143f04697c684d7eb", + "version": "==1.4.33" + }, + "pycodestyle": { + "hash": "sha256:2ce83f2046f5ab85c652ceceddfbde7a64a909900989b4b43e92b10b743d0ce5", + "version": "==2.0.0" + }, + "pyflakes": { + "hash": "sha256:e87bac26c62ea5b45067cc89e4a12f56e1483f1f2cda17e7c9b375b9fd2f40da", + "version": "==1.2.3" + }, + "six": { + "hash": "sha256:0ff78c403d9bccf5a425a6d31a12aa6b47f1c21ca4dc2573a7e2f32a97335eb1", + "version": "==1.10.0" + }, + "tornado": { + "hash": "sha256:f267acc96d5cf3df0fd8a7bfb5a91c2eb4ec81d5962d1a7386ceb34c655634a8", + "version": "==4.4.3" + }, + "tox": { + "hash": "sha256:0f37ea637ead4a5bbae91531b0bf8fd327c7152e20255e5960ee180598228d21", + "version": "==2.7.0" + }, + "virtualenv": { + "hash": "sha256:39d88b533b422825d644087a21e78c45cf5af0ef7a99a1fc9fbb7b481e5c85b0", + "version": "==15.1.0" + } + } +} \ No newline at end of file From 05a0713f1a8ee26a54217ad7da9565a1e6aea32f Mon Sep 17 00:00:00 2001 From: Jace Browning Date: Mon, 21 Aug 2017 19:23:46 -0400 Subject: [PATCH 05/87] Update CI tooling --- .gitignore | 58 ++++++++-- .travis.yml | 39 ++++--- Makefile | 211 ++++++++++++++++++++++++++++++++++-- Pipfile | 5 +- Pipfile.lock | 120 ++++++++++---------- flask_api/app.py | 2 - flask_api/tests/runtests.py | 5 - requirements.txt | 8 -- runtests | 12 -- scent.py | 97 +++++++++++++++++ tox.ini | 6 - 11 files changed, 430 insertions(+), 133 deletions(-) delete mode 100644 flask_api/tests/runtests.py delete mode 100644 requirements.txt delete mode 100755 runtests create mode 100644 scent.py delete mode 100644 tox.ini diff --git a/.gitignore b/.gitignore index 08865de..62c63c8 100644 --- a/.gitignore +++ b/.gitignore @@ -1,11 +1,51 @@ -.env/ -.venv/ -env/ -dist/ -htmlcov/ -site/ -.tox/ -Flask_API.egg-info/ +# Temporary Python files *.pyc +*.egg-info __pycache__ -.coverage +.ipynb_checkpoints + +# Temporary OS files +Icon* + +# Temporary virtual environment files +/.cache/ +/.venv/ + +# Temporary server files +.env +*.pid + +# Generated documentation +/docs/gen/ +/docs/apidocs/ +/site/ +/*.html +/*.rst +/docs/*.png + +# Google Drive +*.gdoc +*.gsheet +*.gslides +*.gdraw + +# Testing and coverage results +/.pytest/ +/.coverage +/.coverage.* +/htmlcov/ +/xmlreport/ +/pyunit.xml +/tmp/ +*.tmp + +# Build and release directories +/build/ +/dist/ +*.spec + +# Sublime Text +*.sublime-workspace + +# Eclipse +.settings diff --git a/.travis.yml b/.travis.yml index ba831a8..bb0d081 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,32 +1,37 @@ language: python -sudo: false python: -- 2.7 -- 3.3 -- 3.4 -- 3.5 + - 2.7 + - 3.3 + - 3.4 + - 3.5 + - 3.6 env: + global: + - RANDOM_SEED=0 + - PIPENV_NOSPIN=true matrix: - FLASK_VERSION=0.10.1 - # TODO: enable when future release is available: - # http://flask.pocoo.org/docs/0.11/changelog/#version-0-10-2 - # - FLASK_VERSION=0.10.2 + - FLASK_VERSION=0.10.2 - FLASK_VERSION=0.11.0 before_install: -- pip install pipenv + - pip install pipenv~=5.0 install: -- pipenv install --dev --system -- pip install flask==${FLASK_VERSION} # override version for the build matrix -- pip install coverage==3.6 -- pip install python-coveralls==2.4.0 -- export PYTHONPATH=. + - make install -before_script: coverage erase +script: + - make check + - make test -script: ./runtests +after_success: + - pip install coveralls scrutinizer-ocular + - coveralls + - ocular -after_success: coverage report; coveralls +notifications: + email: + on_success: never + on_failure: never diff --git a/Makefile b/Makefile index 83ef839..e9e6189 100644 --- a/Makefile +++ b/Makefile @@ -1,34 +1,223 @@ +# Project settings +PROJECT := Flask-API +PACKAGE := flask_api +REPOSITORY := flask-api/flask-api + +# Project paths +PACKAGES := $(PACKAGE) tests +CONFIG := $(wildcard *.py) +MODULES := $(wildcard $(PACKAGE)/*.py) + +# Python settings +PYTHON_MAJOR ?= 2 +PYTHON_MINOR ?= 7 + +# System paths +PLATFORM := $(shell python -c 'import sys; print(sys.platform)') +ifneq ($(findstring win32, $(PLATFORM)), ) + WINDOWS := true + SYS_PYTHON_DIR := C:\\Python$(PYTHON_MAJOR)$(PYTHON_MINOR) + SYS_PYTHON := $(SYS_PYTHON_DIR)\\python.exe + # https://bugs.launchpad.net/virtualenv/+bug/449537 + export TCL_LIBRARY=$(SYS_PYTHON_DIR)\\tcl\\tcl8.5 +else + ifneq ($(findstring darwin, $(PLATFORM)), ) + MAC := true + else + LINUX := true + endif + SYS_PYTHON := python$(PYTHON_MAJOR) + ifdef PYTHON_MINOR + SYS_PYTHON := $(SYS_PYTHON).$(PYTHON_MINOR) + endif +endif + +# Virtual environment paths +ENV := .venv +ifneq ($(findstring win32, $(PLATFORM)), ) + BIN := $(ENV)/Scripts + ACTIVATE := $(BIN)/activate.bat + OPEN := cmd /c start + PYTHON := $(BIN)/python.exe + PIP := $(BIN)/pip.exe +else + BIN := $(ENV)/bin + ACTIVATE := . $(BIN)/activate + ifneq ($(findstring cygwin, $(PLATFORM)), ) + OPEN := cygstart + else + OPEN := open + endif + PYTHON := $(BIN)/python + PIP := $(BIN)/pip +endif + +# MAIN TASKS ################################################################### + +SNIFFER := pipenv run sniffer + .PHONY: all all: install +.PHONY: ci +ci: check test ## Run all tasks that determine CI status + +.PHONY: watch +watch: install .clean-test ## Continuously run all CI tasks when files chanage + $(SNIFFER) + +.PHONY: run ## Start the program +run: install + $(PYTHON) $(PACKAGE)/__main__.py + # PROJECT DEPENDENCIES ######################################################### export PIPENV_SHELL_COMPAT=true export PIPENV_VENV_IN_PROJECT=true +export PIPENV_IGNORE_VIRTUALENVS=true -ENV := .venv DEPENDENCIES := $(ENV)/.installed -PIP := $(ENV)/bin/pip +METADATA := *.egg-info .PHONY: install -install: $(DEPENDENCIES) +install: $(DEPENDENCIES) $(METADATA) $(DEPENDENCIES): $(PIP) Pipfile* - pipenv install --dev --ignore-hashes + pipenv install --dev +ifdef WINDOWS + @ echo "Manually install pywin32: https://sourceforge.net/projects/pywin32/files/pywin32" +else ifdef MAC + $(PIP) install pync MacFSEvents +else ifdef LINUX + $(PIP) install pyinotify +endif + @ touch $@ + +$(METADATA): $(PYTHON) setup.py + $(PYTHON) setup.py develop @ touch $@ -$(PIP): - pipenv --python=python3.6 +$(PYTHON) $(PIP): + pipenv --python=$(SYS_PYTHON) + pipenv run pip --version + +# CHECKS ####################################################################### + +FLAKE8 := pipenv run flake8 + +.PHONY: check +check: flake8 ## Run linters and static analysis -# VALIDATION TARGETS ########################################################### +.PHONY: flake8 +flake8: install + $(FLAKE8) flask_api --ignore=E128,E501 --exclude=__init__.py + +# TESTS ######################################################################## + +NOSE := pipenv run nosetests +COVERAGE := pipenv run coverage +COVERAGE_SPACE := pipenv run coverage.space + +RANDOM_SEED ?= $(shell date +%s) + +NOSE_OPTIONS := --with-doctest +ifndef DISABLE_COVERAGE +NOSE_OPTIONS += --with-coverage --cover-package=$(PACKAGE) --cover-erase --cover-html --cover-html-dir=htmlcov --cover-branches +endif .PHONY: test -test: install ## Run tests and linters - pipenv run nosetests flask_api - pipenv run flake8 flask_api --ignore=E128,E501 --exclude=__init__.py +test: install ## Run unit and integration tests + $(NOSE) $(PACKAGE) $(NOSE_OPTIONS) + $(COVERAGE_SPACE) $(REPOSITORY) overall + +.PHONY: read-coverage +read-coverage: + $(OPEN) coverage/index.html + +# DOCUMENTATION ################################################################ + +MKDOCS := pipenv run mkdocs + +MKDOCS_INDEX := site/index.html + +.PHONY: doc +doc: mkdocs ## Generate documentation + +.PHONY: mkdocs +mkdocs: install $(MKDOCS_INDEX) +$(MKDOCS_INDEX): mkdocs.yml docs/*.md + $(MKDOCS) build --clean --strict + +.PHONY: mkdocs-live +mkdocs-live: mkdocs + eval "sleep 3; open http://127.0.0.1:8000" & + $(MKDOCS) serve + +# RELEASE ###################################################################### + +TWINE := pipenv run twine + +.PHONY: register +register: dist ## Register the project on PyPI + @ echo NOTE: your project must be registered manually + @ echo https://github.com/pypa/python-packaging-user-guide/issues/263 + # TODO: switch to twine when the above issue is resolved + # $(TWINE) register dist/*.whl + +.PHONY: upload +upload: .git-no-changes register ## Upload the current version to PyPI + $(TWINE) upload dist/*.* + $(OPEN) https://pypi.python.org/pypi/$(PROJECT) + +.PHONY: .git-no-changes +.git-no-changes: + @ if git diff --name-only --exit-code; \ + then \ + echo Git working copy is clean...; \ + else \ + echo ERROR: Git working copy is dirty!; \ + echo Commit your changes and try again.; \ + exit -1; \ + fi; # CLEANUP ###################################################################### .PHONY: clean -clean: +clean: .clean-dist .clean-test .clean-doc .clean-build ## Delete all generated and temporary files + +.PHONY: clean-all +clean-all: clean .clean-env .clean-workspace + +.PHONY: .clean-build +.clean-build: + find $(PACKAGES) -name '*.pyc' -delete + find $(PACKAGES) -name '__pycache__' -delete + rm -rf *.egg-info + +.PHONY: .clean-doc +.clean-doc: + rm -rf README.rst docs/apidocs *.html docs/*.png site + +.PHONY: .clean-test +.clean-test: + rm -rf .cache .pytest .coverage htmlcov xmlreport + +.PHONY: .clean-dist +.clean-dist: + rm -rf *.spec dist build + +.PHONY: .clean-env +.clean-env: clean rm -rf $(ENV) + +.PHONY: .clean-workspace +.clean-workspace: + rm -rf *.sublime-workspace + +# HELP ######################################################################### + +.PHONY: help +help: all + @grep -E '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-30s\033[0m %s\n", $$1, $$2}' + +.DEFAULT_GOAL := help diff --git a/Pipfile b/Pipfile index c2d31ca..d189038 100644 --- a/Pipfile +++ b/Pipfile @@ -8,6 +8,7 @@ Flask = "~=0.10.1" [dev-packages] nose = "*" coverage = "~=3.7.1" +"coverage.space" = "*" flake8 = "~=2.1" -mkdocs = "~=0.12" -tox = "~=2.0" +mkdocs = "==0.12" +sniffer = "*" diff --git a/Pipfile.lock b/Pipfile.lock index 6c1bd73..59dbfb4 100644 --- a/Pipfile.lock +++ b/Pipfile.lock @@ -1,7 +1,7 @@ { "_meta": { "hash": { - "sha256": "a0439b121de7a82ce054bdc5d2dde15abc519eae516a6efef81d8bcef577220f" + "sha256": "954e1eeca60d19999a62f8c33aa380983b8deb58b5b635987651ecee76e4418e" }, "requires": {}, "sources": [ @@ -12,103 +12,101 @@ ] }, "default": { - "Flask": { - "hash": "sha256:4c83829ff83d408b5e1d4995472265411d2c414112298f2eb4b359d9e4563373", + "flask": { "version": "==0.10.1" }, - "Jinja2": { - "hash": "sha256:2231bace0dfd8d2bf1e5d7e41239c06c9e0ded46e70cc1094a0aa64b0afeb054", + "itsdangerous": { + "version": "==0.24" + }, + "jinja2": { "version": "==2.9.6" }, - "MarkupSafe": { - "hash": "sha256:a6be69091dac236ea9c6bc7d012beab42010fa914c459791d627dad4910eb665", + "markupsafe": { "version": "==1.0" }, - "Werkzeug": { - "hash": "sha256:918322630c58fa52b89e14c45de3ad78514e18928dac726060bb89cd647f6b83", - "version": "==0.12.1" - }, - "itsdangerous": { - "hash": "sha256:cbb3fcf8d3e33df861709ecaf89d9e6629cff0a217bc2848f1b41cd30d360519", - "version": "==0.24" + "werkzeug": { + "version": "==0.12.2" } }, "develop": { - "Jinja2": { - "hash": "sha256:2231bace0dfd8d2bf1e5d7e41239c06c9e0ded46e70cc1094a0aa64b0afeb054", - "version": "==2.9.6" - }, - "Markdown": { - "hash": "sha256:0ac8a81e658167da95d063a9279c9c1b2699f37c7c4153256a458b3a43860e33", - "version": "==2.6.8" + "backports.shutil-get-terminal-size": { + "version": "==1.0.0" }, - "MarkupSafe": { - "hash": "sha256:a6be69091dac236ea9c6bc7d012beab42010fa914c459791d627dad4910eb665", - "version": "==1.0" + "certifi": { + "version": "==2017.7.27.1" }, - "PyYAML": { - "hash": "sha256:592766c6303207a20efc445587778322d7f73b161bd994f227adaa341ba212ab", - "version": "==3.12" + "chardet": { + "version": "==3.0.4" }, - "click": { - "hash": "sha256:29f99fc6125fbc931b758dc053b3114e55c77a6e4c6c3a2674a2dc986016381d", - "version": "==6.7" + "colorama": { + "version": "==0.3.9" }, "coverage": { - "hash": "sha256:d1aea1c4aa61b8366d6a42dd3650622fbf9c634ed24eaf7f379c8b970e5ed44e", - "version": "==3.7.1" + "version": "==4.4.1" + }, + "coverage.space": { + "version": "==0.8" + }, + "docopt": { + "version": "==0.6.2" }, "flake8": { - "hash": "sha256:7ac3bbaac27174d95bc4734ed23a07de567ffbcf4fc7e316854b4f3015d4fd15", "version": "==2.6.2" }, + "ghp-import": { + "version": "==0.5.5" + }, + "idna": { + "version": "==2.6" + }, + "jinja2": { + "version": "==2.9.6" + }, "livereload": { - "hash": "sha256:422de10d7ea9467a1ba27cbaffa84c74b809d96fb1598d9de4b9b676adf35e2c", "version": "==2.5.1" }, + "markdown": { + "version": "==2.6.9" + }, + "markupsafe": { + "version": "==1.0" + }, "mccabe": { - "hash": "sha256:f9b58bf366c1506dcd6117b33e5c4874746f0de859c9c7cab8b516cb6be1d22e", "version": "==0.5.3" }, - "mkdocs": { - "hash": "sha256:005b87441084aacd67ada15843c4ed2746bf324103a5bd94c02d36d9b307310f", - "version": "==0.16.3" - }, + "mkdocs": "==0.12", "nose": { - "hash": "sha256:9ff7c6cc443f8c51994b34a667bbcf45afd6d945be7477b52e97516fd17c53ac", "version": "==1.3.7" }, - "pluggy": { - "hash": "sha256:d2766caddfbbc8ef641d47da556d2ae3056860ce4d553aa04009e42b76a09951", - "version": "==0.4.0" - }, - "py": { - "hash": "sha256:81b5e37db3cc1052de438375605fb5d3b3e97f950f415f9143f04697c684d7eb", - "version": "==1.4.33" - }, "pycodestyle": { - "hash": "sha256:2ce83f2046f5ab85c652ceceddfbde7a64a909900989b4b43e92b10b743d0ce5", "version": "==2.0.0" }, "pyflakes": { - "hash": "sha256:e87bac26c62ea5b45067cc89e4a12f56e1483f1f2cda17e7c9b375b9fd2f40da", "version": "==1.2.3" }, + "python-termstyle": { + "version": "==0.1.10" + }, + "pyyaml": { + "version": "==3.12" + }, + "requests": { + "version": "==2.18.4" + }, + "setuptools": { + "version": "==36.2.7" + }, "six": { - "hash": "sha256:0ff78c403d9bccf5a425a6d31a12aa6b47f1c21ca4dc2573a7e2f32a97335eb1", "version": "==1.10.0" }, - "tornado": { - "hash": "sha256:f267acc96d5cf3df0fd8a7bfb5a91c2eb4ec81d5962d1a7386ceb34c655634a8", - "version": "==4.4.3" + "sniffer": { + "version": "==0.4.0" }, - "tox": { - "hash": "sha256:0f37ea637ead4a5bbae91531b0bf8fd327c7152e20255e5960ee180598228d21", - "version": "==2.7.0" + "tornado": { + "version": "==4.5.1" }, - "virtualenv": { - "hash": "sha256:39d88b533b422825d644087a21e78c45cf5af0ef7a99a1fc9fbb7b481e5c85b0", - "version": "==15.1.0" + "urllib3": { + "version": "==1.22" } } -} \ No newline at end of file +} diff --git a/flask_api/app.py b/flask_api/app.py index 91fcde7..55c08ab 100644 --- a/flask_api/app.py +++ b/flask_api/app.py @@ -62,8 +62,6 @@ def make_response(self, rv): else: rv = self.response_class.force_type(rv, request.environ) - if status_or_headers is not None: - if isinstance( if status_or_headers is not None: if isinstance(status_or_headers, string_types): rv.status = status_or_headers diff --git a/flask_api/tests/runtests.py b/flask_api/tests/runtests.py deleted file mode 100644 index 53a61fb..0000000 --- a/flask_api/tests/runtests.py +++ /dev/null @@ -1,5 +0,0 @@ -import unittest - - -if __name__ == '__main__': - unittest.main(module='flask_api.tests') diff --git a/requirements.txt b/requirements.txt deleted file mode 100644 index 578ef02..0000000 --- a/requirements.txt +++ /dev/null @@ -1,8 +0,0 @@ -# Production -Flask >= 0.10.1 - -# Development -coverage ~= 3.7.1 -flake8 ~= 2.1 -mkdocs ~= 0.12 -tox ~= 2.0 diff --git a/runtests b/runtests deleted file mode 100755 index ff313a1..0000000 --- a/runtests +++ /dev/null @@ -1,12 +0,0 @@ -#!/usr/bin/env bash - -export PYTHONPATH=. -set -e - -coverage run --omit=*.html,flask_api/tests/runtests.py,flask_api/tests/__init__.py --source=flask_api flask_api/tests/runtests.py $@ -flake8 flask_api --ignore=E128,E501 --exclude=__init__.py - -if [[ ! "$@" ]] ; then - echo - coverage report -fi diff --git a/scent.py b/scent.py new file mode 100644 index 0000000..a2b54fc --- /dev/null +++ b/scent.py @@ -0,0 +1,97 @@ +# -*- coding: utf-8 -*- +"""Configuration file for sniffer.""" +# pylint: disable=superfluous-parens,bad-continuation + +import time +import subprocess + +from sniffer.api import select_runnable, file_validator, runnable +try: + from pync import Notifier +except ImportError: + notify = None +else: + notify = Notifier.notify + + +watch_paths = ["flask_api"] + + +class Options(object): + group = int(time.time()) # unique per run + show_coverage = False + rerun_args = None + + targets = [ + (('make', 'test', 'DISABLE_COVERAGE=true'), "Run Tests", True), + (('make', 'check'), "Static Analysis", True), + (('make', 'doc'), None, True), + ] + + +@select_runnable('run_targets') +@file_validator +def python_files(filename): + return filename.endswith('.py') + + +@select_runnable('run_targets') +@file_validator +def html_files(filename): + return filename.split('.')[-1] in ['html', 'css', 'js'] + + +@runnable +def run_targets(*args): + """Run targets for Python.""" + Options.show_coverage = 'coverage' in args + + count = 0 + for count, (command, title, retry) in enumerate(Options.targets, start=1): + + success = call(command, title, retry) + if not success: + message = "✅ " * (count - 1) + "❌" + show_notification(message, title) + + return False + + message = "✅ " * count + title = "All Targets" + show_notification(message, title) + show_coverage() + + return True + + +def call(command, title, retry): + """Run a command-line program and display the result.""" + if Options.rerun_args: + command, title, retry = Options.rerun_args + Options.rerun_args = None + success = call(command, title, retry) + if not success: + return False + + print("") + print("$ %s" % ' '.join(command)) + failure = subprocess.call(command) + + if failure and retry: + Options.rerun_args = command, title, retry + + return not failure + + +def show_notification(message, title): + """Show a user notification.""" + if notify and title: + notify(message, title=title, group=Options.group) + + +def show_coverage(): + """Launch the coverage report.""" + if Options.show_coverage: + subprocess.call(['make', 'read-coverage']) + + Options.show_coverage = False diff --git a/tox.ini b/tox.ini deleted file mode 100644 index 6bdb1d1..0000000 --- a/tox.ini +++ /dev/null @@ -1,6 +0,0 @@ -[tox] -envlist = py27,py33,py34 - -[testenv] -deps = -r{toxinidir}/requirements.txt -commands = {toxinidir}/runtests From 26d7dcfa62bb05ae0416d31cb73420a8142e0a93 Mon Sep 17 00:00:00 2001 From: Jace Browning Date: Mon, 21 Aug 2017 19:37:34 -0400 Subject: [PATCH 06/87] Test against the latest versions of Flask --- .travis.yml | 4 ++-- README.md | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/.travis.yml b/.travis.yml index bb0d081..c8ef0ec 100644 --- a/.travis.yml +++ b/.travis.yml @@ -12,9 +12,9 @@ env: - RANDOM_SEED=0 - PIPENV_NOSPIN=true matrix: - - FLASK_VERSION=0.10.1 - FLASK_VERSION=0.10.2 - - FLASK_VERSION=0.11.0 + - FLASK_VERSION=0.11.2 + - FLASK_VERSION=0.12.2 before_install: - pip install pipenv~=5.0 diff --git a/README.md b/README.md index f73ec7e..edfed20 100644 --- a/README.md +++ b/README.md @@ -156,10 +156,10 @@ To stay up to date with progress on Flask API, follow [Tom Christie on twitter][ Many thanks to [Nicolas Clairon][nicolas-clarion] for making the `flask_api` PyPI package available. -[travis-image]: http://img.shields.io/travis/tomchristie/flask-api/master.svg -[travis-link]: https://travis-ci.org/tomchristie/flask-api -[coveralls-image]: http://img.shields.io/coveralls/tomchristie/flask-api/master.svg -[coveralls-link]: https://coveralls.io/r/tomchristie/flask-api?branch=master +[travis-image]: http://img.shields.io/travis/flask-api/flask-api/master.svg +[travis-link]: https://travis-ci.org/flask-api/flask-api +[coveralls-image]: http://img.shields.io/coveralls/flask-api/flask-api/master.svg +[coveralls-link]: https://coveralls.io/r/flask-api/flask-api?branch=master [pypi-image]: http://img.shields.io/pypi/v/flask-api.svg [pypi-link]: https://pypi.python.org/pypi/flask-api [django-rest-framework]: http://www.django-rest-framework.org From 838fe8b67554e295812fe41560000374463b3a98 Mon Sep 17 00:00:00 2001 From: Jace Browning Date: Mon, 21 Aug 2017 19:50:03 -0400 Subject: [PATCH 07/87] Add scrutinizer config --- .scrutinizer.yml | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 .scrutinizer.yml diff --git a/.scrutinizer.yml b/.scrutinizer.yml new file mode 100644 index 0000000..7796be8 --- /dev/null +++ b/.scrutinizer.yml @@ -0,0 +1,8 @@ +checks: + python: + code_rating: true + duplicate_code: true +filter: + excluded_paths: + - "*/tests/*" + - "*.min.js" From 53e97af55aae1f4f76eaa358d8c23e07d5620b01 Mon Sep 17 00:00:00 2001 From: Jace Browning Date: Mon, 21 Aug 2017 20:19:37 -0400 Subject: [PATCH 08/87] Update status --- README.md | 54 ++++++++---------------------------------------------- 1 file changed, 8 insertions(+), 46 deletions(-) diff --git a/README.md b/README.md index edfed20..a40628c 100644 --- a/README.md +++ b/README.md @@ -1,42 +1,20 @@ -**Status**: Flask API is not currently under active development. This will be reassessed once the [Django REST framework](https://github.com/tomchristie/django-rest-framework) Kickstarter project reaches completion. +# Flask API -# [Flask API](http://www.flaskapi.org) +Browsable web APIs for Flask. -Browsable Web APIs for Flask - +[![Unix Build Status](https://img.shields.io/travis/flask-api/flask-api.svg)](https://travis-ci.org/flask-api/flask-api) +[![Coverage Status](https://img.shields.io/coveralls/flask-api/flask-api.svg)](https://coveralls.io/r/flask-api/flask-api) +[![Scrutinizer Code Quality](https://img.shields.io/scrutinizer/g/flask-api/flask-api.svg)](https://scrutinizer-ci.com/g/flask-api/flask-api/) +[![PyPI Version](https://img.shields.io/pypi/v/Flask-API.svg)](https://pypi.org/project/Flask-API/) -[![Build Status][travis-image]][travis-link] -[![Coverage Status][coveralls-image]][coveralls-link] -[![PyPI Version][pypi-image]][pypi-link] - ---- +**Status**: This project is in maintenance mode. The original author ([Tom Christie](https://twitter.com/_tomchristie)) has shifted their focus to a more general-purpose API project: http://www.coreapi.org. Passing PRs will still be considered for releases by the maintainers ([Jace Browning](https://twitter.com/jacebrowning)). ## Overview -Flask API is an implementation of the same web browsable APIs that [Django REST framework][django-rest-framework] provides. - -It gives you properly content negotiated responses and smart request parsing. - -It is currently a work in progress, but the fundamentals are in place and you can already start building kick-ass browsable Web APIs with it. If you want to start using Flask API right now go ahead and do so, but be sure to follow the release notes of new versions carefully. +Flask API is a drop-in replacement for Flask that provides implementation of browsable APIs similar to what [Django REST framework](http://www.django-rest-framework.org) provides. It gives you properly content negotiated responses and smart request parsing: ![Screenshot](docs/screenshot.png) -## Roadmap - -Future work on getting Flask API to a 1.0 release will include: - -* Authentication, including session, basic and token authentication. -* Permissions, including a simple user-is-authenticated permission. -* Throttling, including a base rate throttling implementation. -* Support for using class based views, including the base view class. -* Browsable API improvements, such as breadcrumb generation. -* Customizable exception handling. -* CSRF protection for session authenticated requests. -* Login and logout views for the browsable API. -* Documentation on how to deal with request validation. -* Documentation on how to deal with hyperlinking. - -It is also possible that the core of Flask API could be refactored into an external dependency, in order to make browsable APIs easily available to any Python web framework. - ## Installation Requirements: @@ -149,19 +127,3 @@ You can now open a new tab and interact with the API from the command line: {"url": "http://127.0.0.1:5000/1/", "text": "flask api is teh awesomez"} You can also work on the API directly in your browser, by opening . You can then navigate between notes, and make `GET`, `PUT`, `POST` and `DELETE` API requests. - -## Credits - -To stay up to date with progress on Flask API, follow [Tom Christie on twitter][tomchristie]. - -Many thanks to [Nicolas Clairon][nicolas-clarion] for making the `flask_api` PyPI package available. - -[travis-image]: http://img.shields.io/travis/flask-api/flask-api/master.svg -[travis-link]: https://travis-ci.org/flask-api/flask-api -[coveralls-image]: http://img.shields.io/coveralls/flask-api/flask-api/master.svg -[coveralls-link]: https://coveralls.io/r/flask-api/flask-api?branch=master -[pypi-image]: http://img.shields.io/pypi/v/flask-api.svg -[pypi-link]: https://pypi.python.org/pypi/flask-api -[django-rest-framework]: http://www.django-rest-framework.org -[tomchristie]: https://twitter.com/_tomchristie -[nicolas-clarion]: https://github.com/namlook/ From 57ac3d08c2c1b8a883e184e530982a7c7e1502e5 Mon Sep 17 00:00:00 2001 From: Jace Browning Date: Mon, 21 Aug 2017 20:32:54 -0400 Subject: [PATCH 09/87] Link to API Star --- README.md | 4 ++-- scent.py | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index a40628c..74fc053 100644 --- a/README.md +++ b/README.md @@ -7,11 +7,11 @@ Browsable web APIs for Flask. [![Scrutinizer Code Quality](https://img.shields.io/scrutinizer/g/flask-api/flask-api.svg)](https://scrutinizer-ci.com/g/flask-api/flask-api/) [![PyPI Version](https://img.shields.io/pypi/v/Flask-API.svg)](https://pypi.org/project/Flask-API/) -**Status**: This project is in maintenance mode. The original author ([Tom Christie](https://twitter.com/_tomchristie)) has shifted their focus to a more general-purpose API project: http://www.coreapi.org. Passing PRs will still be considered for releases by the maintainers ([Jace Browning](https://twitter.com/jacebrowning)). +**Status**: This project is in maintenance mode. The original author ([Tom Christie](https://twitter.com/_tomchristie)) has shifted their focus to other API projects (http://www.coreapi.org and http://www.api-star.org). Passing PRs will still be considered for releases by the maintainers ([Jace Browning](https://twitter.com/jacebrowning)). ## Overview -Flask API is a drop-in replacement for Flask that provides implementation of browsable APIs similar to what [Django REST framework](http://www.django-rest-framework.org) provides. It gives you properly content negotiated responses and smart request parsing: +Flask API is a drop-in replacement for Flask that provides an implementation of browsable APIs similar to what [Django REST framework](http://www.django-rest-framework.org) provides. It gives you properly content negotiated-responses and smart request parsing: ![Screenshot](docs/screenshot.png) diff --git a/scent.py b/scent.py index a2b54fc..7906bd0 100644 --- a/scent.py +++ b/scent.py @@ -23,7 +23,7 @@ class Options(object): rerun_args = None targets = [ - (('make', 'test', 'DISABLE_COVERAGE=true'), "Run Tests", True), + (('make', 'test'), "Run Tests", True), (('make', 'check'), "Static Analysis", True), (('make', 'doc'), None, True), ] From 42213871c31d26d43b8bfe92b52f3f09b5c09d31 Mon Sep 17 00:00:00 2001 From: Jace Browning Date: Mon, 21 Aug 2017 20:37:42 -0400 Subject: [PATCH 10/87] Add contributor instructions --- CONTRIBUTING.md | 69 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 69 insertions(+) create mode 100644 CONTRIBUTING.md diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000..9086992 --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,69 @@ +# For Contributors + +## Setup + +### Requirements + +* Make: + * Windows: http://mingw.org/download/installer + * Mac: http://developer.apple.com/xcode + * Linux: http://www.gnu.org/software/make +* pipenv: http://docs.pipenv.org + +### Installation + +Install project dependencies into a virtual environment: + +```sh +$ make install +``` + +## Development Tasks + +### Testing + +Manually run the tests: + +```sh +$ make test +``` + +or keep them running on change: + +```sh +$ make watch +``` + +> In order to have OS X notifications, `brew install terminal-notifier`. + +### Documentation + +Build the documentation: + +```sh +$ make doc +``` + +### Static Analysis + +Run linters and static analyzers: + +```sh +$ make check +``` + +## Continuous Integration + +The CI server will report overall build status: + +```sh +$ make ci +``` + +## Release Tasks + +Release to PyPI: + +```sh +$ make upload +``` From 5be9eea1a5e62e669bdc39ec7c59ad467b64628e Mon Sep 17 00:00:00 2001 From: Jace Browning Date: Mon, 21 Aug 2017 21:22:06 -0400 Subject: [PATCH 11/87] Update docs for 1.0 release --- README.md | 4 +- docs/about/release-notes.md | 4 +- docs/index.md | 156 ++++++++++++++---------------------- flask_api/__init__.py | 2 +- setup.py | 13 +-- 5 files changed, 67 insertions(+), 112 deletions(-) diff --git a/README.md b/README.md index 74fc053..ddc8f7c 100644 --- a/README.md +++ b/README.md @@ -22,11 +22,11 @@ Requirements: * Python 2.7+ or 3.3+ * Flask 0.10+ -Install using `pip`. +Install using `pip`: pip install Flask-API -Import and initialize your application. +Import and initialize your application: from flask_api import FlaskAPI diff --git a/docs/about/release-notes.md b/docs/about/release-notes.md index d47df7d..48523cd 100644 --- a/docs/about/release-notes.md +++ b/docs/about/release-notes.md @@ -1,6 +1,8 @@ # Release Notes -This project is currently in beta. It is functional and well tested but you are advised to pay close attention to the release notes when upgrading to future versions. +## Version 1.0 + +* Stable release to enter maintenance mode. ## Version 0.7.1 diff --git a/docs/index.md b/docs/index.md index ef9f084..4bdbcca 100644 --- a/docs/index.md +++ b/docs/index.md @@ -6,31 +6,10 @@ Browsable Web APIs for Flask ## Overview -Flask API is an implementation of the same web browsable APIs that [Django REST framework][django-rest-framework] provides. - -It gives you properly content negotiated responses and smart request parsing. - -It is currently a work in progress, but the fundamentals are in place and you can already start building kick-ass browsable Web APIs with it. If you want to start using Flask API right now go ahead and do so, but be sure to follow the release notes of new versions carefully. +Flask API is a drop-in replacement for Flask that provides an implementation of browsable APIs similar to what [Django REST framework](http://www.django-rest-framework.org) provides. It gives you properly content negotiated-responses and smart request parsing: ![Screenshot](screenshot.png) -## Roadmap - -Future work on getting Flask API to a 1.0 release will include: - -* Authentication, including session, basic and token authentication. -* Permissions, including a simple user-is-authenticated permission. -* Throttling, including a base rate throttling implementation. -* Support for using class based views, including the base view class. -* Browsable API improvements, such as breadcrumb generation. -* Customizable exception handling. -* CSRF protection for session authenticated requests. -* Login and logout views for the browsable API. -* Documentation on how to deal with request validation. -* Documentation on how to deal with hyperlinking. - -It is also possible that the core of Flask API could be refactored into an external dependency, in order to make browsable APIs easily available to any Python web framework. - ## Installation Requirements: @@ -42,14 +21,13 @@ The following packages are optional: * Markdown (2.1.0+) - Markdown support for the browsable API. -Install using `pip`, including any optional packages you want... +Install using `pip`: pip install Flask-API - pip install markdown # Markdown support for the browsable API. -Import and initialize your application. +Import and initialize your application: - from flask.ext.api import FlaskAPI + from flask_api import FlaskAPI app = FlaskAPI(__name__) @@ -75,62 +53,62 @@ Access the parsed request data using `request.data`. This will handle JSON or f The following example demonstrates a simple API for creating, listing, updating and deleting notes. - from flask import request, url_for - from flask.ext.api import FlaskAPI, status, exceptions - - app = FlaskAPI(__name__) - - - notes = { - 0: 'do the shopping', - 1: 'build the codez', - 2: 'paint the door', - } - - def note_repr(key): - return { - 'url': request.host_url.rstrip('/') + url_for('notes_detail', key=key), - 'text': notes[key] - } - - - @app.route("/", methods=['GET', 'POST']) - def notes_list(): - """ - List or create notes. - """ - if request.method == 'POST': - note = str(request.data.get('text', '')) - idx = max(notes.keys()) + 1 - notes[idx] = note - return note_repr(idx), status.HTTP_201_CREATED - - # request.method == 'GET' - return [note_repr(idx) for idx in sorted(notes.keys())] - - - @app.route("//", methods=['GET', 'PUT', 'DELETE']) - def notes_detail(key): - """ - Retrieve, update or delete note instances. - """ - if request.method == 'PUT': - note = str(request.data.get('text', '')) - notes[key] = note - return note_repr(key) - - elif request.method == 'DELETE': - notes.pop(key, None) - return '', status.HTTP_204_NO_CONTENT - - # request.method == 'GET' - if key not in notes: - raise exceptions.NotFound() - return note_repr(key) - - - if __name__ == "__main__": - app.run(debug=True) + from flask import request, url_for + from flask_api import FlaskAPI, status, exceptions + + app = FlaskAPI(__name__) + + + notes = { + 0: 'do the shopping', + 1: 'build the codez', + 2: 'paint the door', + } + + def note_repr(key): + return { + 'url': request.host_url.rstrip('/') + url_for('notes_detail', key=key), + 'text': notes[key] + } + + + @app.route("/", methods=['GET', 'POST']) + def notes_list(): + """ + List or create notes. + """ + if request.method == 'POST': + note = str(request.data.get('text', '')) + idx = max(notes.keys()) + 1 + notes[idx] = note + return note_repr(idx), status.HTTP_201_CREATED + + # request.method == 'GET' + return [note_repr(idx) for idx in sorted(notes.keys())] + + + @app.route("//", methods=['GET', 'PUT', 'DELETE']) + def notes_detail(key): + """ + Retrieve, update or delete note instances. + """ + if request.method == 'PUT': + note = str(request.data.get('text', '')) + notes[key] = note + return note_repr(key) + + elif request.method == 'DELETE': + notes.pop(key, None) + return '', status.HTTP_204_NO_CONTENT + + # request.method == 'GET' + if key not in notes: + raise exceptions.NotFound() + return note_repr(key) + + + if __name__ == "__main__": + app.run(debug=True) Now run the webapp: @@ -148,17 +126,3 @@ You can now open a new tab and interact with the API from the command line: {"url": "http://127.0.0.1:5000/1/", "text": "flask api is teh awesomez"} You can also work on the API directly in your browser, by opening . You can then navigate between notes, and make `GET`, `PUT`, `POST` and `DELETE` API requests. - -## Credits - -To stay up to date with progress on Flask API, follow Tom Christie on twitter, [here][tomchristie]. - -Many thanks to [Nicolas Clairon][nicolas-clarion] for making the `flask_api` PyPI package available. - -[travis-image]: https://travis-ci.org/tomchristie/flask-api.png?branch=master -[travis-link]: https://travis-ci.org/tomchristie/flask-api -[coveralls-image]: https://coveralls.io/repos/tomchristie/flask-api/badge.png?branch=master -[coveralls-link]: https://coveralls.io/r/tomchristie/flask-api?branch=master -[django-rest-framework]: http://www.django-rest-framework.org -[tomchristie]: https://twitter.com/_tomchristie -[nicolas-clarion]: https://github.com/namlook/ diff --git a/flask_api/__init__.py b/flask_api/__init__.py index 9202151..780da12 100644 --- a/flask_api/__init__.py +++ b/flask_api/__init__.py @@ -1,3 +1,3 @@ from flask_api.app import FlaskAPI -__version__ = '0.7.1' +__version__ = '1.0b1' diff --git a/setup.py b/setup.py index 5b59402..4be573a 100755 --- a/setup.py +++ b/setup.py @@ -54,17 +54,6 @@ def get_package_data(package): for filename in filenames]) return {package: filepaths} - -if sys.argv[-1] == 'publish': - os.system("git clean -xdf") - os.system("python setup.py sdist upload") - args = {'version': get_version(package)} - print("You probably want to also tag the version now:") - print(" git tag -a %(version)s -m 'version %(version)s'" % args) - print(" git push --tags") - sys.exit() - - setup( name=name, version=get_version(package), @@ -78,7 +67,7 @@ def get_package_data(package): package_data=get_package_data(package), install_requires=install_requires, classifiers=[ - 'Development Status :: 4 - Beta', + 'Development Status :: 5 - Production/Stable', 'Environment :: Web Environment', 'Framework :: Flask', 'Intended Audience :: Developers', From 8d097ef62ef347d022d8356a12937b2dbc5b4633 Mon Sep 17 00:00:00 2001 From: Jace Browning Date: Mon, 21 Aug 2017 21:40:55 -0400 Subject: [PATCH 12/87] Upload packages with twine --- Makefile | 12 ++++++++++++ Pipfile | 2 ++ Pipfile.lock | 17 ++++++++++++++++- 3 files changed, 30 insertions(+), 1 deletion(-) diff --git a/Makefile b/Makefile index e9e6189..80411ad 100644 --- a/Makefile +++ b/Makefile @@ -153,6 +153,18 @@ mkdocs-live: mkdocs eval "sleep 3; open http://127.0.0.1:8000" & $(MKDOCS) serve +# BUILD ######################################################################## + +DIST_FILES := dist/*.tar.gz dist/*.whl + +.PHONY: dist +dist: install $(DIST_FILES) +$(DIST_FILES): $(MODULES) + rm -f $(DIST_FILES) + $(PYTHON) setup.py check --restructuredtext --strict --metadata + $(PYTHON) setup.py sdist + $(PYTHON) setup.py bdist_wheel + # RELEASE ###################################################################### TWINE := pipenv run twine diff --git a/Pipfile b/Pipfile index d189038..6e9b683 100644 --- a/Pipfile +++ b/Pipfile @@ -11,4 +11,6 @@ coverage = "~=3.7.1" "coverage.space" = "*" flake8 = "~=2.1" mkdocs = "==0.12" +docutils = "*" sniffer = "*" +twine = "*" diff --git a/Pipfile.lock b/Pipfile.lock index 59dbfb4..9257b90 100644 --- a/Pipfile.lock +++ b/Pipfile.lock @@ -1,7 +1,7 @@ { "_meta": { "hash": { - "sha256": "954e1eeca60d19999a62f8c33aa380983b8deb58b5b635987651ecee76e4418e" + "sha256": "25b210bb732e44c53e175b05c7d370a30212d23011ef51d78a212a33eb340e54" }, "requires": {}, "sources": [ @@ -50,6 +50,9 @@ "docopt": { "version": "==0.6.2" }, + "docutils": { + "version": "==0.14" + }, "flake8": { "version": "==2.6.2" }, @@ -78,6 +81,9 @@ "nose": { "version": "==1.3.7" }, + "pkginfo": { + "version": "==1.4.1" + }, "pycodestyle": { "version": "==2.0.0" }, @@ -93,6 +99,9 @@ "requests": { "version": "==2.18.4" }, + "requests-toolbelt": { + "version": "==0.8.0" + }, "setuptools": { "version": "==36.2.7" }, @@ -105,6 +114,12 @@ "tornado": { "version": "==4.5.1" }, + "tqdm": { + "version": "==4.15.0" + }, + "twine": { + "version": "==1.9.1" + }, "urllib3": { "version": "==1.22" } From 79ecbea10287b40e54c97bf68afb12cbd74019cf Mon Sep 17 00:00:00 2001 From: Jace Browning Date: Tue, 22 Aug 2017 06:39:10 -0400 Subject: [PATCH 13/87] Fix merge conflict --- flask_api/__init__.py | 2 +- flask_api/app.py | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/flask_api/__init__.py b/flask_api/__init__.py index 780da12..2891d91 100644 --- a/flask_api/__init__.py +++ b/flask_api/__init__.py @@ -1,3 +1,3 @@ from flask_api.app import FlaskAPI -__version__ = '1.0b1' +__version__ = '1.0b2' diff --git a/flask_api/app.py b/flask_api/app.py index 55c08ab..fbffd20 100644 --- a/flask_api/app.py +++ b/flask_api/app.py @@ -1,7 +1,7 @@ # coding: utf8 from __future__ import unicode_literals from flask import request, Flask, Blueprint -from flask._compat import reraise, string_types +from flask._compat import reraise, string_types, text_type from flask_api.exceptions import APIException from flask_api.request import APIRequest from flask_api.response import APIResponse @@ -55,7 +55,7 @@ def make_response(self, rv): headers, status_or_headers = status_or_headers, None if not isinstance(rv, self.response_class): - if isinstance(rv, self.response_class.api_return_types): + if isinstance(rv, (text_type, bytes, bytearray, list, dict)): status = status_or_headers rv = self.response_class(rv, headers=headers, status=status) headers = status_or_headers = None From b99c8d26e335cef696b931dde783ca80ca4ab798 Mon Sep 17 00:00:00 2001 From: Tom Christie Date: Wed, 23 Aug 2017 11:43:44 +0100 Subject: [PATCH 14/87] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 74fc053..ab72933 100644 --- a/README.md +++ b/README.md @@ -7,7 +7,7 @@ Browsable web APIs for Flask. [![Scrutinizer Code Quality](https://img.shields.io/scrutinizer/g/flask-api/flask-api.svg)](https://scrutinizer-ci.com/g/flask-api/flask-api/) [![PyPI Version](https://img.shields.io/pypi/v/Flask-API.svg)](https://pypi.org/project/Flask-API/) -**Status**: This project is in maintenance mode. The original author ([Tom Christie](https://twitter.com/_tomchristie)) has shifted their focus to other API projects (http://www.coreapi.org and http://www.api-star.org). Passing PRs will still be considered for releases by the maintainers ([Jace Browning](https://twitter.com/jacebrowning)). +**Status**: This project is in maintenance mode. The original author ([Tom Christie](https://twitter.com/_tomchristie)) has shifted his focus to the ["API Star" project](https://github.com/encode/apistar). Passing PRs will still be considered for releases by the maintainers ([Jace Browning](https://twitter.com/jacebrowning)). ## Overview From 59e320ff7edecc80eaafc846ae0f45072515b2c7 Mon Sep 17 00:00:00 2001 From: Jace Browning Date: Thu, 24 Aug 2017 09:43:00 -0400 Subject: [PATCH 15/87] Use Flask version from the build matrix --- .travis.yml | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index c8ef0ec..ae056c3 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,5 +1,4 @@ language: python - python: - 2.7 - 3.3 @@ -7,6 +6,11 @@ python: - 3.5 - 3.6 +cache: + pip: true + directories: + - .venv + env: global: - RANDOM_SEED=0 @@ -22,6 +26,10 @@ before_install: install: - make install +before_script: + # Override the version of Flask based on the build matrix + - pipenv run pip install flask==${FLASK_VERSION} + script: - make check - make test From ce27ac9b8f913cf7b11e22ef39dfa1e6d82f50d2 Mon Sep 17 00:00:00 2001 From: Jace Browning Date: Thu, 24 Aug 2017 09:51:17 -0400 Subject: [PATCH 16/87] Ignore vendored JavaScript --- .scrutinizer.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.scrutinizer.yml b/.scrutinizer.yml index 7796be8..1504dc2 100644 --- a/.scrutinizer.yml +++ b/.scrutinizer.yml @@ -5,4 +5,4 @@ checks: filter: excluded_paths: - "*/tests/*" - - "*.min.js" + - "*/static/js/*min.js" From 933950aaea2243ce6f897ffa92ed27394740ad59 Mon Sep 17 00:00:00 2001 From: Jace Browning Date: Thu, 24 Aug 2017 09:51:32 -0400 Subject: [PATCH 17/87] Remove unpublished Flask versions from build matrix --- .travis.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index ae056c3..4683e15 100644 --- a/.travis.yml +++ b/.travis.yml @@ -16,8 +16,8 @@ env: - RANDOM_SEED=0 - PIPENV_NOSPIN=true matrix: - - FLASK_VERSION=0.10.2 - - FLASK_VERSION=0.11.2 + - FLASK_VERSION=0.10.1 + - FLASK_VERSION=0.11.1 - FLASK_VERSION=0.12.2 before_install: From 27f4228ffc83b67a516ec99904cb72af1a08e418 Mon Sep 17 00:00:00 2001 From: Jace Browning Date: Tue, 29 Aug 2017 00:26:50 -0400 Subject: [PATCH 18/87] Bump version to 1.0 --- Pipfile | 1 + Pipfile.lock | 15 ++++++++++++--- flask_api/__init__.py | 2 +- flask_api/compat.py | 2 +- flask_api/renderers.py | 13 +++++++------ flask_api/tests/test_renderers.py | 21 +++++++++++++++++++-- 6 files changed, 41 insertions(+), 13 deletions(-) diff --git a/Pipfile b/Pipfile index 6e9b683..abb79ad 100644 --- a/Pipfile +++ b/Pipfile @@ -4,6 +4,7 @@ verify_ssl = true [packages] Flask = "~=0.10.1" +Markdown = "*" [dev-packages] nose = "*" diff --git a/Pipfile.lock b/Pipfile.lock index 9257b90..d5151f7 100644 --- a/Pipfile.lock +++ b/Pipfile.lock @@ -1,7 +1,7 @@ { "_meta": { "hash": { - "sha256": "25b210bb732e44c53e175b05c7d370a30212d23011ef51d78a212a33eb340e54" + "sha256": "77d9453222dda519832b3e9753aa60167a725fad64a3e69f11373e375ef71c23" }, "requires": {}, "sources": [ @@ -21,6 +21,9 @@ "jinja2": { "version": "==2.9.6" }, + "markdown": { + "version": "==2.6.9" + }, "markupsafe": { "version": "==1.0" }, @@ -29,6 +32,9 @@ } }, "develop": { + "backports-abc": { + "version": "==0.5" + }, "backports.shutil-get-terminal-size": { "version": "==1.0.0" }, @@ -103,7 +109,10 @@ "version": "==0.8.0" }, "setuptools": { - "version": "==36.2.7" + "version": "==36.3.0" + }, + "singledispatch": { + "version": "==3.4.0.3" }, "six": { "version": "==1.10.0" @@ -112,7 +121,7 @@ "version": "==0.4.0" }, "tornado": { - "version": "==4.5.1" + "version": "==4.5.2" }, "tqdm": { "version": "==4.15.0" diff --git a/flask_api/__init__.py b/flask_api/__init__.py index 2891d91..143cce5 100644 --- a/flask_api/__init__.py +++ b/flask_api/__init__.py @@ -1,3 +1,3 @@ from flask_api.app import FlaskAPI -__version__ = '1.0b2' +__version__ = '1.0' diff --git a/flask_api/compat.py b/flask_api/compat.py index 525884f..65d36a2 100644 --- a/flask_api/compat.py +++ b/flask_api/compat.py @@ -17,7 +17,7 @@ def apply_markdown(text): return md.convert(text) -except ImportError: +except ImportError: # pragma: no cover - markdown installed for tests apply_markdown = None diff --git a/flask_api/renderers.py b/flask_api/renderers.py index debda8a..58582aa 100644 --- a/flask_api/renderers.py +++ b/flask_api/renderers.py @@ -97,12 +97,13 @@ def render(self, data, media_type, **options): endpoint = request.url_rule.endpoint view_name = str(endpoint) view_description = current_app.view_functions[endpoint].__doc__ - if apply_markdown is None and view_description: - view_description = dedent(view_description) - view_description = pydoc.html.preformat(view_description) - elif apply_markdown is not None and view_description: - view_description = dedent(view_description) - view_description = apply_markdown(view_description) + if view_description: + if apply_markdown: + view_description = dedent(view_description) + view_description = apply_markdown(view_description) + else: # pragma: no cover - markdown installed for tests + view_description = dedent(view_description) + view_description = pydoc.html.preformat(view_description) status = options['status'] headers = options['headers'] diff --git a/flask_api/tests/test_renderers.py b/flask_api/tests/test_renderers.py index 79419ee..cbdcbe7 100644 --- a/flask_api/tests/test_renderers.py +++ b/flask_api/tests/test_renderers.py @@ -27,13 +27,30 @@ def love(): return {"test": "I <3 Python"} with app.test_client() as client: - response = client.get('/_love', - headers={"Accept": "text/html"}) + response = client.get('/_love', headers={"Accept": "text/html"}) html = str(response.get_data()) self.assertTrue('I <3 Python' in html) self.assertTrue('

Love

' in html) self.assertTrue('/_love' in html) + def test_render_browsable_encoding_with_markdown(self): + app = FlaskAPI(__name__) + + @app.route('/_foo', methods=['GET']) + def foo(): + """Bar: + - `qux` + """ + return {"test": "I <3 Python"} + + with app.test_client() as client: + response = client.get('/_foo', headers={"Accept": "text/html"}) + html = str(response.get_data()) + print(html) + self.assertTrue('

Foo

' in html) + self.assertTrue('

Bar:' in html) + self.assertTrue('qux' in html) + def test_render_browsable_linking(self): app = FlaskAPI(__name__) From cdf8eec5fd7eef74e1d9d789b3be0cab2b493dcf Mon Sep 17 00:00:00 2001 From: Jace Browning Date: Tue, 29 Aug 2017 00:49:53 -0400 Subject: [PATCH 19/87] Update repository location --- mkdocs.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mkdocs.yml b/mkdocs.yml index 8f40c5d..62e0e9d 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -7,7 +7,7 @@ pages: - ['api-guide/status-codes.md', 'API Guide', 'Status codes'] - ['about/release-notes.md', 'About', 'Release Notes'] - ['about/license.md', 'About', 'License'] -repo_url: https://github.com/tomchristie/flask-api +repo_url: https://github.com/flask-api/flask-api theme_center_homepage_lead: true copyright: 'BSD licensed · Copyright © 2014, Tom Christie.' google_analytics: ['UA-27795084-4', 'flaskapi.org'] From e263d7169b1c99786a7bd88d3dd145c5ceef49cc Mon Sep 17 00:00:00 2001 From: Jace Browning Date: Tue, 29 Aug 2017 01:02:22 -0400 Subject: [PATCH 20/87] Update mkdocs to 0.16 --- Pipfile | 2 +- Pipfile.lock | 12 +++++++----- mkdocs.yml | 1 - 3 files changed, 8 insertions(+), 7 deletions(-) diff --git a/Pipfile b/Pipfile index abb79ad..3ed0eb4 100644 --- a/Pipfile +++ b/Pipfile @@ -11,7 +11,7 @@ nose = "*" coverage = "~=3.7.1" "coverage.space" = "*" flake8 = "~=2.1" -mkdocs = "==0.12" +mkdocs = "*" docutils = "*" sniffer = "*" twine = "*" diff --git a/Pipfile.lock b/Pipfile.lock index d5151f7..958a9ed 100644 --- a/Pipfile.lock +++ b/Pipfile.lock @@ -1,7 +1,7 @@ { "_meta": { "hash": { - "sha256": "77d9453222dda519832b3e9753aa60167a725fad64a3e69f11373e375ef71c23" + "sha256": "becad809c6c13e0d434dfc887c66d2755ab20b4fa55c8b92a5dbe0527e61c563" }, "requires": {}, "sources": [ @@ -44,6 +44,9 @@ "chardet": { "version": "==3.0.4" }, + "click": { + "version": "==6.7" + }, "colorama": { "version": "==0.3.9" }, @@ -62,9 +65,6 @@ "flake8": { "version": "==2.6.2" }, - "ghp-import": { - "version": "==0.5.5" - }, "idna": { "version": "==2.6" }, @@ -83,7 +83,9 @@ "mccabe": { "version": "==0.5.3" }, - "mkdocs": "==0.12", + "mkdocs": { + "version": "==0.16.3" + }, "nose": { "version": "==1.3.7" }, diff --git a/mkdocs.yml b/mkdocs.yml index 62e0e9d..57e0d8e 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -8,6 +8,5 @@ pages: - ['about/release-notes.md', 'About', 'Release Notes'] - ['about/license.md', 'About', 'License'] repo_url: https://github.com/flask-api/flask-api -theme_center_homepage_lead: true copyright: 'BSD licensed · Copyright © 2014, Tom Christie.' google_analytics: ['UA-27795084-4', 'flaskapi.org'] From 16421fabbe600aeb097a9baeba912942ee1972f1 Mon Sep 17 00:00:00 2001 From: Jace Browning Date: Sun, 10 Sep 2017 11:01:13 -0400 Subject: [PATCH 21/87] Add custom favicon --- docs/img/android-chrome-144x144.png | Bin 0 -> 2175 bytes docs/img/android-chrome-192x192.png | Bin 0 -> 2461 bytes docs/img/android-chrome-256x256.png | Bin 0 -> 4322 bytes docs/img/android-chrome-36x36.png | Bin 0 -> 974 bytes docs/img/android-chrome-384x384.png | Bin 0 -> 6500 bytes docs/img/android-chrome-48x48.png | Bin 0 -> 1034 bytes docs/img/android-chrome-512x512.png | Bin 0 -> 8876 bytes docs/img/android-chrome-72x72.png | Bin 0 -> 1301 bytes docs/img/android-chrome-96x96.png | Bin 0 -> 1568 bytes docs/img/apple-touch-icon-114x114.png | Bin 0 -> 1289 bytes docs/img/apple-touch-icon-120x120.png | Bin 0 -> 1268 bytes docs/img/apple-touch-icon-144x144.png | Bin 0 -> 1363 bytes docs/img/apple-touch-icon-152x152.png | Bin 0 -> 1329 bytes docs/img/apple-touch-icon-180x180.png | Bin 0 -> 1479 bytes docs/img/apple-touch-icon-57x57.png | Bin 0 -> 934 bytes docs/img/apple-touch-icon-60x60.png | Bin 0 -> 939 bytes docs/img/apple-touch-icon-72x72.png | Bin 0 -> 1076 bytes docs/img/apple-touch-icon-76x76.png | Bin 0 -> 1088 bytes docs/img/apple-touch-icon.png | Bin 0 -> 1380 bytes docs/img/browserconfig.xml | 12 ++++++ docs/img/favicon-16x16.png | Bin 0 -> 612 bytes docs/img/favicon-194x194.png | Bin 0 -> 2017 bytes docs/img/favicon-32x32.png | Bin 0 -> 812 bytes docs/img/favicon.ico | Bin 0 -> 7406 bytes docs/img/manifest.json | 53 ++++++++++++++++++++++++++ docs/img/mstile-144x144.png | Bin 0 -> 1697 bytes docs/img/mstile-150x150.png | Bin 0 -> 1615 bytes docs/img/mstile-310x150.png | Bin 0 -> 1967 bytes docs/img/mstile-310x310.png | Bin 0 -> 3462 bytes docs/img/mstile-70x70.png | Bin 0 -> 1397 bytes docs/img/safari-pinned-tab.svg | 44 +++++++++++++++++++++ docs/logo.draw.io.xml | 1 + mkdocs.yml | 21 ++++++---- 33 files changed, 123 insertions(+), 8 deletions(-) create mode 100644 docs/img/android-chrome-144x144.png create mode 100644 docs/img/android-chrome-192x192.png create mode 100644 docs/img/android-chrome-256x256.png create mode 100644 docs/img/android-chrome-36x36.png create mode 100644 docs/img/android-chrome-384x384.png create mode 100644 docs/img/android-chrome-48x48.png create mode 100644 docs/img/android-chrome-512x512.png create mode 100644 docs/img/android-chrome-72x72.png create mode 100644 docs/img/android-chrome-96x96.png create mode 100644 docs/img/apple-touch-icon-114x114.png create mode 100644 docs/img/apple-touch-icon-120x120.png create mode 100644 docs/img/apple-touch-icon-144x144.png create mode 100644 docs/img/apple-touch-icon-152x152.png create mode 100644 docs/img/apple-touch-icon-180x180.png create mode 100644 docs/img/apple-touch-icon-57x57.png create mode 100644 docs/img/apple-touch-icon-60x60.png create mode 100644 docs/img/apple-touch-icon-72x72.png create mode 100644 docs/img/apple-touch-icon-76x76.png create mode 100644 docs/img/apple-touch-icon.png create mode 100644 docs/img/browserconfig.xml create mode 100644 docs/img/favicon-16x16.png create mode 100644 docs/img/favicon-194x194.png create mode 100644 docs/img/favicon-32x32.png create mode 100644 docs/img/favicon.ico create mode 100644 docs/img/manifest.json create mode 100644 docs/img/mstile-144x144.png create mode 100644 docs/img/mstile-150x150.png create mode 100644 docs/img/mstile-310x150.png create mode 100644 docs/img/mstile-310x310.png create mode 100644 docs/img/mstile-70x70.png create mode 100644 docs/img/safari-pinned-tab.svg create mode 100644 docs/logo.draw.io.xml diff --git a/docs/img/android-chrome-144x144.png b/docs/img/android-chrome-144x144.png new file mode 100644 index 0000000000000000000000000000000000000000..bb754b44538843085b9b444c2592d61d4f50c4fa GIT binary patch literal 2175 zcmd5+dpOkF8vZdej2X8YBviAf*(jG#njyE*j9iBqmvmz^ICNCfAT+szb{e_Fb}5;5 zowBQ=Q=(F$(l(f45QXeqYS12K?pMxlpZ(YQqXv0)Ryt0Jzrzz`E2c?Gz6H&^{R!96Z_`%B@+4S>Z(Ga5{spBxnf15Sy8K3 zKxn{RT~VpN-Mz!l%H(Hd@Uu@XKYqNrvLaV%YM#%K zZD;#{f?k&kZMh1jU)?*u@8uM2BHIx;dt30jDWnAuBJ%+0+VThc$x0Sfwnyj~n@ z;Ja9*77F>f%*E0RD+X2QlT85 zTYkn{e9BvFA6(>o5G;#i?`M{Gmb^hSIkg=#DuuG`&Ai^}9-y!fIK!bej>@Ephi~TL zOipa$XzbO|zVRi?++Kjm(aQQQ_uiyfB5!@WaIR&lxMgZ~QLI+0zkL&a|1P?)dXo=c zI~;>b4hOWfAyAl(E?f_R)Hhm#GBGtXUcUj2*^D*cWN*FG%Za$%-!&*07vdLrIOSw! zc8(imUrc;LYr5fK&_e5Q&>mt?GO{QPEOZ$GAtc>tJ%sUAySwEX;Ol_W1Bir(Q{#e3 zS#2v^N?j$=Mxz&b=+R{;MK;Eqz{ZC(tX2#3Y72A z&mA(`%iel656*tHrLqLOU`r~IXPH;o#)(R%FvuAHj?wOg{qXsWS!Ru{QZZa1^w>5(C$g zu(fxkFEI{zB?v)OxON4tEy1*grJARAmo|n`uOw{G%(H49I)BNFFnQ}z&>=&;szqD7 zTOT=>sWD&t1<-fwFONTlJHyXD)Tx)&9UPvrr+L-%qihDn+Y-4~c&&9Ui31g8+y-21 zGYq-zweG`Hy){9f_qUxcdPw_xd;f>1+*WHx_Pw#@1KY-mOE2GmUH;m}X-l7w;`8G@ zzh*)SyPj$Z#!Cqnu%pHL<1LxzQhp!7`6H!FRYQu($clxWADmW}roG$bw$%YI)fjpA zNrnf45Be;{UOZlTXL{^YforG6acom=`z)lyUH>Ip2JH@Z(|XcL-dga?ex7pcu<0lA z7N%1+J|=I&M3Zy*PXu$5&~nREFOC*v`ApM!neWA8ONVL-dulst>n^;am?-?x!%({4vVViLkqkz#N?J_sJnolcK5U(vJ=@k+ zcTPO|SE^@0mtG0lLZ~Nf#IWJoJ5tKgeo{JQgJ>nUkaH}KV1yHAZ?y4)&5*m52%go3 zdDf_pTtCiO=dXBe4#l_kzx593d;@{J04z;^D$}%>@;*BI!p}OvU7A`QJm%P)s|wtW z7XI7ou-2Hz(V1Irv`5w)s3>SY*pcD+hqn&y*px4_ooS;EHEPWar5o#z;D}tx*wk+1 zk*BLP$*aMQnsd^l+dR$)#ru+K8bgZ^i%OsHiR$l%mnb>-F-sBTcK68=BR*m<^B+vF zM{AoZikPdsCyxf-j258%a#{Y`FHj?bW954bvo7Mhn({rgkF#2~J9lp@0YYSC z^{ZmTU(Kz|*Z*knF0EaNC_p~VRx!CHoPcrZa`jJ73X2i!a65Q!&2_OM3PR=+7CpQOYrwHer?mJxE zcWk$Fa&dQZ8nn$=_%FfHcdY&+1mDn_HzS1Qvt|kq$3@P+KdXiWCB5j40tg_HiOs&Wf`0>5?GiQs literal 0 HcmV?d00001 diff --git a/docs/img/android-chrome-192x192.png b/docs/img/android-chrome-192x192.png new file mode 100644 index 0000000000000000000000000000000000000000..8290d95dfb62bc660e7863aa6541de6049ab424f GIT binary patch literal 2461 zcmd5-dpy+J7T;q$G9q1+S9ylyl|tsw^_nq5#N?GnAwnguNioUjo$B-;ksOb7Dul>Q zoHD&MGbfKE3WLl{OoVxvnctY{{<`OLKc9R5xc}ev*?WCIYk&4yd#$zCUi(5&pszYg z9|ZtV$K!kmFj9Wb6-byTD%^I0K{3fQz!QK+SJal{lwjF-AC3?JK&}M<;>e@{3Z&cwvT%*@Qt&@dn%z}ni{#>U3h z*4EF@Z^MQSR#sLELmbGgr=fNohp z-*V<%)eE+0cz7J^H4_=k*%Qk2_h#qj{E*9~%ks$5L6Fl8PSQXD4V<7_lj#B)Z4&3r zi3{h%hJOtUU>;17L(r0V8S`sD$ftr+ba0ZcpGO^L2_}8LFjx8w@~EF!0s);q;p@eT zi(no)Acv&bU;7P?Q^y1R*g?2SZ?~C?g=w{)!I3v0kLq^5_d5^bQMy=J8B?>O+`6&w zn}gw{gUMB&sH2NA864B{;-X+-fiDtCmX^fx^StF{83alB{3W4KER)HELJ^lM5D1nQ z7IAPak;|p-??IuL?V{VbC(!w-WUrW+$j$Ko{K^K2bjkvfltQ%`o@vd&WX?6$s+uLftYKbcS@ zz6QB(ZOF7y7LW5?c;OKvyksD>WFQRYHwNO$2cPzG1VXVuAeM-sxw*x;IqoKe)d#pz zU5JFhT>zngR8&${S)qzjTe)hrmbT6sO}%x-re@~4Mm84C+Z}wi;GFz-xCCHB;}2yW z%_X@8@7|M;*mguC9yWo9_xJU|pHpHThXoZPJ^-WgMHQuKy{X}9b|C;tkMKU8A;(6( zGemn05)CQbvtz={vb8P7r<=n$%}AZLBjwT9C|^eX;Z)n+fx30Qk>QL;olF)^q1t2h z7%6OaoFuaxmso3>L>r;T_-<@Cr#a8W&+#wa@zf&MEaPOl-by8`*{hbU2Nx3c?mVKz z>Xuc;xoV~TBVr>h{%e5YpN5*cE3s#p51l)`)6r@hsT^&??D8Aay3Bk9wy1A+^vO}C zP)BE1@U_0#3^hBodt=HdkBW);zki$A-+}H<3s*u>s64x_g-^_qT^|egS5CZX#p+OY zpSccF$?TqjzrCP80Nn{$H%pcdmp`&)LW9V| z{rB13XNSce!DsEm;& zG z?X3KeEaKZ=YW$ey(vjI3_RBE4QN3xn!8U2*p?euBU4ur z57T1v$L(VmzyJIyZOj|yCF>SVx1!X zUzXN^^rI2Tj*eEJlEc18B1S92RE@UL+yi})H0&1aPFRW1EOKmDsc3fpjsx_{{=aMk z;Bf#@U|rZD6U1vDL(y%m8$P7`s&EUT1+EsOO)f3IYgK^HM4wgG?1Uh^jVScSE9n_q zYXvY5$iINe!)pLqTEt-JnflGAuG+cgDvCzPCSPp{c71P9zS4Ne>>h38diUK!mS|&V z%?$^SxAm`Q^+azgrnsj*A0SwoR(Zd4KPXrBN+vr$Fc96>IxV(Kw6As{^Bg=#etLe) z^~4%STv}^kFk!)yo|o+WLz)K#HPxI8vvOnr*N4;d_oQ#$5s|e&VpNhkBDDV<)_))Y zWcvEOg;*&n2}1egHzM-<3eb-H>3-*DbzMXKz4jRL_{}{h5)U;!U!zy6Nt5pzGF zayQ?Md?`cZT?}&b#oT+9`FbCkx@3*h;$36!)Mec1cGLXTs>Y&dRaJJh>Sq7NX=+Ch z(2KufaUlt#?a^si2KC*#R+F4GUs#P8EBb10*H(={Cz={5;d7eKD{D$|+UD#_=TSk5 z$Xa)eflPvr%J~WtSA)LE?Uh;WJKW4I2~!DxK2dXNJS`=;cm{vDVinulqkU&&AL%QU z0DS%`y{ACv-_1d?j?>y9rv(85+x3-UDz>hlL574viWgC_J@A`8Gk8`S??lVBra#lz zQm=5V(=uqu{(jwqhxe*RZq*gG#8Re@ zavM-qvD+>(_7e21ni@2Qf`ghnTHJynr=CP@``rVf8&cq(PWt0{O}w==FUS4xi@UvP zK?r5DSKP32hRL>yGukX7N~5!fo^|Pcm4db>;#H=__@PIH>u=tbZwr&iHt~O`k*Ui$ z29N3}@bzsVVj_qMal}OQzRW}zfTP1^7h4Bc+szIko1M{H9no92Y;tf!J2>=PWpn;Z dAvG-_Wq;29R;WJG8wx7`JSNbm(JS`kKLLhkj3WR5 literal 0 HcmV?d00001 diff --git a/docs/img/android-chrome-256x256.png b/docs/img/android-chrome-256x256.png new file mode 100644 index 0000000000000000000000000000000000000000..0fb7aa10f8bb4f150831fd2c356b48d54de2e06e GIT binary patch literal 4322 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 M)=pNH#{;hZ4MTRF-T(jq literal 0 HcmV?d00001 diff --git a/docs/img/android-chrome-36x36.png b/docs/img/android-chrome-36x36.png new file mode 100644 index 0000000000000000000000000000000000000000..1c8b8c3521ad62e3229e9e038b2d5b88ca253706 GIT binary patch literal 974 zcmeAS@N?(olHy`uVBq!ia0vp^Dj>|k3?#4J%UA`ZSkfJR9T^xl_H+M9WCijSl0AZa z85pY67#JE_7#My5g&JNkFq9fFFuY1&V6d9Oz#v{QXIG#N0|TRYfKP}kP(d0YprfOs zuCA`8rk0$XoRE+ZA0Pki+qdsP@Z-mipFh9<{0XFg{rmx>{{H><|NsBLpFe$Gx9a2K z`Ja|7__TE4??(^begE5W@M-z3M-{ss)$D$J^VPTC&z`=_PJR&+{315w$Fak=-~E#6 zImgg&lA-Y=OVg=M*WUg6@#FiMQ{Rpp`gZitw_}I@zJ2rc*S~Ey-mkv=X3gcd>#n?g z@%h*P|Ns610no;OAn@nU-*4Z3e*gaS_wPR-m;LtOV7Tj+4-Pm*8`weLgK=w0fUC8B*-tA zfr*)wT|i7+Le#At#rBme%d*ZZbe=OHUWa z5R21iuSAA7IY=}l-n>{AylUntv)dUP&zhY!Y-~KBvH9-*|JF@M4mTLzdb#R3-?{1s z$q6S?{;BtgJLI`WZondipvkC(2PT<$sY-=%5Jd{vRIS<6JZi$5=H-J|nGiPhoI zqf13Aw`|(AZC{{Xex9Rh*A9LXklP>s3L`oW!G%Z82*`Dus5oQn$Djyz~+l#x;L zX%+Gp=d)C>=a*|6Dr3cXir_eFgJ?;i_8V8c~vxSdwa$T$Bo=7>o=I&2xlq$-qD z7Nja<7L+72FjUNW{E3I7Fib<^l>g~7o=<}qn3cKplDUPIg}o<>FbgZVG?*MtVOHK8 sqHy}gl@mwK9FaM~e!9V9ftMb`D{;Y+Pfn&&fmSehy85}Sb4q9e03Dpu+yDRo literal 0 HcmV?d00001 diff --git a/docs/img/android-chrome-384x384.png b/docs/img/android-chrome-384x384.png new file mode 100644 index 0000000000000000000000000000000000000000..14e81620dff57b9917c7a9d2bacdb5debe6af425 GIT binary patch literal 6500 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 literal 0 HcmV?d00001 diff --git a/docs/img/android-chrome-48x48.png b/docs/img/android-chrome-48x48.png new file mode 100644 index 0000000000000000000000000000000000000000..33ce393a563dd3e8fcd80e4c928aac32a85020b2 GIT binary patch literal 1034 zcmeAS@N?(olHy`uVBq!ia0vp^1|ZDA3?vioaBc-sEa{HEjtmSN`?>!lvI6-E$sR$z z3=CCj3=9n|3=F@3LJcn%7)pT}UnMXwSj}Ky5HFasE6|34fl(*GC&U$~AdLuMXlSUV zrKPE-+cM)=Bsb-zy1FG;`ytxf|nTyFEbNgrp13;w)ozg?}k$^iFcoq>^Udab++@s zlV6V?y@(Ea5fl6(GT{Bpsn=h874JC1&~TEW?nL>v2Y)|(`nY`Y`&rZ8&z}D6#PPRZ zemCuToWJFM!It}ZoA2+s`TpO(e?Ncz{`T$1&!4}(fB*UI+s_|Ae*OOa=hv^_|Na48 z`1jABKRQ?-!Td^x|Ek5=9*Uw+I+wUi>y7lYFugQm=$n~C6 z=sPdlbFO;({kI>#-+uo2)%$PTG-~33;l*1L#At#rBmiC$nWnDn&cuyC{5Rc<$r(O3uY#`D$d+s)enS24? zw5pvOnNm}hPY~0Xz3JY6*#akrO)H9JCTQ*JzH?;$qW^P*Z?C+vzvVIOM8?MFi@pX` zvkP0ky!_zlxpgw!ca7w^nl4>F?J{4frD=syZ)aWT5^m<^pNc+p5z>;f()=?z#MPEB zOE+kZ%+0Gy6x_T;Mt_Y+*mZ-~(zl*nD|0ARkGpYK`)#rp`>n*EFC>bKr1TvYma;4o zZc1#5Xi1o9*6>)U>3LIyE?;b;vvf*^#^&7Jx?)1<7S`++|6gO@aaB(9#{-?2_s(lw zWMuB=@3cc78<%$A(SUaTiI01Ew8fY+_y2EXS;~~3 z%otaq@u|paaxU}9v`ZH^p7z|d$Y{ZdOV>jc9$rzLfRwl;U21Zr}1{XBSUZQBo%}>cptHiBgVd=S0 zpoZ|Okcg6?#Bzm#qWrYXoK%I9%7Rpd%z~0+28N0`k3aEn6ozSNobo??#`9?q1G6%> zUNX0^vat7L5oTcpmj;u=Da^{7LljQmxN_pinIkes*iScjEb!7}cqJ}a^2y0`D$oiB MPgg&ebxsLQ01VgO^8f$< literal 0 HcmV?d00001 diff --git a/docs/img/android-chrome-512x512.png b/docs/img/android-chrome-512x512.png new file mode 100644 index 0000000000000000000000000000000000000000..efcfa607f02177a2b07ac466750bc2a9ad66f1e9 GIT binary patch literal 8876 zcmdsccUY6lw*CYV*dl^kl%fI(3ep4x=|!a&6p#`+0R=>eGzlOzal73}mq?M0AjJTp zAfTayt%3?l2||<@K)geSywjd{m&oA$;BY!$Kf?fv^-bx_)0Sj>%%0!g^OKmB!{x!9fE zp|e`1KC}2TLTdp7HySXay0+Mo*rC0crMvPvco(z!8F@vspf0xYgC9%VnG1ld(t>8z zxXGT4a2x)ciObKX40JR`hr0aW#0o7%2bjmhwN{o+Mcr6EO~awaslGwaBe2luPt-CW ztkIJksy;P7H*F&F_&sL#d%Q%eb_n-#SPyBCc(~#SfM28aewTG)vig%AuG*g5>V^07 z9SyQzulH(&;QH_>v6armoRCrBgGkE4PPmjkZ^i;5)`rAz*Y6nzJKq_oa`Cg|a#^3$ zO-(j7&JO6K(|cSKwGS~H0MHA*$_!-msUTai#Y?{S65(r+L`S9&@^AgH8khd19QTuoEuj zydF#XMmiHuRDd0=1NO^0UF6O{Gd?;DkZ_l@!QNUPm!3^n(bGKb>Zt5Z(HbC=1iq}Z z!x<8GvrM=a={v!_I?HD(`}N?gtG#>-+T4aV;W!tV=&xdV|CsbuS9hpt&bzRWBKY~$ zgmpInI@L417TKv_{0`Ru(;tr1Jg%@po69qK@|g>`XlnUw9gNJ?7vEf{sa2gBrLTC2 z9dsVyE2F<*umgVa&5M9I0E>UG8e_Ji$83mGI{I5M7bnPLn(hU=V=cNTtSahfV(J&Y z6Zb&NnhP{Xi-mm#-%@MqO~|Wtx#oLmHMwE{yw8)9b*fu<7A?B@>+o%}NmblzEp~!( z&isWkT$_^xD&B{lG1;BF;UN{e7A=U-7(=Dr$O`b*HG*)_?^c#+n|YDwA^2A}qu~w) zxm^IL`Ta0EV6t(8rsFQqOW=VLJS#o?9cUeKy|eI`|C)6Y*f`<1y<4{ZZI0;)(RKmw zFs0sRex^+Zw{&Wm=oO~y@O*oeac-z_kZ%R!?p_(0VnN(d>OAtGndRbHAqnlHrt|L# zo>HFZQhSOaGHXnhDQ8F)) z7+6j~uMA5Cu6B@1+&u2hb;%yRevfh9n^!d#v!L5p_8P~k9PQApc&WQSVSN%mi_T@W z%C5W1*}XXVrZpe?Um ziM=6Ki~^m%umLty_$rOG zT#O@rvNZErn{#mgxvu`ea8QscGD!Jd;bNo1@dWHpK(1xLP|J;ttcJ9WwJF^mDmvq| z?y-AIxq=d&Qc0p>lSiE2Q=PSN4U8Sy{QhFx@4jH1Z)ch&H+-6pA^aMSL)WM6+n%hw zP|_;sY&HFiM{tF)I9A=b&_MILAi;Z?R?!l4jPTnd8O)pw*OVM74w4M1x4 z+gPM&mrKd#mldr&D$5)7LIoEaJK;B(i0;f}bVKOffyiK&`5aZI46)(yrM^g&n#?ri z(p^+EGi27b;7tuQ#$=Ed!q2C&mh2QJww8Bspswh(GtQ{7NG&Vs;&Ey@ITUSTH`QvS zlfTrO!n3}Sq_ol$CfZe(D}>a|LUxlFX>MUAn2C|6{j2Y6aV)w`-yMc}$`Y23xm1Pl zyI`I(HBVlr$)Ll{SDjaQ-a4<`tu(55^`dyK8t?ja`DCmO8fDoVN|(~P+a|W*Cp)y1 z>D$+(%c?G2$;PqdBba^qA}tmdms29G>r?3|cICC`*Yld>AQUtFLNUW!yYn#1%wsEf ze`uLD@Su2OkZ*2MY~$_%`P-IV)QUD$1KRUGkweI2*4ip|q(H1^gb!!CKq<6tIWJMb zxBhI;+{k4t7k+w?4e(#?oG(}_@LQ&HaiI25~nv=Q))<4LGvSn?0?@)x$g`V?=H^jm^H-9WZz|s=dIc^??C7V7h#Pz<9{NJis z9Nf^CLjCo(`F?oiBG~fx^Fcv?2ag~F<3Y1G-(a<0d#n!!$diTKROH+}+^`j(dP=0X z?lO=cbEG{-06l`h%Or|2DyO)zM(pi;KL@@!|6RGmP86zKy0Wsy8OZ}4X4j{+R`z1; zr8_L0NXixjEV(`i_p5#5LsehXcgpcCL!W-DLN6 zO}nz+?j}yTPj^(_OHqP!rB(1rF-`LA#TzmCT5AC|ftop|y+n#D%LHCpd-lctwgrfv zvrBCiD#$Mxj;IwZ4b}l_W5ZdxmkK)k79d3d+CGh&+l8YT3fI> zK;QhHR>yD_H5|H<9YQLX#l@T2^JZrJdjHvVDh zA7X+7wzKKO;{O2pKlQB_=7$ge{1*Q=xJ&zl0lw$z#UvjqRCNYqioHMhwg8xw4M z?G4Ozi(i@v1Jbl)W>Hr-+UvMOi5x~)LbyBr5dzd?E)o{eEvM~Lp@mZ1qw`CgP3A2* z@e5Rt>|W?lTVyY1d@#Dl@6No&H3V3Bsa{O*TNPg)2}I8L^j>q1US?1+3fN?v33#*+AXcutN1*QhSq9gruEf1A3Gz zy!JUBBHJpT`{;?y9ROvcwv}?`spe}4K)(>DEOf8(I3*li@*uM&YEG{~?I*uS(j!?m zImKn0cg8}%pmo;D-R{2JR87?E;B?N{Pl99~m#36UYXO6pp-8zh0De7;ynr-Bp{li$ zxhB^H@BwI(A?O)MSGL1r&J=QmU?v4!d9YqSyV$)91{=~A2}()h8|;8|IZ!csk*=^| z!3V(%)WZIBZ2!F4un8!TRo*TJ6(VRC{S#pRbRFM+m!Ln&f546$8wW(tkMf`E(+l6l z@E_%ON$?M#{S$uwd-XfmJ&JS#2?hB7^4M^Ddia03#HREKv+OU>Y)XbLLLtoI2prlL z=w02shA{^ux~Gdm#@O`)3@UrSpAZ{piU?u$D4X`$rzc3^+ba+^4-`luhqI)h!8FQ= zUPz0K7H__hYoU)g#XBqwk|2T=c>x%g9Ls_r^c0abxeX6eFFTj*Rw~j<@s(9-bxgij zm>K{do5LzTl%4BVfW*+Mohx}VQ+kCO6D$+Z5B?Oer9svGdbmJ zg@x_yqDRonV{ka)a`@fKvSi6epWlnt53XPBLV$HBj{-~s=_N!j^|9)zW1UyEz8Fm5 z3T+U21cGF5f4^-=jwig6(#E@P=udM2M}f`g34#<}FlCd_fDtmK4z8)!P$d2eZ&dmu z$=pfROGN58G`{GUPcb)?4E^^WPH?r`6BtQm`G*Pv>o_HN@sX6NVg!_nQyp#)J%2E= z{=f1zSjbWx-3d@<(xI zp;-?7Qp>J7ZI87tgC@-9gTe+$=J0B|%3>shtLi)Me2XM=?E+b|#3_4syHYvX6!&t{ zgOLUS14Dv2o&}>Vq5iNC@|utVw2Q2XtGivkWc03=$L}ce>w`-o#m)Jh;b4U& z4WRsXhD$S3-ijJ8Ss-^tS!ATLSF|P~m8IAxDh~$p>FHY^pafDbR-K#;xvT8d8>7`x zbDaCKJNVX*(K&)$U2sI9;CVq%La!xYut#)Y;U)rj+nTWKGi6LH)v1>rl~@TBK5!(_I3h7iA5ysmM-J$Ka9Jk?X(9lxg*CE!kb9(t*P4|Gq=wBpnU zbU$YFZUcD^Gg>`YwQdENs`{L@5muno9A_V9HdXyh9_GcScu;CZc&?N04@rKL2IUU=; zc$8XAlqF&|giHcZUb@@C6Hj)J{(OfK3GfT@7y`pdFi#cX5;)Inpt{`h@8kn{JM*P2 zQr(GDMK(@&C^?J#qkOxbnE19pA4gV>clXAsnb5f!?%#_w*gsZJkWBqF0||3K6e|Q< z=v3rZ{ZG0;)wPI@H3(T^g9#lKyVO_e1DO)PgzW%O91=zBFrF-Spm8{%JpWY*QAVA* z-i&W3DRQ?Hd(2Xw<^!E5LnNVuDAJ>X7(8o*l4oi=u%Hxkk4u)cHW>R5D6(5#JvD3` z^4;-%nK;?7oeiI)&jbCaQ_E>{x8W@2nghq8IQST{BON*lZ0qWSpviHe`KFG9O=UN2)@8{}rwGm;m)b+z!Y z?g0?tHr!xio;;)D8K(FiKS?>?YuHEMcR0cO$nIp&6r*HeZbc+U)+?FbowC%1a&hH)zyZeza@QeI|-8${g!X>ry{dZp60W@NrpzNDH^~0&++cz0@ za1E-nzZZo6IPm}H4jOOn)WA$!MK;XzfyJG*FyYyuUh&$ke?d_^G8R#>1(8RCrr%{? z7|4J!{iW80d0eXcXh(4%rDI_3$?g7Nihu6tQ>`zvoPIj>sVrv^Qu;mvFfQ&IH=_kZ zGjF~vKr~}N0{b%}ui*3h8f^~HwA*!u`2U4#{v{dx`yC*i0naDKCM`^!#4YsL z%mJX$2t=woXxZfXnT{#~nQ3WAz&6AQEBVj^pSq$BYTW#Te z8-MSOf{piO%WIeGH`-KvCUql6q*jVq-;nDqTsh}*9x87E?RyY;*AKYP4LKA>GG~uW zb~G+nPE22WoaW6SnAoUAutw5h`#|?jo1+oK>lFjUICkLlxbR>hvwmZ-)@LHtnXI6F z{FdnJ!uN7CHrmxawiD5JeXdRYeTpPY(TB22bSNv#$N7;&w#*pdwG-D)?}V}@#* zLeudewz$-0R?m&kcICLaextb-qbuet#9%ngQ~;=kro0pR<{ij0_cofx8cS^+m=vCg zPX3^|CBQ-Lh>2G^EoI~PI)$m+HOf#-jnX*KdkMkw>Wpz&ml5uh5@Wk-#6qlY=dA7> zV%9qc)M}wS&t$83Z^g#U&XssRt-Ga(yiZoR@H~28T$-7NLF9xC6s!~mJN3>|53T$@ ze=?r-U{bBMJSXzPJ-8F;cwQK!DR3k5o?BP@`3g-5=JsR4)W#OI*6CshFqQ~9cM2GR z@#`CFm0!CQfY}bnroT-5eqpqo3%JI`Da}~n;0i;IgfRKMY-j~f$!HF|w7pOKlqF^h z;D@hc@=In%s#g)>F>(3Qgn(;VH@U#LJhLIA<#pfbq9J+w_j$^yue9&OLT@@=)YD9? z&OTB>=L0ZhW8EUO$@%9XqO4IWmB$IyHH^DjFcqOkcyY9)gb4jO-e(34^Z^pBb=lsud4PNFH7IwEI7Woq~Bsk>jeWLwlTwJ4_ymP_;+`6Y_ zHqu~&>e+Na_`0i1ltAGob075P8`BTn2`I|e87(p~#wO2G_2A1TD^vl=Cwa{CNFU20 zkqyQ>P`#_fTcS|jd@wDAY%66|I`$TJN&AMWN%dv|arrS6MY%T|?FU1Ryq!?wnvyfNL5L?XP6#$ZG0`Ww9f!+GLiZfaVVHnpQAAs(jfXWo3CA#268!(3g zj&eo22_|9coj3IA7dKxAj^%r1U95tMFv?Y}&aYn|Qs;}(Fre3N&&15gBdELJg1aZO zZd?QSWAJ&0Zhts2Eheg9$gDyK18eJS_|Oc~F_=92q{yVF!nZB8a%Rh=e8Jf;OE*c6 zWDQ+5x$*corSObqjB6>a)}wDASEl0_FK2pw2}@TRG&S4%F2lUgNL!uAwi=J}54{|~ z^QoermZ(hI&rl(&rEE>c z8HY&WAvUoFcVW)swcCEonLpx>Ak5Eu!QdzLF%-4BwbI(o`bxWOhvlYj{HjQ6h38+) z0qt8UhcZvjFcsvYZ8>AN2c{toMyFH=k*8H^{3J=o zQ7>ogK9t*bsnRhuwE^|jh{10^wOIRWb-LWTFNcxeT^MsA#6hke2H*MPgBQ13i2ej$ zAGK9}3uBICS$3<1kn0DJwd`&D;F#lKOi(1fa1aC55Z5`yFkWa6fvHa-5!ySWC@H|S zJzD-(@UYOjx!=B25(zURpVf4}a7Ue+qi)#=dSRHBda$)ppCYqEp$<`B0l;Nh30LfU z25*eumkWR(8zdbvC^2gdoIS zwqJhVKJCHVF#SvRE}Q6L*Et^;;GHN6``zrOtArQKgNGBpM>2R2&?V5U>X`SZr+?D< zfb_D)bt%WgEJ&?d@cS}fY%uS@)g9!+pse`U(Lw7yu2xi2m=f-bgt4^C_3QlSrcBp$ zf@B6S0o&YJXQyQGmhlRb@{%S8O(Yp&AA^-SwETFRib`2CgRyU` z<>oY&>P}h^!`PcNoUDSHRMl*cR* z^9EE<6`I-j8wt6bYS_o@F4$o15^Ql^#aD-e@$WF& zCxjK`&daW^HcAY#xU?fvRaASBQt+39SOZ(E+j*?JhU*n~_yLY8DyhmVs>>@WS}7gZ vP(G@md`wpHsD`3qr*zQ7-wp8gb@RL!@;?u_8`zG50|3&%RR6(AmtXz^2HX=a literal 0 HcmV?d00001 diff --git a/docs/img/android-chrome-72x72.png b/docs/img/android-chrome-72x72.png new file mode 100644 index 0000000000000000000000000000000000000000..203309ff179f15bf4517b76d71bea91ebb5291aa GIT binary patch literal 1301 zcmah{X;4#V6#ddD!~|JJqaBwKi%M7)vba>N zVi6UIGPo3JMNqLrM}%4ukU~H}2%9yK1xh54}5|X$W>s^!BTn+%jO#ny=0Dv(` zq6Xju6##7l072ydtjxOcJbF6-xbsoFd7;=q>i>aGr+avKxVyUt1O#|{d;9zQdwP0O zD3m>WqF5|eSXda7$yBK()oS(Blv<@ySuBXnWpE02pi_L09Q5$SQVT%<(Pz)v$WVKos7EB8Z zW}^`c$ZUqqW=up81c4xn*#yn#jk;OmwB86qaC86k&hp+ZR~1{z6t`ZfATwlv;A^e# zfmjCeWtnx#%%7CivPojT-2RMwah~k!#!=V|ssCDN>eDs!Xd4yU28H&CLOZ50%;*=A zv3ocOxREgchqog*tlsFpgB$DXy?!62;|@oJG1uzw$1Y)wy&#+uYCo}r=qnZMoXdtE zh?O-X1zj5y(>Pk^Jk-5AHE6ba2lEOcBk@}B%buc>B(9XdJST zYRD=szi|_vAewM_q&F|&5Vmum%Cbn>ABRryxfd#ap14a2zFa~kq#d~GxXUi2cw@nZ zQZIR8dQ%2O-z#myXJiyp70N)inOzZWgDYI3jMjnloI!P?R0oK5Y}yLp)<0)btZ zC^kJJu*6vLyZOp~-Zp>dqMt*7peNAh>^v^|$z&&M#rYS(jUiNdX~;pR z62jJNgxdwTN7gn@xtNHWA|hESRbGEum($~`w@FRwc8apULFdXoZFn|+^z9qd&23kF zZGj&{Evw3r>ug)oX5S%USMBlz X+LbPXIfj23wgQBQMl$Od3Hg5m+V6jB literal 0 HcmV?d00001 diff --git a/docs/img/android-chrome-96x96.png b/docs/img/android-chrome-96x96.png new file mode 100644 index 0000000000000000000000000000000000000000..6d0977a5c062b55cb472863881fec94a8db30346 GIT binary patch literal 1568 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 Gh5rCBCbC`t literal 0 HcmV?d00001 diff --git a/docs/img/apple-touch-icon-152x152.png b/docs/img/apple-touch-icon-152x152.png new file mode 100644 index 0000000000000000000000000000000000000000..26397cfe917d816bf3d40c6239b27ae249176935 GIT binary patch literal 1329 zcmZ`(Sx}Q_6#Xo12?VCtpr}O~8zl$<64nNTmaP&)kR=G!ff@r?5Qi;9LqQ|8iJ}P( z6bA*Q%ZzA)5*5WkSu_YlmPA1|v6PlT7J-_L{C^f29{bQUbMKjRXU@3~cjjJ*kK5<$ zxWy3w;7pE*O0;q9S|RLg-OpWyveAdf!l~f^+^s~K=^xoNnh}#o1)#(O0M0o8VB3hJ z0H7ETfa(YUp|$|G{QC9;5&-Km<6~*jv$F~!k?7&!fyH7yJv}iPOjuZ$x3@PAha-_l zUS3{z@7`}&gGeZBHX7m8)m4+pys`qpu*nL+7NgN>GFz>yu*qUmdP%>6U94agE)*B2 z&i`mqD$N#ab=Mr_+G|SP>)5*2>Pr<12dRoQnlgc$?PnbvUA%ThTz9(xzz136sBqe;sl_Q}(#Thv`U+fKmpyJ@t4JZbwv=E- zkw*DUA<#hGHQow%dRt(<~@EZ(F?nGmIXV!8Mn8kuR-?m#*pR7 z#}9WP--JHmPjYV2EeHxW*CYtfauBnYriOA4+!I}TJ`}g{O6Dg6+XqKQ9j2p(kg*2y z*_%(Qb0%a@BNKR)?#|;#G3GbMalXLG?UmDRRw+ryK1Cp<4&7;$=>|2}b4 ze!+Vdo}(#qXxTaU2I%8fZd!=n;HA9WhU4$J>&GW#LlZ59@YrI02R>k9NK#C|U^}Xj zaq=^D+#cVzM8k{=S9H0o1r_p3J*yU*arL@uCoA=`9PNdmgvD;!l0{xGL!E8fIzQ=d z-nLDIP&bGi#SivUT!OJ*X0(dyyE8Y7;JQb*s%NGk*OSyhC2DB61OlMs&V6#WgvF}`Njf{8 z)U4FoC;qr8;#D5ncD&{#*N4Q0-!(4yrH}C)4wvfNM>X?{zY^)o6^oHY%X`tecDyok zYwL8Y4jL#Y(Dg0e!kKHGtHy5vJaC7F(zemZq&}QP^LcuCwO6uWJpOm6f`T1Ps(K>C zc?x94{W5D%+J<=dJfpTDd8abLv*tanN+jYZni$_3!uCE3E}8J-O15m+fn56;Ysl$Z z7tubt`6;Jy?Vs#qMyE0}=*-MeMq#FnfIprP;)5sp5b!iYaA=@^XduBG?;ncC?`u2O z{U5`Lyo~HD_Wv7#RWqeFLrMuPm6=FCiOw&~%gWBpL^Ij>ndt0%CIf&|^?z%e5CsQ4 zJzpFc7$nORfgJ|v%Rr(qC`z@f9SR-A2^448VeZq=0~4eDJ%c^&J@x~fn4kCi0+ri( UrY0h&#wvq7rWt=ssI20 literal 0 HcmV?d00001 diff --git a/docs/img/apple-touch-icon-180x180.png b/docs/img/apple-touch-icon-180x180.png new file mode 100644 index 0000000000000000000000000000000000000000..bacb2146d68563d925a2ac268e60df36687e3c0e GIT binary patch literal 1479 zcmZ`%do(^(!%5M1_lO(hK48<3Wvj4 zSXk)m>m!lK{QQE<%q;k%rKNMZkXS4h2!!kFd`Qwt9Z<})+qGw(0tKY+&R zi)(`1W=2fqSZpOdwsI`7di=}8DuZY}>q?wkuqbY;3bGjBw1ibUxRlOVAJ#JA(Jd)Ijzv!@-I?oJtvQy{htm($Dga?5C( z#KSHA#`4SZsgn+jQ^cjR(x(1JjU?)>xOO@C-fWMk7!`>&H~DMB<#5{Wk8>ZX{_hgMhDxm^C*8kfg|Ha9onHlHsL3OCs7bq>7an4ASV`$fvc@QF7q(|NE$rml&_fNS_ns5l+}+lMh-Xk(X(>U5*?BWH4|lLc zF)|vPasFNPtH#O-U#dZ(flGz^=ukn;d`eFjeedYJNz!m#Ii@bsj#&3*xVAO+X~e?9 zBBJIpuaKS?9nHNpd~@7$fqBd;j6Shn&_+w`5m_;3g5`>#D;eHeVaxggeiBnrZ|avK z)t}X`jNALJEYz(XtzFS(!#>;?ZK-aPM3-^qa<>lI?<<)k5wsEM@cA@F`jt1V- z9ed4=*-z6v+%m2^JzPwlFvD{)&A2Sv68L6Et6zJoa8g zoc&5pj&z1*oTj&9?V%p0!@`ozz-X$U;JsS|8+tPMX z^X&?EKSnHg1iX#1>r-#9@2GWuK|6M)LGg@n4Gp!l zv@|s}jf{-6wY7D0bk?q2w`R?n)vH(k{rmU-|NsB~{rhp_`lpTSK5tt8^VZD=?|w`@ z{(REW=M#=R+jaB(zyJUL{{8o1!Q2;-0WV^LKQ39g>f#&bhLa3HRCmIE@r~bq{{8#= z@6)=~FSC+g<)-eq@m{I_yj=fz`Tq0Lz2`DE-23zQ-`_7^em{Hm_v_d1zyCgb_v69a zANSvWfBWV4zkmOK{`~d*`_CUge*OCO`}glZ-@g6$_6^AW`RC8ypFe*7`2O?r*B{rP ze!B4J;5|X-AZBHXIV>EmhoLrfim{yi|Z$pfRK3A%^uI~CD`}XhJmREJY_pE<(Ms<4l zjoa=4l@I=e{88eokLT8E4&ZH0UBNt!Wwl_6)xxxZmw~4II);z6beK+Sd~K-<{Io^& zXd~CM`VFEf+S7#&t6t4vt&5uD;~2O3$&{-3Jx7dMGQXcpewmT;Pv5(((`Ui|xrweT z%+6kWAYUJ0ZDnWa`*B@JR{C@C>EV06e){!nTipKL{()iga`WfK$3_49rpjC+d~d02 zcEeIRdP`(kYX@0Ff`XS zu+%j)2r)FXGBL6;G1N9NvNAAm-<}Q%euReH{FKbJO57UEUfr(&Y6!0ii6{w5ELSKf z%1_J8NmVGREJ#(zEGS84V5pe$_!AFDVVH)-DgV=FJf8+JFe`KGC36ca3wuu%VHQ?! zX)rmQ!mPYGMB(&}D<_VeIU;j}{d9xJ0xvy=SK@*tpPWpm01boFyt=akR{0Jn+A ADF6Tf literal 0 HcmV?d00001 diff --git a/docs/img/apple-touch-icon-60x60.png b/docs/img/apple-touch-icon-60x60.png new file mode 100644 index 0000000000000000000000000000000000000000..58140442482194b4273b7e8723408df70449f040 GIT binary patch literal 939 zcmeAS@N?(olHy`uVBq!ia0vp^HXzKw3=&b&bO2H;>5jgR3=A9lx&I`x0{IHb9znhg z3{`3j3=J&|48MRv4KElNN(~qoUL`OvSj}Ky5HFasD-dW9qj-Q%i0i|LFANP0wY0P} zH8l+k4Aj-tr%jtaWy+MvlPCZE`}hC<|9}7f`}61T@7J$>T)y<<^2ML`?t+B={lD?@ z+mU-8kKX@yL|-efs(1=hv@4LYLlPZalf{%!`yYw|U!6 z3wE3l?L4#o;;XwaKcBew{^Y&)r|-Xi^YPn{??5Ad_MNwL1BM-AlDE4HSH^`eVL%Rh ziKnkC`$JAH0WD3ZdE(1}(t4gQjv*e$-(F1*ZZ?oOP`E`e>rVBxy(_PUw(obJ-~F^>`E{51Hf7yvzn&WY zs(gMRAt|FGr6i}uX~vvQ9m~_xT6g|zJ$mWVrVX321lO<4=a?OR+j@8PynuV#JNUKQ zou0n<@nlPtTF80bq}h#%@$4%fGYCuY8Fj_3dYoozAa+Q?!hnyN{aC3{cWJ+Gg9NM9 z)}CprBow2V7jSgM_9e>PNL0MY+w*doSD{qzHOmm6Q|k3rd`gySLaVoFm`UDnjm=nM z6FNQo?6a?Db65R%x9?3QfB)AI!^*0>t#NU0lc&YhSLbiHx7)uad6v%>!Q&er^;#}F zFmVab9}$DB&&B5dC4QV>DJ|L=|A{y5**m@t!=qWiz*H@9jVMV;EJ?LWE=mPb3`Pcq z=DG%!x`qZJhGteKMph<<+6G2e1_tii(+{9%$jwj5OsmAL!R*!j8lZ;os*s41pu}>8 zf};Gi%$!t(lFEWqh0KDIWCn(cIgdZ_a1@4VXq@stea7=?5CgL^w_Y;0u(GiCWD#az z1(ybs!zs+ln?n>%-?(z($eANDN7zp{cr5VJV|XPlSn|oqbSlsa22WQ%mvv4FO#rLD B$prua literal 0 HcmV?d00001 diff --git a/docs/img/apple-touch-icon-72x72.png b/docs/img/apple-touch-icon-72x72.png new file mode 100644 index 0000000000000000000000000000000000000000..59c9522568b25832c54f63ce90cc6d46e18ce065 GIT binary patch literal 1076 zcmZ{he=ys37{@=Vy=2UeF+Vz+SkCIlSg2Cr){>+|tIOg?nGW%@jFBu(X>W;?ie9k} z*K(MgZ8p34QQOSgO@~!U2&z2+k#Ug#3^dpxj3cPVWyR3r0H}Bu0B#ikFk0d& z04OB@u#*7*@eTkkC2hZd6aj!0jdm`9B9$tFf`WW}e0+U) z$>egmR4PLd^TEM^*=$A-#PnjvFe^69i4F6!h)QL#96VL%MFpn-v|_G zNeV{FR{90aZ@=mxgxa};t(vl}7TQz`adk6Kwsgw&7DXz3J3Uc-w@+(8!dn&qcM|X> zLFMG@HKJL$Mm;#N%`DjYyl9(MsQY`&2%9hUO5SUnd%t-;plP1e{$y>}V1Xb+skE3( zS|jpO3#;@di^T%NCY{cx*BcE6$ZWP4jj&!1L68Z8V3P?k8X?FCX>~^Fj#i@3Z0+e_ zBP?7~5*p_`>&5Rhh&}3NQoEN`Y6A?xe=P0VR!srkRM_qLT@^YJdbqmhadXC@M&!U3 zy>?xAu5)ouZP?cs#Ota_iE?sH`D{~dk8g8Dk8YKDHkxdw|Cymf1%^$HqhO@3*x38} zM0L1)hqk|)9a3;X=p|5Z|F7!*U$L1ib&vN&z2g5!|59S zHgUgWR*UVa4(;$gIezMSQ{}!c# zKbsn#dDZEmJN3?Zx&7|KPl+r(^9+lpS^VnJ4`J|-eJty(Td>$w;QBm2YqX}MQ%{N-DlcLzpX&ho#>`FR5dg545{EA?A8KMM~ zm6sNUHjNDXJJ|^CnK1VR6Wv>x`y0CH&-nK_O;a25$8Hch)y1s>RY7lO)R$b^sPUaPd@kR7GUTjJ-JDb7IA!f01P=FvpV5mPK z%s-Hj5Ew!X4k88z`VoSN1VZ#s-h=-bii)%IbIbqV5VG_9Dr&e;k&w)$Gs{VJB3QO@``y|HNBg>N;pZ%T5$%b^>3kjljYj|wUk3m| zC9xiWixdDh3jknt0YDH+$Ic`IfGIkik(H{|>S;6@nM{s~iXxFnbUHmcIyxpMCM6|> z!C=J4$7?iCP|VJ1oKBa=<8irMPN&liL5{60$ClAyG`cJnhts`jMhttfeh)TT9d3`u zJTh#kE;H0r8mh~8I$GTbqF6G;wrj|3nm1c#GX{P)?jt5?w?2<=5M&$9Wg4&4yXmx)0oz5fvUgzliH!7-+V&v)ZA9Nyh}|4CYBa z0-v+*H6Dm!JRdjN6NP_B)7yyN>=1JzoZ(v`SH6Dam)G7M`nH1?7Mq>_P}UZ5mtCd! zq098;C(ftwoa%#YtA8^mv(`^AbpKwjUcbeDmNd>0cz~cvSkV<4cJQ6`z;@NV1uv-j z@PoeGT+27NbiqXzV;>OmRu>PCj@HfYtR$Zo)~g8Xy)yhpXnSz*@wwiju{&=M=5K^9 z%8T(~EK+30a^=@85fY3_`4^@jVR9~rx)4gEv{VXrKn}sTE=I!hj=-q!dawEZeeD#5 zr{Cb5x)ZLxbQAFjGW^U|x#MJmh2c$PSxL5B=2Bc)`nv=8*Q@g7W9rdu2aZuRvp!c#>%QF3Tt-k!!)r{d$;k$+P{BVW9d5<8tndLN z4X-%U%`Cx9F|SLPn-19I)WfU*clTShUdwR6R|&V#x4a=r%@vgtib|Qq7fMkAGzygw zOG${OQnIK=nRFVHPK~C}m=sFdkL3^kW2mkvsVr;wf5Xwu)yt?Mr!gy6#4oHP3NO@@ zRaTV}MGeAIVx>@23_!hf-Hi7>pG_jooKipL>i7T~=@(b*7Z@3MqCE&3NaTp=6D8Ql q@3V;N#rY}KV^xF-rxvI8ACCi@gjYmnc6=wg0&r7La)#Ljl79fRDIXyK literal 0 HcmV?d00001 diff --git a/docs/img/apple-touch-icon.png b/docs/img/apple-touch-icon.png new file mode 100644 index 0000000000000000000000000000000000000000..75218221376ba86942e10cfb2dd0736c55992fa8 GIT binary patch literal 1380 zcmZ`%dojpng@`FC*KWFK z<#ODzosheXOKdLVGBLxrjJf{iy1)Hn_niG>zw>_2d*1gw&-Y zdwY8e3kw7SQBY8rlamXd%*-sI5K=0Y5{XnG5JQkeAP`CB<~R=umvXX~a_(>n?nBdz zWu7Fzg_%$_MX6#?s-~zl)1PM6nM9`rZ{k;yGy7(GY5Rg|TnD(;3F13EAB;d!IXjiQ zaKeKf=*xL3W@|cGD~# z9*JeEFDmAaxigOwSIWzphnI~~dbTHaX~A*5E2eT%E>|eTV$sNmptn~zJR}#1WOBvW zJilvVt!skY&sbj*rbSESvY!?S7EZp+f0&qYW;v3B@94h_R** z%SrA=-Rxs7@-1)nxzYyvCRR#5FpEDh%iF%Lt??6dsTla@Hk@&Fa@5(@bczNSYEdrk z1htv1>e_qvj^8_C0DwxbizA-=+n43>g~%cFw;fyu)jZ8iU3||J$*ZR*DBpc-D8n-K z@l}iRS8qk)rUpdFmo}6Ex4a_)qWIT7vo7Y@cqxl zvroURdD&D|8PtQMBE2eoC&vnFm(mCN7<(p{tW(D8D=_u3uEhG+<8>XBCovq(vPSJi zQ4xb0A1_QDzdjwnVI2;PWX$Z9bkZ{h;R6K+_HelD<>@II_*LE z#@{eL?rc(cm9SBtb*S_SyQauVhL6G?7Ts#QaBlB2A1sBJ;a-j`myr)u%+^}sdq-oyDznj z4(;#@J<1P;wHiE1k8g|+igQ!`Y`y=cl@Ur&(qHhR-dCFpt`Ie{?gHX77y9;|0@tFQ zk2E;`p>N_`hYY(Ky6b$O(+{6))H!KQYH9aQdi=STdj3N-_aQ>%;vYR*&po|UmpHF+ z0e(Q8RqXJKacKB5`7~8eTD_kv@^2fxL?&bZbsX%yQm@rr+y+GF#BLidY<1Hpf=|@B zz^EYGv%dzx31HAx)+n?M$_h=k+HZ@+z=1?#Y|-ee{uICe5W>RGg`AK5e}bAy`wUC~ NE`+0wl@0;Pe*x$E!fF5j literal 0 HcmV?d00001 diff --git a/docs/img/browserconfig.xml b/docs/img/browserconfig.xml new file mode 100644 index 0000000..7ebe71a --- /dev/null +++ b/docs/img/browserconfig.xml @@ -0,0 +1,12 @@ + + + + + + + + + #e1e1e8 + + + diff --git a/docs/img/favicon-16x16.png b/docs/img/favicon-16x16.png new file mode 100644 index 0000000000000000000000000000000000000000..36a756b15c29e17c6b5545d78d53048bdde7b839 GIT binary patch literal 612 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!63?wyl`GbKJOS+@4BLl<6e(pbstU$g(vPY0F z14ES>14Ba#1H&(%P{RubhEf9thF1v;3|2E37{m+a>H#b)| zcXu~e7Z;ZY4;})+gM0VxojHB?#PK_~?;g5%Ywx+6hcDi`eeeFifB*jf|NrOR+Yi0% z@9N4w_O?I1|14nT9kV&tf>z#s^x?*udOfBydY^XL2bpFe;8`VTby@4wGqe_Va`>B`ej zpS}PU{d)NNi|>-_9*eHsdHETr=gYUBcVB(E^XkjzuRs6(0b2I=LQMBupm!LPyxm;{ zA8obW1>~@oc>21sKjh>R(9*g+-Ax84G|$t;F+}2W>Y3|eO$Iy-4;NSzT(f<2=%Pqg z;rpY%?Wd-$nDe;&>YwGD4T7FagWED^NuGG-RJl4q)cdKIXoPM^zDe|3zwOuAj|E8c zxIgZ+oqJaNfTsYbW8dQmuXoAJh*9%cR=1b2Az>lon zg&G}a%eHT~4==Tl@qd2$tN4Z8cjf&B&&x4AI{kfTkK#VYvMWkAr+lvlMjV4`iEBhj zN@7W>RdP`(kYX@0Ff`XSu+%j)2r)FXGBE-oZ381K1B0^o+E^3~x%nxXX_dG&urnQf Q2-Lvf>FVdQ&MBb@072a^J^%m! literal 0 HcmV?d00001 diff --git a/docs/img/favicon-194x194.png b/docs/img/favicon-194x194.png new file mode 100644 index 0000000000000000000000000000000000000000..ff2186e32592a23febdd5f127faca9e1c5be30cc GIT binary patch literal 2017 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 literal 0 HcmV?d00001 diff --git a/docs/img/favicon.ico b/docs/img/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..b8435c6e36efcdaa80ce3073b89446a468a4c584 GIT binary patch literal 7406 zcmeHM`BRif8h#LuQ5+Zqff?me&<_xX0Y(r8F~R^*G!s!YBZ`{AsEN6c-%^!Sp|5KHXpU z+h14r^9~S$SQHn7atZzv59|hzl@+K<05d(4$^7*TYk+rC0f9Kw1ZOC*b{y;d8UKy( zmyNwnbi5Ofv7Udx<#eK|vJ!5}%@!vL3JPGM+%aZ@(P%{HhjI)Jx#4&)jp@NV==>lV z&e>Vy<>jH{-Hqt!?uOUvL)-ab>dOUNp9?oXD?}gV4+j5@vF^X%-hc}~n>+Ae_%3c; zEymQ45nZ2Tq4P=_wX@^e+rYmlm6Vha|F4*vn}d(i&8sS0c)^aDkzP#MEqLx_JF2Uz z;qiFjrF7#nC0Y%`==vxVrzoHO$%5(8KDb>jn%@SDo4!L|zYEiLE1V7o^7HdCFi7>$ zei(at(DsZSj+q$-ORoThZ=5BuTs`7mMW#IZIzS}0j&D4?n+ z)<*>cpFHZ{U;l-FxJZ41;dnu+{%qRi1cu9*=SBIa z_qU$nD1}~eE{Bei+}xbFCq(%hn>X)g*shc7&t@Ln#&GbN^`iXbnza&!wObqYM|WrV zah}FcXKFMsJhmY!BsE=nE($1DA6XX_5_cr-jRtj(esfxB`Ty_$)2UgM_E8Gy)YVi8 zBA`=mUM+%i+>EX(DWsL+xki2Q^-10kQZk!+DQ|dagOqzE!RkM6~Qq*iJF=k3=Fur{(R|;Q49@}?j5&b znDU_JG@H%D@es#Hx-%6PtBvbT4{1*4%mc17onxf!-jm{m*XaE|FKNcRu-PocPs8mm zOGA1ys5NKD%v@^*b>;x+%sXFcNGD#$^oRxLE{))6N=#?EJwEs-_fXz>B^i_bw@A~{ zct~q9y?Oo9ZS*eExFc4sD`{hp)=ua8@;c>8rIPf$g?v~{y815paf;e|apr=ZYt3Q1 z7j{Z!lPS0wEBT5CeiaY2>LOyhuBj=bSp*qm(>3MOaaUMXRmji1`9Jw&&!9)Up4hM{ zb=`a$uQg}rnkAB|$7+roU7K9Bn4t69H$oYED4|-+E_v#4xqRQ2#b$}WJ-vajz+BGi z0eg9V&LR{rLa=>K(<11?+Dn$Om$x=A^m21+pnv8cQILPQe?^&NT_UmtO^ zt~sziBHc?Q{`COVS0T0^!gdk6wP3&QbZjk0;=ybJgYY!a;Wtld%_rLoSM= zyXX$%K>s}_Kbt$gH}iA(hp!t^U#~?2B^GmLv1WFbTg*m&Mtj{(ey?y*4Ez4T9g2NZ zzti{e&+kmoYPEFU+bDKyMt9er`Mtz!w$k};qWj2n=-$%M&;aANM=17fqxii8Km2hw zwK4I#&e*tz_`P`J&2jYH{5y~1v%A%g-y9;lm*z8xK}$ch^$leI8~@Ls_gfv0i{Gah zzs+jp?pXO*@xbrV0|^OR0V(~9#6c=wvm;lvMy~cllOQA)?3TqO1?p-+kguxQlD_L< zU9FaGkLB@!1VK%9N_0=>U}dRBEe}DhNKi`sCxHJ~s+1~%U9nstU07EN;e3Jka)m-J zSH#7|Day*qq)H`wclp{48`tkDO3hAFZssUnT~e{9x-fqo51VIY<-}*iORBb&rsQS% Rk+>-_v$C>s@Bg~y{{i(cN6i2L literal 0 HcmV?d00001 diff --git a/docs/img/manifest.json b/docs/img/manifest.json new file mode 100644 index 0000000..e85909a --- /dev/null +++ b/docs/img/manifest.json @@ -0,0 +1,53 @@ +{ + "name": "Flask API", + "icons": [ + { + "src": "./img/android-chrome-36x36.png", + "sizes": "36x36", + "type": "image/png" + }, + { + "src": "./img/android-chrome-48x48.png", + "sizes": "48x48", + "type": "image/png" + }, + { + "src": "./img/android-chrome-72x72.png", + "sizes": "72x72", + "type": "image/png" + }, + { + "src": "./img/android-chrome-96x96.png", + "sizes": "96x96", + "type": "image/png" + }, + { + "src": "./img/android-chrome-144x144.png", + "sizes": "144x144", + "type": "image/png" + }, + { + "src": "./img/android-chrome-192x192.png", + "sizes": "192x192", + "type": "image/png" + }, + { + "src": "./img/android-chrome-256x256.png", + "sizes": "256x256", + "type": "image/png" + }, + { + "src": "./img/android-chrome-384x384.png", + "sizes": "384x384", + "type": "image/png" + }, + { + "src": "./img/android-chrome-512x512.png", + "sizes": "512x512", + "type": "image/png" + } + ], + "theme_color": "#e1e1e8", + "background_color": "#e1e1e8", + "display": "standalone" +} \ No newline at end of file diff --git a/docs/img/mstile-144x144.png b/docs/img/mstile-144x144.png new file mode 100644 index 0000000000000000000000000000000000000000..d7cae806d10df4f3d492dc91c394468e67ce04de GIT binary patch literal 1697 zcmZ{jX;c$d7RMh32?;VHU~LskAb=^mNP&X2#6T7yY*K|5EFna2fJ!Bx1aKfgTd@{8 zxQ#|lJ7rwP5k$1?Y6xUQ2?Z<2RuT|M0@-&6P3PNun0M~G|M%`WzkAQU=e=`D2{=di zPB;L-k${g$v1;R=+a6-|!mG~pRFHF(yp8XE$7(LIGDzfWrfi+KdgrlgVf@=#4L@R=<5TQ`ItcXJA30(o0sgn1*3cHV7&>TgnC>@D_~*@TnE-sS_kz9C1 zZ&kC4suhLKV%gB^4XdlFg?D@+tZ%|5I}R7)T;5Y)Jp(9}K#YaX!Qf85zLQt5ZU8{y z2{Gu@GjCQV^~IyXuF#^xa7qn%k1SIcSpHa+d3>Tf+GX+{`F821W(wxV@7iz^;;nV! z5E;Jj;@Hc>EVJeE%?CzC&gY4jJ?$a)&hVpuqzSXWPdV(Jy0seHK}Xnripa}*5qvWw zLES+haOkv(BB+kqZ;lHlf{m&0v@gs=9rTEaMO*XH`DkntkkDndP++F!u$+tAmt5<*e z%nkM4cxAs@6*ayJv~%^`u^A3s*cRIzkp!zj*skAZN_XEV z>$HK_&-9c`-iSKwfgUN>yHh*WisU_rJ7#55&lj#A9;p1y#zDe!u_oHEqgg!N$F$DQ zu9aF7u_5Z@ESk=`t9Pe;5;3EO#FT=tNNms&~pC%E{}ImKaa;eiTlsP zjr-){++@}1W?~%jd0}U3Q+&kcvA*7H_Mx4aum1Ll9twMAZAI(Op7^2V7ORCj%iWf{ zl-S0(J#=d=(tp&lE7$ApEtF3l()!iBsj+F)91@ihNj^of3J3|_8y*n+QNZ5d)V*Pm zp&?fD3l5144lezoGV_0c!jm~Cj+gy^0J>>l&I%l*rKV9+NT(4+r%oO}Q9waZ%Zez7 z6Gc=q0B0Ct)fW4&j-XKdM8ObYAq7B?4uNC`7o*AZB*644=-6u077g+%!7kj^gjS&F;gr6 literal 0 HcmV?d00001 diff --git a/docs/img/mstile-150x150.png b/docs/img/mstile-150x150.png new file mode 100644 index 0000000000000000000000000000000000000000..12115a454729301eaff902611415a3598a8570b2 GIT binary patch literal 1615 zcmah}3pCVO7{4kjl-9O-Eya553F8c#G73Ah7$V~_qLngHNK!N28YHD{oe6D2NGnuZ zwo+Rwm9kbdrkGiIjcCG%8N)q=j_=%XV3o5z2|$J@AuvBckem(+wd^-O0x}S z0DzUjLH>~d7+Dzh@}*D)lVMs7nPthyT}S}h&YNp+#!zgV7!)_zvd6xlybfV>xgNChV- z8;WWDERk$rU^*JZ!Nqd+MYEFN^0>!=H6b+QpOo-Hn3?3&Th7*sCt{>v; z!)o{fZ2iy!22VabJQW!_w)wEM{O}jZaf-Cy6vqU{Y*xRcP-j&68;H4{7_J~+>I~JO0Ht&xLumKob-|g zb^kY>#{`zURwsYYV{R|s7-iQtif7)BaYh>>s7MR``*qs_8-(|g`EcBnL#h*|(x;&8 z$JgvjzF*6DHcM*#k<9x!%X?p0l6?yB6{oD(;kJ}ld+xi;dSUx7kNEi(b)mL>w?_RX zrK;s6`EhI;KANTAdZxv<#y#u0g4lX=jCUv`I*TtDPWOD^#(l^aq>(NkA{=(K)p(%VM4f{-oV%D9n}GRhhp-)@aKCa9?EMr$rj&$UfQyVZu(^FH&- z>X<2yddVc{UNv66bF?)(dSzrh0ZeEiGdJ-M_~6iUk^PQ*WNCQ z^Ma+AjlY|}nIS0h*_4X&;BL|f{Z%Z;BZYcZz#g_wR$5oKrk_3+Z=b~MEnkaIIzXQ{RpwfK03I* zFzb$u#f#hi_QtCh?mlg>&k=eZ*-ZDd`5@%)5gSXo@XMl%lWI27BSys*Z{{)RGIS$}SpQMKo|r=&*o3$3MZ5<{S_Dic*tq}00ce(T;DI7DycT&tjmyrcKf56?2j zE@TV!TMox{?e1HRC>^&U(};dOgtLJkqzQ1OO?G+ruJM?LfBAoLSYe9B{NT9Kqh%hd zb<7Ni%}l~&9`sJcAA}6>fV*#l!4WWbIM#iu_ZAOmxxhWV;qdJJ#Q1*@(le4$59R$g U!DLC#q+y!ifH42tsDzR~02^yCX#fBK literal 0 HcmV?d00001 diff --git a/docs/img/mstile-310x150.png b/docs/img/mstile-310x150.png new file mode 100644 index 0000000000000000000000000000000000000000..d2d64cf93e10d02b35ccce5942f74c184bf51df1 GIT binary patch literal 1967 zcmb7FYfzJC7JdO;5bUmw?Z|?*uo7j7d<(3IfK4?ELI@a%2?z#|5@a({!4RNa4c5yr zMX*?mBCrD9Q0PS}5};_Sl#p-@5N@R`k`R&x0wLEgUy}Wx{ZW7TW6!)Z?>T4A^PKlw zX5QjsM?>DRcd`cnyh8{LA_HIz0buoKI~&wGiP1 zY}WMkE!Ed8*3~Z7*DgJ{Z=QEim zy*{gH8sz*03V0yD+lkHZpHXRr!Z|8QmUu!IPZiToAps;W~0%9!ps(p4q4F{Vf5W*vsSBD zsWe6-va+JqY7H=q=yZnFRjpocKoHcaQLD8klL>~62x8J`bOwXbpoiyVYT=A>Vs2$s zt?!>!9w_N|yuknK1^)XN_~mW0dL0@B*Swgs&g%x}dx#Z6)vE6H^Es;m9-%_GqS95N zdVY5ps;}x`1N>5?_}gdvO$9vrLf)oA-sXH>;nzP8{-SIhkZ}iPKaBjUSk@|)tHaT` zljvNnSmdL}!J+x_(`&}Z#E_u(B;$s9)Uag{B7$vaH`#CT@R;Hp*@5oSzX?HyDW6U* zPD|5HQXOB+9%2Y;ig(^oe4lL}Q6zj4+nf?()iHS>v+ClL=!y1JzCLAZQ+4aBXgPL| zP98L{stGMFRS!q7`XA?otS#o-#O}b7KC{cec42zkcZDy1`mw6@D^#V>A!kXs6L*Wt zc55;I1$=$~yHasoHfiwh4{D-r4iC8J>NZs8M4ju$JwT)P1w`E;54G=kNTWk@!O9w! z-*If3og>7_7zjK+yit(awp_OacX4O|ykw356Y)~Q?5c>4`|ySDSbR3!1UsMI@!$Km z)4m{9UKU71Q)fRAmlpS3;V3)K2*lu|vNHr?IPK@;*-nTAlFlM-I3Gi0x*mcyG=@P_ zd$M-)NX#X)_phy^f4I`}$xKVH_Dc3rKnE>HJk%^6<=ti zH8Z9kne7Sr1e97u(MkFO_y40gX$(6pX^2j67Hhn@cY83vYCR3_65ww6<|ffMgh`&;_Z;_MdYpM33KS)YX_ zlJ6Y8Ixzo$nz2;w&H)?NX@85O*`4UUC*(zhKn-$<4`;5Gm~jLumd}$JW2$zW@!?b+ zCZdbx?Nk=_r85Ja3fkRk4u5#uZ!AP$-Nt2A`p0`8ZT~o&n#Qgj={?7;J7fd-OhM(47u3Vtf>2dmfQV6K){z zloA{BIjy|nT=+9-*}u+1{_3%r{y4`T+^FZyh3xd;Gb`GM^vsL~vGHu%<+Tlnlq>Ls zPezM+EknP#)G#YFjRiwJG5I}tp3jOoqEsqW91C9zYPuzusUOPaMxz;qbw!om zH!qG_+|%2sl}^`*k4j;Ldhc6#fay62YFK%?@6FjE$Dw|F^TPDnFZ6#(NeSZ6d+-h> z+VAQO6pCR5pJ34wS;+xO%w+TeK3?8_o?iZ*-d+^%{Q>)Y(1Z2z3GnjDN+^hX1Mo>2 zopCzn?EqWru2~ciol7~vA}40Mq%+e_Gg6aXSUKs*E{t?m5&)l8&8arqor`jJ=aU4z z1PK|~>~esT9JcM+M!f#6%{G@H_P&>Nn_bNm7s2=l?^W-s9j|N!?9e-55Rh-*%2MHd RE7s~K1Ro9h3V-Ut{{R6)%ZdO1 literal 0 HcmV?d00001 diff --git a/docs/img/mstile-310x310.png b/docs/img/mstile-310x310.png new file mode 100644 index 0000000000000000000000000000000000000000..6fe318976da284feba8491d9202c422cf03b327f GIT binary patch literal 3462 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 literal 0 HcmV?d00001 diff --git a/docs/img/mstile-70x70.png b/docs/img/mstile-70x70.png new file mode 100644 index 0000000000000000000000000000000000000000..7833b6fdf40308d11ffad8b05d45756a90701384 GIT binary patch literal 1397 zcmZ`(X;70_6n!B`LJ-7~)=H_Q1qIm*h$w+#SOP=}1cDF*N+OFzp@2j|m`VUqK!sYX zB5I{A)@5+PmevIkEeIrl2w{n!f?-QSV#uB^A?e4@{^*@^-+AZFIrHYun|algs4z>6 zEd~H!Ne&N*g_*U|Xe7KUrp{<#GTj##83;g2orRvU3f8!^@YqNIiZ{W&V*o%a{sjOI z;QXn(e$T?cfOk9-ocC$jQk7(eUmiC}ny=JUl$EyDEIi=`S%|cSFfI$;566O;r z;!777WspbhOHj@R6>O_=cK4)Ibh>6?PmF+`u%&Jgl=pT|E{RT6FCOm?oE+DZP!4{2X0N^s`|gI>Hng-KeV397i$a< z1kKND`Fv<$!JyYGGR&0kc%UsOvJkXEZR7~o@gGL=%P(dqOGg-QX>pw}yv>gAO( zs8kx2N~_gCkQUNvv}63Gu5s}Tp7`B@oI5S`I5l8h!6w%a3nWU7M*Ea2T3y!bP~HD# zPWE&J-m^#EFKw-T`B4QMdyEs+z!geVDz$cUPS!Um;R_W8gHfx6_b6d_xWij4OIA=Ba~+iP(<( zl8I-}XxCVKp0N@pnA`BU^B zXy~!GHw8~E`64I)Zr{bws5|Iner#pyapZaT1YS)ZF^HO& zw1b#{!J}DLw1@j!#~WH_m8wIcN}ue>CbN4Ff1_q|Mu%j7iTw^^#IK)(S<*kW&lu>v zcO*lyvWlA6Jov(;ADI*0ag!NAX-1=we6 zo_7t&u5l9XU{W3*4Yr(`yFIbDP;!1OO!8)3v6MnZf>4$Qco7bp+nC&|KmB5yiS z%u2bPIl191Tq8a{#~(v9yy82Rme?X1rHe;CoZKb2aCei?>eG_t-yw8>Qguaf0=K5f zI9-YgSze0`ING33&XRG)Aft`&UAysy&qm$+FMx5tCtzz;)7{jul)=&Fo|f&`3CNtN zZOD>Bp}`kduR~N0;NMlWi7M=qZS6h?-1$3C+F~0&E=X){7H;0%Rx3bTuboP;9QOFr ze1lb^bIq^LHMa_fn`Zq4>x)|8Zv|{*l4#6y1~Y?@b}$1b;Dz_x?vD3$_r%9}`VhRm zV7TJF2zdPA)bCUN6UfO;&&oXV{{fUq*EAeRD2}5sV;P0Gyo0%!S=kvl=8?P%Tvi@4 z4S=G{eA#Mre!R0YJDSr+o{a@a2Mdoh3mXTUh_hIv4K9S`{ZBg5;g2{RXPn#9+1F{; fiQ=%r8+UmC;kva=Uo0 literal 0 HcmV?d00001 diff --git a/docs/img/safari-pinned-tab.svg b/docs/img/safari-pinned-tab.svg new file mode 100644 index 0000000..5ce08d0 --- /dev/null +++ b/docs/img/safari-pinned-tab.svg @@ -0,0 +1,44 @@ + + + + +Created by potrace 1.11, written by Peter Selinger 2001-2013 + + + + + + + + + + + + diff --git a/docs/logo.draw.io.xml b/docs/logo.draw.io.xml new file mode 100644 index 0000000..2bb0b6b --- /dev/null +++ b/docs/logo.draw.io.xml @@ -0,0 +1 @@ +7ZdNk6MgEIZ/jXcQNeY4cTO7lznlsGeiHaUGJUXImOyvH1T8iqY2M6VOTe3CQXy7W+FpELRIkF5+SnpMXkQE3LJRdLHID8u2se96+lIoV6Mgb1UpsWSR0Vphx/5A7WjUM4vg1HNUQnDFjn0xFFkGoeppVEqR990OgvffeqQxDIRdSPlQ/c0ilVSq56BW/wUsTtSNYU/D11iKc2ZeZ9nkUJbKnNL6Ucb/lNBI5B2JbC0SSCFU1UovAfCCbU2tinu+Y226LSFTDwWYiDfKz1B3ueyYutYsyuFAEYAssskTpmB3pGFhzXX6tZaolOs7rJsnJcUrBIILWUaTLdbVbyw1TT3SzYFx3vF8LovWY0kjpgdQ2zKRQeEuWkm7o7JonXIWZ1qTVT42ZkQgFVzuYsENbD2JQaSg5FW7mPlapzMfyX3SzTsyIjXzLW4e1ULXDcN9PAf23CloSPVTgIcpsMOiLsT6b3CdCdiSj7DFn2Ab7kfZjkxvWHvIXS3E1gSQ+jtj5rU/nNfYngm9Mzd6hFyyf+jLgpBPgqdl0Tv+16F350YPWNeH0B9Wuq4XRt8nj70hetebCb33H30H/dhGOorenwD96hujv3PkmT4j5NHFMMlq8Oc+2nzidLngasA326+DhvAbberlsP63999b9q49ZO9Pswno2/aPrbR1fovJ9h0= \ No newline at end of file diff --git a/mkdocs.yml b/mkdocs.yml index 57e0d8e..458e404 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -1,12 +1,17 @@ site_name: Flask API +site_favicon: img/favicon-194x194.png + pages: - - ['index.md', 'Home'] - - ['api-guide/renderers.md', 'API Guide', 'Renderers'] - - ['api-guide/parsers.md', 'API Guide', 'Parsers'] - - ['api-guide/exceptions.md', 'API Guide', 'Exceptions'] - - ['api-guide/status-codes.md', 'API Guide', 'Status codes'] - - ['about/release-notes.md', 'About', 'Release Notes'] - - ['about/license.md', 'About', 'License'] + - Home: index.md + - API Guide: + - Renderers: api-guide/renderers.md + - Parsers: api-guide/parsers.md + - Exceptions: api-guide/exceptions.md + - Status Codes: api-guide/status-codes.md + - About: + - Release Notes: about/release-notes.md + - License: about/license.md + repo_url: https://github.com/flask-api/flask-api -copyright: 'BSD licensed · Copyright © 2014, Tom Christie.' +copyright: 'BSD licensed · Copyright © 2017, Tom Christie.' google_analytics: ['UA-27795084-4', 'flaskapi.org'] From 5d83a3fe50e5e53d21da1c865b6620059aea7051 Mon Sep 17 00:00:00 2001 From: Winston Ferreira Date: Thu, 5 Oct 2017 11:50:31 -0300 Subject: [PATCH 22/87] use app.json_encoder --- flask_api/renderers.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/flask_api/renderers.py b/flask_api/renderers.py index 58582aa..f84b366 100644 --- a/flask_api/renderers.py +++ b/flask_api/renderers.py @@ -1,7 +1,6 @@ # coding: utf8 from __future__ import unicode_literals from flask import request, render_template, current_app -from flask.json import JSONEncoder from flask.globals import _request_ctx_stack from flask_api.mediatypes import MediaType from flask_api.compat import apply_markdown @@ -58,7 +57,7 @@ def render(self, data, media_type, **options): indent = None # Indent may be set explicitly, eg when rendered by the browsable API. indent = options.get('indent', indent) - return json.dumps(data, cls=JSONEncoder, ensure_ascii=False, indent=indent) + return json.dumps(data, cls=current_app.json_encoder, ensure_ascii=False, indent=indent) class HTMLRenderer(object): From 716e3066be249f8ff0979dbeff140dcf34b24b57 Mon Sep 17 00:00:00 2001 From: Winston Ferreira Date: Thu, 5 Oct 2017 15:27:42 -0300 Subject: [PATCH 23/87] fixed tests --- flask_api/tests/test_renderers.py | 34 +++++++++++++++++++++++++++++-- 1 file changed, 32 insertions(+), 2 deletions(-) diff --git a/flask_api/tests/test_renderers.py b/flask_api/tests/test_renderers.py index cbdcbe7..e1cc239 100644 --- a/flask_api/tests/test_renderers.py +++ b/flask_api/tests/test_renderers.py @@ -1,5 +1,7 @@ # coding: utf8 from __future__ import unicode_literals +from datetime import datetime +from flask.json import JSONEncoder from flask_api import renderers, status, FlaskAPI from flask_api.decorators import set_renderers from flask_api.mediatypes import MediaType @@ -7,18 +9,46 @@ class RendererTests(unittest.TestCase): + def _make_app(self): + app = FlaskAPI(__name__) + + @app.route('/_love', methods=['GET']) + def love(): + return {"test": "I <3 Python"} + + return app + def test_render_json(self): + app = self._make_app() renderer = renderers.JSONRenderer() - content = renderer.render({'example': 'example'}, MediaType('application/json')) + with app.app_context(): + content = renderer.render({'example': 'example'}, MediaType('application/json')) expected = '{"example": "example"}' self.assertEqual(content, expected) def test_render_json_with_indent(self): + app = self._make_app() renderer = renderers.JSONRenderer() - content = renderer.render({'example': 'example'}, MediaType('application/json; indent=4')) + with app.app_context(): + content = renderer.render({'example': 'example'}, MediaType('application/json; indent=4')) expected = '{\n "example": "example"\n}' self.assertEqual(content, expected) + def test_render_json_with_custom_encoder(self): + class CustomJsonEncoder(JSONEncoder): + def default(self, o): + if isinstance(o, datetime): + return o.isoformat() + return super(CustomJsonEncoder, self).default(o) + + app = self._make_app() + app.json_encoder = CustomJsonEncoder + renderer = renderers.JSONRenderer() + date = datetime(2017, 10, 5, 15, 22) + with app.app_context(): + content = renderer.render(date, MediaType('application/json')) + self.assertEqual(content, '"{}"'.format(date.isoformat())) + def test_render_browsable_encoding(self): app = FlaskAPI(__name__) From 8dfff5db4722e898167784826d3a94b70a380c04 Mon Sep 17 00:00:00 2001 From: Jace Browning Date: Thu, 5 Oct 2017 19:21:03 -0400 Subject: [PATCH 24/87] Bump version to 1.1b1 --- docs/about/release-notes.md | 4 ++++ flask_api/__init__.py | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/docs/about/release-notes.md b/docs/about/release-notes.md index 48523cd..5bd9260 100644 --- a/docs/about/release-notes.md +++ b/docs/about/release-notes.md @@ -1,5 +1,9 @@ # Release Notes +## Version 1.1 (unreleased) + +* Added support for custom JSON encoders + ## Version 1.0 * Stable release to enter maintenance mode. diff --git a/flask_api/__init__.py b/flask_api/__init__.py index 143cce5..2a5ac37 100644 --- a/flask_api/__init__.py +++ b/flask_api/__init__.py @@ -1,3 +1,3 @@ from flask_api.app import FlaskAPI -__version__ = '1.0' +__version__ = '1.1b1' From 9c65b6e3c8550881aebb8ef7050a386f8cf0ef6e Mon Sep 17 00:00:00 2001 From: Marco Marzetti Date: Fri, 1 Dec 2017 22:13:50 +0100 Subject: [PATCH 25/87] fixes https://github.com/flask-api/flask-api/issues/86 --- flask_api/parsers.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/flask_api/parsers.py b/flask_api/parsers.py index de08c02..914fc62 100644 --- a/flask_api/parsers.py +++ b/flask_api/parsers.py @@ -36,8 +36,6 @@ class MultiPartParser(BaseParser): handles_form_data = True def parse(self, stream, media_type, **options): - multipart_parser = WerkzeugMultiPartParser(default_stream_factory) - boundary = media_type.params.get('boundary') if boundary is None: msg = 'Multipart message missing boundary in Content-Type header' @@ -47,6 +45,11 @@ def parse(self, stream, media_type, **options): content_length = options.get('content_length') assert content_length is not None, 'MultiPartParser.parse() requires `content_length` argument' + buffer_size = content_length + while buffer_size % 4 or buffer_size < 1024: + buffer_size += 1 + multipart_parser = WerkzeugMultiPartParser(default_stream_factory, buffer_size=buffer_size) + try: return multipart_parser.parse(stream, boundary, content_length) except ValueError as exc: From fc7d65563a51d3a14cb1e61aa9a715b2d5d84756 Mon Sep 17 00:00:00 2001 From: Rainulf Pineda Date: Wed, 24 Jan 2018 00:21:21 -0500 Subject: [PATCH 26/87] HTTP_204_NO_CONTENT response to handle None return value --- flask_api/app.py | 4 ++++ flask_api/tests/test_app.py | 22 ++++++++++++++++++++++ 2 files changed, 26 insertions(+) diff --git a/flask_api/app.py b/flask_api/app.py index fbffd20..3579c3c 100644 --- a/flask_api/app.py +++ b/flask_api/app.py @@ -6,6 +6,7 @@ from flask_api.request import APIRequest from flask_api.response import APIResponse from flask_api.settings import APISettings +from flask_api.status import HTTP_204_NO_CONTENT from itertools import chain from werkzeug.exceptions import HTTPException import re @@ -48,6 +49,9 @@ def make_response(self, rv): if isinstance(rv, tuple): rv, status_or_headers, headers = rv + (None,) * (3 - len(rv)) + if rv is None and status_or_headers == HTTP_204_NO_CONTENT: + rv = '' + if rv is None and status_or_headers: raise ValueError('View function did not return a response') diff --git a/flask_api/tests/test_app.py b/flask_api/tests/test_app.py index 26dafbf..5c4bebd 100644 --- a/flask_api/tests/test_app.py +++ b/flask_api/tests/test_app.py @@ -62,6 +62,16 @@ def make_response_view(): return response +@app.route('/none_204_response/') +def none_204_response(): + return None, status.HTTP_204_NO_CONTENT + + +@app.route('/none_200_response/') +def none_200_response(): + return None, status.HTTP_200_OK + + @app.route('/api_exception/') def api_exception(): raise exceptions.PermissionDenied() @@ -121,6 +131,18 @@ def test_make_response(self): expected = '{"example": "content"}' self.assertEqual(response.get_data().decode('utf8'), expected) + def test_none_204_response(self): + with app.test_client() as client: + response = client.get('/none_204_response/') + self.assertEqual(response.status_code, status.HTTP_204_NO_CONTENT) + expected = '' + self.assertEqual(response.get_data().decode('utf8'), expected) + + def test_none_200_response(self): + with app.test_client() as client: + with self.assertRaises(ValueError): + client.get('/none_200_response/') + def test_api_exception(self): with app.test_client() as client: response = client.get('/api_exception/') From 5e47a7b633a6657995fed521289e687f9c071401 Mon Sep 17 00:00:00 2001 From: Rainulf Pineda Date: Wed, 24 Jan 2018 01:27:25 -0500 Subject: [PATCH 27/87] Add documentation for browsable template customisation --- docs/api-guide/templates.md | 23 +++++++++++++++++++++++ mkdocs.yml | 1 + 2 files changed, 24 insertions(+) create mode 100644 docs/api-guide/templates.md diff --git a/docs/api-guide/templates.md b/docs/api-guide/templates.md new file mode 100644 index 0000000..715a6b2 --- /dev/null +++ b/docs/api-guide/templates.md @@ -0,0 +1,23 @@ +# Templates + +Flask API utilizes [blueprints](http://flask.pocoo.org/docs/0.12/blueprints/) for managing browsable pages' template path. + +Off the box, it includes a default template. But you would want to customised this for your needs. + +To do that, simply copy `static` and `templates` to your project. + +Then override the previous blueprint with following: + + from flask import Blueprint + from flask_api import FlaskAPI + + theme = Blueprint( + 'flask-api', __name__, + url_prefix='/flask-api', + template_folder='templates', static_folder='static' + ) + + app = FlaskAPI(__name__) + app.blueprints['flask-api'] = theme + +Use `templates/base.html` as your base custom template. Note that this cannot be renamed. \ No newline at end of file diff --git a/mkdocs.yml b/mkdocs.yml index 458e404..f71d1c1 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -6,6 +6,7 @@ pages: - API Guide: - Renderers: api-guide/renderers.md - Parsers: api-guide/parsers.md + - Templates: api-guide/templates.md - Exceptions: api-guide/exceptions.md - Status Codes: api-guide/status-codes.md - About: From 5d9902180f248292f214effdc22a9922218bb856 Mon Sep 17 00:00:00 2001 From: Rainulf Pineda Date: Wed, 24 Jan 2018 08:07:40 -0500 Subject: [PATCH 28/87] Update flask blueprint doc link to latest, minor grammatical changes --- docs/api-guide/templates.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/api-guide/templates.md b/docs/api-guide/templates.md index 715a6b2..a55f621 100644 --- a/docs/api-guide/templates.md +++ b/docs/api-guide/templates.md @@ -1,8 +1,8 @@ # Templates -Flask API utilizes [blueprints](http://flask.pocoo.org/docs/0.12/blueprints/) for managing browsable pages' template path. +Flask API utilizes [blueprints](http://flask.pocoo.org/docs/latest/blueprints/) for managing browsable pages' template path. -Off the box, it includes a default template. But you would want to customised this for your needs. +Off the box, it includes a default template. But you would want to customise this for your needs. To do that, simply copy `static` and `templates` to your project. From f7ff9417485444f896c4e76e50b5809e234e7837 Mon Sep 17 00:00:00 2001 From: Jace Browning Date: Wed, 24 Jan 2018 08:22:58 -0500 Subject: [PATCH 29/87] Bump version to 1.1b2 --- Makefile | 2 +- docs/about/release-notes.md | 3 ++- flask_api/__init__.py | 2 +- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/Makefile b/Makefile index 80411ad..6716987 100644 --- a/Makefile +++ b/Makefile @@ -208,7 +208,7 @@ clean-all: clean .clean-env .clean-workspace .PHONY: .clean-doc .clean-doc: - rm -rf README.rst docs/apidocs *.html docs/*.png site + rm -rf README.rst docs/apidocs *.html site .PHONY: .clean-test .clean-test: diff --git a/docs/about/release-notes.md b/docs/about/release-notes.md index 5bd9260..9e40b58 100644 --- a/docs/about/release-notes.md +++ b/docs/about/release-notes.md @@ -2,7 +2,8 @@ ## Version 1.1 (unreleased) -* Added support for custom JSON encoders +* Added support for custom JSON encoders. +* Added `None` as a valid return value for empty responses (204). ## Version 1.0 diff --git a/flask_api/__init__.py b/flask_api/__init__.py index 2a5ac37..45769de 100644 --- a/flask_api/__init__.py +++ b/flask_api/__init__.py @@ -1,3 +1,3 @@ from flask_api.app import FlaskAPI -__version__ = '1.1b1' +__version__ = '1.1b2' From a9b69e670e30cb7604f5ea7cd7f23e02a4ac75ef Mon Sep 17 00:00:00 2001 From: Rainulf Pineda Date: Thu, 25 Jan 2018 10:54:41 -0500 Subject: [PATCH 30/87] Update request.full_path to request.url to include full root path - See: http://flask.pocoo.org/docs/0.12/api/#flask.Request.url_root --- flask_api/templates/base.html | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/flask_api/templates/base.html b/flask_api/templates/base.html index 0a60422..c80d7fc 100644 --- a/flask_api/templates/base.html +++ b/flask_api/templates/base.html @@ -75,7 +75,7 @@

- GET + GET @@ -113,7 +113,7 @@ {% if view_description %}
{{ view_description|safe }}
{% endif %}
-
{{ request.method }} {{ request.full_path }}
+
{{ request.method }} {{ request.url }}
HTTP {{ status }}{% autoescape off %} @@ -128,7 +128,7 @@
- +
From 915439f78c70cc148e5a61e64b8d91042a3b8632 Mon Sep 17 00:00:00 2001 From: Jace Browning Date: Thu, 25 Jan 2018 21:23:54 -0500 Subject: [PATCH 31/87] Update mkdocs --- Pipfile | 16 ++- Pipfile.lock | 250 +++++++++++++++++++++++++++++++++++++++--- flask_api/__init__.py | 2 +- mkdocs.yml | 1 - 4 files changed, 247 insertions(+), 22 deletions(-) diff --git a/Pipfile b/Pipfile index 3ed0eb4..5200c9d 100644 --- a/Pipfile +++ b/Pipfile @@ -1,17 +1,25 @@ [[source]] + url = "https://pypi.python.org/simple" verify_ssl = true +name = "pypi" [packages] + Flask = "~=0.10.1" Markdown = "*" [dev-packages] + +flake8 = "~=2.1" + nose = "*" -coverage = "~=3.7.1" + "coverage.space" = "*" -flake8 = "~=2.1" -mkdocs = "*" + +mkdocs = "~=0.17.2" docutils = "*" -sniffer = "*" + twine = "*" + +sniffer = "*" diff --git a/Pipfile.lock b/Pipfile.lock index 958a9ed..33321ce 100644 --- a/Pipfile.lock +++ b/Pipfile.lock @@ -1,11 +1,26 @@ { "_meta": { "hash": { - "sha256": "becad809c6c13e0d434dfc887c66d2755ab20b4fa55c8b92a5dbe0527e61c563" - }, + "sha256": "0cf38bb2cbbfe08ce0e77c40c0c4b5275fb6b535efdfacd6dda906d325e0327f" + }, + "host-environment-markers": { + "implementation_name": "cpython", + "implementation_version": "0", + "os_name": "posix", + "platform_machine": "x86_64", + "platform_python_implementation": "CPython", + "platform_release": "17.3.0", + "platform_system": "Darwin", + "platform_version": "Darwin Kernel Version 17.3.0: Thu Nov 9 18:09:22 PST 2017; root:xnu-4570.31.3~1/RELEASE_X86_64", + "python_full_version": "2.7.13", + "python_version": "2.7", + "sys_platform": "darwin" + }, + "pipfile-spec": 6, "requires": {}, "sources": [ { + "name": "pypi", "url": "https://pypi.python.org/simple", "verify_ssl": true } @@ -13,125 +28,328 @@ }, "default": { "flask": { + "hashes": [ + "sha256:4c83829ff83d408b5e1d4995472265411d2c414112298f2eb4b359d9e4563373" + ], "version": "==0.10.1" }, "itsdangerous": { + "hashes": [ + "sha256:cbb3fcf8d3e33df861709ecaf89d9e6629cff0a217bc2848f1b41cd30d360519" + ], "version": "==0.24" }, "jinja2": { - "version": "==2.9.6" + "hashes": [ + "sha256:74c935a1b8bb9a3947c50a54766a969d4846290e1e788ea44c1392163723c3bd", + "sha256:f84be1bb0040caca4cea721fcbbbbd61f9be9464ca236387158b0feea01914a4" + ], + "version": "==2.10" }, "markdown": { - "version": "==2.6.9" + "hashes": [ + "sha256:9ba587db9daee7ec761cfc656272be6aabe2ed300fece21208e4aab2e457bc8f", + "sha256:a856869c7ff079ad84a3e19cd87a64998350c2b94e9e08e44270faef33400f81" + ], + "version": "==2.6.11" }, "markupsafe": { + "hashes": [ + "sha256:a6be69091dac236ea9c6bc7d012beab42010fa914c459791d627dad4910eb665" + ], "version": "==1.0" }, "werkzeug": { - "version": "==0.12.2" + "hashes": [ + "sha256:d5da73735293558eb1651ee2fddc4d0dedcfa06538b8813a2e20011583c9e49b", + "sha256:c3fd7a7d41976d9f44db327260e263132466836cef6f91512889ed60ad26557c" + ], + "version": "==0.14.1" } }, "develop": { "backports-abc": { + "hashes": [ + "sha256:52089f97fe7a9aa0d3277b220c1d730a85aefd64e1b2664696fe35317c5470a7", + "sha256:033be54514a03e255df75c5aee8f9e672f663f93abb723444caec8fe43437bde" + ], "version": "==0.5" }, "backports.shutil-get-terminal-size": { + "hashes": [ + "sha256:0975ba55054c15e346944b38956a4c9cbee9009391e41b86c68990effb8c1f64", + "sha256:713e7a8228ae80341c70586d1cc0a8caa5207346927e23d09dcbcaf18eadec80" + ], "version": "==1.0.0" }, "certifi": { - "version": "==2017.7.27.1" + "hashes": [ + "sha256:14131608ad2fd56836d33a71ee60fa1c82bc9d2c8d98b7bdbc631fe1b3cd1296", + "sha256:edbc3f203427eef571f79a7692bb160a2b0f7ccaa31953e99bd17e307cf63f7d" + ], + "version": "==2018.1.18" }, "chardet": { + "hashes": [ + "sha256:fc323ffcaeaed0e0a02bf4d117757b98aed530d9ed4531e3e15460124c106691", + "sha256:84ab92ed1c4d4f16916e05906b6b75a6c0fb5db821cc65e70cbd64a3e2a5eaae" + ], "version": "==3.0.4" }, "click": { + "hashes": [ + "sha256:29f99fc6125fbc931b758dc053b3114e55c77a6e4c6c3a2674a2dc986016381d", + "sha256:f15516df478d5a56180fbf80e68f206010e6d160fc39fa508b65e035fd75130b" + ], "version": "==6.7" }, "colorama": { + "hashes": [ + "sha256:463f8483208e921368c9f306094eb6f725c6ca42b0f97e313cb5d5512459feda", + "sha256:48eb22f4f8461b1df5734a074b57042430fb06e1d61bd1e11b078c0fe6d7a1f1" + ], "version": "==0.3.9" }, "coverage": { - "version": "==4.4.1" + "hashes": [ + "sha256:d1ee76f560c3c3e8faada866a07a32485445e16ed2206ac8378bd90dadffb9f0", + "sha256:007eeef7e23f9473622f7d94a3e029a45d55a92a1f083f0f3512f5ab9a669b05", + "sha256:17307429935f96c986a1b1674f78079528833410750321d22b5fb35d1883828e", + "sha256:845fddf89dca1e94abe168760a38271abfc2e31863fbb4ada7f9a99337d7c3dc", + "sha256:3f4d0b3403d3e110d2588c275540649b1841725f5a11a7162620224155d00ba2", + "sha256:4c4f368ffe1c2e7602359c2c50233269f3abe1c48ca6b288dcd0fb1d1c679733", + "sha256:f8c55dd0f56d3d618dfacf129e010cbe5d5f94b6951c1b2f13ab1a2f79c284da", + "sha256:cdd92dd9471e624cd1d8c1a2703d25f114b59b736b0f1f659a98414e535ffb3d", + "sha256:2ad357d12971e77360034c1596011a03f50c0f9e1ecd12e081342b8d1aee2236", + "sha256:e9a0e1caed2a52f15c96507ab78a48f346c05681a49c5b003172f8073da6aa6b", + "sha256:eea9135432428d3ca7ee9be86af27cb8e56243f73764a9b6c3e0bda1394916be", + "sha256:700d7579995044dc724847560b78ac786f0ca292867447afda7727a6fbaa082e", + "sha256:66f393e10dd866be267deb3feca39babba08ae13763e0fc7a1063cbe1f8e49f6", + "sha256:5ff16548492e8a12e65ff3d55857ccd818584ed587a6c2898a9ebbe09a880674", + "sha256:d00e29b78ff610d300b2c37049a41234d48ea4f2d2581759ebcf67caaf731c31", + "sha256:87d942863fe74b1c3be83a045996addf1639218c2cb89c5da18c06c0fe3917ea", + "sha256:358d635b1fc22a425444d52f26287ae5aea9e96e254ff3c59c407426f44574f4", + "sha256:81912cfe276e0069dca99e1e4e6be7b06b5fc8342641c6b472cb2fed7de7ae18", + "sha256:079248312838c4c8f3494934ab7382a42d42d5f365f0cf7516f938dbb3f53f3f", + "sha256:b0059630ca5c6b297690a6bf57bf2fdac1395c24b7935fd73ee64190276b743b", + "sha256:493082f104b5ca920e97a485913de254cbe351900deed72d4264571c73464cd0", + "sha256:e3ba9b14607c23623cf38f90b23f5bed4a3be87cbfa96e2e9f4eabb975d1e98b", + "sha256:82cbd3317320aa63c65555aa4894bf33a13fb3a77f079059eb5935eea415938d", + "sha256:9721f1b7275d3112dc7ccf63f0553c769f09b5c25a26ee45872c7f5c09edf6c1", + "sha256:bd4800e32b4c8d99c3a2c943f1ac430cbf80658d884123d19639bcde90dad44a", + "sha256:f29841e865590af72c4b90d7b5b8e93fd560f5dea436c1d5ee8053788f9285de", + "sha256:f3a5c6d054c531536a83521c00e5d4004f1e126e2e2556ce399bef4180fbe540", + "sha256:dd707a21332615108b736ef0b8513d3edaf12d2a7d5fc26cd04a169a8ae9b526", + "sha256:2e1a5c6adebb93c3b175103c2f855eda957283c10cf937d791d81bef8872d6ca", + "sha256:f87f522bde5540d8a4b11df80058281ac38c44b13ce29ced1e294963dd51a8f8", + "sha256:a7cfaebd8f24c2b537fa6a271229b051cdac9c1734bb6f939ccfc7c055689baa", + "sha256:309d91bd7a35063ec7a0e4d75645488bfab3f0b66373e7722f23da7f5b0f34cc", + "sha256:0388c12539372bb92d6dde68b4627f0300d948965bbb7fc104924d715fdc0965", + "sha256:ab3508df9a92c1d3362343d235420d08e2662969b83134f8a97dc1451cbe5e84", + "sha256:43a155eb76025c61fc20c3d03b89ca28efa6f5be572ab6110b2fb68eda96bfea", + "sha256:f98b461cb59f117887aa634a66022c0bd394278245ed51189f63a036516e32de", + "sha256:b6cebae1502ce5b87d7c6f532fa90ab345cfbda62b95aeea4e431e164d498a3d", + "sha256:a4497faa4f1c0fc365ba05eaecfb6b5d24e3c8c72e95938f9524e29dadb15e76", + "sha256:2b4d7f03a8a6632598cbc5df15bbca9f778c43db7cf1a838f4fa2c8599a8691a", + "sha256:1afccd7e27cac1b9617be8c769f6d8a6d363699c9b86820f40c74cfb3328921c" + ], + "version": "==4.4.2" }, "coverage.space": { + "hashes": [ + "sha256:31cb5ba7d28d389e29e9779ba204de27c333d8589161cebe03a1cb1503c66059", + "sha256:54f0e5bf3cfec621b5625969351207f937668bea9159a4c635f722c997bfe546" + ], "version": "==0.8" }, "docopt": { + "hashes": [ + "sha256:49b3a825280bd66b3aa83585ef59c4a8c82f2c8a522dbe754a8bc8d08c85c491" + ], "version": "==0.6.2" }, "docutils": { + "hashes": [ + "sha256:7a4bd47eaf6596e1295ecb11361139febe29b084a87bf005bf899f9a42edc3c6", + "sha256:02aec4bd92ab067f6ff27a38a38a41173bf01bed8f89157768c1573f53e474a6", + "sha256:51e64ef2ebfb29cae1faa133b3710143496eca21c530f3f71424d77687764274" + ], "version": "==0.14" }, "flake8": { + "hashes": [ + "sha256:7ac3bbaac27174d95bc4734ed23a07de567ffbcf4fc7e316854b4f3015d4fd15", + "sha256:231cd86194aaec4bdfaa553ae1a1cd9b7b4558332fbc10136c044940d587a778" + ], "version": "==2.6.2" }, "idna": { + "hashes": [ + "sha256:8c7309c718f94b3a625cb648ace320157ad16ff131ae0af362c9f21b80ef6ec4", + "sha256:2c6a5de3089009e3da7c5dde64a141dbc8551d5b7f6cf4ed7c2568d0cc520a8f" + ], "version": "==2.6" }, "jinja2": { - "version": "==2.9.6" + "hashes": [ + "sha256:74c935a1b8bb9a3947c50a54766a969d4846290e1e788ea44c1392163723c3bd", + "sha256:f84be1bb0040caca4cea721fcbbbbd61f9be9464ca236387158b0feea01914a4" + ], + "version": "==2.10" }, "livereload": { + "hashes": [ + "sha256:5ed6506f5d526ee712da9f3739c27714e6f3376f3e481728d298efceae0ec83a", + "sha256:422de10d7ea9467a1ba27cbaffa84c74b809d96fb1598d9de4b9b676adf35e2c" + ], "version": "==2.5.1" }, "markdown": { - "version": "==2.6.9" + "hashes": [ + "sha256:9ba587db9daee7ec761cfc656272be6aabe2ed300fece21208e4aab2e457bc8f", + "sha256:a856869c7ff079ad84a3e19cd87a64998350c2b94e9e08e44270faef33400f81" + ], + "version": "==2.6.11" }, "markupsafe": { + "hashes": [ + "sha256:a6be69091dac236ea9c6bc7d012beab42010fa914c459791d627dad4910eb665" + ], "version": "==1.0" }, "mccabe": { + "hashes": [ + "sha256:f9b58bf366c1506dcd6117b33e5c4874746f0de859c9c7cab8b516cb6be1d22e", + "sha256:16293af41e7242031afd73896fef6458f4cad38201d21e28f344fff50ae1c25e" + ], "version": "==0.5.3" }, "mkdocs": { - "version": "==0.16.3" + "hashes": [ + "sha256:150795179c32bde225a3596c57b677f856f544351e809048f654cab3fbac90bd", + "sha256:4a6b6b062347448ed42d5e8c0dce8f912e647ce4bd480fdea25017cd63aaa3a1" + ], + "version": "==0.17.2" }, "nose": { + "hashes": [ + "sha256:dadcddc0aefbf99eea214e0f1232b94f2fa9bd98fa8353711dacb112bfcbbb2a", + "sha256:9ff7c6cc443f8c51994b34a667bbcf45afd6d945be7477b52e97516fd17c53ac", + "sha256:f1bffef9cbc82628f6e7d7b40d7e255aefaa1adb6a1b1d26c69a8b79e6208a98" + ], "version": "==1.3.7" }, "pkginfo": { + "hashes": [ + "sha256:31a49103180ae1518b65d3f4ce09c784e2bc54e338197668b4fb7dc539521024", + "sha256:bb1a6aeabfc898f5df124e7e00303a5b3ec9a489535f346bfbddb081af93f89e" + ], "version": "==1.4.1" }, "pycodestyle": { + "hashes": [ + "sha256:2ce83f2046f5ab85c652ceceddfbde7a64a909900989b4b43e92b10b743d0ce5", + "sha256:37f0420b14630b0eaaf452978f3a6ea4816d787c3e6dcbba6fb255030adae2e7" + ], "version": "==2.0.0" }, "pyflakes": { + "hashes": [ + "sha256:e87bac26c62ea5b45067cc89e4a12f56e1483f1f2cda17e7c9b375b9fd2f40da", + "sha256:2e4a1b636d8809d8f0a69f341acf15b2e401a3221ede11be439911d23ce2139e" + ], "version": "==1.2.3" }, "python-termstyle": { + "hashes": [ + "sha256:f42a6bb16fbfc5e2c66d553e7ad46524ea833872f75ee5d827c15115fafc94e2", + "sha256:6faf42ba42f2826c38cf70dacb3ac51f248a418e48afc0e36593df11cf3ab1d2" + ], "version": "==0.1.10" }, "pyyaml": { + "hashes": [ + "sha256:3262c96a1ca437e7e4763e2843746588a965426550f3797a79fca9c6199c431f", + "sha256:16b20e970597e051997d90dc2cddc713a2876c47e3d92d59ee198700c5427736", + "sha256:e863072cdf4c72eebf179342c94e6989c67185842d9997960b3e69290b2fa269", + "sha256:bc6bced57f826ca7cb5125a10b23fd0f2fff3b7c4701d64c439a300ce665fff8", + "sha256:c01b880ec30b5a6e6aa67b09a2fe3fb30473008c85cd6a67359a1b15ed6d83a4", + "sha256:827dc04b8fa7d07c44de11fabbc888e627fa8293b695e0f99cb544fdfa1bf0d1", + "sha256:592766c6303207a20efc445587778322d7f73b161bd994f227adaa341ba212ab", + "sha256:5f84523c076ad14ff5e6c037fe1c89a7f73a3e04cf0377cb4d017014976433f3", + "sha256:0c507b7f74b3d2dd4d1322ec8a94794927305ab4cebbe89cc47fe5e81541e6e8", + "sha256:b4c423ab23291d3945ac61346feeb9a0dc4184999ede5e7c43e1ffb975130ae6", + "sha256:ca233c64c6e40eaa6c66ef97058cdc80e8d0157a443655baa1b2966e812807ca", + "sha256:4474f8ea030b5127225b8894d626bb66c01cda098d47a2b0d3429b6700af9fd8", + "sha256:326420cbb492172dec84b0f65c80942de6cedb5233c413dd824483989c000608", + "sha256:5ac82e411044fb129bae5cfbeb3ba626acb2af31a8d17d175004b70862a741a7" + ], "version": "==3.12" }, "requests": { + "hashes": [ + "sha256:6a1b267aa90cac58ac3a765d067950e7dbbf75b1da07e895d1f594193a40a38b", + "sha256:9c443e7324ba5b85070c4a818ade28bfabedf16ea10206da1132edaa6dda237e" + ], "version": "==2.18.4" }, "requests-toolbelt": { + "hashes": [ + "sha256:42c9c170abc2cacb78b8ab23ac957945c7716249206f90874651971a4acff237", + "sha256:f6a531936c6fa4c6cfce1b9c10d5c4f498d16528d2a54a22ca00011205a187b5" + ], "version": "==0.8.0" }, - "setuptools": { - "version": "==36.3.0" - }, "singledispatch": { + "hashes": [ + "sha256:833b46966687b3de7f438c761ac475213e53b306740f1abfaa86e1d1aae56aa8", + "sha256:5b06af87df13818d14f08a028e42f566640aef80805c3b50c5056b086e3c2b9c" + ], "version": "==3.4.0.3" }, "six": { - "version": "==1.10.0" + "hashes": [ + "sha256:832dc0e10feb1aa2c68dcc57dbb658f1c7e65b9b61af69048abc87a2db00a0eb", + "sha256:70e8a77beed4562e7f14fe23a786b54f6296e34344c23bc42f07b15018ff98e9" + ], + "version": "==1.11.0" }, "sniffer": { + "hashes": [ + "sha256:e8a0daa4c51dff3d00482b45dc9b978159100a8d5a7df327c28ed96586559970", + "sha256:e90c1ad4bd3c31a5fad8e03d45dfc83377b31420aa0779f17280c817ce0c9dd8" + ], "version": "==0.4.0" }, "tornado": { - "version": "==4.5.2" + "hashes": [ + "sha256:92b7ca81e18ba9ec3031a7ee73d4577ac21d41a0c9b775a9182f43301c3b5f8e", + "sha256:b36298e9f63f18cad97378db2222c0e0ca6a55f6304e605515e05a25483ed51a", + "sha256:ab587996fe6fb9ce65abfda440f9b61e4f9f2cf921967723540679176915e4c3", + "sha256:5ef073ac6180038ccf99411fe05ae9aafb675952a2c8db60592d5daf8401f803", + "sha256:6d14e47eab0e15799cf3cdcc86b0b98279da68522caace2bd7ce644287685f0a" + ], + "version": "==4.5.3" }, "tqdm": { - "version": "==4.15.0" + "hashes": [ + "sha256:4c041f8019f7be65b8028ddde9a836f7ccc51c4637f1ff2ba9b5813d38d19d5a", + "sha256:df32e6f127dc0ccbc675eadb33f749abbcb8f174c5cb9ec49c0cdb73aa737377" + ], + "version": "==4.19.5" }, "twine": { + "hashes": [ + "sha256:d3ce5c480c22ccfb761cd358526e862b32546d2fe4bc93d46b5cf04ea3cc46ca", + "sha256:caa45b7987fc96321258cd7668e3be2ff34064f5c66d2d975b641adca659c1ab" + ], "version": "==1.9.1" }, "urllib3": { + "hashes": [ + "sha256:06330f386d6e4b195fbfc736b297f58c5a892e4440e54d294d7004e3a9bbea1b", + "sha256:cc44da8e1145637334317feebd728bd869a35285b93cbb4cca2577da7e62db4f" + ], "version": "==1.22" } } diff --git a/flask_api/__init__.py b/flask_api/__init__.py index 45769de..f5e2c37 100644 --- a/flask_api/__init__.py +++ b/flask_api/__init__.py @@ -1,3 +1,3 @@ from flask_api.app import FlaskAPI -__version__ = '1.1b2' +__version__ = '1.1b3' diff --git a/mkdocs.yml b/mkdocs.yml index f71d1c1..7e1324e 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -1,5 +1,4 @@ site_name: Flask API -site_favicon: img/favicon-194x194.png pages: - Home: index.md From 30775a20f0501e3566ae1361035a192311f480d8 Mon Sep 17 00:00:00 2001 From: Jace Browning Date: Fri, 23 Mar 2018 21:48:47 -0400 Subject: [PATCH 32/87] Update dependencies --- Makefile | 7 -- Pipfile | 10 ++- Pipfile.lock | 246 ++++++++++++++++++++++++++------------------------- 3 files changed, 133 insertions(+), 130 deletions(-) diff --git a/Makefile b/Makefile index 6716987..e95f7ca 100644 --- a/Makefile +++ b/Makefile @@ -84,13 +84,6 @@ install: $(DEPENDENCIES) $(METADATA) $(DEPENDENCIES): $(PIP) Pipfile* pipenv install --dev -ifdef WINDOWS - @ echo "Manually install pywin32: https://sourceforge.net/projects/pywin32/files/pywin32" -else ifdef MAC - $(PIP) install pync MacFSEvents -else ifdef LINUX - $(PIP) install pyinotify -endif @ touch $@ $(METADATA): $(PYTHON) setup.py diff --git a/Pipfile b/Pipfile index 5200c9d..7c273ae 100644 --- a/Pipfile +++ b/Pipfile @@ -11,15 +11,23 @@ Markdown = "*" [dev-packages] +# Linters flake8 = "~=2.1" +# Testing nose = "*" -"coverage.space" = "*" +# Reports +coverage-space = "*" +# Documentation mkdocs = "~=0.17.2" docutils = "*" +# Release twine = "*" +# Tooling sniffer = "*" +pync = { version = "<2.0", sys_platform = "== 'darwin'" } +MacFSEvents = { version = "*", sys_platform = "== 'darwin'" } diff --git a/Pipfile.lock b/Pipfile.lock index 33321ce..8d9aa66 100644 --- a/Pipfile.lock +++ b/Pipfile.lock @@ -1,20 +1,7 @@ { "_meta": { "hash": { - "sha256": "0cf38bb2cbbfe08ce0e77c40c0c4b5275fb6b535efdfacd6dda906d325e0327f" - }, - "host-environment-markers": { - "implementation_name": "cpython", - "implementation_version": "0", - "os_name": "posix", - "platform_machine": "x86_64", - "platform_python_implementation": "CPython", - "platform_release": "17.3.0", - "platform_system": "Darwin", - "platform_version": "Darwin Kernel Version 17.3.0: Thu Nov 9 18:09:22 PST 2017; root:xnu-4570.31.3~1/RELEASE_X86_64", - "python_full_version": "2.7.13", - "python_version": "2.7", - "sys_platform": "darwin" + "sha256": "9d761bfd070ed0c943fa2dcdc6f90a33adfe77d387fc12962fd488d613340720" }, "pipfile-spec": 6, "requires": {}, @@ -31,6 +18,7 @@ "hashes": [ "sha256:4c83829ff83d408b5e1d4995472265411d2c414112298f2eb4b359d9e4563373" ], + "index": "pypi", "version": "==0.10.1" }, "itsdangerous": { @@ -51,6 +39,7 @@ "sha256:9ba587db9daee7ec761cfc656272be6aabe2ed300fece21208e4aab2e457bc8f", "sha256:a856869c7ff079ad84a3e19cd87a64998350c2b94e9e08e44270faef33400f81" ], + "index": "pypi", "version": "==2.6.11" }, "markupsafe": { @@ -61,20 +50,13 @@ }, "werkzeug": { "hashes": [ - "sha256:d5da73735293558eb1651ee2fddc4d0dedcfa06538b8813a2e20011583c9e49b", - "sha256:c3fd7a7d41976d9f44db327260e263132466836cef6f91512889ed60ad26557c" + "sha256:c3fd7a7d41976d9f44db327260e263132466836cef6f91512889ed60ad26557c", + "sha256:d5da73735293558eb1651ee2fddc4d0dedcfa06538b8813a2e20011583c9e49b" ], "version": "==0.14.1" } }, "develop": { - "backports-abc": { - "hashes": [ - "sha256:52089f97fe7a9aa0d3277b220c1d730a85aefd64e1b2664696fe35317c5470a7", - "sha256:033be54514a03e255df75c5aee8f9e672f663f93abb723444caec8fe43437bde" - ], - "version": "==0.5" - }, "backports.shutil-get-terminal-size": { "hashes": [ "sha256:0975ba55054c15e346944b38956a4c9cbee9009391e41b86c68990effb8c1f64", @@ -91,8 +73,8 @@ }, "chardet": { "hashes": [ - "sha256:fc323ffcaeaed0e0a02bf4d117757b98aed530d9ed4531e3e15460124c106691", - "sha256:84ab92ed1c4d4f16916e05906b6b75a6c0fb5db821cc65e70cbd64a3e2a5eaae" + "sha256:84ab92ed1c4d4f16916e05906b6b75a6c0fb5db821cc65e70cbd64a3e2a5eaae", + "sha256:fc323ffcaeaed0e0a02bf4d117757b98aed530d9ed4531e3e15460124c106691" ], "version": "==3.0.4" }, @@ -112,55 +94,52 @@ }, "coverage": { "hashes": [ - "sha256:d1ee76f560c3c3e8faada866a07a32485445e16ed2206ac8378bd90dadffb9f0", - "sha256:007eeef7e23f9473622f7d94a3e029a45d55a92a1f083f0f3512f5ab9a669b05", - "sha256:17307429935f96c986a1b1674f78079528833410750321d22b5fb35d1883828e", - "sha256:845fddf89dca1e94abe168760a38271abfc2e31863fbb4ada7f9a99337d7c3dc", - "sha256:3f4d0b3403d3e110d2588c275540649b1841725f5a11a7162620224155d00ba2", - "sha256:4c4f368ffe1c2e7602359c2c50233269f3abe1c48ca6b288dcd0fb1d1c679733", - "sha256:f8c55dd0f56d3d618dfacf129e010cbe5d5f94b6951c1b2f13ab1a2f79c284da", - "sha256:cdd92dd9471e624cd1d8c1a2703d25f114b59b736b0f1f659a98414e535ffb3d", - "sha256:2ad357d12971e77360034c1596011a03f50c0f9e1ecd12e081342b8d1aee2236", - "sha256:e9a0e1caed2a52f15c96507ab78a48f346c05681a49c5b003172f8073da6aa6b", - "sha256:eea9135432428d3ca7ee9be86af27cb8e56243f73764a9b6c3e0bda1394916be", - "sha256:700d7579995044dc724847560b78ac786f0ca292867447afda7727a6fbaa082e", - "sha256:66f393e10dd866be267deb3feca39babba08ae13763e0fc7a1063cbe1f8e49f6", - "sha256:5ff16548492e8a12e65ff3d55857ccd818584ed587a6c2898a9ebbe09a880674", - "sha256:d00e29b78ff610d300b2c37049a41234d48ea4f2d2581759ebcf67caaf731c31", - "sha256:87d942863fe74b1c3be83a045996addf1639218c2cb89c5da18c06c0fe3917ea", - "sha256:358d635b1fc22a425444d52f26287ae5aea9e96e254ff3c59c407426f44574f4", - "sha256:81912cfe276e0069dca99e1e4e6be7b06b5fc8342641c6b472cb2fed7de7ae18", - "sha256:079248312838c4c8f3494934ab7382a42d42d5f365f0cf7516f938dbb3f53f3f", - "sha256:b0059630ca5c6b297690a6bf57bf2fdac1395c24b7935fd73ee64190276b743b", - "sha256:493082f104b5ca920e97a485913de254cbe351900deed72d4264571c73464cd0", - "sha256:e3ba9b14607c23623cf38f90b23f5bed4a3be87cbfa96e2e9f4eabb975d1e98b", - "sha256:82cbd3317320aa63c65555aa4894bf33a13fb3a77f079059eb5935eea415938d", - "sha256:9721f1b7275d3112dc7ccf63f0553c769f09b5c25a26ee45872c7f5c09edf6c1", - "sha256:bd4800e32b4c8d99c3a2c943f1ac430cbf80658d884123d19639bcde90dad44a", - "sha256:f29841e865590af72c4b90d7b5b8e93fd560f5dea436c1d5ee8053788f9285de", - "sha256:f3a5c6d054c531536a83521c00e5d4004f1e126e2e2556ce399bef4180fbe540", - "sha256:dd707a21332615108b736ef0b8513d3edaf12d2a7d5fc26cd04a169a8ae9b526", - "sha256:2e1a5c6adebb93c3b175103c2f855eda957283c10cf937d791d81bef8872d6ca", - "sha256:f87f522bde5540d8a4b11df80058281ac38c44b13ce29ced1e294963dd51a8f8", - "sha256:a7cfaebd8f24c2b537fa6a271229b051cdac9c1734bb6f939ccfc7c055689baa", - "sha256:309d91bd7a35063ec7a0e4d75645488bfab3f0b66373e7722f23da7f5b0f34cc", - "sha256:0388c12539372bb92d6dde68b4627f0300d948965bbb7fc104924d715fdc0965", - "sha256:ab3508df9a92c1d3362343d235420d08e2662969b83134f8a97dc1451cbe5e84", - "sha256:43a155eb76025c61fc20c3d03b89ca28efa6f5be572ab6110b2fb68eda96bfea", - "sha256:f98b461cb59f117887aa634a66022c0bd394278245ed51189f63a036516e32de", - "sha256:b6cebae1502ce5b87d7c6f532fa90ab345cfbda62b95aeea4e431e164d498a3d", - "sha256:a4497faa4f1c0fc365ba05eaecfb6b5d24e3c8c72e95938f9524e29dadb15e76", - "sha256:2b4d7f03a8a6632598cbc5df15bbca9f778c43db7cf1a838f4fa2c8599a8691a", - "sha256:1afccd7e27cac1b9617be8c769f6d8a6d363699c9b86820f40c74cfb3328921c" - ], - "version": "==4.4.2" - }, - "coverage.space": { - "hashes": [ - "sha256:31cb5ba7d28d389e29e9779ba204de27c333d8589161cebe03a1cb1503c66059", - "sha256:54f0e5bf3cfec621b5625969351207f937668bea9159a4c635f722c997bfe546" - ], - "version": "==0.8" + "sha256:03481e81d558d30d230bc12999e3edffe392d244349a90f4ef9b88425fac74ba", + "sha256:0b136648de27201056c1869a6c0d4e23f464750fd9a9ba9750b8336a244429ed", + "sha256:104ab3934abaf5be871a583541e8829d6c19ce7bde2923b2751e0d3ca44db60a", + "sha256:15b111b6a0f46ee1a485414a52a7ad1d703bdf984e9ed3c288a4414d3871dcbd", + "sha256:198626739a79b09fa0a2f06e083ffd12eb55449b5f8bfdbeed1df4910b2ca640", + "sha256:1c383d2ef13ade2acc636556fd544dba6e14fa30755f26812f54300e401f98f2", + "sha256:28b2191e7283f4f3568962e373b47ef7f0392993bb6660d079c62bd50fe9d162", + "sha256:2eb564bbf7816a9d68dd3369a510be3327f1c618d2357fa6b1216994c2e3d508", + "sha256:337ded681dd2ef9ca04ef5d93cfc87e52e09db2594c296b4a0a3662cb1b41249", + "sha256:3a2184c6d797a125dca8367878d3b9a178b6fdd05fdc2d35d758c3006a1cd694", + "sha256:3c79a6f7b95751cdebcd9037e4d06f8d5a9b60e4ed0cd231342aa8ad7124882a", + "sha256:3d72c20bd105022d29b14a7d628462ebdc61de2f303322c0212a054352f3b287", + "sha256:3eb42bf89a6be7deb64116dd1cc4b08171734d721e7a7e57ad64cc4ef29ed2f1", + "sha256:4635a184d0bbe537aa185a34193898eee409332a8ccb27eea36f262566585000", + "sha256:56e448f051a201c5ebbaa86a5efd0ca90d327204d8b059ab25ad0f35fbfd79f1", + "sha256:5a13ea7911ff5e1796b6d5e4fbbf6952381a611209b736d48e675c2756f3f74e", + "sha256:69bf008a06b76619d3c3f3b1983f5145c75a305a0fea513aca094cae5c40a8f5", + "sha256:6bc583dc18d5979dc0f6cec26a8603129de0304d5ae1f17e57a12834e7235062", + "sha256:701cd6093d63e6b8ad7009d8a92425428bc4d6e7ab8d75efbb665c806c1d79ba", + "sha256:7608a3dd5d73cb06c531b8925e0ef8d3de31fed2544a7de6c63960a1e73ea4bc", + "sha256:76ecd006d1d8f739430ec50cc872889af1f9c1b6b8f48e29941814b09b0fd3cc", + "sha256:7aa36d2b844a3e4a4b356708d79fd2c260281a7390d678a10b91ca595ddc9e99", + "sha256:7d3f553904b0c5c016d1dad058a7554c7ac4c91a789fca496e7d8347ad040653", + "sha256:7e1fe19bd6dce69d9fd159d8e4a80a8f52101380d5d3a4d374b6d3eae0e5de9c", + "sha256:8c3cb8c35ec4d9506979b4cf90ee9918bc2e49f84189d9bf5c36c0c1119c6558", + "sha256:9d6dd10d49e01571bf6e147d3b505141ffc093a06756c60b053a859cb2128b1f", + "sha256:9e112fcbe0148a6fa4f0a02e8d58e94470fc6cb82a5481618fea901699bf34c4", + "sha256:ac4fef68da01116a5c117eba4dd46f2e06847a497de5ed1d64bb99a5fda1ef91", + "sha256:b8815995e050764c8610dbc82641807d196927c3dbed207f0a079833ffcf588d", + "sha256:be6cfcd8053d13f5f5eeb284aa8a814220c3da1b0078fa859011c7fffd86dab9", + "sha256:c1bb572fab8208c400adaf06a8133ac0712179a334c09224fb11393e920abcdd", + "sha256:de4418dadaa1c01d497e539210cb6baa015965526ff5afc078c57ca69160108d", + "sha256:e05cb4d9aad6233d67e0541caa7e511fa4047ed7750ec2510d466e806e0255d6", + "sha256:e4d96c07229f58cb686120f168276e434660e4358cc9cf3b0464210b04913e77", + "sha256:f3f501f345f24383c0000395b26b726e46758b71393267aeae0bd36f8b3ade80", + "sha256:f8a923a85cb099422ad5a2e345fe877bbc89a8a8b23235824a93488150e45f6e" + ], + "version": "==4.5.1" + }, + "coverage-space": { + "hashes": [ + "sha256:e68f7451acee5b23f1ec374739e6011321712db319eee9b8e264d5d28911f701", + "sha256:e89e898bdbb4aa45ccb57124a5136e4c03a73711919e8e23b6110400c61017cd" + ], + "index": "pypi", + "version": "==1.0" }, "docopt": { "hashes": [ @@ -170,23 +149,25 @@ }, "docutils": { "hashes": [ - "sha256:7a4bd47eaf6596e1295ecb11361139febe29b084a87bf005bf899f9a42edc3c6", "sha256:02aec4bd92ab067f6ff27a38a38a41173bf01bed8f89157768c1573f53e474a6", - "sha256:51e64ef2ebfb29cae1faa133b3710143496eca21c530f3f71424d77687764274" + "sha256:51e64ef2ebfb29cae1faa133b3710143496eca21c530f3f71424d77687764274", + "sha256:7a4bd47eaf6596e1295ecb11361139febe29b084a87bf005bf899f9a42edc3c6" ], + "index": "pypi", "version": "==0.14" }, "flake8": { "hashes": [ - "sha256:7ac3bbaac27174d95bc4734ed23a07de567ffbcf4fc7e316854b4f3015d4fd15", - "sha256:231cd86194aaec4bdfaa553ae1a1cd9b7b4558332fbc10136c044940d587a778" + "sha256:231cd86194aaec4bdfaa553ae1a1cd9b7b4558332fbc10136c044940d587a778", + "sha256:7ac3bbaac27174d95bc4734ed23a07de567ffbcf4fc7e316854b4f3015d4fd15" ], + "index": "pypi", "version": "==2.6.2" }, "idna": { "hashes": [ - "sha256:8c7309c718f94b3a625cb648ace320157ad16ff131ae0af362c9f21b80ef6ec4", - "sha256:2c6a5de3089009e3da7c5dde64a141dbc8551d5b7f6cf4ed7c2568d0cc520a8f" + "sha256:2c6a5de3089009e3da7c5dde64a141dbc8551d5b7f6cf4ed7c2568d0cc520a8f", + "sha256:8c7309c718f94b3a625cb648ace320157ad16ff131ae0af362c9f21b80ef6ec4" ], "version": "==2.6" }, @@ -199,16 +180,25 @@ }, "livereload": { "hashes": [ - "sha256:5ed6506f5d526ee712da9f3739c27714e6f3376f3e481728d298efceae0ec83a", - "sha256:422de10d7ea9467a1ba27cbaffa84c74b809d96fb1598d9de4b9b676adf35e2c" + "sha256:422de10d7ea9467a1ba27cbaffa84c74b809d96fb1598d9de4b9b676adf35e2c", + "sha256:5ed6506f5d526ee712da9f3739c27714e6f3376f3e481728d298efceae0ec83a" ], "version": "==2.5.1" }, + "macfsevents": { + "hashes": [ + "sha256:1324b66b356051de662ba87d84f73ada062acd42b047ed1246e60a449f833e10" + ], + "index": "pypi", + "markers": "sys_platform == 'darwin'", + "version": "==0.8.1" + }, "markdown": { "hashes": [ "sha256:9ba587db9daee7ec761cfc656272be6aabe2ed300fece21208e4aab2e457bc8f", "sha256:a856869c7ff079ad84a3e19cd87a64998350c2b94e9e08e44270faef33400f81" ], + "index": "pypi", "version": "==2.6.11" }, "markupsafe": { @@ -219,32 +209,34 @@ }, "mccabe": { "hashes": [ - "sha256:f9b58bf366c1506dcd6117b33e5c4874746f0de859c9c7cab8b516cb6be1d22e", - "sha256:16293af41e7242031afd73896fef6458f4cad38201d21e28f344fff50ae1c25e" + "sha256:16293af41e7242031afd73896fef6458f4cad38201d21e28f344fff50ae1c25e", + "sha256:f9b58bf366c1506dcd6117b33e5c4874746f0de859c9c7cab8b516cb6be1d22e" ], "version": "==0.5.3" }, "mkdocs": { "hashes": [ - "sha256:150795179c32bde225a3596c57b677f856f544351e809048f654cab3fbac90bd", - "sha256:4a6b6b062347448ed42d5e8c0dce8f912e647ce4bd480fdea25017cd63aaa3a1" + "sha256:126e9b871adeb077facccc375066fddae1485c7deebe3f10f2052b9a15514fb9", + "sha256:5f4317fd593ea07798bdb083bc06ca4e6b1e745fd1240d459f03cd0af1d58692" ], - "version": "==0.17.2" + "index": "pypi", + "version": "==0.17.3" }, "nose": { "hashes": [ - "sha256:dadcddc0aefbf99eea214e0f1232b94f2fa9bd98fa8353711dacb112bfcbbb2a", "sha256:9ff7c6cc443f8c51994b34a667bbcf45afd6d945be7477b52e97516fd17c53ac", + "sha256:dadcddc0aefbf99eea214e0f1232b94f2fa9bd98fa8353711dacb112bfcbbb2a", "sha256:f1bffef9cbc82628f6e7d7b40d7e255aefaa1adb6a1b1d26c69a8b79e6208a98" ], + "index": "pypi", "version": "==1.3.7" }, "pkginfo": { "hashes": [ - "sha256:31a49103180ae1518b65d3f4ce09c784e2bc54e338197668b4fb7dc539521024", - "sha256:bb1a6aeabfc898f5df124e7e00303a5b3ec9a489535f346bfbddb081af93f89e" + "sha256:5878d542a4b3f237e359926384f1dde4e099c9f5525d236b1840cf704fa8d474", + "sha256:a39076cb3eb34c333a0dd390b568e9e1e881c7bf2cc0aee12120636816f55aee" ], - "version": "==1.4.1" + "version": "==1.4.2" }, "pycodestyle": { "hashes": [ @@ -255,34 +247,49 @@ }, "pyflakes": { "hashes": [ - "sha256:e87bac26c62ea5b45067cc89e4a12f56e1483f1f2cda17e7c9b375b9fd2f40da", - "sha256:2e4a1b636d8809d8f0a69f341acf15b2e401a3221ede11be439911d23ce2139e" + "sha256:2e4a1b636d8809d8f0a69f341acf15b2e401a3221ede11be439911d23ce2139e", + "sha256:e87bac26c62ea5b45067cc89e4a12f56e1483f1f2cda17e7c9b375b9fd2f40da" ], "version": "==1.2.3" }, + "pync": { + "hashes": [ + "sha256:85737aab9fc69cf59dc9fe831adbe94ac224944c05e297c98de3c2413f253530" + ], + "index": "pypi", + "markers": "sys_platform == 'darwin'", + "version": "==1.6.1" + }, + "python-dateutil": { + "hashes": [ + "sha256:07009062406cffd554a9b4135cd2ff167c9bf6b7aac61fe946c93e69fad1bbd8", + "sha256:8f95bb7e6edbb2456a51a1fb58c8dca942024b4f5844cae62c90aa88afe6e300" + ], + "version": "==2.7.0" + }, "python-termstyle": { "hashes": [ - "sha256:f42a6bb16fbfc5e2c66d553e7ad46524ea833872f75ee5d827c15115fafc94e2", - "sha256:6faf42ba42f2826c38cf70dacb3ac51f248a418e48afc0e36593df11cf3ab1d2" + "sha256:6faf42ba42f2826c38cf70dacb3ac51f248a418e48afc0e36593df11cf3ab1d2", + "sha256:f42a6bb16fbfc5e2c66d553e7ad46524ea833872f75ee5d827c15115fafc94e2" ], "version": "==0.1.10" }, "pyyaml": { "hashes": [ - "sha256:3262c96a1ca437e7e4763e2843746588a965426550f3797a79fca9c6199c431f", + "sha256:0c507b7f74b3d2dd4d1322ec8a94794927305ab4cebbe89cc47fe5e81541e6e8", "sha256:16b20e970597e051997d90dc2cddc713a2876c47e3d92d59ee198700c5427736", - "sha256:e863072cdf4c72eebf179342c94e6989c67185842d9997960b3e69290b2fa269", - "sha256:bc6bced57f826ca7cb5125a10b23fd0f2fff3b7c4701d64c439a300ce665fff8", - "sha256:c01b880ec30b5a6e6aa67b09a2fe3fb30473008c85cd6a67359a1b15ed6d83a4", - "sha256:827dc04b8fa7d07c44de11fabbc888e627fa8293b695e0f99cb544fdfa1bf0d1", + "sha256:3262c96a1ca437e7e4763e2843746588a965426550f3797a79fca9c6199c431f", + "sha256:326420cbb492172dec84b0f65c80942de6cedb5233c413dd824483989c000608", + "sha256:4474f8ea030b5127225b8894d626bb66c01cda098d47a2b0d3429b6700af9fd8", "sha256:592766c6303207a20efc445587778322d7f73b161bd994f227adaa341ba212ab", + "sha256:5ac82e411044fb129bae5cfbeb3ba626acb2af31a8d17d175004b70862a741a7", "sha256:5f84523c076ad14ff5e6c037fe1c89a7f73a3e04cf0377cb4d017014976433f3", - "sha256:0c507b7f74b3d2dd4d1322ec8a94794927305ab4cebbe89cc47fe5e81541e6e8", + "sha256:827dc04b8fa7d07c44de11fabbc888e627fa8293b695e0f99cb544fdfa1bf0d1", "sha256:b4c423ab23291d3945ac61346feeb9a0dc4184999ede5e7c43e1ffb975130ae6", + "sha256:bc6bced57f826ca7cb5125a10b23fd0f2fff3b7c4701d64c439a300ce665fff8", + "sha256:c01b880ec30b5a6e6aa67b09a2fe3fb30473008c85cd6a67359a1b15ed6d83a4", "sha256:ca233c64c6e40eaa6c66ef97058cdc80e8d0157a443655baa1b2966e812807ca", - "sha256:4474f8ea030b5127225b8894d626bb66c01cda098d47a2b0d3429b6700af9fd8", - "sha256:326420cbb492172dec84b0f65c80942de6cedb5233c413dd824483989c000608", - "sha256:5ac82e411044fb129bae5cfbeb3ba626acb2af31a8d17d175004b70862a741a7" + "sha256:e863072cdf4c72eebf179342c94e6989c67185842d9997960b3e69290b2fa269" ], "version": "==3.12" }, @@ -300,17 +307,10 @@ ], "version": "==0.8.0" }, - "singledispatch": { - "hashes": [ - "sha256:833b46966687b3de7f438c761ac475213e53b306740f1abfaa86e1d1aae56aa8", - "sha256:5b06af87df13818d14f08a028e42f566640aef80805c3b50c5056b086e3c2b9c" - ], - "version": "==3.4.0.3" - }, "six": { "hashes": [ - "sha256:832dc0e10feb1aa2c68dcc57dbb658f1c7e65b9b61af69048abc87a2db00a0eb", - "sha256:70e8a77beed4562e7f14fe23a786b54f6296e34344c23bc42f07b15018ff98e9" + "sha256:70e8a77beed4562e7f14fe23a786b54f6296e34344c23bc42f07b15018ff98e9", + "sha256:832dc0e10feb1aa2c68dcc57dbb658f1c7e65b9b61af69048abc87a2db00a0eb" ], "version": "==1.11.0" }, @@ -319,31 +319,33 @@ "sha256:e8a0daa4c51dff3d00482b45dc9b978159100a8d5a7df327c28ed96586559970", "sha256:e90c1ad4bd3c31a5fad8e03d45dfc83377b31420aa0779f17280c817ce0c9dd8" ], + "index": "pypi", "version": "==0.4.0" }, "tornado": { "hashes": [ + "sha256:5ef073ac6180038ccf99411fe05ae9aafb675952a2c8db60592d5daf8401f803", + "sha256:6d14e47eab0e15799cf3cdcc86b0b98279da68522caace2bd7ce644287685f0a", "sha256:92b7ca81e18ba9ec3031a7ee73d4577ac21d41a0c9b775a9182f43301c3b5f8e", - "sha256:b36298e9f63f18cad97378db2222c0e0ca6a55f6304e605515e05a25483ed51a", "sha256:ab587996fe6fb9ce65abfda440f9b61e4f9f2cf921967723540679176915e4c3", - "sha256:5ef073ac6180038ccf99411fe05ae9aafb675952a2c8db60592d5daf8401f803", - "sha256:6d14e47eab0e15799cf3cdcc86b0b98279da68522caace2bd7ce644287685f0a" + "sha256:b36298e9f63f18cad97378db2222c0e0ca6a55f6304e605515e05a25483ed51a" ], "version": "==4.5.3" }, "tqdm": { "hashes": [ - "sha256:4c041f8019f7be65b8028ddde9a836f7ccc51c4637f1ff2ba9b5813d38d19d5a", - "sha256:df32e6f127dc0ccbc675eadb33f749abbcb8f174c5cb9ec49c0cdb73aa737377" + "sha256:05e991ecb0f874046ddcb374396a626afd046fb4d31f73633ea752b844458a7a", + "sha256:2aea9f81fdf127048667e0ba22f5fc10ebc879fb838dc52dcf055242037ec1f7" ], - "version": "==4.19.5" + "version": "==4.19.8" }, "twine": { "hashes": [ - "sha256:d3ce5c480c22ccfb761cd358526e862b32546d2fe4bc93d46b5cf04ea3cc46ca", - "sha256:caa45b7987fc96321258cd7668e3be2ff34064f5c66d2d975b641adca659c1ab" + "sha256:08eb132bbaec40c6d25b358f546ec1dc96ebd2638a86eea68769d9e67fe2b129", + "sha256:2fd9a4d9ff0bcacf41fdc40c8cb0cfaef1f1859457c9653fd1b92237cc4e9f25" ], - "version": "==1.9.1" + "index": "pypi", + "version": "==1.11.0" }, "urllib3": { "hashes": [ From bd72d356940be30c26afce96cc8d907ae0b5cfc7 Mon Sep 17 00:00:00 2001 From: Jace Browning Date: Thu, 26 Apr 2018 18:27:30 -0400 Subject: [PATCH 33/87] Add Flask 1.0 support; Drop Python 3.3 support --- .gitignore | 1 - .scrutinizer.yml | 4 ++ .travis.yml | 14 ++--- CONTRIBUTING.md | 2 +- Makefile | 149 ++++++++++++----------------------------------- Pipfile | 2 +- Pipfile.lock | 22 +++---- README.md | 2 +- scent.py | 2 +- setup.py | 3 +- 10 files changed, 64 insertions(+), 137 deletions(-) diff --git a/.gitignore b/.gitignore index 62c63c8..edcf3b4 100644 --- a/.gitignore +++ b/.gitignore @@ -30,7 +30,6 @@ Icon* *.gdraw # Testing and coverage results -/.pytest/ /.coverage /.coverage.* /htmlcov/ diff --git a/.scrutinizer.yml b/.scrutinizer.yml index 1504dc2..d04d2a2 100644 --- a/.scrutinizer.yml +++ b/.scrutinizer.yml @@ -1,3 +1,7 @@ +build: + tests: + override: + - pylint-run --rcfile=.pylint.ini checks: python: code_rating: true diff --git a/.travis.yml b/.travis.yml index 4683e15..439b9ae 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,7 +1,6 @@ language: python python: - 2.7 - - 3.3 - 3.4 - 3.5 - 3.6 @@ -13,21 +12,20 @@ cache: env: global: - - RANDOM_SEED=0 - - PIPENV_NOSPIN=true + - RANDOM_SEED=0 matrix: - - FLASK_VERSION=0.10.1 - - FLASK_VERSION=0.11.1 - - FLASK_VERSION=0.12.2 + - FLASK_VERSION=0.10.1 + - FLASK_VERSION=0.11.1 + - FLASK_VERSION=0.12.2 + - FLASK_VERSION=1.0.0 before_install: - - pip install pipenv~=5.0 + - pip install pipenv install: - make install before_script: - # Override the version of Flask based on the build matrix - pipenv run pip install flask==${FLASK_VERSION} script: diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 9086992..d66699e 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -41,7 +41,7 @@ $ make watch Build the documentation: ```sh -$ make doc +$ make docs ``` ### Static Analysis diff --git a/Makefile b/Makefile index e95f7ca..f9c87cf 100644 --- a/Makefile +++ b/Makefile @@ -8,51 +8,12 @@ PACKAGES := $(PACKAGE) tests CONFIG := $(wildcard *.py) MODULES := $(wildcard $(PACKAGE)/*.py) -# Python settings -PYTHON_MAJOR ?= 2 -PYTHON_MINOR ?= 7 - -# System paths -PLATFORM := $(shell python -c 'import sys; print(sys.platform)') -ifneq ($(findstring win32, $(PLATFORM)), ) - WINDOWS := true - SYS_PYTHON_DIR := C:\\Python$(PYTHON_MAJOR)$(PYTHON_MINOR) - SYS_PYTHON := $(SYS_PYTHON_DIR)\\python.exe - # https://bugs.launchpad.net/virtualenv/+bug/449537 - export TCL_LIBRARY=$(SYS_PYTHON_DIR)\\tcl\\tcl8.5 -else - ifneq ($(findstring darwin, $(PLATFORM)), ) - MAC := true - else - LINUX := true - endif - SYS_PYTHON := python$(PYTHON_MAJOR) - ifdef PYTHON_MINOR - SYS_PYTHON := $(SYS_PYTHON).$(PYTHON_MINOR) - endif -endif - # Virtual environment paths -ENV := .venv -ifneq ($(findstring win32, $(PLATFORM)), ) - BIN := $(ENV)/Scripts - ACTIVATE := $(BIN)/activate.bat - OPEN := cmd /c start - PYTHON := $(BIN)/python.exe - PIP := $(BIN)/pip.exe -else - BIN := $(ENV)/bin - ACTIVATE := . $(BIN)/activate - ifneq ($(findstring cygwin, $(PLATFORM)), ) - OPEN := cygstart - else - OPEN := open - endif - PYTHON := $(BIN)/python - PIP := $(BIN)/pip -endif +export PIPENV_VENV_IN_PROJECT=true +export PIPENV_IGNORE_VIRTUALENVS=true +VENV := .venv -# MAIN TASKS ################################################################### +# MAIN TASKS ################################################################## SNIFFER := pipenv run sniffer @@ -68,33 +29,21 @@ watch: install .clean-test ## Continuously run all CI tasks when files chanage .PHONY: run ## Start the program run: install - $(PYTHON) $(PACKAGE)/__main__.py + pipenv run python $(PACKAGE)/__main__.py -# PROJECT DEPENDENCIES ######################################################### +# PROJECT DEPENDENCIES ######################################################## -export PIPENV_SHELL_COMPAT=true -export PIPENV_VENV_IN_PROJECT=true -export PIPENV_IGNORE_VIRTUALENVS=true - -DEPENDENCIES := $(ENV)/.installed -METADATA := *.egg-info +DEPENDENCIES := $(VENV)/.installed .PHONY: install -install: $(DEPENDENCIES) $(METADATA) +install: $(DEPENDENCIES) -$(DEPENDENCIES): $(PIP) Pipfile* +$(DEPENDENCIES): Pipfile* setup.py + pipenv run python setup.py develop pipenv install --dev @ touch $@ -$(METADATA): $(PYTHON) setup.py - $(PYTHON) setup.py develop - @ touch $@ - -$(PYTHON) $(PIP): - pipenv --python=$(SYS_PYTHON) - pipenv run pip --version - -# CHECKS ####################################################################### +# CHECKS ###################################################################### FLAKE8 := pipenv run flake8 @@ -105,7 +54,7 @@ check: flake8 ## Run linters and static analysis flake8: install $(FLAKE8) flask_api --ignore=E128,E501 --exclude=__init__.py -# TESTS ######################################################################## +# TESTS ####################################################################### NOSE := pipenv run nosetests COVERAGE := pipenv run coverage @@ -125,16 +74,16 @@ test: install ## Run unit and integration tests .PHONY: read-coverage read-coverage: - $(OPEN) coverage/index.html + open htmlcov/index.html -# DOCUMENTATION ################################################################ +# DOCUMENTATION ############################################################### MKDOCS := pipenv run mkdocs MKDOCS_INDEX := site/index.html -.PHONY: doc -doc: mkdocs ## Generate documentation +.PHONY: docs +docs: mkdocs ## Generate documentation .PHONY: mkdocs mkdocs: install $(MKDOCS_INDEX) @@ -146,7 +95,7 @@ mkdocs-live: mkdocs eval "sleep 3; open http://127.0.0.1:8000" & $(MKDOCS) serve -# BUILD ######################################################################## +# BUILD ####################################################################### DIST_FILES := dist/*.tar.gz dist/*.whl @@ -154,75 +103,51 @@ DIST_FILES := dist/*.tar.gz dist/*.whl dist: install $(DIST_FILES) $(DIST_FILES): $(MODULES) rm -f $(DIST_FILES) - $(PYTHON) setup.py check --restructuredtext --strict --metadata - $(PYTHON) setup.py sdist - $(PYTHON) setup.py bdist_wheel + pipenv run python setup.py check --restructuredtext --strict --metadata + pipenv run python setup.py sdist + pipenv run python setup.py bdist_wheel # RELEASE ###################################################################### TWINE := pipenv run twine -.PHONY: register -register: dist ## Register the project on PyPI - @ echo NOTE: your project must be registered manually - @ echo https://github.com/pypa/python-packaging-user-guide/issues/263 - # TODO: switch to twine when the above issue is resolved - # $(TWINE) register dist/*.whl - .PHONY: upload -upload: .git-no-changes register ## Upload the current version to PyPI +upload: dist ## Upload the current version to PyPI + git diff --name-only --exit-code $(TWINE) upload dist/*.* - $(OPEN) https://pypi.python.org/pypi/$(PROJECT) - -.PHONY: .git-no-changes -.git-no-changes: - @ if git diff --name-only --exit-code; \ - then \ - echo Git working copy is clean...; \ - else \ - echo ERROR: Git working copy is dirty!; \ - echo Commit your changes and try again.; \ - exit -1; \ - fi; + open https://pypi.org/project/$(PROJECT) -# CLEANUP ###################################################################### +# CLEANUP ##################################################################### .PHONY: clean -clean: .clean-dist .clean-test .clean-doc .clean-build ## Delete all generated and temporary files +clean: .clean-build .clean-docs .clean-test .clean-install ## Delete all generated and temporary files .PHONY: clean-all -clean-all: clean .clean-env .clean-workspace +clean-all: clean + rm -rf $(VENV) -.PHONY: .clean-build -.clean-build: +.PHONY: .clean-install +.clean-install: find $(PACKAGES) -name '*.pyc' -delete find $(PACKAGES) -name '__pycache__' -delete rm -rf *.egg-info -.PHONY: .clean-doc -.clean-doc: - rm -rf README.rst docs/apidocs *.html site - .PHONY: .clean-test .clean-test: rm -rf .cache .pytest .coverage htmlcov xmlreport -.PHONY: .clean-dist -.clean-dist: - rm -rf *.spec dist build - -.PHONY: .clean-env -.clean-env: clean - rm -rf $(ENV) +.PHONY: .clean-docs +.clean-docs: + rm -rf *.rst docs/apidocs *.html docs/*.png site -.PHONY: .clean-workspace -.clean-workspace: - rm -rf *.sublime-workspace +.PHONY: .clean-build +.clean-build: + rm -rf *.spec dist build -# HELP ######################################################################### +# HELP ######################################################################## .PHONY: help help: all - @grep -E '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-30s\033[0m %s\n", $$1, $$2}' + @ grep -E '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-30s\033[0m %s\n", $$1, $$2}' .DEFAULT_GOAL := help diff --git a/Pipfile b/Pipfile index 7c273ae..b78b7c1 100644 --- a/Pipfile +++ b/Pipfile @@ -1,6 +1,6 @@ [[source]] -url = "https://pypi.python.org/simple" +url = "https://pypi.org/simple" verify_ssl = true name = "pypi" diff --git a/Pipfile.lock b/Pipfile.lock index 8d9aa66..3fa74de 100644 --- a/Pipfile.lock +++ b/Pipfile.lock @@ -1,14 +1,14 @@ { "_meta": { "hash": { - "sha256": "9d761bfd070ed0c943fa2dcdc6f90a33adfe77d387fc12962fd488d613340720" + "sha256": "294c934862a9e807b54fa42dd5753daa5e14b8f5f72634410172e2096ddfbcf1" }, "pipfile-spec": 6, "requires": {}, "sources": [ { "name": "pypi", - "url": "https://pypi.python.org/simple", + "url": "https://pypi.org/simple", "verify_ssl": true } ] @@ -66,10 +66,10 @@ }, "certifi": { "hashes": [ - "sha256:14131608ad2fd56836d33a71ee60fa1c82bc9d2c8d98b7bdbc631fe1b3cd1296", - "sha256:edbc3f203427eef571f79a7692bb160a2b0f7ccaa31953e99bd17e307cf63f7d" + "sha256:13e698f54293db9f89122b0581843a782ad0934a4fe0172d2a980ba77fc61bb7", + "sha256:9fa520c1bacfb634fa7af20a76bcbd3d5fb390481724c597da32c719a7dca4b0" ], - "version": "==2018.1.18" + "version": "==2018.4.16" }, "chardet": { "hashes": [ @@ -262,10 +262,10 @@ }, "python-dateutil": { "hashes": [ - "sha256:07009062406cffd554a9b4135cd2ff167c9bf6b7aac61fe946c93e69fad1bbd8", - "sha256:8f95bb7e6edbb2456a51a1fb58c8dca942024b4f5844cae62c90aa88afe6e300" + "sha256:3220490fb9741e2342e1cf29a503394fdac874bc39568288717ee67047ff29df", + "sha256:9d8074be4c993fbe4947878ce593052f71dac82932a677d49194d8ce9778002e" ], - "version": "==2.7.0" + "version": "==2.7.2" }, "python-termstyle": { "hashes": [ @@ -334,10 +334,10 @@ }, "tqdm": { "hashes": [ - "sha256:05e991ecb0f874046ddcb374396a626afd046fb4d31f73633ea752b844458a7a", - "sha256:2aea9f81fdf127048667e0ba22f5fc10ebc879fb838dc52dcf055242037ec1f7" + "sha256:22c760d05b2eb6e96a91ad7ed1b03c9c97e6256fb7716410c27c2cb3265a5913", + "sha256:d7bfa112a55290a5e2d0c3263a09b17b24240686fbf20d1ef7c5e8edfbb71ad0" ], - "version": "==4.19.8" + "version": "==4.23.1" }, "twine": { "hashes": [ diff --git a/README.md b/README.md index eb69591..d2bfab5 100644 --- a/README.md +++ b/README.md @@ -19,7 +19,7 @@ Flask API is a drop-in replacement for Flask that provides an implementation of Requirements: -* Python 2.7+ or 3.3+ +* Python 2.7+ or 3.4+ * Flask 0.10+ Install using `pip`: diff --git a/scent.py b/scent.py index 7906bd0..31b9083 100644 --- a/scent.py +++ b/scent.py @@ -25,7 +25,7 @@ class Options(object): targets = [ (('make', 'test'), "Run Tests", True), (('make', 'check'), "Static Analysis", True), - (('make', 'doc'), None, True), + (('make', 'docs'), None, True), ] diff --git a/setup.py b/setup.py index 4be573a..ba6468d 100755 --- a/setup.py +++ b/setup.py @@ -75,8 +75,9 @@ def get_package_data(package): 'Natural Language :: English', 'Operating System :: OS Independent', 'Programming Language :: Python', + 'Programming Language :: Python :: 2', + 'Programming Language :: Python :: 2.7', 'Programming Language :: Python :: 3', - 'Programming Language :: Python :: 3.3', 'Programming Language :: Python :: 3.4', 'Programming Language :: Python :: 3.5', 'Programming Language :: Python :: 3.6', From f38375e573b688d54afa101280d8aef37db5cb2d Mon Sep 17 00:00:00 2001 From: Jace Browning Date: Thu, 26 Apr 2018 18:31:49 -0400 Subject: [PATCH 34/87] Test against the latest version of 0.12.x --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 439b9ae..151b713 100644 --- a/.travis.yml +++ b/.travis.yml @@ -16,7 +16,7 @@ env: matrix: - FLASK_VERSION=0.10.1 - FLASK_VERSION=0.11.1 - - FLASK_VERSION=0.12.2 + - FLASK_VERSION=0.12.3 - FLASK_VERSION=1.0.0 before_install: From ea01422031d2272cbb716fbf22266638859df06d Mon Sep 17 00:00:00 2001 From: Jace Browning Date: Thu, 26 Apr 2018 18:49:19 -0400 Subject: [PATCH 35/87] Update README.md --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index d2bfab5..784b1fd 100644 --- a/README.md +++ b/README.md @@ -7,11 +7,11 @@ Browsable web APIs for Flask. [![Scrutinizer Code Quality](https://img.shields.io/scrutinizer/g/flask-api/flask-api.svg)](https://scrutinizer-ci.com/g/flask-api/flask-api/) [![PyPI Version](https://img.shields.io/pypi/v/Flask-API.svg)](https://pypi.org/project/Flask-API/) -**Status**: This project is in maintenance mode. The original author ([Tom Christie](https://twitter.com/_tomchristie)) has shifted his focus to the ["API Star" project](https://github.com/encode/apistar). Passing PRs will still be considered for releases by the maintainers ([Jace Browning](https://twitter.com/jacebrowning)). +**Status**: This project is in maintenance mode. The original author ([Tom Christie](https://twitter.com/_tomchristie)) has shifted his focus to the ["API Star" project](https://github.com/encode/apistar). Passing PRs will still be considered for releases by the maintainer ([Jace Browning](https://twitter.com/jacebrowning)). ## Overview -Flask API is a drop-in replacement for Flask that provides an implementation of browsable APIs similar to what [Django REST framework](http://www.django-rest-framework.org) provides. It gives you properly content negotiated-responses and smart request parsing: +Flask API is a drop-in replacement for Flask that provides an implementation of browsable APIs similar to what [Django REST framework](http://www.django-rest-framework.org) offers. It gives you properly content negotiated-responses and smart request parsing: ![Screenshot](docs/screenshot.png) @@ -40,7 +40,7 @@ Return any valid response object as normal, or return a `list` or `dict`. def example(): return {'hello': 'world'} -A renderer for the response data will be selected using content negotiation based on the client 'Accept' header. If you're making the API request from a regular client, this will default to a JSON response. If you're viewing the API in a browser it'll default to the browsable API HTML. +A renderer for the response data will be selected using content negotiation based on the client 'Accept' header. If you're making the API request from a regular client, this will default to a JSON response. If you're viewing the API in a browser, it'll default to the browsable API HTML. ## Requests From 35d468d9e902ea1105a6063f79c694ca7f21639f Mon Sep 17 00:00:00 2001 From: Jace Browning Date: Sat, 30 Jun 2018 15:27:26 -0400 Subject: [PATCH 36/87] Fix grammar --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 784b1fd..fb5430c 100644 --- a/README.md +++ b/README.md @@ -7,11 +7,11 @@ Browsable web APIs for Flask. [![Scrutinizer Code Quality](https://img.shields.io/scrutinizer/g/flask-api/flask-api.svg)](https://scrutinizer-ci.com/g/flask-api/flask-api/) [![PyPI Version](https://img.shields.io/pypi/v/Flask-API.svg)](https://pypi.org/project/Flask-API/) -**Status**: This project is in maintenance mode. The original author ([Tom Christie](https://twitter.com/_tomchristie)) has shifted his focus to the ["API Star" project](https://github.com/encode/apistar). Passing PRs will still be considered for releases by the maintainer ([Jace Browning](https://twitter.com/jacebrowning)). +**Status**: This project is in maintenance mode. The original author ([Tom Christie](https://twitter.com/_tomchristie)) has shifted his focus to [API Star](https://github.com/encode/apistar). Passing PRs will still be considered for releases by the maintainer ([Jace Browning](https://twitter.com/jacebrowning)). ## Overview -Flask API is a drop-in replacement for Flask that provides an implementation of browsable APIs similar to what [Django REST framework](http://www.django-rest-framework.org) offers. It gives you properly content negotiated-responses and smart request parsing: +Flask API is a drop-in replacement for Flask that provides an implementation of browsable APIs similar to what [Django REST framework](http://www.django-rest-framework.org) offers. It gives you properly content-negotiated responses and smart request parsing: ![Screenshot](docs/screenshot.png) From 45a7efbf72388273335e73c8b2e3532becf086c6 Mon Sep 17 00:00:00 2001 From: Songkran Nethan Date: Fri, 9 Nov 2018 15:38:52 +0700 Subject: [PATCH 37/87] Fixed importing statement Using flask_api instead of flask.ext.api --- docs/api-guide/status-codes.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/api-guide/status-codes.md b/docs/api-guide/status-codes.md index f72c800..837a774 100644 --- a/docs/api-guide/status-codes.md +++ b/docs/api-guide/status-codes.md @@ -2,7 +2,7 @@ Flask API includes a set of named constants that you can use to make more code more obvious and readable. - from flask.ext.api import status + from flask_api import status ... @@ -15,7 +15,7 @@ The full set of HTTP status codes included in the `status` module is listed belo The module also includes a set of helper functions for testing if a status code is in a given range. - from flask.ext.api import status + from flask_api import status import unittest ... From de1a55d2469a624b0f4dc16609c3ed30e2566e9f Mon Sep 17 00:00:00 2001 From: Jace Browning Date: Fri, 16 Nov 2018 08:45:00 -0500 Subject: [PATCH 38/87] Document that Markdown 3.0 is not supported --- docs/index.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/index.md b/docs/index.md index 4bdbcca..78460aa 100644 --- a/docs/index.md +++ b/docs/index.md @@ -19,7 +19,7 @@ Requirements: The following packages are optional: -* Markdown (2.1.0+) - Markdown support for the browsable API. +* Markdown (`2.1.0+, <3.0`): Markdown support for the browsable API Install using `pip`: From 8acc41c45d02393c54f5f0e5423b919e405d4856 Mon Sep 17 00:00:00 2001 From: Jace Browning Date: Mon, 19 Nov 2018 11:18:21 -0500 Subject: [PATCH 39/87] Drop support for earlier versions of Flask --- .travis.yml | 6 +- Makefile | 4 +- Pipfile | 6 +- Pipfile.lock | 285 +++++++++++++++++++++++------------- README.md | 2 +- docs/about/release-notes.md | 1 + docs/index.md | 4 +- setup.py | 2 +- 8 files changed, 196 insertions(+), 114 deletions(-) diff --git a/.travis.yml b/.travis.yml index 151b713..948b7ae 100644 --- a/.travis.yml +++ b/.travis.yml @@ -14,10 +14,8 @@ env: global: - RANDOM_SEED=0 matrix: - - FLASK_VERSION=0.10.1 - - FLASK_VERSION=0.11.1 - - FLASK_VERSION=0.12.3 - - FLASK_VERSION=1.0.0 + - FLASK_VERSION=0.12.4 + - FLASK_VERSION=1.0.2 before_install: - pip install pipenv diff --git a/Makefile b/Makefile index f9c87cf..121c48f 100644 --- a/Makefile +++ b/Makefile @@ -58,7 +58,7 @@ flake8: install NOSE := pipenv run nosetests COVERAGE := pipenv run coverage -COVERAGE_SPACE := pipenv run coverage.space +COVERAGESPACE := pipenv run coveragespace RANDOM_SEED ?= $(shell date +%s) @@ -70,7 +70,7 @@ endif .PHONY: test test: install ## Run unit and integration tests $(NOSE) $(PACKAGE) $(NOSE_OPTIONS) - $(COVERAGE_SPACE) $(REPOSITORY) overall + $(COVERAGESPACE) $(REPOSITORY) overall .PHONY: read-coverage read-coverage: diff --git a/Pipfile b/Pipfile index b78b7c1..44c7127 100644 --- a/Pipfile +++ b/Pipfile @@ -6,8 +6,8 @@ name = "pypi" [packages] -Flask = "~=0.10.1" -Markdown = "*" +Flask = "*" +Markdown = "<3" [dev-packages] @@ -18,7 +18,7 @@ flake8 = "~=2.1" nose = "*" # Reports -coverage-space = "*" +coveragespace = "*" # Documentation mkdocs = "~=0.17.2" diff --git a/Pipfile.lock b/Pipfile.lock index 3fa74de..95649e3 100644 --- a/Pipfile.lock +++ b/Pipfile.lock @@ -1,7 +1,7 @@ { "_meta": { "hash": { - "sha256": "294c934862a9e807b54fa42dd5753daa5e14b8f5f72634410172e2096ddfbcf1" + "sha256": "594412d0816530df7cf2020970de492e606ceb3d28c3c1172b312917c11f9ce6" }, "pipfile-spec": 6, "requires": {}, @@ -14,18 +14,27 @@ ] }, "default": { + "click": { + "hashes": [ + "sha256:2335065e6395b9e67ca716de5f7526736bfa6ceead690adf616d925bdc622b13", + "sha256:5b94b49521f6456670fdb30cd82a4eca9412788a93fa6dd6df72c94d5a8ff2d7" + ], + "version": "==7.0" + }, "flask": { "hashes": [ - "sha256:4c83829ff83d408b5e1d4995472265411d2c414112298f2eb4b359d9e4563373" + "sha256:2271c0070dbcb5275fad4a82e29f23ab92682dc45f9dfbc22c02ba9b9322ce48", + "sha256:a080b744b7e345ccfcbc77954861cb05b3c63786e93f2b3875e0913d44b43f05" ], "index": "pypi", - "version": "==0.10.1" + "version": "==1.0.2" }, "itsdangerous": { "hashes": [ - "sha256:cbb3fcf8d3e33df861709ecaf89d9e6629cff0a217bc2848f1b41cd30d360519" + "sha256:321b033d07f2a4136d3ec762eac9f16a10ccd60f53c0c91af90217ace7ba1f19", + "sha256:b12271b2047cb23eeb98c8b5622e2e5c5e9abd9784a153e9d8ef9cb4dd09d749" ], - "version": "==0.24" + "version": "==1.1.0" }, "jinja2": { "hashes": [ @@ -44,9 +53,36 @@ }, "markupsafe": { "hashes": [ - "sha256:a6be69091dac236ea9c6bc7d012beab42010fa914c459791d627dad4910eb665" - ], - "version": "==1.0" + "sha256:048ef924c1623740e70204aa7143ec592504045ae4429b59c30054cb31e3c432", + "sha256:130f844e7f5bdd8e9f3f42e7102ef1d49b2e6fdf0d7526df3f87281a532d8c8b", + "sha256:19f637c2ac5ae9da8bfd98cef74d64b7e1bb8a63038a3505cd182c3fac5eb4d9", + "sha256:1b8a7a87ad1b92bd887568ce54b23565f3fd7018c4180136e1cf412b405a47af", + "sha256:1c25694ca680b6919de53a4bb3bdd0602beafc63ff001fea2f2fc16ec3a11834", + "sha256:1f19ef5d3908110e1e891deefb5586aae1b49a7440db952454b4e281b41620cd", + "sha256:1fa6058938190ebe8290e5cae6c351e14e7bb44505c4a7624555ce57fbbeba0d", + "sha256:31cbb1359e8c25f9f48e156e59e2eaad51cd5242c05ed18a8de6dbe85184e4b7", + "sha256:3e835d8841ae7863f64e40e19477f7eb398674da6a47f09871673742531e6f4b", + "sha256:4e97332c9ce444b0c2c38dd22ddc61c743eb208d916e4265a2a3b575bdccb1d3", + "sha256:525396ee324ee2da82919f2ee9c9e73b012f23e7640131dd1b53a90206a0f09c", + "sha256:52b07fbc32032c21ad4ab060fec137b76eb804c4b9a1c7c7dc562549306afad2", + "sha256:52ccb45e77a1085ec5461cde794e1aa037df79f473cbc69b974e73940655c8d7", + "sha256:5c3fbebd7de20ce93103cb3183b47671f2885307df4a17a0ad56a1dd51273d36", + "sha256:5e5851969aea17660e55f6a3be00037a25b96a9b44d2083651812c99d53b14d1", + "sha256:5edfa27b2d3eefa2210fb2f5d539fbed81722b49f083b2c6566455eb7422fd7e", + "sha256:7d263e5770efddf465a9e31b78362d84d015cc894ca2c131901a4445eaa61ee1", + "sha256:83381342bfc22b3c8c06f2dd93a505413888694302de25add756254beee8449c", + "sha256:857eebb2c1dc60e4219ec8e98dfa19553dae33608237e107db9c6078b1167856", + "sha256:98e439297f78fca3a6169fd330fbe88d78b3bb72f967ad9961bcac0d7fdd1550", + "sha256:bf54103892a83c64db58125b3f2a43df6d2cb2d28889f14c78519394feb41492", + "sha256:d9ac82be533394d341b41d78aca7ed0e0f4ba5a2231602e2f05aa87f25c51672", + "sha256:e982fe07ede9fada6ff6705af70514a52beb1b2c3d25d4e873e82114cf3c5401", + "sha256:edce2ea7f3dfc981c4ddc97add8a61381d9642dc3273737e756517cc03e84dd6", + "sha256:efdc45ef1afc238db84cb4963aa689c0408912a0239b0721cb172b4016eb31d6", + "sha256:f137c02498f8b935892d5c0172560d7ab54bc45039de8805075e19079c639a9c", + "sha256:f82e347a72f955b7017a39708a3667f106e6ad4d10b25f237396a7115d8ed5fd", + "sha256:fb7c206e01ad85ce57feeaaa0bf784b97fa3cad0d4a5737bc5295785f5c613a1" + ], + "version": "==1.1.0" }, "werkzeug": { "hashes": [ @@ -64,12 +100,19 @@ ], "version": "==1.0.0" }, + "bleach": { + "hashes": [ + "sha256:48d39675b80a75f6d1c3bdbffec791cf0bbbab665cf01e20da701c77de278718", + "sha256:73d26f018af5d5adcdabf5c1c974add4361a9c76af215fe32fdec8a6fc5fb9b9" + ], + "version": "==3.0.2" + }, "certifi": { "hashes": [ - "sha256:13e698f54293db9f89122b0581843a782ad0934a4fe0172d2a980ba77fc61bb7", - "sha256:9fa520c1bacfb634fa7af20a76bcbd3d5fb390481724c597da32c719a7dca4b0" + "sha256:339dc09518b07e2fa7eda5450740925974815557727d6bd35d319c1524a04a4c", + "sha256:6d58c986d22b038c8c0df30d639f23a3e6d172a05c3583e766f4c0b785c0986a" ], - "version": "==2018.4.16" + "version": "==2018.10.15" }, "chardet": { "hashes": [ @@ -80,10 +123,10 @@ }, "click": { "hashes": [ - "sha256:29f99fc6125fbc931b758dc053b3114e55c77a6e4c6c3a2674a2dc986016381d", - "sha256:f15516df478d5a56180fbf80e68f206010e6d160fc39fa508b65e035fd75130b" + "sha256:2335065e6395b9e67ca716de5f7526736bfa6ceead690adf616d925bdc622b13", + "sha256:5b94b49521f6456670fdb30cd82a4eca9412788a93fa6dd6df72c94d5a8ff2d7" ], - "version": "==6.7" + "version": "==7.0" }, "colorama": { "hashes": [ @@ -94,52 +137,47 @@ }, "coverage": { "hashes": [ - "sha256:03481e81d558d30d230bc12999e3edffe392d244349a90f4ef9b88425fac74ba", - "sha256:0b136648de27201056c1869a6c0d4e23f464750fd9a9ba9750b8336a244429ed", - "sha256:104ab3934abaf5be871a583541e8829d6c19ce7bde2923b2751e0d3ca44db60a", - "sha256:15b111b6a0f46ee1a485414a52a7ad1d703bdf984e9ed3c288a4414d3871dcbd", - "sha256:198626739a79b09fa0a2f06e083ffd12eb55449b5f8bfdbeed1df4910b2ca640", - "sha256:1c383d2ef13ade2acc636556fd544dba6e14fa30755f26812f54300e401f98f2", - "sha256:28b2191e7283f4f3568962e373b47ef7f0392993bb6660d079c62bd50fe9d162", - "sha256:2eb564bbf7816a9d68dd3369a510be3327f1c618d2357fa6b1216994c2e3d508", - "sha256:337ded681dd2ef9ca04ef5d93cfc87e52e09db2594c296b4a0a3662cb1b41249", - "sha256:3a2184c6d797a125dca8367878d3b9a178b6fdd05fdc2d35d758c3006a1cd694", - "sha256:3c79a6f7b95751cdebcd9037e4d06f8d5a9b60e4ed0cd231342aa8ad7124882a", - "sha256:3d72c20bd105022d29b14a7d628462ebdc61de2f303322c0212a054352f3b287", - "sha256:3eb42bf89a6be7deb64116dd1cc4b08171734d721e7a7e57ad64cc4ef29ed2f1", - "sha256:4635a184d0bbe537aa185a34193898eee409332a8ccb27eea36f262566585000", - "sha256:56e448f051a201c5ebbaa86a5efd0ca90d327204d8b059ab25ad0f35fbfd79f1", - "sha256:5a13ea7911ff5e1796b6d5e4fbbf6952381a611209b736d48e675c2756f3f74e", - "sha256:69bf008a06b76619d3c3f3b1983f5145c75a305a0fea513aca094cae5c40a8f5", - "sha256:6bc583dc18d5979dc0f6cec26a8603129de0304d5ae1f17e57a12834e7235062", - "sha256:701cd6093d63e6b8ad7009d8a92425428bc4d6e7ab8d75efbb665c806c1d79ba", - "sha256:7608a3dd5d73cb06c531b8925e0ef8d3de31fed2544a7de6c63960a1e73ea4bc", - "sha256:76ecd006d1d8f739430ec50cc872889af1f9c1b6b8f48e29941814b09b0fd3cc", - "sha256:7aa36d2b844a3e4a4b356708d79fd2c260281a7390d678a10b91ca595ddc9e99", - "sha256:7d3f553904b0c5c016d1dad058a7554c7ac4c91a789fca496e7d8347ad040653", - "sha256:7e1fe19bd6dce69d9fd159d8e4a80a8f52101380d5d3a4d374b6d3eae0e5de9c", - "sha256:8c3cb8c35ec4d9506979b4cf90ee9918bc2e49f84189d9bf5c36c0c1119c6558", - "sha256:9d6dd10d49e01571bf6e147d3b505141ffc093a06756c60b053a859cb2128b1f", - "sha256:9e112fcbe0148a6fa4f0a02e8d58e94470fc6cb82a5481618fea901699bf34c4", - "sha256:ac4fef68da01116a5c117eba4dd46f2e06847a497de5ed1d64bb99a5fda1ef91", - "sha256:b8815995e050764c8610dbc82641807d196927c3dbed207f0a079833ffcf588d", - "sha256:be6cfcd8053d13f5f5eeb284aa8a814220c3da1b0078fa859011c7fffd86dab9", - "sha256:c1bb572fab8208c400adaf06a8133ac0712179a334c09224fb11393e920abcdd", - "sha256:de4418dadaa1c01d497e539210cb6baa015965526ff5afc078c57ca69160108d", - "sha256:e05cb4d9aad6233d67e0541caa7e511fa4047ed7750ec2510d466e806e0255d6", - "sha256:e4d96c07229f58cb686120f168276e434660e4358cc9cf3b0464210b04913e77", - "sha256:f3f501f345f24383c0000395b26b726e46758b71393267aeae0bd36f8b3ade80", - "sha256:f8a923a85cb099422ad5a2e345fe877bbc89a8a8b23235824a93488150e45f6e" - ], - "version": "==4.5.1" - }, - "coverage-space": { - "hashes": [ - "sha256:e68f7451acee5b23f1ec374739e6011321712db319eee9b8e264d5d28911f701", - "sha256:e89e898bdbb4aa45ccb57124a5136e4c03a73711919e8e23b6110400c61017cd" + "sha256:09e47c529ff77bf042ecfe858fb55c3e3eb97aac2c87f0349ab5a7efd6b3939f", + "sha256:0a1f9b0eb3aa15c990c328535655847b3420231af299386cfe5efc98f9c250fe", + "sha256:0cc941b37b8c2ececfed341444a456912e740ecf515d560de58b9a76562d966d", + "sha256:10e8af18d1315de936d67775d3a814cc81d0747a1a0312d84e27ae5610e313b0", + "sha256:1b4276550b86caa60606bd3572b52769860a81a70754a54acc8ba789ce74d607", + "sha256:1e8a2627c48266c7b813975335cfdea58c706fe36f607c97d9392e61502dc79d", + "sha256:2b224052bfd801beb7478b03e8a66f3f25ea56ea488922e98903914ac9ac930b", + "sha256:447c450a093766744ab53bf1e7063ec82866f27bcb4f4c907da25ad293bba7e3", + "sha256:46101fc20c6f6568561cdd15a54018bb42980954b79aa46da8ae6f008066a30e", + "sha256:4710dc676bb4b779c4361b54eb308bc84d64a2fa3d78e5f7228921eccce5d815", + "sha256:510986f9a280cd05189b42eee2b69fecdf5bf9651d4cd315ea21d24a964a3c36", + "sha256:5535dda5739257effef56e49a1c51c71f1d37a6e5607bb25a5eee507c59580d1", + "sha256:5a7524042014642b39b1fcae85fb37556c200e64ec90824ae9ecf7b667ccfc14", + "sha256:5f55028169ef85e1fa8e4b8b1b91c0b3b0fa3297c4fb22990d46ff01d22c2d6c", + "sha256:6694d5573e7790a0e8d3d177d7a416ca5f5c150742ee703f3c18df76260de794", + "sha256:6831e1ac20ac52634da606b658b0b2712d26984999c9d93f0c6e59fe62ca741b", + "sha256:77f0d9fa5e10d03aa4528436e33423bfa3718b86c646615f04616294c935f840", + "sha256:828ad813c7cdc2e71dcf141912c685bfe4b548c0e6d9540db6418b807c345ddd", + "sha256:85a06c61598b14b015d4df233d249cd5abfa61084ef5b9f64a48e997fd829a82", + "sha256:8cb4febad0f0b26c6f62e1628f2053954ad2c555d67660f28dfb1b0496711952", + "sha256:a5c58664b23b248b16b96253880b2868fb34358911400a7ba39d7f6399935389", + "sha256:aaa0f296e503cda4bc07566f592cd7a28779d433f3a23c48082af425d6d5a78f", + "sha256:ab235d9fe64833f12d1334d29b558aacedfbca2356dfb9691f2d0d38a8a7bfb4", + "sha256:b3b0c8f660fae65eac74fbf003f3103769b90012ae7a460863010539bb7a80da", + "sha256:bab8e6d510d2ea0f1d14f12642e3f35cefa47a9b2e4c7cea1852b52bc9c49647", + "sha256:c45297bbdbc8bb79b02cf41417d63352b70bcb76f1bbb1ee7d47b3e89e42f95d", + "sha256:d19bca47c8a01b92640c614a9147b081a1974f69168ecd494687c827109e8f42", + "sha256:d64b4340a0c488a9e79b66ec9f9d77d02b99b772c8b8afd46c1294c1d39ca478", + "sha256:da969da069a82bbb5300b59161d8d7c8d423bc4ccd3b410a9b4d8932aeefc14b", + "sha256:ed02c7539705696ecb7dc9d476d861f3904a8d2b7e894bd418994920935d36bb", + "sha256:ee5b8abc35b549012e03a7b1e86c09491457dba6c94112a2482b18589cc2bdb9" + ], + "version": "==4.5.2" + }, + "coveragespace": { + "hashes": [ + "sha256:498b54ec158a19e1f5647da681dc77fd9d17df11ecff1253d60ac7970209f6e5", + "sha256:7c5ce4641e0f995b9be0e8b53401fd7b6d17db1b8c23bfd06f0c845ad0de5b5f" ], "index": "pypi", - "version": "==1.0" + "version": "==2.1" }, "docopt": { "hashes": [ @@ -166,10 +204,10 @@ }, "idna": { "hashes": [ - "sha256:2c6a5de3089009e3da7c5dde64a141dbc8551d5b7f6cf4ed7c2568d0cc520a8f", - "sha256:8c7309c718f94b3a625cb648ace320157ad16ff131ae0af362c9f21b80ef6ec4" + "sha256:156a6814fb5ac1fc6850fb002e0852d56c0c8d2531923a51032d1b70760e186e", + "sha256:684a38a6f903c1d71d6d5fac066b58d7768af4de2b832e426ec79c30daa94a16" ], - "version": "==2.6" + "version": "==2.7" }, "jinja2": { "hashes": [ @@ -180,10 +218,10 @@ }, "livereload": { "hashes": [ - "sha256:422de10d7ea9467a1ba27cbaffa84c74b809d96fb1598d9de4b9b676adf35e2c", - "sha256:5ed6506f5d526ee712da9f3739c27714e6f3376f3e481728d298efceae0ec83a" + "sha256:583179dc8d49b040a9da79bd33de59e160d2a8802b939e304eb359a4419f6498", + "sha256:dd4469a8f5a6833576e9f5433f1439c306de15dbbfeceabd32479b1123380fa5" ], - "version": "==2.5.1" + "version": "==2.5.2" }, "macfsevents": { "hashes": [ @@ -203,9 +241,36 @@ }, "markupsafe": { "hashes": [ - "sha256:a6be69091dac236ea9c6bc7d012beab42010fa914c459791d627dad4910eb665" - ], - "version": "==1.0" + "sha256:048ef924c1623740e70204aa7143ec592504045ae4429b59c30054cb31e3c432", + "sha256:130f844e7f5bdd8e9f3f42e7102ef1d49b2e6fdf0d7526df3f87281a532d8c8b", + "sha256:19f637c2ac5ae9da8bfd98cef74d64b7e1bb8a63038a3505cd182c3fac5eb4d9", + "sha256:1b8a7a87ad1b92bd887568ce54b23565f3fd7018c4180136e1cf412b405a47af", + "sha256:1c25694ca680b6919de53a4bb3bdd0602beafc63ff001fea2f2fc16ec3a11834", + "sha256:1f19ef5d3908110e1e891deefb5586aae1b49a7440db952454b4e281b41620cd", + "sha256:1fa6058938190ebe8290e5cae6c351e14e7bb44505c4a7624555ce57fbbeba0d", + "sha256:31cbb1359e8c25f9f48e156e59e2eaad51cd5242c05ed18a8de6dbe85184e4b7", + "sha256:3e835d8841ae7863f64e40e19477f7eb398674da6a47f09871673742531e6f4b", + "sha256:4e97332c9ce444b0c2c38dd22ddc61c743eb208d916e4265a2a3b575bdccb1d3", + "sha256:525396ee324ee2da82919f2ee9c9e73b012f23e7640131dd1b53a90206a0f09c", + "sha256:52b07fbc32032c21ad4ab060fec137b76eb804c4b9a1c7c7dc562549306afad2", + "sha256:52ccb45e77a1085ec5461cde794e1aa037df79f473cbc69b974e73940655c8d7", + "sha256:5c3fbebd7de20ce93103cb3183b47671f2885307df4a17a0ad56a1dd51273d36", + "sha256:5e5851969aea17660e55f6a3be00037a25b96a9b44d2083651812c99d53b14d1", + "sha256:5edfa27b2d3eefa2210fb2f5d539fbed81722b49f083b2c6566455eb7422fd7e", + "sha256:7d263e5770efddf465a9e31b78362d84d015cc894ca2c131901a4445eaa61ee1", + "sha256:83381342bfc22b3c8c06f2dd93a505413888694302de25add756254beee8449c", + "sha256:857eebb2c1dc60e4219ec8e98dfa19553dae33608237e107db9c6078b1167856", + "sha256:98e439297f78fca3a6169fd330fbe88d78b3bb72f967ad9961bcac0d7fdd1550", + "sha256:bf54103892a83c64db58125b3f2a43df6d2cb2d28889f14c78519394feb41492", + "sha256:d9ac82be533394d341b41d78aca7ed0e0f4ba5a2231602e2f05aa87f25c51672", + "sha256:e982fe07ede9fada6ff6705af70514a52beb1b2c3d25d4e873e82114cf3c5401", + "sha256:edce2ea7f3dfc981c4ddc97add8a61381d9642dc3273737e756517cc03e84dd6", + "sha256:efdc45ef1afc238db84cb4963aa689c0408912a0239b0721cb172b4016eb31d6", + "sha256:f137c02498f8b935892d5c0172560d7ab54bc45039de8805075e19079c639a9c", + "sha256:f82e347a72f955b7017a39708a3667f106e6ad4d10b25f237396a7115d8ed5fd", + "sha256:fb7c206e01ad85ce57feeaaa0bf784b97fa3cad0d4a5737bc5295785f5c613a1" + ], + "version": "==1.1.0" }, "mccabe": { "hashes": [ @@ -216,11 +281,11 @@ }, "mkdocs": { "hashes": [ - "sha256:126e9b871adeb077facccc375066fddae1485c7deebe3f10f2052b9a15514fb9", - "sha256:5f4317fd593ea07798bdb083bc06ca4e6b1e745fd1240d459f03cd0af1d58692" + "sha256:1b4d46cd1cb517cd743358da96a3efc588fd86f81512fb9c28214597b6dc731f", + "sha256:cd7264ea42d76f5bc1a0bd8b0a2c6c6e6be3a8742f5e78f47104a452dbe93600" ], "index": "pypi", - "version": "==0.17.3" + "version": "==0.17.5" }, "nose": { "hashes": [ @@ -252,6 +317,13 @@ ], "version": "==1.2.3" }, + "pygments": { + "hashes": [ + "sha256:78f3f434bcc5d6ee09020f92ba487f95ba50f1e3ef83ae96b9d5ffa1bab25c5d", + "sha256:dbae1046def0efb574852fab9e90209b23f556367b5a320c0bcb871c77c3e8cc" + ], + "version": "==2.2.0" + }, "pync": { "hashes": [ "sha256:85737aab9fc69cf59dc9fe831adbe94ac224944c05e297c98de3c2413f253530" @@ -262,10 +334,10 @@ }, "python-dateutil": { "hashes": [ - "sha256:3220490fb9741e2342e1cf29a503394fdac874bc39568288717ee67047ff29df", - "sha256:9d8074be4c993fbe4947878ce593052f71dac82932a677d49194d8ce9778002e" + "sha256:063df5763652e21de43de7d9e00ccf239f953a832941e37be541614732cdfc93", + "sha256:88f9287c0174266bb0d8cedd395cfba9c58e87e5ad86b2ce58859bc11be3cf02" ], - "version": "==2.7.2" + "version": "==2.7.5" }, "python-termstyle": { "hashes": [ @@ -276,29 +348,33 @@ }, "pyyaml": { "hashes": [ - "sha256:0c507b7f74b3d2dd4d1322ec8a94794927305ab4cebbe89cc47fe5e81541e6e8", - "sha256:16b20e970597e051997d90dc2cddc713a2876c47e3d92d59ee198700c5427736", - "sha256:3262c96a1ca437e7e4763e2843746588a965426550f3797a79fca9c6199c431f", - "sha256:326420cbb492172dec84b0f65c80942de6cedb5233c413dd824483989c000608", - "sha256:4474f8ea030b5127225b8894d626bb66c01cda098d47a2b0d3429b6700af9fd8", - "sha256:592766c6303207a20efc445587778322d7f73b161bd994f227adaa341ba212ab", - "sha256:5ac82e411044fb129bae5cfbeb3ba626acb2af31a8d17d175004b70862a741a7", - "sha256:5f84523c076ad14ff5e6c037fe1c89a7f73a3e04cf0377cb4d017014976433f3", - "sha256:827dc04b8fa7d07c44de11fabbc888e627fa8293b695e0f99cb544fdfa1bf0d1", - "sha256:b4c423ab23291d3945ac61346feeb9a0dc4184999ede5e7c43e1ffb975130ae6", - "sha256:bc6bced57f826ca7cb5125a10b23fd0f2fff3b7c4701d64c439a300ce665fff8", - "sha256:c01b880ec30b5a6e6aa67b09a2fe3fb30473008c85cd6a67359a1b15ed6d83a4", - "sha256:ca233c64c6e40eaa6c66ef97058cdc80e8d0157a443655baa1b2966e812807ca", - "sha256:e863072cdf4c72eebf179342c94e6989c67185842d9997960b3e69290b2fa269" - ], - "version": "==3.12" + "sha256:3d7da3009c0f3e783b2c873687652d83b1bbfd5c88e9813fb7e5b03c0dd3108b", + "sha256:3ef3092145e9b70e3ddd2c7ad59bdd0252a94dfe3949721633e41344de00a6bf", + "sha256:40c71b8e076d0550b2e6380bada1f1cd1017b882f7e16f09a65be98e017f211a", + "sha256:558dd60b890ba8fd982e05941927a3911dc409a63dcb8b634feaa0cda69330d3", + "sha256:a7c28b45d9f99102fa092bb213aa12e0aaf9a6a1f5e395d36166639c1f96c3a1", + "sha256:aa7dd4a6a427aed7df6fb7f08a580d68d9b118d90310374716ae90b710280af1", + "sha256:bc558586e6045763782014934bfaf39d48b8ae85a2713117d16c39864085c613", + "sha256:d46d7982b62e0729ad0175a9bc7e10a566fc07b224d2c79fafb5e032727eaa04", + "sha256:d5eef459e30b09f5a098b9cea68bebfeb268697f78d647bd255a085371ac7f3f", + "sha256:e01d3203230e1786cd91ccfdc8f8454c8069c91bee3962ad93b87a4b2860f537", + "sha256:e170a9e6fcfd19021dd29845af83bb79236068bf5fd4df3327c1be18182b2531" + ], + "version": "==3.13" + }, + "readme-renderer": { + "hashes": [ + "sha256:bb16f55b259f27f75f640acf5e00cf897845a8b3e4731b5c1a436e4b8529202f", + "sha256:c8532b79afc0375a85f10433eca157d6b50f7d6990f337fa498c96cd4bfc203d" + ], + "version": "==24.0" }, "requests": { "hashes": [ - "sha256:6a1b267aa90cac58ac3a765d067950e7dbbf75b1da07e895d1f594193a40a38b", - "sha256:9c443e7324ba5b85070c4a818ade28bfabedf16ea10206da1132edaa6dda237e" + "sha256:65b3a120e4329e33c9889db89c80976c5272f56ea92d3e74da8a463992e3ff54", + "sha256:ea881206e59f41dbd0bd445437d792e43906703fff75ca8ff43ccdb11f33f263" ], - "version": "==2.18.4" + "version": "==2.20.1" }, "requests-toolbelt": { "hashes": [ @@ -334,25 +410,32 @@ }, "tqdm": { "hashes": [ - "sha256:22c760d05b2eb6e96a91ad7ed1b03c9c97e6256fb7716410c27c2cb3265a5913", - "sha256:d7bfa112a55290a5e2d0c3263a09b17b24240686fbf20d1ef7c5e8edfbb71ad0" + "sha256:3c4d4a5a41ef162dd61f1edb86b0e1c7859054ab656b2e7c7b77e7fbf6d9f392", + "sha256:5b4d5549984503050883bc126280b386f5f4ca87e6c023c5d015655ad75bdebb" ], - "version": "==4.23.1" + "version": "==4.28.1" }, "twine": { "hashes": [ - "sha256:08eb132bbaec40c6d25b358f546ec1dc96ebd2638a86eea68769d9e67fe2b129", - "sha256:2fd9a4d9ff0bcacf41fdc40c8cb0cfaef1f1859457c9653fd1b92237cc4e9f25" + "sha256:7d89bc6acafb31d124e6e5b295ef26ac77030bf098960c2a4c4e058335827c5c", + "sha256:fad6f1251195f7ddd1460cb76d6ea106c93adb4e56c41e0da79658e56e547d2c" ], "index": "pypi", - "version": "==1.11.0" + "version": "==1.12.1" }, "urllib3": { "hashes": [ - "sha256:06330f386d6e4b195fbfc736b297f58c5a892e4440e54d294d7004e3a9bbea1b", - "sha256:cc44da8e1145637334317feebd728bd869a35285b93cbb4cca2577da7e62db4f" + "sha256:61bf29cada3fc2fbefad4fdf059ea4bd1b4a86d2b6d15e1c7c0b582b9752fe39", + "sha256:de9529817c93f27c8ccbfead6985011db27bd0ddfcdb2d86f3f663385c6a9c22" + ], + "version": "==1.24.1" + }, + "webencodings": { + "hashes": [ + "sha256:a0af1213f3c2226497a97e2b3aa01a7e4bee4f403f95be16fc9acd2947514a78", + "sha256:b36a1c245f2d304965eb4e0a82848379241dc04b865afcc4aab16748587e1923" ], - "version": "==1.22" + "version": "==0.5.1" } } } diff --git a/README.md b/README.md index fb5430c..bc7a772 100644 --- a/README.md +++ b/README.md @@ -20,7 +20,7 @@ Flask API is a drop-in replacement for Flask that provides an implementation of Requirements: * Python 2.7+ or 3.4+ -* Flask 0.10+ +* Flask 0.12.3+ Install using `pip`: diff --git a/docs/about/release-notes.md b/docs/about/release-notes.md index 9e40b58..b527d5b 100644 --- a/docs/about/release-notes.md +++ b/docs/about/release-notes.md @@ -4,6 +4,7 @@ * Added support for custom JSON encoders. * Added `None` as a valid return value for empty responses (204). +* Dropped support for Flask `<0.12.3` due to [CVE-2018-1000656](https://nvd.nist.gov/vuln/detail/CVE-2018-1000656). ## Version 1.0 diff --git a/docs/index.md b/docs/index.md index 78460aa..a4133a6 100644 --- a/docs/index.md +++ b/docs/index.md @@ -14,8 +14,8 @@ Flask API is a drop-in replacement for Flask that provides an implementation of Requirements: -* Python 2.7+ or 3.3+ -* Flask 0.10+ +* Python 2.7+ or 3.4+ +* Flask 0.12.3+ The following packages are optional: diff --git a/setup.py b/setup.py index ba6468d..da7bb3e 100755 --- a/setup.py +++ b/setup.py @@ -16,7 +16,7 @@ author_email = 'tom@tomchristie.com' license = 'BSD' install_requires = [ - 'Flask >= 0.10.1', + 'Flask >= 0.12.3', ] long_description = """Browsable web APIs for Flask.""" From 028c1bfb3161b7c8cb14ad5c77d69fc31cde8b61 Mon Sep 17 00:00:00 2001 From: Jace Browning Date: Mon, 19 Nov 2018 11:34:13 -0500 Subject: [PATCH 40/87] Fix Scrutinizer config --- .scrutinizer.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.scrutinizer.yml b/.scrutinizer.yml index d04d2a2..7d1d4c9 100644 --- a/.scrutinizer.yml +++ b/.scrutinizer.yml @@ -2,6 +2,7 @@ build: tests: override: - pylint-run --rcfile=.pylint.ini + - py-scrutinizer-run checks: python: code_rating: true From 6b8a2a6c1d030ff514ca9c6a518d67fb61f32e43 Mon Sep 17 00:00:00 2001 From: Thomas Power Date: Wed, 28 Nov 2018 16:11:35 +0000 Subject: [PATCH 41/87] Ensure custom response classes are used throughout Fixes #96. --- flask_api/app.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/flask_api/app.py b/flask_api/app.py index 3579c3c..6036c4c 100644 --- a/flask_api/app.py +++ b/flask_api/app.py @@ -107,7 +107,9 @@ def handle_user_exception(self, e): reraise(exc_type, exc_value, tb) def handle_api_exception(self, exc): - return APIResponse({'message': exc.detail}, status=exc.status_code) + content = {'message': exc.detail} + status = exc.status_code + return self.response_class(content, status=status) def create_url_adapter(self, request): """ From 9cc148db209f05d6e490b866440f1b5ee205c076 Mon Sep 17 00:00:00 2001 From: Dmitry Shachnev Date: Wed, 19 Dec 2018 14:21:21 +0300 Subject: [PATCH 42/87] Support Python-Markdown 3.0 The minimal supported version is now 2.6, released in February 2015. Fixes #94. --- docs/index.md | 2 +- flask_api/compat.py | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/docs/index.md b/docs/index.md index a4133a6..87835a7 100644 --- a/docs/index.md +++ b/docs/index.md @@ -19,7 +19,7 @@ Requirements: The following packages are optional: -* Markdown (`2.1.0+, <3.0`): Markdown support for the browsable API +* Markdown (`2.6+`): Markdown support for the browsable API Install using `pip`: diff --git a/flask_api/compat.py b/flask_api/compat.py index 65d36a2..c59b984 100644 --- a/flask_api/compat.py +++ b/flask_api/compat.py @@ -5,6 +5,7 @@ # Markdown is optional try: import markdown + from markdown.extensions.toc import TocExtension def apply_markdown(text): """ @@ -12,7 +13,7 @@ def apply_markdown(text): of '#' style headers to

. """ - extensions = ['headerid(level=2)'] + extensions = [TocExtension(baselevel=2)] md = markdown.Markdown(extensions=extensions) return md.convert(text) From 1e5fe0732832d2172ae7f7d17f811eec75654993 Mon Sep 17 00:00:00 2001 From: Jace Browning Date: Wed, 19 Dec 2018 10:26:18 -0500 Subject: [PATCH 43/87] Update Scrutinizer config --- .scrutinizer.yml | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/.scrutinizer.yml b/.scrutinizer.yml index 7d1d4c9..77822ca 100644 --- a/.scrutinizer.yml +++ b/.scrutinizer.yml @@ -1,8 +1,10 @@ build: - tests: - override: - - pylint-run --rcfile=.pylint.ini - - py-scrutinizer-run + nodes: + analysis: + tests: + override: + - pylint-run --rcfile=.pylint.ini + - py-scrutinizer-run checks: python: code_rating: true From 5ed444265b2e3c4890a98573ae0f12301ce9160a Mon Sep 17 00:00:00 2001 From: Jace Browning Date: Wed, 19 Dec 2018 11:27:56 -0500 Subject: [PATCH 44/87] Add syntax highlighting --- README.md | 166 ++++++++++++++++++++++++++++++------------------------ 1 file changed, 92 insertions(+), 74 deletions(-) diff --git a/README.md b/README.md index bc7a772..cf188b0 100644 --- a/README.md +++ b/README.md @@ -24,21 +24,27 @@ Requirements: Install using `pip`: - pip install Flask-API +```shell +$ pip install Flask-API +``` Import and initialize your application: - from flask_api import FlaskAPI +```python +from flask_api import FlaskAPI - app = FlaskAPI(__name__) +app = FlaskAPI(__name__) +``` ## Responses Return any valid response object as normal, or return a `list` or `dict`. - @app.route('/example/') - def example(): - return {'hello': 'world'} +```python +@app.route('/example/') +def example(): + return {'hello': 'world'} +``` A renderer for the response data will be selected using content negotiation based on the client 'Accept' header. If you're making the API request from a regular client, this will default to a JSON response. If you're viewing the API in a browser, it'll default to the browsable API HTML. @@ -46,84 +52,96 @@ A renderer for the response data will be selected using content negotiation base Access the parsed request data using `request.data`. This will handle JSON or form data by default. - @app.route('/example/') - def example(): - return {'request data': request.data} +```python +@app.route('/example/') +def example(): + return {'request data': request.data} +``` ## Example The following example demonstrates a simple API for creating, listing, updating and deleting notes. - from flask import request, url_for - from flask_api import FlaskAPI, status, exceptions - - app = FlaskAPI(__name__) - - - notes = { - 0: 'do the shopping', - 1: 'build the codez', - 2: 'paint the door', - } - - def note_repr(key): - return { - 'url': request.host_url.rstrip('/') + url_for('notes_detail', key=key), - 'text': notes[key] - } - - - @app.route("/", methods=['GET', 'POST']) - def notes_list(): - """ - List or create notes. - """ - if request.method == 'POST': - note = str(request.data.get('text', '')) - idx = max(notes.keys()) + 1 - notes[idx] = note - return note_repr(idx), status.HTTP_201_CREATED - - # request.method == 'GET' - return [note_repr(idx) for idx in sorted(notes.keys())] - - - @app.route("//", methods=['GET', 'PUT', 'DELETE']) - def notes_detail(key): - """ - Retrieve, update or delete note instances. - """ - if request.method == 'PUT': - note = str(request.data.get('text', '')) - notes[key] = note - return note_repr(key) - - elif request.method == 'DELETE': - notes.pop(key, None) - return '', status.HTTP_204_NO_CONTENT - - # request.method == 'GET' - if key not in notes: - raise exceptions.NotFound() - return note_repr(key) - - - if __name__ == "__main__": - app.run(debug=True) +```python +from flask import request, url_for +from flask_api import FlaskAPI, status, exceptions + +app = FlaskAPI(__name__) + + +notes = { + 0: 'do the shopping', + 1: 'build the codez', + 2: 'paint the door', +} + +def note_repr(key): + return { + 'url': request.host_url.rstrip('/') + url_for('notes_detail', key=key), + 'text': notes[key] + } + + +@app.route("/", methods=['GET', 'POST']) +def notes_list(): + """ + List or create notes. + """ + if request.method == 'POST': + note = str(request.data.get('text', '')) + idx = max(notes.keys()) + 1 + notes[idx] = note + return note_repr(idx), status.HTTP_201_CREATED + + # request.method == 'GET' + return [note_repr(idx) for idx in sorted(notes.keys())] + + +@app.route("//", methods=['GET', 'PUT', 'DELETE']) +def notes_detail(key): + """ + Retrieve, update or delete note instances. + """ + if request.method == 'PUT': + note = str(request.data.get('text', '')) + notes[key] = note + return note_repr(key) + + elif request.method == 'DELETE': + notes.pop(key, None) + return '', status.HTTP_204_NO_CONTENT + + # request.method == 'GET' + if key not in notes: + raise exceptions.NotFound() + return note_repr(key) + + +if __name__ == "__main__": + app.run(debug=True) +``` Now run the webapp: - $ python ./example.py - * Running on http://127.0.0.1:5000/ - * Restarting with reloader +```shell +$ python ./example.py + * Running on http://127.0.0.1:5000/ + * Restarting with reloader +``` You can now open a new tab and interact with the API from the command line: - $ curl -X GET http://127.0.0.1:5000/ - [{"url": "http://127.0.0.1:5000/0/", "text": "do the shopping"}, {"url": "http://127.0.0.1:5000/1/", "text": "build the codez"}, {"url": "http://127.0.0.1:5000/2/", "text": "paint the door"}] - $ curl -X GET http://127.0.0.1:5000/1/ - {"url": "http://127.0.0.1:5000/1/", "text": "build the codez"} - $ curl -X PUT http://127.0.0.1:5000/1/ -d text="flask api is teh awesomez" - {"url": "http://127.0.0.1:5000/1/", "text": "flask api is teh awesomez"} +```shell +$ curl -X GET http://127.0.0.1:5000/ +[{"url": "http://127.0.0.1:5000/0/", "text": "do the shopping"}, + {"url": "http://127.0.0.1:5000/1/", "text": "build the codez"}, + {"url": "http://127.0.0.1:5000/2/", "text": "paint the door"}] + +$ curl -X GET http://127.0.0.1:5000/1/ +{"url": "http://127.0.0.1:5000/1/", "text": "build the codez"} + +$ curl -X PUT http://127.0.0.1:5000/1/ -d text="flask api is teh awesomez" +{"url": "http://127.0.0.1:5000/1/", "text": "flask api is teh awesomez"} +``` You can also work on the API directly in your browser, by opening . You can then navigate between notes, and make `GET`, `PUT`, `POST` and `DELETE` API requests. From 02bd0fe00d96176dbdc9a5652e5b1e849d0fbce4 Mon Sep 17 00:00:00 2001 From: Jace Browning Date: Thu, 20 Dec 2018 19:02:33 -0500 Subject: [PATCH 45/87] Bump version to 1.1 --- docs/about/release-notes.md | 3 ++- flask_api/__init__.py | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/docs/about/release-notes.md b/docs/about/release-notes.md index b527d5b..f31fa3b 100644 --- a/docs/about/release-notes.md +++ b/docs/about/release-notes.md @@ -1,10 +1,11 @@ # Release Notes -## Version 1.1 (unreleased) +## Version 1.1 * Added support for custom JSON encoders. * Added `None` as a valid return value for empty responses (204). * Dropped support for Flask `<0.12.3` due to [CVE-2018-1000656](https://nvd.nist.gov/vuln/detail/CVE-2018-1000656). +* Added support for `python-markdown` 3+. ## Version 1.0 diff --git a/flask_api/__init__.py b/flask_api/__init__.py index f5e2c37..519fd4d 100644 --- a/flask_api/__init__.py +++ b/flask_api/__init__.py @@ -1,3 +1,3 @@ from flask_api.app import FlaskAPI -__version__ = '1.1b3' +__version__ = '1.1' From f89e18ca7d45d26b6b2d1ad140319213842347fc Mon Sep 17 00:00:00 2001 From: Findlay Smith Date: Fri, 25 Jan 2019 02:29:22 +0000 Subject: [PATCH 46/87] Add RFC 2324 compatability Implemented support for the HTTP 418 status code, specified in [RFC 2324](https://tools.ietf.org/html/rfc2324) --- flask_api/status.py | 1 + 1 file changed, 1 insertion(+) diff --git a/flask_api/status.py b/flask_api/status.py index 4163c7b..422c0ef 100644 --- a/flask_api/status.py +++ b/flask_api/status.py @@ -67,6 +67,7 @@ def is_server_error(code): HTTP_415_UNSUPPORTED_MEDIA_TYPE = 415 HTTP_416_REQUESTED_RANGE_NOT_SATISFIABLE = 416 HTTP_417_EXPECTATION_FAILED = 417 +HTTP_418_IM_A_TEAPOT = 418 HTTP_428_PRECONDITION_REQUIRED = 428 HTTP_429_TOO_MANY_REQUESTS = 429 HTTP_431_REQUEST_HEADER_FIELDS_TOO_LARGE = 431 From 51277d01a80eeb86e76e3eba89fcad36444f70aa Mon Sep 17 00:00:00 2001 From: Jace Browning Date: Tue, 9 Jul 2019 10:00:38 -0400 Subject: [PATCH 47/87] Test against Python 3.7 --- .travis.yml | 3 + Pipfile.lock | 318 +++++++++++++++++++++++++-------------------------- setup.py | 1 + 3 files changed, 163 insertions(+), 159 deletions(-) diff --git a/.travis.yml b/.travis.yml index 948b7ae..c92956a 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,9 +1,12 @@ +dist: xenial + language: python python: - 2.7 - 3.4 - 3.5 - 3.6 + - 3.7 cache: pip: true diff --git a/Pipfile.lock b/Pipfile.lock index 95649e3..c249c09 100644 --- a/Pipfile.lock +++ b/Pipfile.lock @@ -23,11 +23,11 @@ }, "flask": { "hashes": [ - "sha256:2271c0070dbcb5275fad4a82e29f23ab92682dc45f9dfbc22c02ba9b9322ce48", - "sha256:a080b744b7e345ccfcbc77954861cb05b3c63786e93f2b3875e0913d44b43f05" + "sha256:13f9f196f330c7c2c5d7a5cf91af894110ca0215ac051b5844701f2bfd934d52", + "sha256:45eb5a6fd193d6cf7e0cf5d8a5b31f83d5faae0293695626f539a823e93b13f6" ], "index": "pypi", - "version": "==1.0.2" + "version": "==1.1.1" }, "itsdangerous": { "hashes": [ @@ -38,10 +38,10 @@ }, "jinja2": { "hashes": [ - "sha256:74c935a1b8bb9a3947c50a54766a969d4846290e1e788ea44c1392163723c3bd", - "sha256:f84be1bb0040caca4cea721fcbbbbd61f9be9464ca236387158b0feea01914a4" + "sha256:065c4f02ebe7f7cf559e49ee5a95fb800a9e4528727aec6f24402a5374c65013", + "sha256:14dd6caf1527abb21f08f86c784eac40853ba93edb79552aa1e4b8aef1b61c7b" ], - "version": "==2.10" + "version": "==2.10.1" }, "markdown": { "hashes": [ @@ -53,43 +53,43 @@ }, "markupsafe": { "hashes": [ - "sha256:048ef924c1623740e70204aa7143ec592504045ae4429b59c30054cb31e3c432", - "sha256:130f844e7f5bdd8e9f3f42e7102ef1d49b2e6fdf0d7526df3f87281a532d8c8b", - "sha256:19f637c2ac5ae9da8bfd98cef74d64b7e1bb8a63038a3505cd182c3fac5eb4d9", - "sha256:1b8a7a87ad1b92bd887568ce54b23565f3fd7018c4180136e1cf412b405a47af", - "sha256:1c25694ca680b6919de53a4bb3bdd0602beafc63ff001fea2f2fc16ec3a11834", - "sha256:1f19ef5d3908110e1e891deefb5586aae1b49a7440db952454b4e281b41620cd", - "sha256:1fa6058938190ebe8290e5cae6c351e14e7bb44505c4a7624555ce57fbbeba0d", - "sha256:31cbb1359e8c25f9f48e156e59e2eaad51cd5242c05ed18a8de6dbe85184e4b7", - "sha256:3e835d8841ae7863f64e40e19477f7eb398674da6a47f09871673742531e6f4b", - "sha256:4e97332c9ce444b0c2c38dd22ddc61c743eb208d916e4265a2a3b575bdccb1d3", - "sha256:525396ee324ee2da82919f2ee9c9e73b012f23e7640131dd1b53a90206a0f09c", - "sha256:52b07fbc32032c21ad4ab060fec137b76eb804c4b9a1c7c7dc562549306afad2", - "sha256:52ccb45e77a1085ec5461cde794e1aa037df79f473cbc69b974e73940655c8d7", - "sha256:5c3fbebd7de20ce93103cb3183b47671f2885307df4a17a0ad56a1dd51273d36", - "sha256:5e5851969aea17660e55f6a3be00037a25b96a9b44d2083651812c99d53b14d1", - "sha256:5edfa27b2d3eefa2210fb2f5d539fbed81722b49f083b2c6566455eb7422fd7e", - "sha256:7d263e5770efddf465a9e31b78362d84d015cc894ca2c131901a4445eaa61ee1", - "sha256:83381342bfc22b3c8c06f2dd93a505413888694302de25add756254beee8449c", - "sha256:857eebb2c1dc60e4219ec8e98dfa19553dae33608237e107db9c6078b1167856", - "sha256:98e439297f78fca3a6169fd330fbe88d78b3bb72f967ad9961bcac0d7fdd1550", - "sha256:bf54103892a83c64db58125b3f2a43df6d2cb2d28889f14c78519394feb41492", - "sha256:d9ac82be533394d341b41d78aca7ed0e0f4ba5a2231602e2f05aa87f25c51672", - "sha256:e982fe07ede9fada6ff6705af70514a52beb1b2c3d25d4e873e82114cf3c5401", - "sha256:edce2ea7f3dfc981c4ddc97add8a61381d9642dc3273737e756517cc03e84dd6", - "sha256:efdc45ef1afc238db84cb4963aa689c0408912a0239b0721cb172b4016eb31d6", - "sha256:f137c02498f8b935892d5c0172560d7ab54bc45039de8805075e19079c639a9c", - "sha256:f82e347a72f955b7017a39708a3667f106e6ad4d10b25f237396a7115d8ed5fd", - "sha256:fb7c206e01ad85ce57feeaaa0bf784b97fa3cad0d4a5737bc5295785f5c613a1" - ], - "version": "==1.1.0" + "sha256:00bc623926325b26bb9605ae9eae8a215691f33cae5df11ca5424f06f2d1f473", + "sha256:09027a7803a62ca78792ad89403b1b7a73a01c8cb65909cd876f7fcebd79b161", + "sha256:09c4b7f37d6c648cb13f9230d847adf22f8171b1ccc4d5682398e77f40309235", + "sha256:1027c282dad077d0bae18be6794e6b6b8c91d58ed8a8d89a89d59693b9131db5", + "sha256:24982cc2533820871eba85ba648cd53d8623687ff11cbb805be4ff7b4c971aff", + "sha256:29872e92839765e546828bb7754a68c418d927cd064fd4708fab9fe9c8bb116b", + "sha256:43a55c2930bbc139570ac2452adf3d70cdbb3cfe5912c71cdce1c2c6bbd9c5d1", + "sha256:46c99d2de99945ec5cb54f23c8cd5689f6d7177305ebff350a58ce5f8de1669e", + "sha256:500d4957e52ddc3351cabf489e79c91c17f6e0899158447047588650b5e69183", + "sha256:535f6fc4d397c1563d08b88e485c3496cf5784e927af890fb3c3aac7f933ec66", + "sha256:62fe6c95e3ec8a7fad637b7f3d372c15ec1caa01ab47926cfdf7a75b40e0eac1", + "sha256:6dd73240d2af64df90aa7c4e7481e23825ea70af4b4922f8ede5b9e35f78a3b1", + "sha256:717ba8fe3ae9cc0006d7c451f0bb265ee07739daf76355d06366154ee68d221e", + "sha256:79855e1c5b8da654cf486b830bd42c06e8780cea587384cf6545b7d9ac013a0b", + "sha256:7c1699dfe0cf8ff607dbdcc1e9b9af1755371f92a68f706051cc8c37d447c905", + "sha256:88e5fcfb52ee7b911e8bb6d6aa2fd21fbecc674eadd44118a9cc3863f938e735", + "sha256:8defac2f2ccd6805ebf65f5eeb132adcf2ab57aa11fdf4c0dd5169a004710e7d", + "sha256:98c7086708b163d425c67c7a91bad6e466bb99d797aa64f965e9d25c12111a5e", + "sha256:9add70b36c5666a2ed02b43b335fe19002ee5235efd4b8a89bfcf9005bebac0d", + "sha256:9bf40443012702a1d2070043cb6291650a0841ece432556f784f004937f0f32c", + "sha256:ade5e387d2ad0d7ebf59146cc00c8044acbd863725f887353a10df825fc8ae21", + "sha256:b00c1de48212e4cc9603895652c5c410df699856a2853135b3967591e4beebc2", + "sha256:b1282f8c00509d99fef04d8ba936b156d419be841854fe901d8ae224c59f0be5", + "sha256:b2051432115498d3562c084a49bba65d97cf251f5a331c64a12ee7e04dacc51b", + "sha256:ba59edeaa2fc6114428f1637ffff42da1e311e29382d81b339c1817d37ec93c6", + "sha256:c8716a48d94b06bb3b2524c2b77e055fb313aeb4ea620c8dd03a105574ba704f", + "sha256:cd5df75523866410809ca100dc9681e301e3c27567cf498077e8551b6d20e42f", + "sha256:e249096428b3ae81b08327a63a485ad0878de3fb939049038579ac0ef61e17e7" + ], + "version": "==1.1.1" }, "werkzeug": { "hashes": [ - "sha256:c3fd7a7d41976d9f44db327260e263132466836cef6f91512889ed60ad26557c", - "sha256:d5da73735293558eb1651ee2fddc4d0dedcfa06538b8813a2e20011583c9e49b" + "sha256:865856ebb55c4dcd0630cdd8f3331a1847a819dda7e8c750d3db6f2aa6c0209c", + "sha256:a0b915f0815982fb2a09161cb8f31708052d0951c3ba433ccc5e1aa276507ca6" ], - "version": "==0.14.1" + "version": "==0.15.4" } }, "develop": { @@ -102,17 +102,17 @@ }, "bleach": { "hashes": [ - "sha256:48d39675b80a75f6d1c3bdbffec791cf0bbbab665cf01e20da701c77de278718", - "sha256:73d26f018af5d5adcdabf5c1c974add4361a9c76af215fe32fdec8a6fc5fb9b9" + "sha256:213336e49e102af26d9cde77dd2d0397afabc5a6bf2fed985dc35b5d1e285a16", + "sha256:3fdf7f77adcf649c9911387df51254b813185e32b2c6619f690b593a617e19fa" ], - "version": "==3.0.2" + "version": "==3.1.0" }, "certifi": { "hashes": [ - "sha256:339dc09518b07e2fa7eda5450740925974815557727d6bd35d319c1524a04a4c", - "sha256:6d58c986d22b038c8c0df30d639f23a3e6d172a05c3583e766f4c0b785c0986a" + "sha256:046832c04d4e752f37383b628bc601a7ea7211496b4638f6514d0e5b9acc4939", + "sha256:945e3ba63a0b9f577b1395204e13c3a231f9bc0223888be653286534e5873695" ], - "version": "==2018.10.15" + "version": "==2019.6.16" }, "chardet": { "hashes": [ @@ -137,39 +137,39 @@ }, "coverage": { "hashes": [ - "sha256:09e47c529ff77bf042ecfe858fb55c3e3eb97aac2c87f0349ab5a7efd6b3939f", - "sha256:0a1f9b0eb3aa15c990c328535655847b3420231af299386cfe5efc98f9c250fe", - "sha256:0cc941b37b8c2ececfed341444a456912e740ecf515d560de58b9a76562d966d", - "sha256:10e8af18d1315de936d67775d3a814cc81d0747a1a0312d84e27ae5610e313b0", - "sha256:1b4276550b86caa60606bd3572b52769860a81a70754a54acc8ba789ce74d607", - "sha256:1e8a2627c48266c7b813975335cfdea58c706fe36f607c97d9392e61502dc79d", - "sha256:2b224052bfd801beb7478b03e8a66f3f25ea56ea488922e98903914ac9ac930b", - "sha256:447c450a093766744ab53bf1e7063ec82866f27bcb4f4c907da25ad293bba7e3", - "sha256:46101fc20c6f6568561cdd15a54018bb42980954b79aa46da8ae6f008066a30e", - "sha256:4710dc676bb4b779c4361b54eb308bc84d64a2fa3d78e5f7228921eccce5d815", - "sha256:510986f9a280cd05189b42eee2b69fecdf5bf9651d4cd315ea21d24a964a3c36", - "sha256:5535dda5739257effef56e49a1c51c71f1d37a6e5607bb25a5eee507c59580d1", - "sha256:5a7524042014642b39b1fcae85fb37556c200e64ec90824ae9ecf7b667ccfc14", - "sha256:5f55028169ef85e1fa8e4b8b1b91c0b3b0fa3297c4fb22990d46ff01d22c2d6c", - "sha256:6694d5573e7790a0e8d3d177d7a416ca5f5c150742ee703f3c18df76260de794", - "sha256:6831e1ac20ac52634da606b658b0b2712d26984999c9d93f0c6e59fe62ca741b", - "sha256:77f0d9fa5e10d03aa4528436e33423bfa3718b86c646615f04616294c935f840", - "sha256:828ad813c7cdc2e71dcf141912c685bfe4b548c0e6d9540db6418b807c345ddd", - "sha256:85a06c61598b14b015d4df233d249cd5abfa61084ef5b9f64a48e997fd829a82", - "sha256:8cb4febad0f0b26c6f62e1628f2053954ad2c555d67660f28dfb1b0496711952", - "sha256:a5c58664b23b248b16b96253880b2868fb34358911400a7ba39d7f6399935389", - "sha256:aaa0f296e503cda4bc07566f592cd7a28779d433f3a23c48082af425d6d5a78f", - "sha256:ab235d9fe64833f12d1334d29b558aacedfbca2356dfb9691f2d0d38a8a7bfb4", - "sha256:b3b0c8f660fae65eac74fbf003f3103769b90012ae7a460863010539bb7a80da", - "sha256:bab8e6d510d2ea0f1d14f12642e3f35cefa47a9b2e4c7cea1852b52bc9c49647", - "sha256:c45297bbdbc8bb79b02cf41417d63352b70bcb76f1bbb1ee7d47b3e89e42f95d", - "sha256:d19bca47c8a01b92640c614a9147b081a1974f69168ecd494687c827109e8f42", - "sha256:d64b4340a0c488a9e79b66ec9f9d77d02b99b772c8b8afd46c1294c1d39ca478", - "sha256:da969da069a82bbb5300b59161d8d7c8d423bc4ccd3b410a9b4d8932aeefc14b", - "sha256:ed02c7539705696ecb7dc9d476d861f3904a8d2b7e894bd418994920935d36bb", - "sha256:ee5b8abc35b549012e03a7b1e86c09491457dba6c94112a2482b18589cc2bdb9" - ], - "version": "==4.5.2" + "sha256:3684fabf6b87a369017756b551cef29e505cb155ddb892a7a29277b978da88b9", + "sha256:39e088da9b284f1bd17c750ac672103779f7954ce6125fd4382134ac8d152d74", + "sha256:3c205bc11cc4fcc57b761c2da73b9b72a59f8d5ca89979afb0c1c6f9e53c7390", + "sha256:465ce53a8c0f3a7950dfb836438442f833cf6663d407f37d8c52fe7b6e56d7e8", + "sha256:48020e343fc40f72a442c8a1334284620f81295256a6b6ca6d8aa1350c763bbe", + "sha256:5296fc86ab612ec12394565c500b412a43b328b3907c0d14358950d06fd83baf", + "sha256:5f61bed2f7d9b6a9ab935150a6b23d7f84b8055524e7be7715b6513f3328138e", + "sha256:68a43a9f9f83693ce0414d17e019daee7ab3f7113a70c79a3dd4c2f704e4d741", + "sha256:6b8033d47fe22506856fe450470ccb1d8ba1ffb8463494a15cfc96392a288c09", + "sha256:7ad7536066b28863e5835e8cfeaa794b7fe352d99a8cded9f43d1161be8e9fbd", + "sha256:7bacb89ccf4bedb30b277e96e4cc68cd1369ca6841bde7b005191b54d3dd1034", + "sha256:839dc7c36501254e14331bcb98b27002aa415e4af7ea039d9009409b9d2d5420", + "sha256:8f9a95b66969cdea53ec992ecea5406c5bd99c9221f539bca1e8406b200ae98c", + "sha256:932c03d2d565f75961ba1d3cec41ddde00e162c5b46d03f7423edcb807734eab", + "sha256:988529edadc49039d205e0aa6ce049c5ccda4acb2d6c3c5c550c17e8c02c05ba", + "sha256:998d7e73548fe395eeb294495a04d38942edb66d1fa61eb70418871bc621227e", + "sha256:9de60893fb447d1e797f6bf08fdf0dbcda0c1e34c1b06c92bd3a363c0ea8c609", + "sha256:9e80d45d0c7fcee54e22771db7f1b0b126fb4a6c0a2e5afa72f66827207ff2f2", + "sha256:a545a3dfe5082dc8e8c3eb7f8a2cf4f2870902ff1860bd99b6198cfd1f9d1f49", + "sha256:a5d8f29e5ec661143621a8f4de51adfb300d7a476224156a39a392254f70687b", + "sha256:aca06bfba4759bbdb09bf52ebb15ae20268ee1f6747417837926fae990ebc41d", + "sha256:bb23b7a6fd666e551a3094ab896a57809e010059540ad20acbeec03a154224ce", + "sha256:bfd1d0ae7e292105f29d7deaa9d8f2916ed8553ab9d5f39ec65bcf5deadff3f9", + "sha256:c62ca0a38958f541a73cf86acdab020c2091631c137bd359c4f5bddde7b75fd4", + "sha256:c709d8bda72cf4cd348ccec2a4881f2c5848fd72903c185f363d361b2737f773", + "sha256:c968a6aa7e0b56ecbd28531ddf439c2ec103610d3e2bf3b75b813304f8cb7723", + "sha256:df785d8cb80539d0b55fd47183264b7002077859028dfe3070cf6359bf8b2d9c", + "sha256:f406628ca51e0ae90ae76ea8398677a921b36f0bd71aab2099dfed08abd0322f", + "sha256:f46087bbd95ebae244a0eda01a618aff11ec7a069b15a3ef8f6b520db523dcf1", + "sha256:f8019c5279eb32360ca03e9fac40a12667715546eed5c5eb59eb381f2f501260", + "sha256:fc5f4d209733750afd2714e9109816a29500718b32dd9a5db01c0cb3a019b96a" + ], + "version": "==4.5.3" }, "coveragespace": { "hashes": [ @@ -204,24 +204,24 @@ }, "idna": { "hashes": [ - "sha256:156a6814fb5ac1fc6850fb002e0852d56c0c8d2531923a51032d1b70760e186e", - "sha256:684a38a6f903c1d71d6d5fac066b58d7768af4de2b832e426ec79c30daa94a16" + "sha256:c357b3f628cf53ae2c4c05627ecc484553142ca23264e593d327bcde5e9c3407", + "sha256:ea8b7f6188e6fa117537c3df7da9fc686d485087abf6ac197f9c46432f7e4a3c" ], - "version": "==2.7" + "version": "==2.8" }, "jinja2": { "hashes": [ - "sha256:74c935a1b8bb9a3947c50a54766a969d4846290e1e788ea44c1392163723c3bd", - "sha256:f84be1bb0040caca4cea721fcbbbbd61f9be9464ca236387158b0feea01914a4" + "sha256:065c4f02ebe7f7cf559e49ee5a95fb800a9e4528727aec6f24402a5374c65013", + "sha256:14dd6caf1527abb21f08f86c784eac40853ba93edb79552aa1e4b8aef1b61c7b" ], - "version": "==2.10" + "version": "==2.10.1" }, "livereload": { "hashes": [ - "sha256:583179dc8d49b040a9da79bd33de59e160d2a8802b939e304eb359a4419f6498", - "sha256:dd4469a8f5a6833576e9f5433f1439c306de15dbbfeceabd32479b1123380fa5" + "sha256:78d55f2c268a8823ba499305dcac64e28ddeb9a92571e12d543cd304faf5817b", + "sha256:89254f78d7529d7ea0a3417d224c34287ebfe266b05e67e51facaf82c27f0f66" ], - "version": "==2.5.2" + "version": "==2.6.1" }, "macfsevents": { "hashes": [ @@ -241,36 +241,36 @@ }, "markupsafe": { "hashes": [ - "sha256:048ef924c1623740e70204aa7143ec592504045ae4429b59c30054cb31e3c432", - "sha256:130f844e7f5bdd8e9f3f42e7102ef1d49b2e6fdf0d7526df3f87281a532d8c8b", - "sha256:19f637c2ac5ae9da8bfd98cef74d64b7e1bb8a63038a3505cd182c3fac5eb4d9", - "sha256:1b8a7a87ad1b92bd887568ce54b23565f3fd7018c4180136e1cf412b405a47af", - "sha256:1c25694ca680b6919de53a4bb3bdd0602beafc63ff001fea2f2fc16ec3a11834", - "sha256:1f19ef5d3908110e1e891deefb5586aae1b49a7440db952454b4e281b41620cd", - "sha256:1fa6058938190ebe8290e5cae6c351e14e7bb44505c4a7624555ce57fbbeba0d", - "sha256:31cbb1359e8c25f9f48e156e59e2eaad51cd5242c05ed18a8de6dbe85184e4b7", - "sha256:3e835d8841ae7863f64e40e19477f7eb398674da6a47f09871673742531e6f4b", - "sha256:4e97332c9ce444b0c2c38dd22ddc61c743eb208d916e4265a2a3b575bdccb1d3", - "sha256:525396ee324ee2da82919f2ee9c9e73b012f23e7640131dd1b53a90206a0f09c", - "sha256:52b07fbc32032c21ad4ab060fec137b76eb804c4b9a1c7c7dc562549306afad2", - "sha256:52ccb45e77a1085ec5461cde794e1aa037df79f473cbc69b974e73940655c8d7", - "sha256:5c3fbebd7de20ce93103cb3183b47671f2885307df4a17a0ad56a1dd51273d36", - "sha256:5e5851969aea17660e55f6a3be00037a25b96a9b44d2083651812c99d53b14d1", - "sha256:5edfa27b2d3eefa2210fb2f5d539fbed81722b49f083b2c6566455eb7422fd7e", - "sha256:7d263e5770efddf465a9e31b78362d84d015cc894ca2c131901a4445eaa61ee1", - "sha256:83381342bfc22b3c8c06f2dd93a505413888694302de25add756254beee8449c", - "sha256:857eebb2c1dc60e4219ec8e98dfa19553dae33608237e107db9c6078b1167856", - "sha256:98e439297f78fca3a6169fd330fbe88d78b3bb72f967ad9961bcac0d7fdd1550", - "sha256:bf54103892a83c64db58125b3f2a43df6d2cb2d28889f14c78519394feb41492", - "sha256:d9ac82be533394d341b41d78aca7ed0e0f4ba5a2231602e2f05aa87f25c51672", - "sha256:e982fe07ede9fada6ff6705af70514a52beb1b2c3d25d4e873e82114cf3c5401", - "sha256:edce2ea7f3dfc981c4ddc97add8a61381d9642dc3273737e756517cc03e84dd6", - "sha256:efdc45ef1afc238db84cb4963aa689c0408912a0239b0721cb172b4016eb31d6", - "sha256:f137c02498f8b935892d5c0172560d7ab54bc45039de8805075e19079c639a9c", - "sha256:f82e347a72f955b7017a39708a3667f106e6ad4d10b25f237396a7115d8ed5fd", - "sha256:fb7c206e01ad85ce57feeaaa0bf784b97fa3cad0d4a5737bc5295785f5c613a1" - ], - "version": "==1.1.0" + "sha256:00bc623926325b26bb9605ae9eae8a215691f33cae5df11ca5424f06f2d1f473", + "sha256:09027a7803a62ca78792ad89403b1b7a73a01c8cb65909cd876f7fcebd79b161", + "sha256:09c4b7f37d6c648cb13f9230d847adf22f8171b1ccc4d5682398e77f40309235", + "sha256:1027c282dad077d0bae18be6794e6b6b8c91d58ed8a8d89a89d59693b9131db5", + "sha256:24982cc2533820871eba85ba648cd53d8623687ff11cbb805be4ff7b4c971aff", + "sha256:29872e92839765e546828bb7754a68c418d927cd064fd4708fab9fe9c8bb116b", + "sha256:43a55c2930bbc139570ac2452adf3d70cdbb3cfe5912c71cdce1c2c6bbd9c5d1", + "sha256:46c99d2de99945ec5cb54f23c8cd5689f6d7177305ebff350a58ce5f8de1669e", + "sha256:500d4957e52ddc3351cabf489e79c91c17f6e0899158447047588650b5e69183", + "sha256:535f6fc4d397c1563d08b88e485c3496cf5784e927af890fb3c3aac7f933ec66", + "sha256:62fe6c95e3ec8a7fad637b7f3d372c15ec1caa01ab47926cfdf7a75b40e0eac1", + "sha256:6dd73240d2af64df90aa7c4e7481e23825ea70af4b4922f8ede5b9e35f78a3b1", + "sha256:717ba8fe3ae9cc0006d7c451f0bb265ee07739daf76355d06366154ee68d221e", + "sha256:79855e1c5b8da654cf486b830bd42c06e8780cea587384cf6545b7d9ac013a0b", + "sha256:7c1699dfe0cf8ff607dbdcc1e9b9af1755371f92a68f706051cc8c37d447c905", + "sha256:88e5fcfb52ee7b911e8bb6d6aa2fd21fbecc674eadd44118a9cc3863f938e735", + "sha256:8defac2f2ccd6805ebf65f5eeb132adcf2ab57aa11fdf4c0dd5169a004710e7d", + "sha256:98c7086708b163d425c67c7a91bad6e466bb99d797aa64f965e9d25c12111a5e", + "sha256:9add70b36c5666a2ed02b43b335fe19002ee5235efd4b8a89bfcf9005bebac0d", + "sha256:9bf40443012702a1d2070043cb6291650a0841ece432556f784f004937f0f32c", + "sha256:ade5e387d2ad0d7ebf59146cc00c8044acbd863725f887353a10df825fc8ae21", + "sha256:b00c1de48212e4cc9603895652c5c410df699856a2853135b3967591e4beebc2", + "sha256:b1282f8c00509d99fef04d8ba936b156d419be841854fe901d8ae224c59f0be5", + "sha256:b2051432115498d3562c084a49bba65d97cf251f5a331c64a12ee7e04dacc51b", + "sha256:ba59edeaa2fc6114428f1637ffff42da1e311e29382d81b339c1817d37ec93c6", + "sha256:c8716a48d94b06bb3b2524c2b77e055fb313aeb4ea620c8dd03a105574ba704f", + "sha256:cd5df75523866410809ca100dc9681e301e3c27567cf498077e8551b6d20e42f", + "sha256:e249096428b3ae81b08327a63a485ad0878de3fb939049038579ac0ef61e17e7" + ], + "version": "==1.1.1" }, "mccabe": { "hashes": [ @@ -298,10 +298,10 @@ }, "pkginfo": { "hashes": [ - "sha256:5878d542a4b3f237e359926384f1dde4e099c9f5525d236b1840cf704fa8d474", - "sha256:a39076cb3eb34c333a0dd390b568e9e1e881c7bf2cc0aee12120636816f55aee" + "sha256:7424f2c8511c186cd5424bbf31045b77435b37a8d604990b79d4e70d741148bb", + "sha256:a6d9e40ca61ad3ebd0b72fbadd4fba16e4c0e4df0428c041e01e06eb6ee71f32" ], - "version": "==1.4.2" + "version": "==1.5.0.1" }, "pycodestyle": { "hashes": [ @@ -319,10 +319,10 @@ }, "pygments": { "hashes": [ - "sha256:78f3f434bcc5d6ee09020f92ba487f95ba50f1e3ef83ae96b9d5ffa1bab25c5d", - "sha256:dbae1046def0efb574852fab9e90209b23f556367b5a320c0bcb871c77c3e8cc" + "sha256:71e430bc85c88a430f000ac1d9b331d2407f681d6f6aec95e8bcfbc3df5b0127", + "sha256:881c4c157e45f30af185c1ffe8d549d48ac9127433f2c380c24b84572ad66297" ], - "version": "==2.2.0" + "version": "==2.4.2" }, "pync": { "hashes": [ @@ -334,10 +334,10 @@ }, "python-dateutil": { "hashes": [ - "sha256:063df5763652e21de43de7d9e00ccf239f953a832941e37be541614732cdfc93", - "sha256:88f9287c0174266bb0d8cedd395cfba9c58e87e5ad86b2ce58859bc11be3cf02" + "sha256:7e6584c74aeed623791615e26efd690f29817a27c73085b78e4bad02493df2fb", + "sha256:c89805f6f4d64db21ed966fda138f8a5ed7a4fdbc1a8ee329ce1b74e3c74da9e" ], - "version": "==2.7.5" + "version": "==2.8.0" }, "python-termstyle": { "hashes": [ @@ -348,19 +348,19 @@ }, "pyyaml": { "hashes": [ - "sha256:3d7da3009c0f3e783b2c873687652d83b1bbfd5c88e9813fb7e5b03c0dd3108b", - "sha256:3ef3092145e9b70e3ddd2c7ad59bdd0252a94dfe3949721633e41344de00a6bf", - "sha256:40c71b8e076d0550b2e6380bada1f1cd1017b882f7e16f09a65be98e017f211a", - "sha256:558dd60b890ba8fd982e05941927a3911dc409a63dcb8b634feaa0cda69330d3", - "sha256:a7c28b45d9f99102fa092bb213aa12e0aaf9a6a1f5e395d36166639c1f96c3a1", - "sha256:aa7dd4a6a427aed7df6fb7f08a580d68d9b118d90310374716ae90b710280af1", - "sha256:bc558586e6045763782014934bfaf39d48b8ae85a2713117d16c39864085c613", - "sha256:d46d7982b62e0729ad0175a9bc7e10a566fc07b224d2c79fafb5e032727eaa04", - "sha256:d5eef459e30b09f5a098b9cea68bebfeb268697f78d647bd255a085371ac7f3f", - "sha256:e01d3203230e1786cd91ccfdc8f8454c8069c91bee3962ad93b87a4b2860f537", - "sha256:e170a9e6fcfd19021dd29845af83bb79236068bf5fd4df3327c1be18182b2531" + "sha256:57acc1d8533cbe51f6662a55434f0dbecfa2b9eaf115bede8f6fd00115a0c0d3", + "sha256:588c94b3d16b76cfed8e0be54932e5729cc185caffaa5a451e7ad2f7ed8b4043", + "sha256:68c8dd247f29f9a0d09375c9c6b8fdc64b60810ebf07ba4cdd64ceee3a58c7b7", + "sha256:70d9818f1c9cd5c48bb87804f2efc8692f1023dac7f1a1a5c61d454043c1d265", + "sha256:86a93cccd50f8c125286e637328ff4eef108400dd7089b46a7be3445eecfa391", + "sha256:a0f329125a926876f647c9fa0ef32801587a12328b4a3c741270464e3e4fa778", + "sha256:a3c252ab0fa1bb0d5a3f6449a4826732f3eb6c0270925548cac342bc9b22c225", + "sha256:b4bb4d3f5e232425e25dda21c070ce05168a786ac9eda43768ab7f3ac2770955", + "sha256:cd0618c5ba5bda5f4039b9398bb7fb6a317bb8298218c3de25c47c4740e4b95e", + "sha256:ceacb9e5f8474dcf45b940578591c7f3d960e82f926c707788a570b51ba59190", + "sha256:fe6a88094b64132c4bb3b631412e90032e8cfe9745a58370462240b8cb7553cd" ], - "version": "==3.13" + "version": "==5.1.1" }, "readme-renderer": { "hashes": [ @@ -371,32 +371,32 @@ }, "requests": { "hashes": [ - "sha256:65b3a120e4329e33c9889db89c80976c5272f56ea92d3e74da8a463992e3ff54", - "sha256:ea881206e59f41dbd0bd445437d792e43906703fff75ca8ff43ccdb11f33f263" + "sha256:11e007a8a2aa0323f5a921e9e6a2d7e4e67d9877e85773fba9ba6419025cbeb4", + "sha256:9cf5292fcd0f598c671cfc1e0d7d1a7f13bb8085e9a590f48c010551dc6c4b31" ], - "version": "==2.20.1" + "version": "==2.22.0" }, "requests-toolbelt": { "hashes": [ - "sha256:42c9c170abc2cacb78b8ab23ac957945c7716249206f90874651971a4acff237", - "sha256:f6a531936c6fa4c6cfce1b9c10d5c4f498d16528d2a54a22ca00011205a187b5" + "sha256:380606e1d10dc85c3bd47bf5a6095f815ec007be7a8b69c878507068df059e6f", + "sha256:968089d4584ad4ad7c171454f0a5c6dac23971e9472521ea3b6d49d610aa6fc0" ], - "version": "==0.8.0" + "version": "==0.9.1" }, "six": { "hashes": [ - "sha256:70e8a77beed4562e7f14fe23a786b54f6296e34344c23bc42f07b15018ff98e9", - "sha256:832dc0e10feb1aa2c68dcc57dbb658f1c7e65b9b61af69048abc87a2db00a0eb" + "sha256:3350809f0555b11f552448330d0b52d5f24c91a322ea4a15ef22629740f3761c", + "sha256:d16a0141ec1a18405cd4ce8b4613101da75da0e9a7aec5bdd4fa804d0e0eba73" ], - "version": "==1.11.0" + "version": "==1.12.0" }, "sniffer": { "hashes": [ - "sha256:e8a0daa4c51dff3d00482b45dc9b978159100a8d5a7df327c28ed96586559970", - "sha256:e90c1ad4bd3c31a5fad8e03d45dfc83377b31420aa0779f17280c817ce0c9dd8" + "sha256:b37665053fb83d7790bf9e51d616c11970863d14b5ea5a51155a4e95759d1529", + "sha256:f120843fe152d0e380402fc11313b151e2044c47fdd36895de2efedc8624dbb8" ], "index": "pypi", - "version": "==0.4.0" + "version": "==0.4.1" }, "tornado": { "hashes": [ @@ -410,25 +410,25 @@ }, "tqdm": { "hashes": [ - "sha256:3c4d4a5a41ef162dd61f1edb86b0e1c7859054ab656b2e7c7b77e7fbf6d9f392", - "sha256:5b4d5549984503050883bc126280b386f5f4ca87e6c023c5d015655ad75bdebb" + "sha256:14a285392c32b6f8222ecfbcd217838f88e11630affe9006cd0e94c7eff3cb61", + "sha256:25d4c0ea02a305a688e7e9c2cdc8f862f989ef2a4701ab28ee963295f5b109ab" ], - "version": "==4.28.1" + "version": "==4.32.2" }, "twine": { "hashes": [ - "sha256:7d89bc6acafb31d124e6e5b295ef26ac77030bf098960c2a4c4e058335827c5c", - "sha256:fad6f1251195f7ddd1460cb76d6ea106c93adb4e56c41e0da79658e56e547d2c" + "sha256:0fb0bfa3df4f62076cab5def36b1a71a2e4acb4d1fa5c97475b048117b1a6446", + "sha256:d6c29c933ecfc74e9b1d9fa13aa1f87c5d5770e119f5a4ce032092f0ff5b14dc" ], "index": "pypi", - "version": "==1.12.1" + "version": "==1.13.0" }, "urllib3": { "hashes": [ - "sha256:61bf29cada3fc2fbefad4fdf059ea4bd1b4a86d2b6d15e1c7c0b582b9752fe39", - "sha256:de9529817c93f27c8ccbfead6985011db27bd0ddfcdb2d86f3f663385c6a9c22" + "sha256:b246607a25ac80bedac05c6f282e3cdaf3afb65420fd024ac94435cabe6e18d1", + "sha256:dbe59173209418ae49d485b87d1681aefa36252ee85884c31346debd19463232" ], - "version": "==1.24.1" + "version": "==1.25.3" }, "webencodings": { "hashes": [ diff --git a/setup.py b/setup.py index da7bb3e..442c5c6 100755 --- a/setup.py +++ b/setup.py @@ -81,6 +81,7 @@ def get_package_data(package): 'Programming Language :: Python :: 3.4', 'Programming Language :: Python :: 3.5', 'Programming Language :: Python :: 3.6', + 'Programming Language :: Python :: 3.7', 'Topic :: Internet :: WWW/HTTP', ] ) From 2e72da69331a63f947bc6a8964480b4c43127810 Mon Sep 17 00:00:00 2001 From: Jace Browning Date: Tue, 9 Jul 2019 10:23:25 -0400 Subject: [PATCH 48/87] Drop support for Python 3.4 --- .travis.yml | 1 - setup.py | 1 - 2 files changed, 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index c92956a..a9da7e0 100644 --- a/.travis.yml +++ b/.travis.yml @@ -3,7 +3,6 @@ dist: xenial language: python python: - 2.7 - - 3.4 - 3.5 - 3.6 - 3.7 diff --git a/setup.py b/setup.py index 442c5c6..720649b 100755 --- a/setup.py +++ b/setup.py @@ -78,7 +78,6 @@ def get_package_data(package): 'Programming Language :: Python :: 2', 'Programming Language :: Python :: 2.7', 'Programming Language :: Python :: 3', - 'Programming Language :: Python :: 3.4', 'Programming Language :: Python :: 3.5', 'Programming Language :: Python :: 3.6', 'Programming Language :: Python :: 3.7', From 56232bde9540aa4f237a987b5c71418f85f40a37 Mon Sep 17 00:00:00 2001 From: Jace Browning Date: Thu, 7 Nov 2019 09:54:27 -0500 Subject: [PATCH 49/87] Test against the latest version of Flask --- .travis.yml | 3 ++- README.md | 10 +++++----- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/.travis.yml b/.travis.yml index a9da7e0..3d5dbf4 100644 --- a/.travis.yml +++ b/.travis.yml @@ -17,7 +17,8 @@ env: - RANDOM_SEED=0 matrix: - FLASK_VERSION=0.12.4 - - FLASK_VERSION=1.0.2 + - FLASK_VERSION=1.0.4 + - FLASK_VERSION=1.1.1 before_install: - pip install pipenv diff --git a/README.md b/README.md index cf188b0..688a6ec 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ Browsable web APIs for Flask. -[![Unix Build Status](https://img.shields.io/travis/flask-api/flask-api.svg)](https://travis-ci.org/flask-api/flask-api) +[![Unix Build Status](https://img.shields.io/travis/flask-api/flask-api.svg)](https://travis-ci.org/flask-api/flask-api) [![Coverage Status](https://img.shields.io/coveralls/flask-api/flask-api.svg)](https://coveralls.io/r/flask-api/flask-api) [![Scrutinizer Code Quality](https://img.shields.io/scrutinizer/g/flask-api/flask-api.svg)](https://scrutinizer-ci.com/g/flask-api/flask-api/) [![PyPI Version](https://img.shields.io/pypi/v/Flask-API.svg)](https://pypi.org/project/Flask-API/) @@ -20,7 +20,7 @@ Flask API is a drop-in replacement for Flask that provides an implementation of Requirements: * Python 2.7+ or 3.4+ -* Flask 0.12.3+ +* Flask 0.12.4+ Install using `pip`: @@ -46,7 +46,7 @@ def example(): return {'hello': 'world'} ``` -A renderer for the response data will be selected using content negotiation based on the client 'Accept' header. If you're making the API request from a regular client, this will default to a JSON response. If you're viewing the API in a browser, it'll default to the browsable API HTML. +A renderer for the response data will be selected using content negotiation based on the client 'Accept' header. If you're making the API request from a regular client, this will default to a JSON response. If you're viewing the API in a browser, it'll default to the browsable API HTML. ## Requests @@ -133,8 +133,8 @@ You can now open a new tab and interact with the API from the command line: ```shell $ curl -X GET http://127.0.0.1:5000/ -[{"url": "http://127.0.0.1:5000/0/", "text": "do the shopping"}, - {"url": "http://127.0.0.1:5000/1/", "text": "build the codez"}, +[{"url": "http://127.0.0.1:5000/0/", "text": "do the shopping"}, + {"url": "http://127.0.0.1:5000/1/", "text": "build the codez"}, {"url": "http://127.0.0.1:5000/2/", "text": "paint the door"}] $ curl -X GET http://127.0.0.1:5000/1/ From adc4204d26f5f52ac9d504bc4d59ddde1e108fd2 Mon Sep 17 00:00:00 2001 From: Jace Browning Date: Wed, 27 Nov 2019 13:35:52 -0500 Subject: [PATCH 50/87] Drop support for Python <3.5 and Flask <1.1 --- .travis.yml | 3 --- README.md | 4 ++-- docs/about/release-notes.md | 5 +++++ docs/index.md | 32 ++++++++++++++++---------------- flask_api/__init__.py | 2 +- setup.py | 6 +----- 6 files changed, 25 insertions(+), 27 deletions(-) diff --git a/.travis.yml b/.travis.yml index 3d5dbf4..b892afd 100644 --- a/.travis.yml +++ b/.travis.yml @@ -2,7 +2,6 @@ dist: xenial language: python python: - - 2.7 - 3.5 - 3.6 - 3.7 @@ -16,8 +15,6 @@ env: global: - RANDOM_SEED=0 matrix: - - FLASK_VERSION=0.12.4 - - FLASK_VERSION=1.0.4 - FLASK_VERSION=1.1.1 before_install: diff --git a/README.md b/README.md index 688a6ec..85d1a59 100644 --- a/README.md +++ b/README.md @@ -19,8 +19,8 @@ Flask API is a drop-in replacement for Flask that provides an implementation of Requirements: -* Python 2.7+ or 3.4+ -* Flask 0.12.4+ +* Python 3.5+ +* Flask 1.1.+ Install using `pip`: diff --git a/docs/about/release-notes.md b/docs/about/release-notes.md index f31fa3b..1b0412c 100644 --- a/docs/about/release-notes.md +++ b/docs/about/release-notes.md @@ -1,5 +1,10 @@ # Release Notes +## Version 2.0 (unreleased) + +* Dropped support for Python `<3.5`. +* Dropped support for Flask `<1.1`. + ## Version 1.1 * Added support for custom JSON encoders. diff --git a/docs/index.md b/docs/index.md index 87835a7..39f2574 100644 --- a/docs/index.md +++ b/docs/index.md @@ -14,8 +14,8 @@ Flask API is a drop-in replacement for Flask that provides an implementation of Requirements: -* Python 2.7+ or 3.4+ -* Flask 0.12.3+ +* Python 3.5+ +* Flask 1.1+ The following packages are optional: @@ -39,7 +39,7 @@ Return any valid response object as normal, or return a `list` or `dict`. def example(): return {'hello': 'world'} -A renderer for the response data will be selected using content negotiation based on the client 'Accept' header. If you're making the API request from a regular client, this will default to a JSON response. If you're viewing the API in a browser it'll default to the browsable API HTML. +A renderer for the response data will be selected using content negotiation based on the client 'Accept' header. If you're making the API request from a regular client, this will default to a JSON response. If you're viewing the API in a browser it'll default to the browsable API HTML. ## Requests @@ -55,23 +55,23 @@ The following example demonstrates a simple API for creating, listing, updating from flask import request, url_for from flask_api import FlaskAPI, status, exceptions - + app = FlaskAPI(__name__) - - + + notes = { 0: 'do the shopping', 1: 'build the codez', 2: 'paint the door', } - + def note_repr(key): return { 'url': request.host_url.rstrip('/') + url_for('notes_detail', key=key), 'text': notes[key] } - - + + @app.route("/", methods=['GET', 'POST']) def notes_list(): """ @@ -82,11 +82,11 @@ The following example demonstrates a simple API for creating, listing, updating idx = max(notes.keys()) + 1 notes[idx] = note return note_repr(idx), status.HTTP_201_CREATED - + # request.method == 'GET' return [note_repr(idx) for idx in sorted(notes.keys())] - - + + @app.route("//", methods=['GET', 'PUT', 'DELETE']) def notes_detail(key): """ @@ -96,17 +96,17 @@ The following example demonstrates a simple API for creating, listing, updating note = str(request.data.get('text', '')) notes[key] = note return note_repr(key) - + elif request.method == 'DELETE': notes.pop(key, None) return '', status.HTTP_204_NO_CONTENT - + # request.method == 'GET' if key not in notes: raise exceptions.NotFound() return note_repr(key) - - + + if __name__ == "__main__": app.run(debug=True) diff --git a/flask_api/__init__.py b/flask_api/__init__.py index 519fd4d..4449650 100644 --- a/flask_api/__init__.py +++ b/flask_api/__init__.py @@ -1,3 +1,3 @@ from flask_api.app import FlaskAPI -__version__ = '1.1' +__version__ = '2.0b1' diff --git a/setup.py b/setup.py index 720649b..0c685e3 100755 --- a/setup.py +++ b/setup.py @@ -15,9 +15,7 @@ author = 'Tom Christie' author_email = 'tom@tomchristie.com' license = 'BSD' -install_requires = [ - 'Flask >= 0.12.3', -] +install_requires = ['Flask >= 1.1'] long_description = """Browsable web APIs for Flask.""" @@ -75,8 +73,6 @@ def get_package_data(package): 'Natural Language :: English', 'Operating System :: OS Independent', 'Programming Language :: Python', - 'Programming Language :: Python :: 2', - 'Programming Language :: Python :: 2.7', 'Programming Language :: Python :: 3', 'Programming Language :: Python :: 3.5', 'Programming Language :: Python :: 3.6', From 2c2ac63b46fa9239b76ed98fce4c805a52ce1799 Mon Sep 17 00:00:00 2001 From: Jace Browning Date: Wed, 27 Nov 2019 13:44:59 -0500 Subject: [PATCH 51/87] Add Python 3.8 to the test matrix --- .travis.yml | 1 + setup.py | 1 + 2 files changed, 2 insertions(+) diff --git a/.travis.yml b/.travis.yml index b892afd..2c4ef67 100644 --- a/.travis.yml +++ b/.travis.yml @@ -5,6 +5,7 @@ python: - 3.5 - 3.6 - 3.7 + - 3.8 cache: pip: true diff --git a/setup.py b/setup.py index 0c685e3..6145833 100755 --- a/setup.py +++ b/setup.py @@ -77,6 +77,7 @@ def get_package_data(package): 'Programming Language :: Python :: 3.5', 'Programming Language :: Python :: 3.6', 'Programming Language :: Python :: 3.7', + 'Programming Language :: Python :: 3.8', 'Topic :: Internet :: WWW/HTTP', ] ) From d748f34a4e4e86cef451eea7eb6cfa9a6ec525b4 Mon Sep 17 00:00:00 2001 From: Jace Browning Date: Wed, 27 Nov 2019 13:51:00 -0500 Subject: [PATCH 52/87] Update flake8 --- Pipfile | 2 +- Pipfile.lock | 225 +++++++++++++++++++++++----------------- flask_api/mediatypes.py | 3 +- flask_api/request.py | 4 +- 4 files changed, 136 insertions(+), 98 deletions(-) diff --git a/Pipfile b/Pipfile index 44c7127..ff5cb05 100644 --- a/Pipfile +++ b/Pipfile @@ -12,7 +12,7 @@ Markdown = "<3" [dev-packages] # Linters -flake8 = "~=2.1" +flake8 = "~=3.7.9" # Testing nose = "*" diff --git a/Pipfile.lock b/Pipfile.lock index c249c09..f6040f9 100644 --- a/Pipfile.lock +++ b/Pipfile.lock @@ -1,7 +1,7 @@ { "_meta": { "hash": { - "sha256": "594412d0816530df7cf2020970de492e606ceb3d28c3c1172b312917c11f9ce6" + "sha256": "06c6e9a34817de4ee1793e152bd952ef30fe97bafb85001461f3cb5e5d7e969e" }, "pipfile-spec": 6, "requires": {}, @@ -38,10 +38,10 @@ }, "jinja2": { "hashes": [ - "sha256:065c4f02ebe7f7cf559e49ee5a95fb800a9e4528727aec6f24402a5374c65013", - "sha256:14dd6caf1527abb21f08f86c784eac40853ba93edb79552aa1e4b8aef1b61c7b" + "sha256:74320bb91f31270f9551d46522e33af46a80c3d619f4a4bf42b3164d30b5911f", + "sha256:9fe95f19286cfefaa917656583d020be14e7859c6b0252588391e47db34527de" ], - "version": "==2.10.1" + "version": "==2.10.3" }, "markdown": { "hashes": [ @@ -86,10 +86,10 @@ }, "werkzeug": { "hashes": [ - "sha256:865856ebb55c4dcd0630cdd8f3331a1847a819dda7e8c750d3db6f2aa6c0209c", - "sha256:a0b915f0815982fb2a09161cb8f31708052d0951c3ba433ccc5e1aa276507ca6" + "sha256:7280924747b5733b246fe23972186c6b348f9ae29724135a6dfc1e53cea433e7", + "sha256:e5f4a1f98b52b18a93da705a7458e55afb26f32bff83ff5d19189f92462d65c4" ], - "version": "==0.15.4" + "version": "==0.16.0" } }, "develop": { @@ -109,10 +109,10 @@ }, "certifi": { "hashes": [ - "sha256:046832c04d4e752f37383b628bc601a7ea7211496b4638f6514d0e5b9acc4939", - "sha256:945e3ba63a0b9f577b1395204e13c3a231f9bc0223888be653286534e5873695" + "sha256:e4f3620cfea4f83eedc95b24abd9cd56f3c4b146dd0177e83a21b4eb49e21e50", + "sha256:fd7c7c74727ddcf00e9acd26bba8da604ffec95bf1c2144e67aff7a8b50e6cef" ], - "version": "==2019.6.16" + "version": "==2019.9.11" }, "chardet": { "hashes": [ @@ -137,39 +137,40 @@ }, "coverage": { "hashes": [ - "sha256:3684fabf6b87a369017756b551cef29e505cb155ddb892a7a29277b978da88b9", - "sha256:39e088da9b284f1bd17c750ac672103779f7954ce6125fd4382134ac8d152d74", - "sha256:3c205bc11cc4fcc57b761c2da73b9b72a59f8d5ca89979afb0c1c6f9e53c7390", - "sha256:465ce53a8c0f3a7950dfb836438442f833cf6663d407f37d8c52fe7b6e56d7e8", - "sha256:48020e343fc40f72a442c8a1334284620f81295256a6b6ca6d8aa1350c763bbe", - "sha256:5296fc86ab612ec12394565c500b412a43b328b3907c0d14358950d06fd83baf", - "sha256:5f61bed2f7d9b6a9ab935150a6b23d7f84b8055524e7be7715b6513f3328138e", - "sha256:68a43a9f9f83693ce0414d17e019daee7ab3f7113a70c79a3dd4c2f704e4d741", - "sha256:6b8033d47fe22506856fe450470ccb1d8ba1ffb8463494a15cfc96392a288c09", - "sha256:7ad7536066b28863e5835e8cfeaa794b7fe352d99a8cded9f43d1161be8e9fbd", - "sha256:7bacb89ccf4bedb30b277e96e4cc68cd1369ca6841bde7b005191b54d3dd1034", - "sha256:839dc7c36501254e14331bcb98b27002aa415e4af7ea039d9009409b9d2d5420", - "sha256:8f9a95b66969cdea53ec992ecea5406c5bd99c9221f539bca1e8406b200ae98c", - "sha256:932c03d2d565f75961ba1d3cec41ddde00e162c5b46d03f7423edcb807734eab", - "sha256:988529edadc49039d205e0aa6ce049c5ccda4acb2d6c3c5c550c17e8c02c05ba", - "sha256:998d7e73548fe395eeb294495a04d38942edb66d1fa61eb70418871bc621227e", - "sha256:9de60893fb447d1e797f6bf08fdf0dbcda0c1e34c1b06c92bd3a363c0ea8c609", - "sha256:9e80d45d0c7fcee54e22771db7f1b0b126fb4a6c0a2e5afa72f66827207ff2f2", - "sha256:a545a3dfe5082dc8e8c3eb7f8a2cf4f2870902ff1860bd99b6198cfd1f9d1f49", - "sha256:a5d8f29e5ec661143621a8f4de51adfb300d7a476224156a39a392254f70687b", - "sha256:aca06bfba4759bbdb09bf52ebb15ae20268ee1f6747417837926fae990ebc41d", - "sha256:bb23b7a6fd666e551a3094ab896a57809e010059540ad20acbeec03a154224ce", - "sha256:bfd1d0ae7e292105f29d7deaa9d8f2916ed8553ab9d5f39ec65bcf5deadff3f9", - "sha256:c62ca0a38958f541a73cf86acdab020c2091631c137bd359c4f5bddde7b75fd4", - "sha256:c709d8bda72cf4cd348ccec2a4881f2c5848fd72903c185f363d361b2737f773", - "sha256:c968a6aa7e0b56ecbd28531ddf439c2ec103610d3e2bf3b75b813304f8cb7723", - "sha256:df785d8cb80539d0b55fd47183264b7002077859028dfe3070cf6359bf8b2d9c", - "sha256:f406628ca51e0ae90ae76ea8398677a921b36f0bd71aab2099dfed08abd0322f", - "sha256:f46087bbd95ebae244a0eda01a618aff11ec7a069b15a3ef8f6b520db523dcf1", - "sha256:f8019c5279eb32360ca03e9fac40a12667715546eed5c5eb59eb381f2f501260", - "sha256:fc5f4d209733750afd2714e9109816a29500718b32dd9a5db01c0cb3a019b96a" - ], - "version": "==4.5.3" + "sha256:08907593569fe59baca0bf152c43f3863201efb6113ecb38ce7e97ce339805a6", + "sha256:0be0f1ed45fc0c185cfd4ecc19a1d6532d72f86a2bac9de7e24541febad72650", + "sha256:141f08ed3c4b1847015e2cd62ec06d35e67a3ac185c26f7635f4406b90afa9c5", + "sha256:19e4df788a0581238e9390c85a7a09af39c7b539b29f25c89209e6c3e371270d", + "sha256:23cc09ed395b03424d1ae30dcc292615c1372bfba7141eb85e11e50efaa6b351", + "sha256:245388cda02af78276b479f299bbf3783ef0a6a6273037d7c60dc73b8d8d7755", + "sha256:331cb5115673a20fb131dadd22f5bcaf7677ef758741312bee4937d71a14b2ef", + "sha256:386e2e4090f0bc5df274e720105c342263423e77ee8826002dcffe0c9533dbca", + "sha256:3a794ce50daee01c74a494919d5ebdc23d58873747fa0e288318728533a3e1ca", + "sha256:60851187677b24c6085248f0a0b9b98d49cba7ecc7ec60ba6b9d2e5574ac1ee9", + "sha256:63a9a5fc43b58735f65ed63d2cf43508f462dc49857da70b8980ad78d41d52fc", + "sha256:6b62544bb68106e3f00b21c8930e83e584fdca005d4fffd29bb39fb3ffa03cb5", + "sha256:6ba744056423ef8d450cf627289166da65903885272055fb4b5e113137cfa14f", + "sha256:7494b0b0274c5072bddbfd5b4a6c6f18fbbe1ab1d22a41e99cd2d00c8f96ecfe", + "sha256:826f32b9547c8091679ff292a82aca9c7b9650f9fda3e2ca6bf2ac905b7ce888", + "sha256:93715dffbcd0678057f947f496484e906bf9509f5c1c38fc9ba3922893cda5f5", + "sha256:9a334d6c83dfeadae576b4d633a71620d40d1c379129d587faa42ee3e2a85cce", + "sha256:af7ed8a8aa6957aac47b4268631fa1df984643f07ef00acd374e456364b373f5", + "sha256:bf0a7aed7f5521c7ca67febd57db473af4762b9622254291fbcbb8cd0ba5e33e", + "sha256:bf1ef9eb901113a9805287e090452c05547578eaab1b62e4ad456fcc049a9b7e", + "sha256:c0afd27bc0e307a1ffc04ca5ec010a290e49e3afbe841c5cafc5c5a80ecd81c9", + "sha256:dd579709a87092c6dbee09d1b7cfa81831040705ffa12a1b248935274aee0437", + "sha256:df6712284b2e44a065097846488f66840445eb987eb81b3cc6e4149e7b6982e1", + "sha256:e07d9f1a23e9e93ab5c62902833bf3e4b1f65502927379148b6622686223125c", + "sha256:e2ede7c1d45e65e209d6093b762e98e8318ddeff95317d07a27a2140b80cfd24", + "sha256:e4ef9c164eb55123c62411f5936b5c2e521b12356037b6e1c2617cef45523d47", + "sha256:eca2b7343524e7ba246cab8ff00cab47a2d6d54ada3b02772e908a45675722e2", + "sha256:eee64c616adeff7db37cc37da4180a3a5b6177f5c46b187894e633f088fb5b28", + "sha256:ef824cad1f980d27f26166f86856efe11eff9912c4fed97d3804820d43fa550c", + "sha256:efc89291bd5a08855829a3c522df16d856455297cf35ae827a37edac45f466a7", + "sha256:fa964bae817babece5aa2e8c1af841bebb6d0b9add8e637548809d040443fee0", + "sha256:ff37757e068ae606659c28c3bd0d923f9d29a85de79bf25b2b34b148473b5025" + ], + "version": "==4.5.4" }, "coveragespace": { "hashes": [ @@ -187,20 +188,27 @@ }, "docutils": { "hashes": [ - "sha256:02aec4bd92ab067f6ff27a38a38a41173bf01bed8f89157768c1573f53e474a6", - "sha256:51e64ef2ebfb29cae1faa133b3710143496eca21c530f3f71424d77687764274", - "sha256:7a4bd47eaf6596e1295ecb11361139febe29b084a87bf005bf899f9a42edc3c6" + "sha256:6c4f696463b79f1fb8ba0c594b63840ebd41f059e92b31957c46b74a4599b6d0", + "sha256:9e4d7ecfc600058e07ba661411a2b7de2fd0fafa17d1a7f7361cd47b1175c827", + "sha256:a2aeea129088da402665e92e0b25b04b073c04b2dce4ab65caaa38b7ce2e1a99" ], "index": "pypi", - "version": "==0.14" + "version": "==0.15.2" + }, + "entrypoints": { + "hashes": [ + "sha256:589f874b313739ad35be6e0cd7efde2a4e9b6fea91edcc34e58ecbb8dbe56d19", + "sha256:c70dd71abe5a8c85e55e12c19bd91ccfeec11a6e99044204511f9ed547d48451" + ], + "version": "==0.3" }, "flake8": { "hashes": [ - "sha256:231cd86194aaec4bdfaa553ae1a1cd9b7b4558332fbc10136c044940d587a778", - "sha256:7ac3bbaac27174d95bc4734ed23a07de567ffbcf4fc7e316854b4f3015d4fd15" + "sha256:45681a117ecc81e870cbf1262835ae4af5e7a8b08e40b944a8a6e6b895914cfb", + "sha256:49356e766643ad15072a789a20915d3c91dc89fd313ccd71802303fd67e4deca" ], "index": "pypi", - "version": "==2.6.2" + "version": "==3.7.9" }, "idna": { "hashes": [ @@ -209,12 +217,27 @@ ], "version": "==2.8" }, + "importlib-metadata": { + "hashes": [ + "sha256:aa18d7378b00b40847790e7c27e11673d7fed219354109d0e7b9e5b25dc3ad26", + "sha256:d5f18a79777f3aa179c145737780282e27b508fc8fd688cb17c7a813e8bd39af" + ], + "markers": "python_version < '3.8'", + "version": "==0.23" + }, "jinja2": { "hashes": [ - "sha256:065c4f02ebe7f7cf559e49ee5a95fb800a9e4528727aec6f24402a5374c65013", - "sha256:14dd6caf1527abb21f08f86c784eac40853ba93edb79552aa1e4b8aef1b61c7b" + "sha256:74320bb91f31270f9551d46522e33af46a80c3d619f4a4bf42b3164d30b5911f", + "sha256:9fe95f19286cfefaa917656583d020be14e7859c6b0252588391e47db34527de" + ], + "version": "==2.10.3" + }, + "keyring": { + "hashes": [ + "sha256:91037ccaf0c9a112a76f7740e4a416b9457a69b66c2799421581bee710a974b3", + "sha256:f5bb20ea6c57c2360daf0c591931c9ea0d7660a8d9e32ca84d63273f131ea605" ], - "version": "==2.10.1" + "version": "==19.2.0" }, "livereload": { "hashes": [ @@ -274,10 +297,10 @@ }, "mccabe": { "hashes": [ - "sha256:16293af41e7242031afd73896fef6458f4cad38201d21e28f344fff50ae1c25e", - "sha256:f9b58bf366c1506dcd6117b33e5c4874746f0de859c9c7cab8b516cb6be1d22e" + "sha256:ab8a6258860da4b6677da4bd2fe5dc2c659cff31b3ee4f7f5d64e79735b80d42", + "sha256:dd8d182285a0fe56bace7f45b5e7d1a6ebcbf524e8f3bd87eb0f125271b8831f" ], - "version": "==0.5.3" + "version": "==0.6.1" }, "mkdocs": { "hashes": [ @@ -287,6 +310,13 @@ "index": "pypi", "version": "==0.17.5" }, + "more-itertools": { + "hashes": [ + "sha256:409cd48d4db7052af495b09dec721011634af3753ae1ef92d2b32f73a745f832", + "sha256:92b8c4b06dac4f0611c0729b2f2ede52b2e1bac1ab48f089c7ddc12e26bb60c4" + ], + "version": "==7.2.0" + }, "nose": { "hashes": [ "sha256:9ff7c6cc443f8c51994b34a667bbcf45afd6d945be7477b52e97516fd17c53ac", @@ -305,24 +335,24 @@ }, "pycodestyle": { "hashes": [ - "sha256:2ce83f2046f5ab85c652ceceddfbde7a64a909900989b4b43e92b10b743d0ce5", - "sha256:37f0420b14630b0eaaf452978f3a6ea4816d787c3e6dcbba6fb255030adae2e7" + "sha256:95a2219d12372f05704562a14ec30bc76b05a5b297b21a5dfe3f6fac3491ae56", + "sha256:e40a936c9a450ad81df37f549d676d127b1b66000a6c500caa2b085bc0ca976c" ], - "version": "==2.0.0" + "version": "==2.5.0" }, "pyflakes": { "hashes": [ - "sha256:2e4a1b636d8809d8f0a69f341acf15b2e401a3221ede11be439911d23ce2139e", - "sha256:e87bac26c62ea5b45067cc89e4a12f56e1483f1f2cda17e7c9b375b9fd2f40da" + "sha256:17dbeb2e3f4d772725c777fabc446d5634d1038f234e77343108ce445ea69ce0", + "sha256:d976835886f8c5b31d47970ed689944a0262b5f3afa00a5a7b4dc81e5449f8a2" ], - "version": "==1.2.3" + "version": "==2.1.1" }, "pygments": { "hashes": [ - "sha256:71e430bc85c88a430f000ac1d9b331d2407f681d6f6aec95e8bcfbc3df5b0127", - "sha256:881c4c157e45f30af185c1ffe8d549d48ac9127433f2c380c24b84572ad66297" + "sha256:83ec6c6133ca6b529b7ff5aa826328fd14b5bb02a58c37f4f06384e96a0f94ab", + "sha256:b7949de3d396836085fea596998b135a22610bbcc4f2abfe9e448e44cbc58388" ], - "version": "==2.4.2" + "version": "==2.5.1" }, "pync": { "hashes": [ @@ -334,10 +364,10 @@ }, "python-dateutil": { "hashes": [ - "sha256:7e6584c74aeed623791615e26efd690f29817a27c73085b78e4bad02493df2fb", - "sha256:c89805f6f4d64db21ed966fda138f8a5ed7a4fdbc1a8ee329ce1b74e3c74da9e" + "sha256:73ebfe9dbf22e832286dafa60473e4cd239f8592f699aa5adaf10050e6e1823c", + "sha256:75bb3f31ea686f1197762692a9ee6a7550b59fc6ca3a1f4b5d7e32fb98e2da2a" ], - "version": "==2.8.0" + "version": "==2.8.1" }, "python-termstyle": { "hashes": [ @@ -348,19 +378,21 @@ }, "pyyaml": { "hashes": [ - "sha256:57acc1d8533cbe51f6662a55434f0dbecfa2b9eaf115bede8f6fd00115a0c0d3", - "sha256:588c94b3d16b76cfed8e0be54932e5729cc185caffaa5a451e7ad2f7ed8b4043", - "sha256:68c8dd247f29f9a0d09375c9c6b8fdc64b60810ebf07ba4cdd64ceee3a58c7b7", - "sha256:70d9818f1c9cd5c48bb87804f2efc8692f1023dac7f1a1a5c61d454043c1d265", - "sha256:86a93cccd50f8c125286e637328ff4eef108400dd7089b46a7be3445eecfa391", - "sha256:a0f329125a926876f647c9fa0ef32801587a12328b4a3c741270464e3e4fa778", - "sha256:a3c252ab0fa1bb0d5a3f6449a4826732f3eb6c0270925548cac342bc9b22c225", - "sha256:b4bb4d3f5e232425e25dda21c070ce05168a786ac9eda43768ab7f3ac2770955", - "sha256:cd0618c5ba5bda5f4039b9398bb7fb6a317bb8298218c3de25c47c4740e4b95e", - "sha256:ceacb9e5f8474dcf45b940578591c7f3d960e82f926c707788a570b51ba59190", - "sha256:fe6a88094b64132c4bb3b631412e90032e8cfe9745a58370462240b8cb7553cd" - ], - "version": "==5.1.1" + "sha256:0113bc0ec2ad727182326b61326afa3d1d8280ae1122493553fd6f4397f33df9", + "sha256:01adf0b6c6f61bd11af6e10ca52b7d4057dd0be0343eb9283c878cf3af56aee4", + "sha256:5124373960b0b3f4aa7df1707e63e9f109b5263eca5976c66e08b1c552d4eaf8", + "sha256:5ca4f10adbddae56d824b2c09668e91219bb178a1eee1faa56af6f99f11bf696", + "sha256:7907be34ffa3c5a32b60b95f4d95ea25361c951383a894fec31be7252b2b6f34", + "sha256:7ec9b2a4ed5cad025c2278a1e6a19c011c80a3caaac804fd2d329e9cc2c287c9", + "sha256:87ae4c829bb25b9fe99cf71fbb2140c448f534e24c998cc60f39ae4f94396a73", + "sha256:9de9919becc9cc2ff03637872a440195ac4241c80536632fffeb6a1e25a74299", + "sha256:a5a85b10e450c66b49f98846937e8cfca1db3127a9d5d1e31ca45c3d0bef4c5b", + "sha256:b0997827b4f6a7c286c01c5f60384d218dca4ed7d9efa945c3e1aa623d5709ae", + "sha256:b631ef96d3222e62861443cc89d6563ba3eeb816eeb96b2629345ab795e53681", + "sha256:bf47c0607522fdbca6c9e817a6e81b08491de50f3766a7a0e6a5be7905961b41", + "sha256:f81025eddd0327c7d4cfe9b62cf33190e1e736cc6e97502b3ec425f574b3e7a8" + ], + "version": "==5.1.2" }, "readme-renderer": { "hashes": [ @@ -385,10 +417,10 @@ }, "six": { "hashes": [ - "sha256:3350809f0555b11f552448330d0b52d5f24c91a322ea4a15ef22629740f3761c", - "sha256:d16a0141ec1a18405cd4ce8b4613101da75da0e9a7aec5bdd4fa804d0e0eba73" + "sha256:1f1b7d42e254082a9db6279deae68afb421ceba6158efa6131de7b3003ee93fd", + "sha256:30f610279e8b2578cab6db20741130331735c781b56053c59c4076da27f06b66" ], - "version": "==1.12.0" + "version": "==1.13.0" }, "sniffer": { "hashes": [ @@ -410,25 +442,25 @@ }, "tqdm": { "hashes": [ - "sha256:14a285392c32b6f8222ecfbcd217838f88e11630affe9006cd0e94c7eff3cb61", - "sha256:25d4c0ea02a305a688e7e9c2cdc8f862f989ef2a4701ab28ee963295f5b109ab" + "sha256:5a1f3d58f3eb53264387394387fe23df469d2a3fab98c9e7f99d5c146c119873", + "sha256:f1a1613fee07cc30a253051617f2a219a785c58877f9f6bfa129446cbaf8b4c1" ], - "version": "==4.32.2" + "version": "==4.39.0" }, "twine": { "hashes": [ - "sha256:0fb0bfa3df4f62076cab5def36b1a71a2e4acb4d1fa5c97475b048117b1a6446", - "sha256:d6c29c933ecfc74e9b1d9fa13aa1f87c5d5770e119f5a4ce032092f0ff5b14dc" + "sha256:c1af8ca391e43b0a06bbc155f7f67db0bf0d19d284bfc88d1675da497a946124", + "sha256:d561a5e511f70275e5a485a6275ff61851c16ffcb3a95a602189161112d9f160" ], "index": "pypi", - "version": "==1.13.0" + "version": "==3.1.1" }, "urllib3": { "hashes": [ - "sha256:b246607a25ac80bedac05c6f282e3cdaf3afb65420fd024ac94435cabe6e18d1", - "sha256:dbe59173209418ae49d485b87d1681aefa36252ee85884c31346debd19463232" + "sha256:a8a318824cc77d1fd4b2bec2ded92646630d7fe8619497b142c84a9e6f5a7293", + "sha256:f3c5fd51747d450d4dcf6f923c81f78f811aab8205fda64b0aba34a4e48b0745" ], - "version": "==1.25.3" + "version": "==1.25.7" }, "webencodings": { "hashes": [ @@ -436,6 +468,13 @@ "sha256:b36a1c245f2d304965eb4e0a82848379241dc04b865afcc4aab16748587e1923" ], "version": "==0.5.1" + }, + "zipp": { + "hashes": [ + "sha256:3718b1cbcd963c7d4c5511a8240812904164b7f381b647143a89d3b98f9bcd8e", + "sha256:f06903e9f1f43b12d371004b4ac7b06ab39a44adc747266928ae6debfa7b3335" + ], + "version": "==0.6.0" } } } diff --git a/flask_api/mediatypes.py b/flask_api/mediatypes.py index eac96e8..7b9bcb9 100644 --- a/flask_api/mediatypes.py +++ b/flask_api/mediatypes.py @@ -88,8 +88,7 @@ def __hash__(self): def __eq__(self, other): # Compare two MediaType instances, ignoring parameter ordering. return ( - self.full_type == other.full_type and - self.params == other.params + self.full_type == other.full_type and self.params == other.params ) diff --git a/flask_api/request.py b/flask_api/request.py index aee96ce..d9d291a 100644 --- a/flask_api/request.py +++ b/flask_api/request.py @@ -51,11 +51,11 @@ def _parse(self): try: parser, media_type = negotiator.select_parser(parsers) ret = parser.parse(self.stream, media_type, **options) - except: + except Exception as e: # Ensure that accessing `request.data` again does not reraise # the exception, so that eg exceptions can handle properly. self._set_empty_data() - raise + raise e from None if parser.handles_file_uploads: assert isinstance(ret, tuple) and len(ret) == 2, 'Expected a two-tuple of (data, files)' From 393e7caf8575550d4d0e72af2e8c9e1a6330e73f Mon Sep 17 00:00:00 2001 From: Jace Browning Date: Wed, 27 Nov 2019 14:33:27 -0500 Subject: [PATCH 53/87] Drop support for Python 3.5 as it's no longer supported by twine --- .travis.yml | 1 - README.md | 2 +- docs/about/release-notes.md | 2 +- docs/index.md | 2 +- setup.py | 1 - 5 files changed, 3 insertions(+), 5 deletions(-) diff --git a/.travis.yml b/.travis.yml index 2c4ef67..2f94a62 100644 --- a/.travis.yml +++ b/.travis.yml @@ -2,7 +2,6 @@ dist: xenial language: python python: - - 3.5 - 3.6 - 3.7 - 3.8 diff --git a/README.md b/README.md index 85d1a59..d9eaabf 100644 --- a/README.md +++ b/README.md @@ -19,7 +19,7 @@ Flask API is a drop-in replacement for Flask that provides an implementation of Requirements: -* Python 3.5+ +* Python 3.6+ * Flask 1.1.+ Install using `pip`: diff --git a/docs/about/release-notes.md b/docs/about/release-notes.md index 1b0412c..0a48485 100644 --- a/docs/about/release-notes.md +++ b/docs/about/release-notes.md @@ -2,7 +2,7 @@ ## Version 2.0 (unreleased) -* Dropped support for Python `<3.5`. +* Dropped support for Python `<3.6`. * Dropped support for Flask `<1.1`. ## Version 1.1 diff --git a/docs/index.md b/docs/index.md index 39f2574..43831b7 100644 --- a/docs/index.md +++ b/docs/index.md @@ -14,7 +14,7 @@ Flask API is a drop-in replacement for Flask that provides an implementation of Requirements: -* Python 3.5+ +* Python 3.6+ * Flask 1.1+ The following packages are optional: diff --git a/setup.py b/setup.py index 6145833..e70591a 100755 --- a/setup.py +++ b/setup.py @@ -74,7 +74,6 @@ def get_package_data(package): 'Operating System :: OS Independent', 'Programming Language :: Python', 'Programming Language :: Python :: 3', - 'Programming Language :: Python :: 3.5', 'Programming Language :: Python :: 3.6', 'Programming Language :: Python :: 3.7', 'Programming Language :: Python :: 3.8', From 6566cf1162785cf168e52ae180d437c80e5a746d Mon Sep 17 00:00:00 2001 From: Jace Browning Date: Wed, 27 Nov 2019 15:01:31 -0500 Subject: [PATCH 54/87] Bump version to 2.0 --- docs/about/release-notes.md | 2 +- flask_api/__init__.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/about/release-notes.md b/docs/about/release-notes.md index 0a48485..8c72f8e 100644 --- a/docs/about/release-notes.md +++ b/docs/about/release-notes.md @@ -1,6 +1,6 @@ # Release Notes -## Version 2.0 (unreleased) +## Version 2.0 * Dropped support for Python `<3.6`. * Dropped support for Flask `<1.1`. diff --git a/flask_api/__init__.py b/flask_api/__init__.py index 4449650..7053768 100644 --- a/flask_api/__init__.py +++ b/flask_api/__init__.py @@ -1,3 +1,3 @@ from flask_api.app import FlaskAPI -__version__ = '2.0b1' +__version__ = '2.0' From a5b4e326048832650ecd6eb5af3a0b21e46433bd Mon Sep 17 00:00:00 2001 From: Tim Gates Date: Sun, 9 Feb 2020 20:01:43 +1100 Subject: [PATCH 55/87] Fix simple typo: satifies -> satisfies Closes #113 --- flask_api/request.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/flask_api/request.py b/flask_api/request.py index d9d291a..dc435ca 100644 --- a/flask_api/request.py +++ b/flask_api/request.py @@ -38,7 +38,7 @@ def files(self): def _parse(self): """ - Parse the body of the request, using whichever parser satifies the + Parse the body of the request, using whichever parser satisfies the client 'Content-Type' header. """ if not self.content_type or not self.content_length: From 8f24f925da047dfb0203e3b146df3b9e6532d3d1 Mon Sep 17 00:00:00 2001 From: Louis Sautier Date: Tue, 22 Sep 2020 00:46:38 +0200 Subject: [PATCH 56/87] Fix tests with PyPy, remove unused Python2-related code --- flask_api/tests/test_parsers.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/flask_api/tests/test_parsers.py b/flask_api/tests/test_parsers.py index 90a6b83..b7968f6 100644 --- a/flask_api/tests/test_parsers.py +++ b/flask_api/tests/test_parsers.py @@ -36,9 +36,9 @@ def test_invalid_json(self): with self.assertRaises(exceptions.ParseError) as context: parser.parse(stream, mediatypes.MediaType('application/json')) detail = str(context.exception) - expected_py2 = 'JSON parse error - Expecting property name: line 1 column 1 (char 1)' + expected_pypy = 'JSON parse error - Key name must be string at char: line 1 column 2 (char 1)' expected_py3 = 'JSON parse error - Expecting property name enclosed in double quotes: line 1 column 2 (char 1)' - self.assertIn(detail, (expected_py2, expected_py3)) + self.assertIn(detail, (expected_pypy, expected_py3)) def test_invalid_multipart(self): parser = parsers.MultiPartParser() From 424785922d118fd2de9a480865e8c862b50b1edf Mon Sep 17 00:00:00 2001 From: alexmisk Date: Fri, 6 Nov 2020 17:03:28 +0300 Subject: [PATCH 57/87] Update screenshot in documentation (fix #102) --- docs/screenshot.png | Bin 59600 -> 71682 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/docs/screenshot.png b/docs/screenshot.png index 9dba138e08c6f38e331825ac501cf91949d47298..5d0122279a888f0931a872e7c19c9d0b30ef5df8 100644 GIT binary patch literal 71682 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�W>?Ix!L31(jOU)wc}IqI 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 b+YyC^_T3GCnb=k>t^ Date: Fri, 6 Nov 2020 14:42:42 +0000 Subject: [PATCH 58/87] Bump bleach from 3.1.0 to 3.1.4 Bumps [bleach](https://github.com/mozilla/bleach) from 3.1.0 to 3.1.4. - [Release notes](https://github.com/mozilla/bleach/releases) - [Changelog](https://github.com/mozilla/bleach/blob/master/CHANGES) - [Commits](https://github.com/mozilla/bleach/compare/v3.1.0...v3.1.4) Signed-off-by: dependabot[bot] --- Pipfile.lock | 253 +++++++++++++++++++++++++++++++++------------------ 1 file changed, 165 insertions(+), 88 deletions(-) diff --git a/Pipfile.lock b/Pipfile.lock index f6040f9..bf677a7 100644 --- a/Pipfile.lock +++ b/Pipfile.lock @@ -16,10 +16,10 @@ "default": { "click": { "hashes": [ - "sha256:2335065e6395b9e67ca716de5f7526736bfa6ceead690adf616d925bdc622b13", - "sha256:5b94b49521f6456670fdb30cd82a4eca9412788a93fa6dd6df72c94d5a8ff2d7" + "sha256:d2b5255c7c6349bc1bd1e59e08cd12acbbd63ce649f2588755783aa94dfb6b1a", + "sha256:dacca89f4bfadd5de3d7489b7c8a566eee0d3676333fbb50030263894c38c0dc" ], - "version": "==7.0" + "version": "==7.1.2" }, "flask": { "hashes": [ @@ -38,10 +38,10 @@ }, "jinja2": { "hashes": [ - "sha256:74320bb91f31270f9551d46522e33af46a80c3d619f4a4bf42b3164d30b5911f", - "sha256:9fe95f19286cfefaa917656583d020be14e7859c6b0252588391e47db34527de" + "sha256:89aab215427ef59c34ad58735269eb58b1a5808103067f7bb9d5836c651b3bb0", + "sha256:f0a4641d3cf955324a89c04f3d94663aa4d638abe8f733ecd3582848e1c37035" ], - "version": "==2.10.3" + "version": "==2.11.2" }, "markdown": { "hashes": [ @@ -57,13 +57,16 @@ "sha256:09027a7803a62ca78792ad89403b1b7a73a01c8cb65909cd876f7fcebd79b161", "sha256:09c4b7f37d6c648cb13f9230d847adf22f8171b1ccc4d5682398e77f40309235", "sha256:1027c282dad077d0bae18be6794e6b6b8c91d58ed8a8d89a89d59693b9131db5", + "sha256:13d3144e1e340870b25e7b10b98d779608c02016d5184cfb9927a9f10c689f42", "sha256:24982cc2533820871eba85ba648cd53d8623687ff11cbb805be4ff7b4c971aff", "sha256:29872e92839765e546828bb7754a68c418d927cd064fd4708fab9fe9c8bb116b", "sha256:43a55c2930bbc139570ac2452adf3d70cdbb3cfe5912c71cdce1c2c6bbd9c5d1", "sha256:46c99d2de99945ec5cb54f23c8cd5689f6d7177305ebff350a58ce5f8de1669e", "sha256:500d4957e52ddc3351cabf489e79c91c17f6e0899158447047588650b5e69183", "sha256:535f6fc4d397c1563d08b88e485c3496cf5784e927af890fb3c3aac7f933ec66", + "sha256:596510de112c685489095da617b5bcbbac7dd6384aeebeda4df6025d0256a81b", "sha256:62fe6c95e3ec8a7fad637b7f3d372c15ec1caa01ab47926cfdf7a75b40e0eac1", + "sha256:6788b695d50a51edb699cb55e35487e430fa21f1ed838122d722e0ff0ac5ba15", "sha256:6dd73240d2af64df90aa7c4e7481e23825ea70af4b4922f8ede5b9e35f78a3b1", "sha256:717ba8fe3ae9cc0006d7c451f0bb265ee07739daf76355d06366154ee68d221e", "sha256:79855e1c5b8da654cf486b830bd42c06e8780cea587384cf6545b7d9ac013a0b", @@ -80,16 +83,18 @@ "sha256:ba59edeaa2fc6114428f1637ffff42da1e311e29382d81b339c1817d37ec93c6", "sha256:c8716a48d94b06bb3b2524c2b77e055fb313aeb4ea620c8dd03a105574ba704f", "sha256:cd5df75523866410809ca100dc9681e301e3c27567cf498077e8551b6d20e42f", - "sha256:e249096428b3ae81b08327a63a485ad0878de3fb939049038579ac0ef61e17e7" + "sha256:cdb132fc825c38e1aeec2c8aa9338310d29d337bebbd7baa06889d09a60a1fa2", + "sha256:e249096428b3ae81b08327a63a485ad0878de3fb939049038579ac0ef61e17e7", + "sha256:e8313f01ba26fbbe36c7be1966a7b7424942f670f38e666995b88d012765b9be" ], "version": "==1.1.1" }, "werkzeug": { "hashes": [ - "sha256:7280924747b5733b246fe23972186c6b348f9ae29724135a6dfc1e53cea433e7", - "sha256:e5f4a1f98b52b18a93da705a7458e55afb26f32bff83ff5d19189f92462d65c4" + "sha256:2de2a5db0baeae7b2d2664949077c2ac63fbd16d98da0ff71837f7d1dea3fd43", + "sha256:6c80b1e5ad3665290ea39320b91e1be1e0d5f60652b964a3070216de83d2e47c" ], - "version": "==0.16.0" + "version": "==1.0.1" } }, "develop": { @@ -102,17 +107,59 @@ }, "bleach": { "hashes": [ - "sha256:213336e49e102af26d9cde77dd2d0397afabc5a6bf2fed985dc35b5d1e285a16", - "sha256:3fdf7f77adcf649c9911387df51254b813185e32b2c6619f690b593a617e19fa" + "sha256:cc8da25076a1fe56c3ac63671e2194458e0c4d9c7becfd52ca251650d517903c", + "sha256:e78e426105ac07026ba098f04de8abe9b6e3e98b5befbf89b51a5ef0a4292b03" ], - "version": "==3.1.0" + "index": "pypi", + "version": "==3.1.4" }, "certifi": { "hashes": [ - "sha256:e4f3620cfea4f83eedc95b24abd9cd56f3c4b146dd0177e83a21b4eb49e21e50", - "sha256:fd7c7c74727ddcf00e9acd26bba8da604ffec95bf1c2144e67aff7a8b50e6cef" - ], - "version": "==2019.9.11" + "sha256:5930595817496dd21bb8dc35dad090f1c2cd0adfaf21204bf6732ca5d8ee34d3", + "sha256:8fc0819f1f30ba15bdb34cceffb9ef04d99f420f68eb75d901e9560b8749fc41" + ], + "version": "==2020.6.20" + }, + "cffi": { + "hashes": [ + "sha256:005f2bfe11b6745d726dbb07ace4d53f057de66e336ff92d61b8c7e9c8f4777d", + "sha256:09e96138280241bd355cd585148dec04dbbedb4f46128f340d696eaafc82dd7b", + "sha256:0b1ad452cc824665ddc682400b62c9e4f5b64736a2ba99110712fdee5f2505c4", + "sha256:0ef488305fdce2580c8b2708f22d7785ae222d9825d3094ab073e22e93dfe51f", + "sha256:15f351bed09897fbda218e4db5a3d5c06328862f6198d4fb385f3e14e19decb3", + "sha256:22399ff4870fb4c7ef19fff6eeb20a8bbf15571913c181c78cb361024d574579", + "sha256:23e5d2040367322824605bc29ae8ee9175200b92cb5483ac7d466927a9b3d537", + "sha256:2791f68edc5749024b4722500e86303a10d342527e1e3bcac47f35fbd25b764e", + "sha256:2f9674623ca39c9ebe38afa3da402e9326c245f0f5ceff0623dccdac15023e05", + "sha256:3363e77a6176afb8823b6e06db78c46dbc4c7813b00a41300a4873b6ba63b171", + "sha256:33c6cdc071ba5cd6d96769c8969a0531be2d08c2628a0143a10a7dcffa9719ca", + "sha256:3b8eaf915ddc0709779889c472e553f0d3e8b7bdf62dab764c8921b09bf94522", + "sha256:3cb3e1b9ec43256c4e0f8d2837267a70b0e1ca8c4f456685508ae6106b1f504c", + "sha256:3eeeb0405fd145e714f7633a5173318bd88d8bbfc3dd0a5751f8c4f70ae629bc", + "sha256:44f60519595eaca110f248e5017363d751b12782a6f2bd6a7041cba275215f5d", + "sha256:4d7c26bfc1ea9f92084a1d75e11999e97b62d63128bcc90c3624d07813c52808", + "sha256:529c4ed2e10437c205f38f3691a68be66c39197d01062618c55f74294a4a4828", + "sha256:6642f15ad963b5092d65aed022d033c77763515fdc07095208f15d3563003869", + "sha256:85ba797e1de5b48aa5a8427b6ba62cf69607c18c5d4eb747604b7302f1ec382d", + "sha256:8f0f1e499e4000c4c347a124fa6a27d37608ced4fe9f7d45070563b7c4c370c9", + "sha256:a624fae282e81ad2e4871bdb767e2c914d0539708c0f078b5b355258293c98b0", + "sha256:b0358e6fefc74a16f745afa366acc89f979040e0cbc4eec55ab26ad1f6a9bfbc", + "sha256:bbd2f4dfee1079f76943767fce837ade3087b578aeb9f69aec7857d5bf25db15", + "sha256:bf39a9e19ce7298f1bd6a9758fa99707e9e5b1ebe5e90f2c3913a47bc548747c", + "sha256:c11579638288e53fc94ad60022ff1b67865363e730ee41ad5e6f0a17188b327a", + "sha256:c150eaa3dadbb2b5339675b88d4573c1be3cb6f2c33a6c83387e10cc0bf05bd3", + "sha256:c53af463f4a40de78c58b8b2710ade243c81cbca641e34debf3396a9640d6ec1", + "sha256:cb763ceceae04803adcc4e2d80d611ef201c73da32d8f2722e9d0ab0c7f10768", + "sha256:cc75f58cdaf043fe6a7a6c04b3b5a0e694c6a9e24050967747251fb80d7bce0d", + "sha256:d80998ed59176e8cba74028762fbd9b9153b9afc71ea118e63bbf5d4d0f9552b", + "sha256:de31b5164d44ef4943db155b3e8e17929707cac1e5bd2f363e67a56e3af4af6e", + "sha256:e66399cf0fc07de4dce4f588fc25bfe84a6d1285cc544e67987d22663393926d", + "sha256:f0620511387790860b249b9241c2f13c3a80e21a73e0b861a2df24e9d6f56730", + "sha256:f4eae045e6ab2bb54ca279733fe4eb85f1effda392666308250714e01907f394", + "sha256:f92cdecb618e5fa4658aeb97d5eb3d2f47aa94ac6477c6daf0f306c5a3b9e6b1", + "sha256:f92f789e4f9241cd262ad7a555ca2c648a98178a953af117ef7fad46aa1d5591" + ], + "version": "==1.14.3" }, "chardet": { "hashes": [ @@ -123,10 +170,10 @@ }, "click": { "hashes": [ - "sha256:2335065e6395b9e67ca716de5f7526736bfa6ceead690adf616d925bdc622b13", - "sha256:5b94b49521f6456670fdb30cd82a4eca9412788a93fa6dd6df72c94d5a8ff2d7" + "sha256:d2b5255c7c6349bc1bd1e59e08cd12acbbd63ce649f2588755783aa94dfb6b1a", + "sha256:dacca89f4bfadd5de3d7489b7c8a566eee0d3676333fbb50030263894c38c0dc" ], - "version": "==7.0" + "version": "==7.1.2" }, "colorama": { "hashes": [ @@ -180,6 +227,33 @@ "index": "pypi", "version": "==2.1" }, + "cryptography": { + "hashes": [ + "sha256:07ca431b788249af92764e3be9a488aa1d39a0bc3be313d826bbec690417e538", + "sha256:13b88a0bd044b4eae1ef40e265d006e34dbcde0c2f1e15eb9896501b2d8f6c6f", + "sha256:32434673d8505b42c0de4de86da8c1620651abd24afe91ae0335597683ed1b77", + "sha256:3cd75a683b15576cfc822c7c5742b3276e50b21a06672dc3a800a2d5da4ecd1b", + "sha256:4e7268a0ca14536fecfdf2b00297d4e407da904718658c1ff1961c713f90fd33", + "sha256:545a8550782dda68f8cdc75a6e3bf252017aa8f75f19f5a9ca940772fc0cb56e", + "sha256:55d0b896631412b6f0c7de56e12eb3e261ac347fbaa5d5e705291a9016e5f8cb", + "sha256:5849d59358547bf789ee7e0d7a9036b2d29e9a4ddf1ce5e06bb45634f995c53e", + "sha256:6dc59630ecce8c1f558277ceb212c751d6730bd12c80ea96b4ac65637c4f55e7", + "sha256:7117319b44ed1842c617d0a452383a5a052ec6aa726dfbaffa8b94c910444297", + "sha256:75e8e6684cf0034f6bf2a97095cb95f81537b12b36a8fedf06e73050bb171c2d", + "sha256:7b8d9d8d3a9bd240f453342981f765346c87ade811519f98664519696f8e6ab7", + "sha256:a035a10686532b0587d58a606004aa20ad895c60c4d029afa245802347fab57b", + "sha256:a4e27ed0b2504195f855b52052eadcc9795c59909c9d84314c5408687f933fc7", + "sha256:a733671100cd26d816eed39507e585c156e4498293a907029969234e5e634bc4", + "sha256:a75f306a16d9f9afebfbedc41c8c2351d8e61e818ba6b4c40815e2b5740bb6b8", + "sha256:bd717aa029217b8ef94a7d21632a3bb5a4e7218a4513d2521c2a2fd63011e98b", + "sha256:d25cecbac20713a7c3bc544372d42d8eafa89799f492a43b79e1dfd650484851", + "sha256:d26a2557d8f9122f9bf445fc7034242f4375bd4e95ecda007667540270965b13", + "sha256:d3545829ab42a66b84a9aaabf216a4dce7f16dbc76eb69be5c302ed6b8f4a29b", + "sha256:d3d5e10be0cf2a12214ddee45c6bd203dab435e3d83b4560c03066eda600bfe3", + "sha256:efe15aca4f64f3a7ea0c09c87826490e50ed166ce67368a68f315ea0807a20df" + ], + "version": "==3.2.1" + }, "docopt": { "hashes": [ "sha256:49b3a825280bd66b3aa83585ef59c4a8c82f2c8a522dbe754a8bc8d08c85c491" @@ -212,39 +286,38 @@ }, "idna": { "hashes": [ - "sha256:c357b3f628cf53ae2c4c05627ecc484553142ca23264e593d327bcde5e9c3407", - "sha256:ea8b7f6188e6fa117537c3df7da9fc686d485087abf6ac197f9c46432f7e4a3c" + "sha256:b307872f855b18632ce0c21c5e45be78c0ea7ae4c15c828c20788b26921eb3f6", + "sha256:b97d804b1e9b523befed77c48dacec60e6dcb0b5391d57af6a65a312a90648c0" ], - "version": "==2.8" + "version": "==2.10" }, - "importlib-metadata": { + "jeepney": { "hashes": [ - "sha256:aa18d7378b00b40847790e7c27e11673d7fed219354109d0e7b9e5b25dc3ad26", - "sha256:d5f18a79777f3aa179c145737780282e27b508fc8fd688cb17c7a813e8bd39af" + "sha256:3479b861cc2b6407de5188695fa1a8d57e5072d7059322469b62628869b8e36e", + "sha256:d6c6b49683446d2407d2fe3acb7a368a77ff063f9182fe427da15d622adc24cf" ], - "markers": "python_version < '3.8'", - "version": "==0.23" + "markers": "sys_platform == 'linux'", + "version": "==0.4.3" }, "jinja2": { "hashes": [ - "sha256:74320bb91f31270f9551d46522e33af46a80c3d619f4a4bf42b3164d30b5911f", - "sha256:9fe95f19286cfefaa917656583d020be14e7859c6b0252588391e47db34527de" + "sha256:89aab215427ef59c34ad58735269eb58b1a5808103067f7bb9d5836c651b3bb0", + "sha256:f0a4641d3cf955324a89c04f3d94663aa4d638abe8f733ecd3582848e1c37035" ], - "version": "==2.10.3" + "version": "==2.11.2" }, "keyring": { "hashes": [ - "sha256:91037ccaf0c9a112a76f7740e4a416b9457a69b66c2799421581bee710a974b3", - "sha256:f5bb20ea6c57c2360daf0c591931c9ea0d7660a8d9e32ca84d63273f131ea605" + "sha256:4e34ea2fdec90c1c43d6610b5a5fafa1b9097db1802948e90caf5763974b8f8d", + "sha256:9aeadd006a852b78f4b4ef7c7556c2774d2432bbef8ee538a3e9089ac8b11466" ], - "version": "==19.2.0" + "version": "==21.4.0" }, "livereload": { "hashes": [ - "sha256:78d55f2c268a8823ba499305dcac64e28ddeb9a92571e12d543cd304faf5817b", - "sha256:89254f78d7529d7ea0a3417d224c34287ebfe266b05e67e51facaf82c27f0f66" + "sha256:776f2f865e59fde56490a56bcc6773b6917366bce0c267c60ee8aaf1a0959869" ], - "version": "==2.6.1" + "version": "==2.6.3" }, "macfsevents": { "hashes": [ @@ -268,13 +341,16 @@ "sha256:09027a7803a62ca78792ad89403b1b7a73a01c8cb65909cd876f7fcebd79b161", "sha256:09c4b7f37d6c648cb13f9230d847adf22f8171b1ccc4d5682398e77f40309235", "sha256:1027c282dad077d0bae18be6794e6b6b8c91d58ed8a8d89a89d59693b9131db5", + "sha256:13d3144e1e340870b25e7b10b98d779608c02016d5184cfb9927a9f10c689f42", "sha256:24982cc2533820871eba85ba648cd53d8623687ff11cbb805be4ff7b4c971aff", "sha256:29872e92839765e546828bb7754a68c418d927cd064fd4708fab9fe9c8bb116b", "sha256:43a55c2930bbc139570ac2452adf3d70cdbb3cfe5912c71cdce1c2c6bbd9c5d1", "sha256:46c99d2de99945ec5cb54f23c8cd5689f6d7177305ebff350a58ce5f8de1669e", "sha256:500d4957e52ddc3351cabf489e79c91c17f6e0899158447047588650b5e69183", "sha256:535f6fc4d397c1563d08b88e485c3496cf5784e927af890fb3c3aac7f933ec66", + "sha256:596510de112c685489095da617b5bcbbac7dd6384aeebeda4df6025d0256a81b", "sha256:62fe6c95e3ec8a7fad637b7f3d372c15ec1caa01ab47926cfdf7a75b40e0eac1", + "sha256:6788b695d50a51edb699cb55e35487e430fa21f1ed838122d722e0ff0ac5ba15", "sha256:6dd73240d2af64df90aa7c4e7481e23825ea70af4b4922f8ede5b9e35f78a3b1", "sha256:717ba8fe3ae9cc0006d7c451f0bb265ee07739daf76355d06366154ee68d221e", "sha256:79855e1c5b8da654cf486b830bd42c06e8780cea587384cf6545b7d9ac013a0b", @@ -291,7 +367,9 @@ "sha256:ba59edeaa2fc6114428f1637ffff42da1e311e29382d81b339c1817d37ec93c6", "sha256:c8716a48d94b06bb3b2524c2b77e055fb313aeb4ea620c8dd03a105574ba704f", "sha256:cd5df75523866410809ca100dc9681e301e3c27567cf498077e8551b6d20e42f", - "sha256:e249096428b3ae81b08327a63a485ad0878de3fb939049038579ac0ef61e17e7" + "sha256:cdb132fc825c38e1aeec2c8aa9338310d29d337bebbd7baa06889d09a60a1fa2", + "sha256:e249096428b3ae81b08327a63a485ad0878de3fb939049038579ac0ef61e17e7", + "sha256:e8313f01ba26fbbe36c7be1966a7b7424942f670f38e666995b88d012765b9be" ], "version": "==1.1.1" }, @@ -310,13 +388,6 @@ "index": "pypi", "version": "==0.17.5" }, - "more-itertools": { - "hashes": [ - "sha256:409cd48d4db7052af495b09dec721011634af3753ae1ef92d2b32f73a745f832", - "sha256:92b8c4b06dac4f0611c0729b2f2ede52b2e1bac1ab48f089c7ddc12e26bb60c4" - ], - "version": "==7.2.0" - }, "nose": { "hashes": [ "sha256:9ff7c6cc443f8c51994b34a667bbcf45afd6d945be7477b52e97516fd17c53ac", @@ -328,10 +399,10 @@ }, "pkginfo": { "hashes": [ - "sha256:7424f2c8511c186cd5424bbf31045b77435b37a8d604990b79d4e70d741148bb", - "sha256:a6d9e40ca61ad3ebd0b72fbadd4fba16e4c0e4df0428c041e01e06eb6ee71f32" + "sha256:a6a4ac943b496745cec21f14f021bbd869d5e9b4f6ec06918cffea5a2f4b9193", + "sha256:ce14d7296c673dc4c61c759a0b6c14bae34e34eb819c0017bb6ca5b7292c56e9" ], - "version": "==1.5.0.1" + "version": "==1.6.1" }, "pycodestyle": { "hashes": [ @@ -340,6 +411,13 @@ ], "version": "==2.5.0" }, + "pycparser": { + "hashes": [ + "sha256:2d475327684562c3a96cc71adf7dc8c4f0565175cf86b6d7a404ff4c771f15f0", + "sha256:7582ad22678f0fcd81102833f60ef8d0e57288b6b5fb00323d101be910e35705" + ], + "version": "==2.20" + }, "pyflakes": { "hashes": [ "sha256:17dbeb2e3f4d772725c777fabc446d5634d1038f234e77343108ce445ea69ce0", @@ -349,10 +427,10 @@ }, "pygments": { "hashes": [ - "sha256:83ec6c6133ca6b529b7ff5aa826328fd14b5bb02a58c37f4f06384e96a0f94ab", - "sha256:b7949de3d396836085fea596998b135a22610bbcc4f2abfe9e448e44cbc58388" + "sha256:381985fcc551eb9d37c52088a32914e00517e57f4a21609f48141ba08e193fa0", + "sha256:88a0bbcd659fcb9573703957c6b9cff9fab7295e6e76db54c9d00ae42df32773" ], - "version": "==2.5.1" + "version": "==2.7.2" }, "pync": { "hashes": [ @@ -378,35 +456,33 @@ }, "pyyaml": { "hashes": [ - "sha256:0113bc0ec2ad727182326b61326afa3d1d8280ae1122493553fd6f4397f33df9", - "sha256:01adf0b6c6f61bd11af6e10ca52b7d4057dd0be0343eb9283c878cf3af56aee4", - "sha256:5124373960b0b3f4aa7df1707e63e9f109b5263eca5976c66e08b1c552d4eaf8", - "sha256:5ca4f10adbddae56d824b2c09668e91219bb178a1eee1faa56af6f99f11bf696", - "sha256:7907be34ffa3c5a32b60b95f4d95ea25361c951383a894fec31be7252b2b6f34", - "sha256:7ec9b2a4ed5cad025c2278a1e6a19c011c80a3caaac804fd2d329e9cc2c287c9", - "sha256:87ae4c829bb25b9fe99cf71fbb2140c448f534e24c998cc60f39ae4f94396a73", - "sha256:9de9919becc9cc2ff03637872a440195ac4241c80536632fffeb6a1e25a74299", - "sha256:a5a85b10e450c66b49f98846937e8cfca1db3127a9d5d1e31ca45c3d0bef4c5b", - "sha256:b0997827b4f6a7c286c01c5f60384d218dca4ed7d9efa945c3e1aa623d5709ae", - "sha256:b631ef96d3222e62861443cc89d6563ba3eeb816eeb96b2629345ab795e53681", - "sha256:bf47c0607522fdbca6c9e817a6e81b08491de50f3766a7a0e6a5be7905961b41", - "sha256:f81025eddd0327c7d4cfe9b62cf33190e1e736cc6e97502b3ec425f574b3e7a8" - ], - "version": "==5.1.2" + "sha256:06a0d7ba600ce0b2d2fe2e78453a470b5a6e000a985dd4a4e54e436cc36b0e97", + "sha256:240097ff019d7c70a4922b6869d8a86407758333f02203e0fc6ff79c5dcede76", + "sha256:4f4b913ca1a7319b33cfb1369e91e50354d6f07a135f3b901aca02aa95940bd2", + "sha256:69f00dca373f240f842b2931fb2c7e14ddbacd1397d57157a9b005a6a9942648", + "sha256:73f099454b799e05e5ab51423c7bcf361c58d3206fa7b0d555426b1f4d9a3eaf", + "sha256:74809a57b329d6cc0fdccee6318f44b9b8649961fa73144a98735b0aaf029f1f", + "sha256:7739fc0fa8205b3ee8808aea45e968bc90082c10aef6ea95e855e10abf4a37b2", + "sha256:95f71d2af0ff4227885f7a6605c37fd53d3a106fcab511b8860ecca9fcf400ee", + "sha256:b8eac752c5e14d3eca0e6dd9199cd627518cb5ec06add0de9d32baeee6fe645d", + "sha256:cc8955cfbfc7a115fa81d85284ee61147059a753344bc51098f3ccd69b0d7e0c", + "sha256:d13155f591e6fcc1ec3b30685d50bf0711574e2c0dfffd7644babf8b5102ca1a" + ], + "version": "==5.3.1" }, "readme-renderer": { "hashes": [ - "sha256:bb16f55b259f27f75f640acf5e00cf897845a8b3e4731b5c1a436e4b8529202f", - "sha256:c8532b79afc0375a85f10433eca157d6b50f7d6990f337fa498c96cd4bfc203d" + "sha256:267854ac3b1530633c2394ead828afcd060fc273217c42ac36b6be9c42cd9a9d", + "sha256:6b7e5aa59210a40de72eb79931491eaf46fefca2952b9181268bd7c7c65c260a" ], - "version": "==24.0" + "version": "==28.0" }, "requests": { "hashes": [ - "sha256:11e007a8a2aa0323f5a921e9e6a2d7e4e67d9877e85773fba9ba6419025cbeb4", - "sha256:9cf5292fcd0f598c671cfc1e0d7d1a7f13bb8085e9a590f48c010551dc6c4b31" + "sha256:b3559a131db72c33ee969480840fff4bb6dd111de7dd27c8ee1f820f4f00231b", + "sha256:fe75cc94a9443b9246fc7049224f75604b113c36acb93f87b80ed42c44cbb898" ], - "version": "==2.22.0" + "version": "==2.24.0" }, "requests-toolbelt": { "hashes": [ @@ -415,12 +491,20 @@ ], "version": "==0.9.1" }, + "secretstorage": { + "hashes": [ + "sha256:15da8a989b65498e29be338b3b279965f1b8f09b9668bd8010da183024c8bff6", + "sha256:b5ec909dde94d4ae2fa26af7c089036997030f0cf0a5cb372b4cccabd81c143b" + ], + "markers": "sys_platform == 'linux'", + "version": "==3.1.2" + }, "six": { "hashes": [ - "sha256:1f1b7d42e254082a9db6279deae68afb421ceba6158efa6131de7b3003ee93fd", - "sha256:30f610279e8b2578cab6db20741130331735c781b56053c59c4076da27f06b66" + "sha256:30639c035cdb23534cd4aa2dd52c3bf48f06e5f4a941509c8bafd8ce11080259", + "sha256:8b74bedcbbbaca38ff6d7491d76f2b06b3592611af620f8426e82dddb04a5ced" ], - "version": "==1.13.0" + "version": "==1.15.0" }, "sniffer": { "hashes": [ @@ -442,10 +526,10 @@ }, "tqdm": { "hashes": [ - "sha256:5a1f3d58f3eb53264387394387fe23df469d2a3fab98c9e7f99d5c146c119873", - "sha256:f1a1613fee07cc30a253051617f2a219a785c58877f9f6bfa129446cbaf8b4c1" + "sha256:9ad44aaf0fc3697c06f6e05c7cf025dd66bc7bcb7613c66d85f4464c47ac8fad", + "sha256:ef54779f1c09f346b2b5a8e5c61f96fbcb639929e640e59f8cf810794f406432" ], - "version": "==4.39.0" + "version": "==4.51.0" }, "twine": { "hashes": [ @@ -457,10 +541,10 @@ }, "urllib3": { "hashes": [ - "sha256:a8a318824cc77d1fd4b2bec2ded92646630d7fe8619497b142c84a9e6f5a7293", - "sha256:f3c5fd51747d450d4dcf6f923c81f78f811aab8205fda64b0aba34a4e48b0745" + "sha256:8d7eaa5a82a1cac232164990f04874c594c9453ec55eef02eab885aa02fc17a2", + "sha256:f5321fbe4bf3fefa0efd0bfe7fb14e90909eb62a48ccda331726b4319897dd5e" ], - "version": "==1.25.7" + "version": "==1.25.11" }, "webencodings": { "hashes": [ @@ -468,13 +552,6 @@ "sha256:b36a1c245f2d304965eb4e0a82848379241dc04b865afcc4aab16748587e1923" ], "version": "==0.5.1" - }, - "zipp": { - "hashes": [ - "sha256:3718b1cbcd963c7d4c5511a8240812904164b7f381b647143a89d3b98f9bcd8e", - "sha256:f06903e9f1f43b12d371004b4ac7b06ab39a44adc747266928ae6debfa7b3335" - ], - "version": "==0.6.0" } } } From ebf75c2b5e14bc1ac5228bcf5bfb7ee38dd7f7e4 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 2 Feb 2021 21:53:17 +0000 Subject: [PATCH 59/87] Bump bleach from 3.1.4 to 3.3.0 Bumps [bleach](https://github.com/mozilla/bleach) from 3.1.4 to 3.3.0. - [Release notes](https://github.com/mozilla/bleach/releases) - [Changelog](https://github.com/mozilla/bleach/blob/master/CHANGES) - [Commits](https://github.com/mozilla/bleach/compare/v3.1.4...v3.3.0) Signed-off-by: dependabot[bot] --- Pipfile.lock | 287 ++++++++++++++++++++++++++++++--------------------- 1 file changed, 171 insertions(+), 116 deletions(-) diff --git a/Pipfile.lock b/Pipfile.lock index bf677a7..a13be41 100644 --- a/Pipfile.lock +++ b/Pipfile.lock @@ -38,10 +38,10 @@ }, "jinja2": { "hashes": [ - "sha256:89aab215427ef59c34ad58735269eb58b1a5808103067f7bb9d5836c651b3bb0", - "sha256:f0a4641d3cf955324a89c04f3d94663aa4d638abe8f733ecd3582848e1c37035" + "sha256:03e47ad063331dd6a3f04a43eddca8a966a26ba0c5b7207a9a9e4e08f1b29419", + "sha256:a6d58433de0ae800347cab1fa3043cebbabe8baa9d29e668f1c768cb87a333c6" ], - "version": "==2.11.2" + "version": "==2.11.3" }, "markdown": { "hashes": [ @@ -58,8 +58,12 @@ "sha256:09c4b7f37d6c648cb13f9230d847adf22f8171b1ccc4d5682398e77f40309235", "sha256:1027c282dad077d0bae18be6794e6b6b8c91d58ed8a8d89a89d59693b9131db5", "sha256:13d3144e1e340870b25e7b10b98d779608c02016d5184cfb9927a9f10c689f42", + "sha256:195d7d2c4fbb0ee8139a6cf67194f3973a6b3042d742ebe0a9ed36d8b6f0c07f", + "sha256:22c178a091fc6630d0d045bdb5992d2dfe14e3259760e713c490da5323866c39", "sha256:24982cc2533820871eba85ba648cd53d8623687ff11cbb805be4ff7b4c971aff", "sha256:29872e92839765e546828bb7754a68c418d927cd064fd4708fab9fe9c8bb116b", + "sha256:2beec1e0de6924ea551859edb9e7679da6e4870d32cb766240ce17e0a0ba2014", + "sha256:3b8a6499709d29c2e2399569d96719a1b21dcd94410a586a18526b143ec8470f", "sha256:43a55c2930bbc139570ac2452adf3d70cdbb3cfe5912c71cdce1c2c6bbd9c5d1", "sha256:46c99d2de99945ec5cb54f23c8cd5689f6d7177305ebff350a58ce5f8de1669e", "sha256:500d4957e52ddc3351cabf489e79c91c17f6e0899158447047588650b5e69183", @@ -68,24 +72,39 @@ "sha256:62fe6c95e3ec8a7fad637b7f3d372c15ec1caa01ab47926cfdf7a75b40e0eac1", "sha256:6788b695d50a51edb699cb55e35487e430fa21f1ed838122d722e0ff0ac5ba15", "sha256:6dd73240d2af64df90aa7c4e7481e23825ea70af4b4922f8ede5b9e35f78a3b1", + "sha256:6f1e273a344928347c1290119b493a1f0303c52f5a5eae5f16d74f48c15d4a85", + "sha256:6fffc775d90dcc9aed1b89219549b329a9250d918fd0b8fa8d93d154918422e1", "sha256:717ba8fe3ae9cc0006d7c451f0bb265ee07739daf76355d06366154ee68d221e", "sha256:79855e1c5b8da654cf486b830bd42c06e8780cea587384cf6545b7d9ac013a0b", "sha256:7c1699dfe0cf8ff607dbdcc1e9b9af1755371f92a68f706051cc8c37d447c905", + "sha256:7fed13866cf14bba33e7176717346713881f56d9d2bcebab207f7a036f41b850", + "sha256:84dee80c15f1b560d55bcfe6d47b27d070b4681c699c572af2e3c7cc90a3b8e0", "sha256:88e5fcfb52ee7b911e8bb6d6aa2fd21fbecc674eadd44118a9cc3863f938e735", "sha256:8defac2f2ccd6805ebf65f5eeb132adcf2ab57aa11fdf4c0dd5169a004710e7d", + "sha256:98bae9582248d6cf62321dcb52aaf5d9adf0bad3b40582925ef7c7f0ed85fceb", "sha256:98c7086708b163d425c67c7a91bad6e466bb99d797aa64f965e9d25c12111a5e", "sha256:9add70b36c5666a2ed02b43b335fe19002ee5235efd4b8a89bfcf9005bebac0d", "sha256:9bf40443012702a1d2070043cb6291650a0841ece432556f784f004937f0f32c", + "sha256:a6a744282b7718a2a62d2ed9d993cad6f5f585605ad352c11de459f4108df0a1", + "sha256:acf08ac40292838b3cbbb06cfe9b2cb9ec78fce8baca31ddb87aaac2e2dc3bc2", "sha256:ade5e387d2ad0d7ebf59146cc00c8044acbd863725f887353a10df825fc8ae21", "sha256:b00c1de48212e4cc9603895652c5c410df699856a2853135b3967591e4beebc2", "sha256:b1282f8c00509d99fef04d8ba936b156d419be841854fe901d8ae224c59f0be5", + "sha256:b1dba4527182c95a0db8b6060cc98ac49b9e2f5e64320e2b56e47cb2831978c7", "sha256:b2051432115498d3562c084a49bba65d97cf251f5a331c64a12ee7e04dacc51b", + "sha256:b7d644ddb4dbd407d31ffb699f1d140bc35478da613b441c582aeb7c43838dd8", "sha256:ba59edeaa2fc6114428f1637ffff42da1e311e29382d81b339c1817d37ec93c6", + "sha256:bf5aa3cbcfdf57fa2ee9cd1822c862ef23037f5c832ad09cfea57fa846dec193", "sha256:c8716a48d94b06bb3b2524c2b77e055fb313aeb4ea620c8dd03a105574ba704f", + "sha256:caabedc8323f1e93231b52fc32bdcde6db817623d33e100708d9a68e1f53b26b", "sha256:cd5df75523866410809ca100dc9681e301e3c27567cf498077e8551b6d20e42f", "sha256:cdb132fc825c38e1aeec2c8aa9338310d29d337bebbd7baa06889d09a60a1fa2", + "sha256:d53bc011414228441014aa71dbec320c66468c1030aae3a6e29778a3382d96e5", + "sha256:d73a845f227b0bfe8a7455ee623525ee656a9e2e749e4742706d80a6065d5e2c", + "sha256:d9be0ba6c527163cbed5e0857c451fcd092ce83947944d6c14bc95441203f032", "sha256:e249096428b3ae81b08327a63a485ad0878de3fb939049038579ac0ef61e17e7", - "sha256:e8313f01ba26fbbe36c7be1966a7b7424942f670f38e666995b88d012765b9be" + "sha256:e8313f01ba26fbbe36c7be1966a7b7424942f670f38e666995b88d012765b9be", + "sha256:feb7b34d6325451ef96bc0e36e1a6c0c1c64bc1fbec4b854f4529e51887b1621" ], "version": "==1.1.1" }, @@ -107,66 +126,67 @@ }, "bleach": { "hashes": [ - "sha256:cc8da25076a1fe56c3ac63671e2194458e0c4d9c7becfd52ca251650d517903c", - "sha256:e78e426105ac07026ba098f04de8abe9b6e3e98b5befbf89b51a5ef0a4292b03" + "sha256:6123ddc1052673e52bab52cdc955bcb57a015264a1c57d37bea2f6b817af0125", + "sha256:98b3170739e5e83dd9dc19633f074727ad848cbedb6026708c8ac2d3b697a433" ], "index": "pypi", - "version": "==3.1.4" + "version": "==3.3.0" }, "certifi": { "hashes": [ - "sha256:5930595817496dd21bb8dc35dad090f1c2cd0adfaf21204bf6732ca5d8ee34d3", - "sha256:8fc0819f1f30ba15bdb34cceffb9ef04d99f420f68eb75d901e9560b8749fc41" + "sha256:1a4995114262bffbc2413b159f2a1a480c969de6e6eb13ee966d470af86af59c", + "sha256:719a74fb9e33b9bd44cc7f3a8d94bc35e4049deebe19ba7d8e108280cfd59830" ], - "version": "==2020.6.20" + "version": "==2020.12.5" }, "cffi": { "hashes": [ - "sha256:005f2bfe11b6745d726dbb07ace4d53f057de66e336ff92d61b8c7e9c8f4777d", - "sha256:09e96138280241bd355cd585148dec04dbbedb4f46128f340d696eaafc82dd7b", - "sha256:0b1ad452cc824665ddc682400b62c9e4f5b64736a2ba99110712fdee5f2505c4", - "sha256:0ef488305fdce2580c8b2708f22d7785ae222d9825d3094ab073e22e93dfe51f", - "sha256:15f351bed09897fbda218e4db5a3d5c06328862f6198d4fb385f3e14e19decb3", - "sha256:22399ff4870fb4c7ef19fff6eeb20a8bbf15571913c181c78cb361024d574579", - "sha256:23e5d2040367322824605bc29ae8ee9175200b92cb5483ac7d466927a9b3d537", - "sha256:2791f68edc5749024b4722500e86303a10d342527e1e3bcac47f35fbd25b764e", - "sha256:2f9674623ca39c9ebe38afa3da402e9326c245f0f5ceff0623dccdac15023e05", - "sha256:3363e77a6176afb8823b6e06db78c46dbc4c7813b00a41300a4873b6ba63b171", - "sha256:33c6cdc071ba5cd6d96769c8969a0531be2d08c2628a0143a10a7dcffa9719ca", - "sha256:3b8eaf915ddc0709779889c472e553f0d3e8b7bdf62dab764c8921b09bf94522", - "sha256:3cb3e1b9ec43256c4e0f8d2837267a70b0e1ca8c4f456685508ae6106b1f504c", - "sha256:3eeeb0405fd145e714f7633a5173318bd88d8bbfc3dd0a5751f8c4f70ae629bc", - "sha256:44f60519595eaca110f248e5017363d751b12782a6f2bd6a7041cba275215f5d", - "sha256:4d7c26bfc1ea9f92084a1d75e11999e97b62d63128bcc90c3624d07813c52808", - "sha256:529c4ed2e10437c205f38f3691a68be66c39197d01062618c55f74294a4a4828", - "sha256:6642f15ad963b5092d65aed022d033c77763515fdc07095208f15d3563003869", - "sha256:85ba797e1de5b48aa5a8427b6ba62cf69607c18c5d4eb747604b7302f1ec382d", - "sha256:8f0f1e499e4000c4c347a124fa6a27d37608ced4fe9f7d45070563b7c4c370c9", - "sha256:a624fae282e81ad2e4871bdb767e2c914d0539708c0f078b5b355258293c98b0", - "sha256:b0358e6fefc74a16f745afa366acc89f979040e0cbc4eec55ab26ad1f6a9bfbc", - "sha256:bbd2f4dfee1079f76943767fce837ade3087b578aeb9f69aec7857d5bf25db15", - "sha256:bf39a9e19ce7298f1bd6a9758fa99707e9e5b1ebe5e90f2c3913a47bc548747c", - "sha256:c11579638288e53fc94ad60022ff1b67865363e730ee41ad5e6f0a17188b327a", - "sha256:c150eaa3dadbb2b5339675b88d4573c1be3cb6f2c33a6c83387e10cc0bf05bd3", - "sha256:c53af463f4a40de78c58b8b2710ade243c81cbca641e34debf3396a9640d6ec1", - "sha256:cb763ceceae04803adcc4e2d80d611ef201c73da32d8f2722e9d0ab0c7f10768", - "sha256:cc75f58cdaf043fe6a7a6c04b3b5a0e694c6a9e24050967747251fb80d7bce0d", - "sha256:d80998ed59176e8cba74028762fbd9b9153b9afc71ea118e63bbf5d4d0f9552b", - "sha256:de31b5164d44ef4943db155b3e8e17929707cac1e5bd2f363e67a56e3af4af6e", - "sha256:e66399cf0fc07de4dce4f588fc25bfe84a6d1285cc544e67987d22663393926d", - "sha256:f0620511387790860b249b9241c2f13c3a80e21a73e0b861a2df24e9d6f56730", - "sha256:f4eae045e6ab2bb54ca279733fe4eb85f1effda392666308250714e01907f394", - "sha256:f92cdecb618e5fa4658aeb97d5eb3d2f47aa94ac6477c6daf0f306c5a3b9e6b1", - "sha256:f92f789e4f9241cd262ad7a555ca2c648a98178a953af117ef7fad46aa1d5591" - ], - "version": "==1.14.3" + "sha256:00a1ba5e2e95684448de9b89888ccd02c98d512064b4cb987d48f4b40aa0421e", + "sha256:00e28066507bfc3fe865a31f325c8391a1ac2916219340f87dfad602c3e48e5d", + "sha256:045d792900a75e8b1e1b0ab6787dd733a8190ffcf80e8c8ceb2fb10a29ff238a", + "sha256:0638c3ae1a0edfb77c6765d487fee624d2b1ee1bdfeffc1f0b58c64d149e7eec", + "sha256:105abaf8a6075dc96c1fe5ae7aae073f4696f2905fde6aeada4c9d2926752362", + "sha256:155136b51fd733fa94e1c2ea5211dcd4c8879869008fc811648f16541bf99668", + "sha256:1a465cbe98a7fd391d47dce4b8f7e5b921e6cd805ef421d04f5f66ba8f06086c", + "sha256:1d2c4994f515e5b485fd6d3a73d05526aa0fcf248eb135996b088d25dfa1865b", + "sha256:2c24d61263f511551f740d1a065eb0212db1dbbbbd241db758f5244281590c06", + "sha256:51a8b381b16ddd370178a65360ebe15fbc1c71cf6f584613a7ea08bfad946698", + "sha256:594234691ac0e9b770aee9fcdb8fa02c22e43e5c619456efd0d6c2bf276f3eb2", + "sha256:5cf4be6c304ad0b6602f5c4e90e2f59b47653ac1ed9c662ed379fe48a8f26b0c", + "sha256:64081b3f8f6f3c3de6191ec89d7dc6c86a8a43911f7ecb422c60e90c70be41c7", + "sha256:6bc25fc545a6b3d57b5f8618e59fc13d3a3a68431e8ca5fd4c13241cd70d0009", + "sha256:798caa2a2384b1cbe8a2a139d80734c9db54f9cc155c99d7cc92441a23871c03", + "sha256:7c6b1dece89874d9541fc974917b631406233ea0440d0bdfbb8e03bf39a49b3b", + "sha256:7ef7d4ced6b325e92eb4d3502946c78c5367bc416398d387b39591532536734e", + "sha256:840793c68105fe031f34d6a086eaea153a0cd5c491cde82a74b420edd0a2b909", + "sha256:8d6603078baf4e11edc4168a514c5ce5b3ba6e3e9c374298cb88437957960a53", + "sha256:9cc46bc107224ff5b6d04369e7c595acb700c3613ad7bcf2e2012f62ece80c35", + "sha256:9f7a31251289b2ab6d4012f6e83e58bc3b96bd151f5b5262467f4bb6b34a7c26", + "sha256:9ffb888f19d54a4d4dfd4b3f29bc2c16aa4972f1c2ab9c4ab09b8ab8685b9c2b", + "sha256:a5ed8c05548b54b998b9498753fb9cadbfd92ee88e884641377d8a8b291bcc01", + "sha256:a7711edca4dcef1a75257b50a2fbfe92a65187c47dab5a0f1b9b332c5919a3fb", + "sha256:af5c59122a011049aad5dd87424b8e65a80e4a6477419c0c1015f73fb5ea0293", + "sha256:b18e0a9ef57d2b41f5c68beefa32317d286c3d6ac0484efd10d6e07491bb95dd", + "sha256:b4e248d1087abf9f4c10f3c398896c87ce82a9856494a7155823eb45a892395d", + "sha256:ba4e9e0ae13fc41c6b23299545e5ef73055213e466bd107953e4a013a5ddd7e3", + "sha256:c6332685306b6417a91b1ff9fae889b3ba65c2292d64bd9245c093b1b284809d", + "sha256:d5ff0621c88ce83a28a10d2ce719b2ee85635e85c515f12bac99a95306da4b2e", + "sha256:d9efd8b7a3ef378dd61a1e77367f1924375befc2eba06168b6ebfa903a5e59ca", + "sha256:df5169c4396adc04f9b0a05f13c074df878b6052430e03f50e68adf3a57aa28d", + "sha256:ebb253464a5d0482b191274f1c8bf00e33f7e0b9c66405fbffc61ed2c839c775", + "sha256:ec80dc47f54e6e9a78181ce05feb71a0353854cc26999db963695f950b5fb375", + "sha256:f032b34669220030f905152045dfa27741ce1a6db3324a5bc0b96b6c7420c87b", + "sha256:f60567825f791c6f8a592f3c6e3bd93dd2934e3f9dac189308426bd76b00ef3b", + "sha256:f803eaa94c2fcda012c047e62bc7a51b0bdabda1cad7a92a522694ea2d76e49f" + ], + "version": "==1.14.4" }, "chardet": { "hashes": [ - "sha256:84ab92ed1c4d4f16916e05906b6b75a6c0fb5db821cc65e70cbd64a3e2a5eaae", - "sha256:fc323ffcaeaed0e0a02bf4d117757b98aed530d9ed4531e3e15460124c106691" + "sha256:0d6f53a15db4120f2b08c94f11e7d93d2c911ee118b6b30a04ec3ee8310179fa", + "sha256:f864054d66fd9118f2e67044ac8981a54775ec5b67aed0441892edb553d21da5" ], - "version": "==3.0.4" + "version": "==4.0.0" }, "click": { "hashes": [ @@ -229,30 +249,22 @@ }, "cryptography": { "hashes": [ - "sha256:07ca431b788249af92764e3be9a488aa1d39a0bc3be313d826bbec690417e538", - "sha256:13b88a0bd044b4eae1ef40e265d006e34dbcde0c2f1e15eb9896501b2d8f6c6f", - "sha256:32434673d8505b42c0de4de86da8c1620651abd24afe91ae0335597683ed1b77", - "sha256:3cd75a683b15576cfc822c7c5742b3276e50b21a06672dc3a800a2d5da4ecd1b", - "sha256:4e7268a0ca14536fecfdf2b00297d4e407da904718658c1ff1961c713f90fd33", - "sha256:545a8550782dda68f8cdc75a6e3bf252017aa8f75f19f5a9ca940772fc0cb56e", - "sha256:55d0b896631412b6f0c7de56e12eb3e261ac347fbaa5d5e705291a9016e5f8cb", - "sha256:5849d59358547bf789ee7e0d7a9036b2d29e9a4ddf1ce5e06bb45634f995c53e", - "sha256:6dc59630ecce8c1f558277ceb212c751d6730bd12c80ea96b4ac65637c4f55e7", - "sha256:7117319b44ed1842c617d0a452383a5a052ec6aa726dfbaffa8b94c910444297", - "sha256:75e8e6684cf0034f6bf2a97095cb95f81537b12b36a8fedf06e73050bb171c2d", - "sha256:7b8d9d8d3a9bd240f453342981f765346c87ade811519f98664519696f8e6ab7", - "sha256:a035a10686532b0587d58a606004aa20ad895c60c4d029afa245802347fab57b", - "sha256:a4e27ed0b2504195f855b52052eadcc9795c59909c9d84314c5408687f933fc7", - "sha256:a733671100cd26d816eed39507e585c156e4498293a907029969234e5e634bc4", - "sha256:a75f306a16d9f9afebfbedc41c8c2351d8e61e818ba6b4c40815e2b5740bb6b8", - "sha256:bd717aa029217b8ef94a7d21632a3bb5a4e7218a4513d2521c2a2fd63011e98b", - "sha256:d25cecbac20713a7c3bc544372d42d8eafa89799f492a43b79e1dfd650484851", - "sha256:d26a2557d8f9122f9bf445fc7034242f4375bd4e95ecda007667540270965b13", - "sha256:d3545829ab42a66b84a9aaabf216a4dce7f16dbc76eb69be5c302ed6b8f4a29b", - "sha256:d3d5e10be0cf2a12214ddee45c6bd203dab435e3d83b4560c03066eda600bfe3", - "sha256:efe15aca4f64f3a7ea0c09c87826490e50ed166ce67368a68f315ea0807a20df" - ], - "version": "==3.2.1" + "sha256:0003a52a123602e1acee177dc90dd201f9bb1e73f24a070db7d36c588e8f5c7d", + "sha256:0e85aaae861d0485eb5a79d33226dd6248d2a9f133b81532c8f5aae37de10ff7", + "sha256:594a1db4511bc4d960571536abe21b4e5c3003e8750ab8365fafce71c5d86901", + "sha256:69e836c9e5ff4373ce6d3ab311c1a2eed274793083858d3cd4c7d12ce20d5f9c", + "sha256:788a3c9942df5e4371c199d10383f44a105d67d401fb4304178020142f020244", + "sha256:7e177e4bea2de937a584b13645cab32f25e3d96fc0bc4a4cf99c27dc77682be6", + "sha256:83d9d2dfec70364a74f4e7c70ad04d3ca2e6a08b703606993407bf46b97868c5", + "sha256:84ef7a0c10c24a7773163f917f1cb6b4444597efd505a8aed0a22e8c4780f27e", + "sha256:9e21301f7a1e7c03dbea73e8602905a4ebba641547a462b26dd03451e5769e7c", + "sha256:9f6b0492d111b43de5f70052e24c1f0951cb9e6022188ebcb1cc3a3d301469b0", + "sha256:a69bd3c68b98298f490e84519b954335154917eaab52cf582fa2c5c7efc6e812", + "sha256:b4890d5fb9b7a23e3bf8abf5a8a7da8e228f1e97dc96b30b95685df840b6914a", + "sha256:c366df0401d1ec4e548bebe8f91d55ebcc0ec3137900d214dd7aac8427ef3030", + "sha256:dc42f645f8f3a489c3dd416730a514e7a91a59510ddaadc09d04224c098d3302" + ], + "version": "==3.3.1" }, "docopt": { "hashes": [ @@ -293,25 +305,25 @@ }, "jeepney": { "hashes": [ - "sha256:3479b861cc2b6407de5188695fa1a8d57e5072d7059322469b62628869b8e36e", - "sha256:d6c6b49683446d2407d2fe3acb7a368a77ff063f9182fe427da15d622adc24cf" + "sha256:7d59b6622675ca9e993a6bd38de845051d315f8b0c72cca3aef733a20b648657", + "sha256:aec56c0eb1691a841795111e184e13cad504f7703b9a64f63020816afa79a8ae" ], "markers": "sys_platform == 'linux'", - "version": "==0.4.3" + "version": "==0.6.0" }, "jinja2": { "hashes": [ - "sha256:89aab215427ef59c34ad58735269eb58b1a5808103067f7bb9d5836c651b3bb0", - "sha256:f0a4641d3cf955324a89c04f3d94663aa4d638abe8f733ecd3582848e1c37035" + "sha256:03e47ad063331dd6a3f04a43eddca8a966a26ba0c5b7207a9a9e4e08f1b29419", + "sha256:a6d58433de0ae800347cab1fa3043cebbabe8baa9d29e668f1c768cb87a333c6" ], - "version": "==2.11.2" + "version": "==2.11.3" }, "keyring": { "hashes": [ - "sha256:4e34ea2fdec90c1c43d6610b5a5fafa1b9097db1802948e90caf5763974b8f8d", - "sha256:9aeadd006a852b78f4b4ef7c7556c2774d2432bbef8ee538a3e9089ac8b11466" + "sha256:9acb3e1452edbb7544822b12fd25459078769e560fa51f418b6d00afaa6178df", + "sha256:9f44660a5d4931bdc14c08a1d01ef30b18a7a8147380710d8c9f9531e1f6c3c0" ], - "version": "==21.4.0" + "version": "==22.0.1" }, "livereload": { "hashes": [ @@ -342,8 +354,12 @@ "sha256:09c4b7f37d6c648cb13f9230d847adf22f8171b1ccc4d5682398e77f40309235", "sha256:1027c282dad077d0bae18be6794e6b6b8c91d58ed8a8d89a89d59693b9131db5", "sha256:13d3144e1e340870b25e7b10b98d779608c02016d5184cfb9927a9f10c689f42", + "sha256:195d7d2c4fbb0ee8139a6cf67194f3973a6b3042d742ebe0a9ed36d8b6f0c07f", + "sha256:22c178a091fc6630d0d045bdb5992d2dfe14e3259760e713c490da5323866c39", "sha256:24982cc2533820871eba85ba648cd53d8623687ff11cbb805be4ff7b4c971aff", "sha256:29872e92839765e546828bb7754a68c418d927cd064fd4708fab9fe9c8bb116b", + "sha256:2beec1e0de6924ea551859edb9e7679da6e4870d32cb766240ce17e0a0ba2014", + "sha256:3b8a6499709d29c2e2399569d96719a1b21dcd94410a586a18526b143ec8470f", "sha256:43a55c2930bbc139570ac2452adf3d70cdbb3cfe5912c71cdce1c2c6bbd9c5d1", "sha256:46c99d2de99945ec5cb54f23c8cd5689f6d7177305ebff350a58ce5f8de1669e", "sha256:500d4957e52ddc3351cabf489e79c91c17f6e0899158447047588650b5e69183", @@ -352,24 +368,39 @@ "sha256:62fe6c95e3ec8a7fad637b7f3d372c15ec1caa01ab47926cfdf7a75b40e0eac1", "sha256:6788b695d50a51edb699cb55e35487e430fa21f1ed838122d722e0ff0ac5ba15", "sha256:6dd73240d2af64df90aa7c4e7481e23825ea70af4b4922f8ede5b9e35f78a3b1", + "sha256:6f1e273a344928347c1290119b493a1f0303c52f5a5eae5f16d74f48c15d4a85", + "sha256:6fffc775d90dcc9aed1b89219549b329a9250d918fd0b8fa8d93d154918422e1", "sha256:717ba8fe3ae9cc0006d7c451f0bb265ee07739daf76355d06366154ee68d221e", "sha256:79855e1c5b8da654cf486b830bd42c06e8780cea587384cf6545b7d9ac013a0b", "sha256:7c1699dfe0cf8ff607dbdcc1e9b9af1755371f92a68f706051cc8c37d447c905", + "sha256:7fed13866cf14bba33e7176717346713881f56d9d2bcebab207f7a036f41b850", + "sha256:84dee80c15f1b560d55bcfe6d47b27d070b4681c699c572af2e3c7cc90a3b8e0", "sha256:88e5fcfb52ee7b911e8bb6d6aa2fd21fbecc674eadd44118a9cc3863f938e735", "sha256:8defac2f2ccd6805ebf65f5eeb132adcf2ab57aa11fdf4c0dd5169a004710e7d", + "sha256:98bae9582248d6cf62321dcb52aaf5d9adf0bad3b40582925ef7c7f0ed85fceb", "sha256:98c7086708b163d425c67c7a91bad6e466bb99d797aa64f965e9d25c12111a5e", "sha256:9add70b36c5666a2ed02b43b335fe19002ee5235efd4b8a89bfcf9005bebac0d", "sha256:9bf40443012702a1d2070043cb6291650a0841ece432556f784f004937f0f32c", + "sha256:a6a744282b7718a2a62d2ed9d993cad6f5f585605ad352c11de459f4108df0a1", + "sha256:acf08ac40292838b3cbbb06cfe9b2cb9ec78fce8baca31ddb87aaac2e2dc3bc2", "sha256:ade5e387d2ad0d7ebf59146cc00c8044acbd863725f887353a10df825fc8ae21", "sha256:b00c1de48212e4cc9603895652c5c410df699856a2853135b3967591e4beebc2", "sha256:b1282f8c00509d99fef04d8ba936b156d419be841854fe901d8ae224c59f0be5", + "sha256:b1dba4527182c95a0db8b6060cc98ac49b9e2f5e64320e2b56e47cb2831978c7", "sha256:b2051432115498d3562c084a49bba65d97cf251f5a331c64a12ee7e04dacc51b", + "sha256:b7d644ddb4dbd407d31ffb699f1d140bc35478da613b441c582aeb7c43838dd8", "sha256:ba59edeaa2fc6114428f1637ffff42da1e311e29382d81b339c1817d37ec93c6", + "sha256:bf5aa3cbcfdf57fa2ee9cd1822c862ef23037f5c832ad09cfea57fa846dec193", "sha256:c8716a48d94b06bb3b2524c2b77e055fb313aeb4ea620c8dd03a105574ba704f", + "sha256:caabedc8323f1e93231b52fc32bdcde6db817623d33e100708d9a68e1f53b26b", "sha256:cd5df75523866410809ca100dc9681e301e3c27567cf498077e8551b6d20e42f", "sha256:cdb132fc825c38e1aeec2c8aa9338310d29d337bebbd7baa06889d09a60a1fa2", + "sha256:d53bc011414228441014aa71dbec320c66468c1030aae3a6e29778a3382d96e5", + "sha256:d73a845f227b0bfe8a7455ee623525ee656a9e2e749e4742706d80a6065d5e2c", + "sha256:d9be0ba6c527163cbed5e0857c451fcd092ce83947944d6c14bc95441203f032", "sha256:e249096428b3ae81b08327a63a485ad0878de3fb939049038579ac0ef61e17e7", - "sha256:e8313f01ba26fbbe36c7be1966a7b7424942f670f38e666995b88d012765b9be" + "sha256:e8313f01ba26fbbe36c7be1966a7b7424942f670f38e666995b88d012765b9be", + "sha256:feb7b34d6325451ef96bc0e36e1a6c0c1c64bc1fbec4b854f4529e51887b1621" ], "version": "==1.1.1" }, @@ -397,12 +428,19 @@ "index": "pypi", "version": "==1.3.7" }, + "packaging": { + "hashes": [ + "sha256:5b327ac1320dc863dca72f4514ecc086f31186744b84a230374cc1fd776feae5", + "sha256:67714da7f7bc052e064859c05c595155bd1ee9f69f76557e21f051443c20947a" + ], + "version": "==20.9" + }, "pkginfo": { "hashes": [ - "sha256:a6a4ac943b496745cec21f14f021bbd869d5e9b4f6ec06918cffea5a2f4b9193", - "sha256:ce14d7296c673dc4c61c759a0b6c14bae34e34eb819c0017bb6ca5b7292c56e9" + "sha256:029a70cb45c6171c329dfc890cde0879f8c52d6f3922794796e06f577bb03db4", + "sha256:9fdbea6495622e022cc72c2e5e1b735218e4ffb2a2a69cde2694a6c1f16afb75" ], - "version": "==1.6.1" + "version": "==1.7.0" }, "pycodestyle": { "hashes": [ @@ -427,10 +465,10 @@ }, "pygments": { "hashes": [ - "sha256:381985fcc551eb9d37c52088a32914e00517e57f4a21609f48141ba08e193fa0", - "sha256:88a0bbcd659fcb9573703957c6b9cff9fab7295e6e76db54c9d00ae42df32773" + "sha256:bc9591213a8f0e0ca1a5e68a479b4887fdc3e75d0774e5c71c31920c427de435", + "sha256:df49d09b498e83c1a73128295860250b0b7edd4c723a32e9bc0d295c7c2ec337" ], - "version": "==2.7.2" + "version": "==2.7.4" }, "pync": { "hashes": [ @@ -440,6 +478,13 @@ "markers": "sys_platform == 'darwin'", "version": "==1.6.1" }, + "pyparsing": { + "hashes": [ + "sha256:c203ec8783bf771a155b207279b9bccb8dea02d8f0c9e5f8ead507bc3246ecc1", + "sha256:ef9d7589ef3c200abe66653d3f1ab1033c3c419ae9b9bdb1240a85b024efc88b" + ], + "version": "==2.4.7" + }, "python-dateutil": { "hashes": [ "sha256:73ebfe9dbf22e832286dafa60473e4cd239f8592f699aa5adaf10050e6e1823c", @@ -456,19 +501,29 @@ }, "pyyaml": { "hashes": [ - "sha256:06a0d7ba600ce0b2d2fe2e78453a470b5a6e000a985dd4a4e54e436cc36b0e97", - "sha256:240097ff019d7c70a4922b6869d8a86407758333f02203e0fc6ff79c5dcede76", - "sha256:4f4b913ca1a7319b33cfb1369e91e50354d6f07a135f3b901aca02aa95940bd2", - "sha256:69f00dca373f240f842b2931fb2c7e14ddbacd1397d57157a9b005a6a9942648", - "sha256:73f099454b799e05e5ab51423c7bcf361c58d3206fa7b0d555426b1f4d9a3eaf", - "sha256:74809a57b329d6cc0fdccee6318f44b9b8649961fa73144a98735b0aaf029f1f", - "sha256:7739fc0fa8205b3ee8808aea45e968bc90082c10aef6ea95e855e10abf4a37b2", - "sha256:95f71d2af0ff4227885f7a6605c37fd53d3a106fcab511b8860ecca9fcf400ee", - "sha256:b8eac752c5e14d3eca0e6dd9199cd627518cb5ec06add0de9d32baeee6fe645d", - "sha256:cc8955cfbfc7a115fa81d85284ee61147059a753344bc51098f3ccd69b0d7e0c", - "sha256:d13155f591e6fcc1ec3b30685d50bf0711574e2c0dfffd7644babf8b5102ca1a" - ], - "version": "==5.3.1" + "sha256:08682f6b72c722394747bddaf0aa62277e02557c0fd1c42cb853016a38f8dedf", + "sha256:0f5f5786c0e09baddcd8b4b45f20a7b5d61a7e7e99846e3c799b05c7c53fa696", + "sha256:129def1b7c1bf22faffd67b8f3724645203b79d8f4cc81f674654d9902cb4393", + "sha256:294db365efa064d00b8d1ef65d8ea2c3426ac366c0c4368d930bf1c5fb497f77", + "sha256:3b2b1824fe7112845700f815ff6a489360226a5609b96ec2190a45e62a9fc922", + "sha256:3bd0e463264cf257d1ffd2e40223b197271046d09dadf73a0fe82b9c1fc385a5", + "sha256:4465124ef1b18d9ace298060f4eccc64b0850899ac4ac53294547536533800c8", + "sha256:49d4cdd9065b9b6e206d0595fee27a96b5dd22618e7520c33204a4a3239d5b10", + "sha256:4e0583d24c881e14342eaf4ec5fbc97f934b999a6828693a99157fde912540cc", + "sha256:5accb17103e43963b80e6f837831f38d314a0495500067cb25afab2e8d7a4018", + "sha256:607774cbba28732bfa802b54baa7484215f530991055bb562efbed5b2f20a45e", + "sha256:6c78645d400265a062508ae399b60b8c167bf003db364ecb26dcab2bda048253", + "sha256:74c1485f7707cf707a7aef42ef6322b8f97921bd89be2ab6317fd782c2d53183", + "sha256:8c1be557ee92a20f184922c7b6424e8ab6691788e6d86137c5d93c1a6ec1b8fb", + "sha256:bb4191dfc9306777bc594117aee052446b3fa88737cd13b7188d0e7aa8162185", + "sha256:c20cfa2d49991c8b4147af39859b167664f2ad4561704ee74c1de03318e898db", + "sha256:d2d9808ea7b4af864f35ea216be506ecec180628aced0704e34aca0b040ffe46", + "sha256:dd5de0646207f053eb0d6c74ae45ba98c3395a571a2891858e87df7c9b9bd51b", + "sha256:e1d4970ea66be07ae37a3c2e48b5ec63f7ba6804bdddfdbd3cfd954d25a82e63", + "sha256:e4fac90784481d221a8e4b1162afa7c47ed953be40d31ab4629ae917510051df", + "sha256:fa5ae20527d8e831e8230cbffd9f8fe952815b2b7dae6ffec25318803a7528fc" + ], + "version": "==5.4.1" }, "readme-renderer": { "hashes": [ @@ -479,10 +534,10 @@ }, "requests": { "hashes": [ - "sha256:b3559a131db72c33ee969480840fff4bb6dd111de7dd27c8ee1f820f4f00231b", - "sha256:fe75cc94a9443b9246fc7049224f75604b113c36acb93f87b80ed42c44cbb898" + "sha256:27973dd4a904a4f13b263a19c866c13b92a39ed1c964655f025f3f8d3d75b804", + "sha256:c210084e36a42ae6b9219e00e48287def368a26d03a048ddad7bfee44f75871e" ], - "version": "==2.24.0" + "version": "==2.25.1" }, "requests-toolbelt": { "hashes": [ @@ -493,11 +548,11 @@ }, "secretstorage": { "hashes": [ - "sha256:15da8a989b65498e29be338b3b279965f1b8f09b9668bd8010da183024c8bff6", - "sha256:b5ec909dde94d4ae2fa26af7c089036997030f0cf0a5cb372b4cccabd81c143b" + "sha256:30cfdef28829dad64d6ea1ed08f8eff6aa115a77068926bcc9f5225d5a3246aa", + "sha256:5c36f6537a523ec5f969ef9fad61c98eb9e017bc601d811e53aa25bece64892f" ], "markers": "sys_platform == 'linux'", - "version": "==3.1.2" + "version": "==3.3.0" }, "six": { "hashes": [ @@ -526,10 +581,10 @@ }, "tqdm": { "hashes": [ - "sha256:9ad44aaf0fc3697c06f6e05c7cf025dd66bc7bcb7613c66d85f4464c47ac8fad", - "sha256:ef54779f1c09f346b2b5a8e5c61f96fbcb639929e640e59f8cf810794f406432" + "sha256:4621f6823bab46a9cc33d48105753ccbea671b68bab2c50a9f0be23d4065cb5a", + "sha256:fe3d08dd00a526850568d542ff9de9bbc2a09a791da3c334f3213d8d0bbbca65" ], - "version": "==4.51.0" + "version": "==4.56.0" }, "twine": { "hashes": [ @@ -541,10 +596,10 @@ }, "urllib3": { "hashes": [ - "sha256:8d7eaa5a82a1cac232164990f04874c594c9453ec55eef02eab885aa02fc17a2", - "sha256:f5321fbe4bf3fefa0efd0bfe7fb14e90909eb62a48ccda331726b4319897dd5e" + "sha256:1b465e494e3e0d8939b50680403e3aedaa2bc434b7d5af64dfd3c958d7f5ae80", + "sha256:de3eedaad74a2683334e282005cd8d7f22f4d55fa690a2a1020a416cb0a47e73" ], - "version": "==1.25.11" + "version": "==1.26.3" }, "webencodings": { "hashes": [ From 717dc7ec3f5925b00eae0508d3bf63188ec681ae Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 10 Feb 2021 02:27:25 +0000 Subject: [PATCH 60/87] Bump cryptography from 3.3.1 to 3.3.2 Bumps [cryptography](https://github.com/pyca/cryptography) from 3.3.1 to 3.3.2. - [Release notes](https://github.com/pyca/cryptography/releases) - [Changelog](https://github.com/pyca/cryptography/blob/master/CHANGELOG.rst) - [Commits](https://github.com/pyca/cryptography/compare/3.3.1...3.3.2) Signed-off-by: dependabot[bot] --- Pipfile.lock | 44 ++++++++++++++++++++++---------------------- 1 file changed, 22 insertions(+), 22 deletions(-) diff --git a/Pipfile.lock b/Pipfile.lock index a13be41..97c8aeb 100644 --- a/Pipfile.lock +++ b/Pipfile.lock @@ -129,7 +129,6 @@ "sha256:6123ddc1052673e52bab52cdc955bcb57a015264a1c57d37bea2f6b817af0125", "sha256:98b3170739e5e83dd9dc19633f074727ad848cbedb6026708c8ac2d3b697a433" ], - "index": "pypi", "version": "==3.3.0" }, "certifi": { @@ -249,22 +248,23 @@ }, "cryptography": { "hashes": [ - "sha256:0003a52a123602e1acee177dc90dd201f9bb1e73f24a070db7d36c588e8f5c7d", - "sha256:0e85aaae861d0485eb5a79d33226dd6248d2a9f133b81532c8f5aae37de10ff7", - "sha256:594a1db4511bc4d960571536abe21b4e5c3003e8750ab8365fafce71c5d86901", - "sha256:69e836c9e5ff4373ce6d3ab311c1a2eed274793083858d3cd4c7d12ce20d5f9c", - "sha256:788a3c9942df5e4371c199d10383f44a105d67d401fb4304178020142f020244", - "sha256:7e177e4bea2de937a584b13645cab32f25e3d96fc0bc4a4cf99c27dc77682be6", - "sha256:83d9d2dfec70364a74f4e7c70ad04d3ca2e6a08b703606993407bf46b97868c5", - "sha256:84ef7a0c10c24a7773163f917f1cb6b4444597efd505a8aed0a22e8c4780f27e", - "sha256:9e21301f7a1e7c03dbea73e8602905a4ebba641547a462b26dd03451e5769e7c", - "sha256:9f6b0492d111b43de5f70052e24c1f0951cb9e6022188ebcb1cc3a3d301469b0", - "sha256:a69bd3c68b98298f490e84519b954335154917eaab52cf582fa2c5c7efc6e812", - "sha256:b4890d5fb9b7a23e3bf8abf5a8a7da8e228f1e97dc96b30b95685df840b6914a", - "sha256:c366df0401d1ec4e548bebe8f91d55ebcc0ec3137900d214dd7aac8427ef3030", - "sha256:dc42f645f8f3a489c3dd416730a514e7a91a59510ddaadc09d04224c098d3302" + "sha256:0d7b69674b738068fa6ffade5c962ecd14969690585aaca0a1b1fc9058938a72", + "sha256:1bd0ccb0a1ed775cd7e2144fe46df9dc03eefd722bbcf587b3e0616ea4a81eff", + "sha256:3c284fc1e504e88e51c428db9c9274f2da9f73fdf5d7e13a36b8ecb039af6e6c", + "sha256:49570438e60f19243e7e0d504527dd5fe9b4b967b5a1ff21cc12b57602dd85d3", + "sha256:541dd758ad49b45920dda3b5b48c968f8b2533d8981bcdb43002798d8f7a89ed", + "sha256:5a60d3780149e13b7a6ff7ad6526b38846354d11a15e21068e57073e29e19bed", + "sha256:7951a966613c4211b6612b0352f5bf29989955ee592c4a885d8c7d0f830d0433", + "sha256:922f9602d67c15ade470c11d616f2b2364950602e370c76f0c94c94ae672742e", + "sha256:a0f0b96c572fc9f25c3f4ddbf4688b9b38c69836713fb255f4a2715d93cbaf44", + "sha256:a777c096a49d80f9d2979695b835b0f9c9edab73b59e4ceb51f19724dda887ed", + "sha256:a9a4ac9648d39ce71c2f63fe7dc6db144b9fa567ddfc48b9fde1b54483d26042", + "sha256:aa4969f24d536ae2268c902b2c3d62ab464b5a66bcb247630d208a79a8098e9b", + "sha256:c7390f9b2119b2b43160abb34f63277a638504ef8df99f11cb52c1fda66a2e6f", + "sha256:e18e6ab84dfb0ab997faf8cca25a86ff15dfea4027b986322026cc99e0a892da" ], - "version": "==3.3.1" + "index": "pypi", + "version": "==3.3.2" }, "docopt": { "hashes": [ @@ -548,11 +548,11 @@ }, "secretstorage": { "hashes": [ - "sha256:30cfdef28829dad64d6ea1ed08f8eff6aa115a77068926bcc9f5225d5a3246aa", - "sha256:5c36f6537a523ec5f969ef9fad61c98eb9e017bc601d811e53aa25bece64892f" + "sha256:422d82c36172d88d6a0ed5afdec956514b189ddbfb72fefab0c8a1cee4eaf71f", + "sha256:fd666c51a6bf200643495a04abb261f83229dcb6fd8472ec393df7ffc8b6f195" ], "markers": "sys_platform == 'linux'", - "version": "==3.3.0" + "version": "==3.3.1" }, "six": { "hashes": [ @@ -581,10 +581,10 @@ }, "tqdm": { "hashes": [ - "sha256:4621f6823bab46a9cc33d48105753ccbea671b68bab2c50a9f0be23d4065cb5a", - "sha256:fe3d08dd00a526850568d542ff9de9bbc2a09a791da3c334f3213d8d0bbbca65" + "sha256:2874fa525c051177583ec59c0fb4583e91f28ccd3f217ffad2acdb32d2c789ac", + "sha256:ab9b659241d82b8b51b2269ee243ec95286046bf06015c4e15a947cc15914211" ], - "version": "==4.56.0" + "version": "==4.56.1" }, "twine": { "hashes": [ From 0cd17a48e740840f3456fc9e18e76c0a0260ac87 Mon Sep 17 00:00:00 2001 From: Jace Browning Date: Sat, 13 Feb 2021 11:31:05 -0500 Subject: [PATCH 61/87] Update Travis CI badge to travis-ci.com --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index d9eaabf..29166a3 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ Browsable web APIs for Flask. -[![Unix Build Status](https://img.shields.io/travis/flask-api/flask-api.svg)](https://travis-ci.org/flask-api/flask-api) +[![Unix Build Status](https://img.shields.io/travis/com/flask-api/flask-api.svg)](https://travis-ci.com/flask-api/flask-api) [![Coverage Status](https://img.shields.io/coveralls/flask-api/flask-api.svg)](https://coveralls.io/r/flask-api/flask-api) [![Scrutinizer Code Quality](https://img.shields.io/scrutinizer/g/flask-api/flask-api.svg)](https://scrutinizer-ci.com/g/flask-api/flask-api/) [![PyPI Version](https://img.shields.io/pypi/v/Flask-API.svg)](https://pypi.org/project/Flask-API/) From ff99f839691ef361422354bb612f8bd6afc20cd6 Mon Sep 17 00:00:00 2001 From: Jace Browning Date: Sat, 13 Feb 2021 11:42:28 -0500 Subject: [PATCH 62/87] Remove custom domain --- docs/CNAME | 1 - flask_api/templates/base.html | 2 +- mkdocs.yml | 1 - setup.py | 2 +- 4 files changed, 2 insertions(+), 4 deletions(-) delete mode 100644 docs/CNAME diff --git a/docs/CNAME b/docs/CNAME deleted file mode 100644 index 08b39d2..0000000 --- a/docs/CNAME +++ /dev/null @@ -1 +0,0 @@ -www.flaskapi.org diff --git a/flask_api/templates/base.html b/flask_api/templates/base.html index c80d7fc..0603943 100644 --- a/flask_api/templates/base.html +++ b/flask_api/templates/base.html @@ -31,7 +31,7 @@