Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -141,3 +141,6 @@ logs/

# mypy
.mypy_cache/

# terminalizer
config.yml
2 changes: 2 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ format: #: Format and fix python code with black, isort, autoflake
@echo "\n$(BOLD_CYAN)Flaking$(RESET_STYLES) ❄️"
flake8 --version
autoflake --remove-all-unused-imports --remove-unused-variables --remove-duplicate-keys --ignore-init-module-imports -i -r $(APP_DIR) $(TEST_DIR) $(HOME_DIR_PY_FILES)
@echo "\n"


lint: #: Run static analysis with flake8, radon, mypy and bandit
Expand All @@ -91,4 +92,5 @@ lint: #: Run static analysis with flake8, radon, mypy and bandit
@echo "\n$(BOLD_CYAN)Running pre-commit hooks$(RESET_STYLES) 🏁️️️"
pre-commit run --all-files
@echo "\n$(BOLD_CYAN)All checks passed$(RESET_STYLES) 🏳️️️️"
@echo "\n"

56 changes: 43 additions & 13 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,34 +19,33 @@ Tools
[![Static Typing: mypy](https://img.shields.io/badge/static%20typing-mypy-blue.svg?style=flat)](https://github.com/python/mypy/)
[![Security: bandit](https://img.shields.io/badge/security-bandit-yellow.svg?style=flat)](https://github.com/PyCQA/bandit)
[![pre-commit](https://img.shields.io/badge/pre--commit-enabled-brightgreen?style=flat&logo=pre-commit&logoColor=white)](https://github.com/pre-commit/pre-commit)
[![API Specs](https://img.shields.io/badge/specs-flasgger-6D9A00?style=flat&logo=swagger&logoColor=white)](https://github.com/flasgger/flasgger)


Usage Guide
------------------------------------------------------------------------------
This is a template project hosted on GitHub which can be used to create new repositories.

Steps for creating boilerplate project in GitHub
------------------------------------------------------------------------------
0. Create a new repository named "my-pyflask-project" using this template repository *
0. `git clone https://www.github.com/username/my-pyflask-project.git`
0. `cd my-pyflask-project`
0. Create and activate conda environment `conda activate my-conda-venv` **
0. `make setup` : Use pip-tools, pip-compile, pip install to setup python packages

### Steps for creating boilerplate project in GitHub
1. Create a new repository named "my-pyflask-project" using this template repository *
1. `git clone https://www.github.com/username/my-pyflask-project.git`
1. `cd my-pyflask-project`
1. Create and activate conda environment `conda activate my-conda-venv` **
1. `make setup` : Use pip-tools, pip-compile, pip install to setup python packages

\* [GitHub Guide: Creating a repository from a template](https://docs.github.com/en/github/creating-cloning-and-archiving-repositories/creating-a-repository-from-a-template)
<br>
\** [Guide to Conda environment](https://github.com/pritam001/pyflask-microservice-base/blob/master/documentation/conda.md)


Make Guide
------------------------------------------------------------------------------
### Make Guide
Type `make help` for available commands

<p align="center"><img src="documentation/assets/make-help.gif" /></p>


Linting Guide
------------------------------------------------------------------------------
### Linting Guide
`make format` : Format and fix python code with black, isort, autoflake

<p align="center"><img src="documentation/assets/make-format.gif" /></p>
Expand All @@ -56,8 +55,39 @@ Linting Guide
<p align="center"><img src="documentation/assets/make-lint.gif" /></p>


Contributing
### Documentation
Flasgger docs can be found at http://0.0.0.0:8420/api/v1/pyflask-service/swagger

API specs can be found at http://0.0.0.0:8420/api/v1/pyflask-service/swagger_spec

Flasgger UI version: v2 | OpenAPI version: 2

<p align="center"><img src="documentation/assets/flasgger_intro.png" /></p>


Development Setup
------------------------------------------------------------------------------
[![](https://sourcerer.io/fame/pritam001/pritam001/pyflask-microservice-base/images/0)](https://sourcerer.io/fame/pritam001/pritam001/pyflask-microservice-base/links/0)[![](https://sourcerer.io/fame/pritam001/pritam001/pyflask-microservice-base/images/1)](https://sourcerer.io/fame/pritam001/pritam001/pyflask-microservice-base/links/1)[![](https://sourcerer.io/fame/pritam001/pritam001/pyflask-microservice-base/images/2)](https://sourcerer.io/fame/pritam001/pritam001/pyflask-microservice-base/links/2)[![](https://sourcerer.io/fame/pritam001/pritam001/pyflask-microservice-base/images/3)](https://sourcerer.io/fame/pritam001/pritam001/pyflask-microservice-base/links/3)[![](https://sourcerer.io/fame/pritam001/pritam001/pyflask-microservice-base/images/4)](https://sourcerer.io/fame/pritam001/pritam001/pyflask-microservice-base/links/4)[![](https://sourcerer.io/fame/pritam001/pritam001/pyflask-microservice-base/images/5)](https://sourcerer.io/fame/pritam001/pritam001/pyflask-microservice-base/links/5)[![](https://sourcerer.io/fame/pritam001/pritam001/pyflask-microservice-base/images/6)](https://sourcerer.io/fame/pritam001/pritam001/pyflask-microservice-base/links/6)[![](https://sourcerer.io/fame/pritam001/pritam001/pyflask-microservice-base/images/7)](https://sourcerer.io/fame/pritam001/pritam001/pyflask-microservice-base/links/7)
To be updated


Contributing
------------------------------------------------------------------------------
[![](https://sourcerer.io/fame/pritam001/pritam001/pyflask-microservice-base/images/0)](https://sourcerer.io/fame/pritam001/pritam001/pyflask-microservice-base/links/0)
[![](https://sourcerer.io/fame/pritam001/pritam001/pyflask-microservice-base/images/1)](https://sourcerer.io/fame/pritam001/pritam001/pyflask-microservice-base/links/1)
[![](https://sourcerer.io/fame/pritam001/pritam001/pyflask-microservice-base/images/2)](https://sourcerer.io/fame/pritam001/pritam001/pyflask-microservice-base/links/2)
[![](https://sourcerer.io/fame/pritam001/pritam001/pyflask-microservice-base/images/3)](https://sourcerer.io/fame/pritam001/pritam001/pyflask-microservice-base/links/3)
[![](https://sourcerer.io/fame/pritam001/pritam001/pyflask-microservice-base/images/4)](https://sourcerer.io/fame/pritam001/pritam001/pyflask-microservice-base/links/4)
[![](https://sourcerer.io/fame/pritam001/pritam001/pyflask-microservice-base/images/5)](https://sourcerer.io/fame/pritam001/pritam001/pyflask-microservice-base/links/5)
[![](https://sourcerer.io/fame/pritam001/pritam001/pyflask-microservice-base/images/6)](https://sourcerer.io/fame/pritam001/pritam001/pyflask-microservice-base/links/6)
[![](https://sourcerer.io/fame/pritam001/pritam001/pyflask-microservice-base/images/7)](https://sourcerer.io/fame/pritam001/pritam001/pyflask-microservice-base/links/7)


TODO
-----------------------------------------------------------------------------
- [x] Swagger support
- [ ] Update linting documentation
- [ ] Introduction of testing tools
- [ ] Testing tools documentation
- [ ] Version handling by tbump
- [ ] Add CoC, Contribution guidelines, PR and issue

Binary file added documentation/assets/flasgger_intro.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified documentation/assets/make-lint.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Empty file added documentation/flasgger.md
Empty file.
1 change: 1 addition & 0 deletions requirements/dev-requirements.in
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ flake8-blind-except
flake8-breakpoint
flake8-builtins
flake8-comprehensions
flake8-eradicate
flake8-logging-format
flake8-print
flake8-pytest
Expand Down
6 changes: 4 additions & 2 deletions requirements/dev-requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -6,19 +6,21 @@
#
appdirs==1.4.4 # via black, virtualenv
astroid==2.4.2 # via pylint
attrs==19.3.0 # via black
attrs==19.3.0 # via black, flake8-eradicate
autoflake==1.3.1 # via -r requirements/dev-requirements.in
bandit==1.6.2 # via -r requirements/dev-requirements.in
black==19.10b0 # via -r requirements/dev-requirements.in
cfgv==3.2.0 # via pre-commit
click==7.1.2 # via black
colorama==0.4.3 # via radon
distlib==0.3.1 # via virtualenv
eradicate==1.0 # via flake8-eradicate
filelock==3.0.12 # via virtualenv
flake8-blind-except==0.1.1 # via -r requirements/dev-requirements.in
flake8-breakpoint==1.1.0 # via -r requirements/dev-requirements.in
flake8-builtins==1.5.3 # via -r requirements/dev-requirements.in
flake8-comprehensions==3.2.3 # via -r requirements/dev-requirements.in
flake8-eradicate==0.4.0 # via -r requirements/dev-requirements.in
flake8-flask==0.9.3 # via -r requirements/dev-requirements.in
flake8-logging-format==0.6.0 # via -r requirements/dev-requirements.in
flake8-plugin-utils==1.3.1 # via flake8-breakpoint, flake8-pytest-style, flake8-return
Expand All @@ -27,7 +29,7 @@ flake8-print==3.1.4 # via -r requirements/dev-requirements.in
flake8-pytest-style==1.2.3 # via -r requirements/dev-requirements.in
flake8-pytest==1.3 # via -r requirements/dev-requirements.in
flake8-return==1.1.2 # via -r requirements/dev-requirements.in
flake8==3.8.3 # via -r requirements/dev-requirements.in, flake8-builtins, flake8-comprehensions, flake8-flask, flake8-polyfill, flake8-print, flake8-pytest
flake8==3.8.3 # via -r requirements/dev-requirements.in, flake8-builtins, flake8-comprehensions, flake8-eradicate, flake8-flask, flake8-polyfill, flake8-print, flake8-pytest
future==0.18.2 # via radon
gitdb==4.0.5 # via gitpython
gitpython==3.1.7 # via bandit
Expand Down
6 changes: 4 additions & 2 deletions requirements/requirements.in
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
Flask
dynaconf
flask_apispec
flask_cors
flask_cors
flasgger
marshmallow
apispec
19 changes: 13 additions & 6 deletions requirements/requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,23 @@
#
# pip-compile --output-file=requirements/requirements.txt requirements/requirements.in
#
apispec==3.3.1 # via flask-apispec
apispec==3.3.1 # via -r requirements/requirements.in
attrs==19.3.0 # via jsonschema
click==7.1.2 # via flask
dynaconf==3.0.0 # via -r requirements/requirements.in
flask-apispec==0.9.0 # via -r requirements/requirements.in
flasgger==0.9.5 # via -r requirements/requirements.in
flask-cors==3.0.8 # via -r requirements/requirements.in
flask==1.1.2 # via -r requirements/requirements.in, flask-apispec, flask-cors
flask==1.1.2 # via -r requirements/requirements.in, flasgger, flask-cors
itsdangerous==1.1.0 # via flask
jinja2==2.11.2 # via flask
jsonschema==3.2.0 # via flasgger
markupsafe==1.1.1 # via jinja2
marshmallow==3.7.1 # via flask-apispec, webargs
six==1.15.0 # via flask-apispec, flask-cors
webargs==5.5.3 # via flask-apispec
marshmallow==3.7.1 # via -r requirements/requirements.in
mistune==0.8.4 # via flasgger
pyrsistent==0.16.0 # via jsonschema
pyyaml==5.3.1 # via flasgger
six==1.15.0 # via flasgger, flask-cors, jsonschema
werkzeug==1.0.1 # via flask

# The following packages are considered to be unsafe in a requirements file:
# setuptools
1 change: 1 addition & 0 deletions settings.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
{
"default": {
"DEBUG": true,
"VERSION": "0.0.1",
"PROFILER": {
"flask-profiler": true,
"line-profiler": true,
Expand Down
Empty file added src/config/__init__.py
Empty file.
35 changes: 35 additions & 0 deletions src/config/flasgger.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
from apispec.ext.marshmallow import MarshmallowPlugin
from dynaconf import settings
from flasgger import APISpec


def fetch_flasgger_template(app):
# Create an APISpec
title = settings.APP_NAME.replace("-", " ")
version = settings.VERSION
spec = APISpec(title=title, version=version, openapi_version="3.0", plugins=[MarshmallowPlugin()])

template = spec.to_flasgger(app, definitions=[], paths=[])
return template


def fetch_flasgger_config():
title = settings.APP_NAME.replace("-", " ")
base_api_url = settings.API.VERSION + settings.APP_NAME
return {
"headers": [],
"title": title,
"description": "",
"termsOfService": "",
"specs": [
{
"endpoint": "swagger_spec",
"route": f"{base_api_url}/swagger_spec",
"rule_filter": lambda rule: True, # all in
"model_filter": lambda tag: True, # all in
}
],
"static_url_path": "/flasgger_static",
"swagger_ui": True,
"specs_route": f"{base_api_url}/swagger",
}
9 changes: 7 additions & 2 deletions src/routes/health/__init__.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
from typing import Dict

from flasgger import swag_from

from src.core import Logger, Namespace

Client = Namespace("health")
Expand All @@ -6,6 +10,7 @@


@api.route("/ping", methods=["GET"])
def get_health():
@swag_from("specs/health.yml")
def get_health() -> Dict[str, str]:
log.info("Request received : ping")
return {"statusCode": 200}
return {"status": "UP"}
Empty file.
13 changes: 13 additions & 0 deletions src/routes/health/specs/health.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
This is the health API for the service
Call this api to check if service is up.
---
responses:
200:
description: Health status of the service
schema:
id: health
properties:
status:
type: string
description: Service status
default: UP
5 changes: 3 additions & 2 deletions src/server.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
from dynaconf import settings
from flasgger import Swagger
from flask import Flask
from flask_apispec import FlaskApiSpec
from flask_cors import CORS

from src.config.flasgger import fetch_flasgger_config, fetch_flasgger_template
from src.core import Logger, Singleton

log = Logger()
Expand All @@ -15,7 +16,7 @@ def __init__(self):
log.info(f"Starting {settings.APP_NAME} server on {settings.API.SERVER}")
CORS(app)
self.app = app
self.docs = FlaskApiSpec(app)
self.docs = Swagger(app, template=fetch_flasgger_template(app), config=fetch_flasgger_config())

def get_app(self):
return self.app
Expand Down