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
5 changes: 5 additions & 0 deletions .bandit.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
[bandit]
targets: src,test,*.py
exclude: dummy.py
skips:
tests:
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -138,3 +138,5 @@ DS_Store
# logs
logs/

# mypy
.mypy_cache/
12 changes: 12 additions & 0 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# See https://pre-commit.com for more information
# See https://pre-commit.com/hooks.html for more hooks
repos:
- repo: https://github.com/ambv/black
rev: stable
hooks:
- id: black
language_version: python3.8
- repo: https://gitlab.com/pycqa/flake8
rev: 3.8.3
hooks:
- id: flake8
91 changes: 91 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
CONDA_ENV_NAME=pyflask-base
APP_NAME=pyflask-service
APP_DIR=src
TEST_DIR=test
HOME_DIR_PY_FILES=*.py

# echo _FormatCode_ guide:
# 0 Reset all styles
# 1 Bold
# 32 Green
# 34 Blue
# 35 Magenta
# 36 Cyan
RESET_STYLES=\033[0m
BOLD_BLUE=\033[1m\033[34m
BOLD_CYAN=\033[1m\033[36m

# Signifies our desired python version
# Makefile macros (or variables) are defined a little bit differently than traditional bash, keep in mind that in the Makefile there's top-level Makefile-only syntax, and everything else is bash script syntax.
PYTHON = python3

# .PHONY defines parts of the makefile that are not dependant on any specific file
# This is most often used to store functions
.PHONY = help setup format lint test debug clean

# Defining an array variable
FILES = input output

# Defines the default target that `make` will to try to make, or in the case of a phony target, execute the specified commands
# This target is executed whenever we just type `make`
.DEFAULT_GOAL = help


# The @ makes sure that the command itself isn't echoed in the terminal
help:
@echo "$(BOLD_BLUE)-----------------------------MAKE GUIDE----------------------------$(RESET_STYLES)"
@echo "$(BOLD_CYAN)make setup$(RESET_STYLES) : Setup pyflask-service"
@echo "$(BOLD_CYAN)make format$(RESET_STYLES) : Format and fix python code pyflask-service"
@echo "$(BOLD_CYAN)make lint$(RESET_STYLES) : Lint pyflask-service"
@echo "$(BOLD_CYAN)make test$(RESET_STYLES) : Test pyflask-service"
@echo "$(BOLD_CYAN)make debug$(RESET_STYLES) : Debug pyflask-service"
@echo "$(BOLD_CYAN)make clean$(RESET_STYLES) : Clean pyflask-service"
@echo "$(BOLD_CYAN)make dev-run$(RESET_STYLES) : Run pyflask-service in environment=development"
@echo "$(BOLD_CYAN)make prod-run$(RESET_STYLES) : Run pyflask-service in environment=prod"
@echo "$(BOLD_BLUE)-------------------------------------------------------------------$(RESET_STYLES)"


setup: #: Use pip-tools, pip-compile, pip install
@echo "$(BOLD_CYAN)Setting up pyflask base$(RESET_STYLES)"
# Check for venv, conda else exit
@echo "$(BOLD_CYAN)Installing pip-tools . . .$(RESET_STYLES)"
pip install pip-tools
@echo "$(BOLD_CYAN)Generating requirements$(RESET_STYLES)"
pip-compile -q --build-isolation --output-file=requirements/requirements.txt requirements/requirements.in
@echo "$(BOLD_CYAN)Generating dev requirements$(RESET_STYLES)"
pip-compile -q --build-isolation --output-file=requirements/dev-requirements.txt requirements/dev-requirements.in
@echo "$(BOLD_CYAN)Syncing requirements$(RESET_STYLES)"
pip-sync -q requirements/requirements.txt requirements/dev-requirements.txt
@echo "$(BOLD_CYAN)Installing requirements$(RESET_STYLES)"
pip install -r requirements/requirements.txt
@echo "$(BOLD_CYAN)Installing dev requirements$(RESET_STYLES)"
pip install -r requirements/dev-requirements.txt
@echo "$(BOLD_CYAN)Adding pre-commit hooks$(RESET_STYLES)"
pre-commit install


format: #: Format and fix python code with black, isort, autoflake
@echo "$(BOLD_CYAN)Blackifying $(RESET_STYLES)🍳"
black --version
black $(APP_DIR) $(TEST_DIR) $(HOME_DIR_PY_FILES)
@echo "$(BOLD_CYAN)ISorting 〽️$(RESET_STYLES)️"
isort --recursive $(APP_DIR) $(TEST_DIR) $(HOME_DIR_PY_FILES)
@echo "$(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)


lint: #: Run static analysis with flake8, mypy and bandit
@echo "$(BOLD_CYAN)Flake linting ❄️$(RESET_STYLES)"
flake8 --version
flake8 $(APP_DIR) $(TEST_DIR) $(HOME_DIR_PY_FILES)
@echo "$(BOLD_CYAN)Static typing️️$(RESET_STYLES)⌨️"
mypy --version
mypy $(APP_DIR) $(HOME_DIR_PY_FILES)
@echo "$(BOLD_CYAN)Securing with bandit️🕵️️$(RESET_STYLES)"
bandit --version
bandit -l -i -r . --format=custom
@echo "$(BOLD_CYAN)Running pre-commit hooks 🏁️️️$(RESET_STYLES)"
pre-commit run --all-files
@echo "$(BOLD_CYAN)All checks passed 🏳️️️️$(RESET_STYLES)"

31 changes: 29 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,42 @@ An "optionally opinionated and structured" flask boilerplate microservice for id
![Built with](https://img.shields.io/badge/-Built%20with-073551?style=flat-square)
![Python](https://img.shields.io/badge/-Python-3776AB?style=flat-square&logo=Python&logoColor=white)
![Flask](https://img.shields.io/badge/-Flask-000000?style=flat-square&logo=flask&logoColor=white)
![License](https://img.shields.io/github/license/pritam001/pyflask-microservice-base?style=flat-square&label=License)

Minimum supporting Python version: 3.6
Tools
------------------------------------------------------------------------------
[![Min Python Version 3.6+](https://img.shields.io/badge/python-3.6+-3776AB.svg)](https://www.python.org/download/releases/3.6.0/)
[![Code style: black](https://img.shields.io/badge/code%20style-black-000000.svg)](https://github.com/psf/black)
[![Static Analysis: flake8](https://img.shields.io/badge/static%20analysis-flake8-white.svg)](https://www.python.org/dev/peps/pep-0008/)
[![Static Typing: mypy](https://img.shields.io/badge/static%20typing-mypy-blue.svg)](https://www.python.org/dev/peps/pep-0008/)
[![Security: bandit](https://img.shields.io/badge/security-bandit-yellow.svg)](https://github.com/PyCQA/bandit)
[![pre-commit](https://img.shields.io/badge/pre--commit-enabled-brightgreen?logo=pre-commit&logoColor=white)](https://github.com/pre-commit/pre-commit)

Development Status
------------------------------------------------------------------------------
![WIP](https://img.shields.io/badge/%20%F0%9F%9A%A7%20-Work%20in%20progress-important)

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

[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)
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

\* [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)



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

`make lint` : Run static analysis with flake8, mypy and bandit

20 changes: 0 additions & 20 deletions base_constructor.sh

This file was deleted.

Empty file added documentation/bandit.md
Empty file.
Empty file added documentation/black.md
Empty file.
1 change: 1 addition & 0 deletions documentation/conda.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
# Conda documentation

### 1. Install Pip
https://www.shellhacks.com/python-install-pip-mac-ubuntu-centos/
### 2. Install Anaconda
##### Linux
`wget https://repo.continuum.io/miniconda/Miniconda3-latest-Linux-x86_64.sh`
Expand Down
Empty file added documentation/flake8.md
Empty file.
Empty file added documentation/isort.md
Empty file.
Empty file added documentation/linting.md
Empty file.
Empty file added documentation/mypy.md
Empty file.
22 changes: 22 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
[tool.black]
line-length = 127
target-version = ['py36', 'py37', 'py38']
include = '\.pyi?$'
exclude = '''
/(
\.eggs
| \.git
| \.hg
| \.mypy_cache
| \.tox
| \.venv
| _build
| buck-out
| build
| dist
# The following are specific to Black, you probably don't want those.
| blib2to3
| tests/data
| profiling
)/
'''
29 changes: 29 additions & 0 deletions requirements/dev-requirements.in
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
# Pylint is a Python static code analysis tool which looks for programming errors, helps enforcing a coding standard, sniffs for code smells and offers simple refactoring suggestions
pylint
# Black is the uncompromising Python code formatter
black
# Remove unused imports and unused variables from Python code
autoflake
# Sort imports alphabetically, and automatically separate into sections and by type
isort
# Mypy is an optional static type checker for Python that aims to combine the benefits of dynamic (or "duck") typing and static typing
mypy
# Security oriented static analyser for python code
bandit

# Flake8
flake8
flake8-flask
flake8-blind-except
flake8-breakpoint
flake8-builtins
flake8-comprehensions
flake8-logging-format
flake8-print
flake8-pytest
flake8-pytest-style
flake8-return
pep8-naming

# A framework for managing and maintaining multi-language pre-commit hooks
pre-commit
53 changes: 53 additions & 0 deletions requirements/dev-requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,56 @@
#
# pip-compile --output-file=requirements/dev-requirements.txt requirements/dev-requirements.in
#
appdirs==1.4.4 # via black, virtualenv
astroid==2.4.2 # via pylint
attrs==19.3.0 # via black
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
distlib==0.3.1 # via virtualenv
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-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
flake8-polyfill==1.0.2 # via pep8-naming
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
gitdb==4.0.5 # via gitpython
gitpython==3.1.7 # via bandit
identify==1.4.25 # via pre-commit
isort==4.3.21 # via -r requirements/dev-requirements.in, pylint
lazy-object-proxy==1.4.3 # via astroid
mccabe==0.6.1 # via flake8, pylint
mypy-extensions==0.4.3 # via mypy
mypy==0.782 # via -r requirements/dev-requirements.in
nodeenv==1.4.0 # via pre-commit
pathspec==0.8.0 # via black
pbr==5.4.5 # via stevedore
pep8-naming==0.11.1 # via -r requirements/dev-requirements.in
pre-commit==2.6.0 # via -r requirements/dev-requirements.in
pycodestyle==2.6.0 # via flake8, flake8-print
pyflakes==2.2.0 # via autoflake, flake8
pylint==2.5.3 # via -r requirements/dev-requirements.in
pyyaml==5.3.1 # via bandit, pre-commit
r2c-py-ast==0.1.0b1 # via flake8-flask
regex==2020.7.14 # via black
six==1.15.0 # via astroid, bandit, flake8-print, virtualenv
smmap==3.0.4 # via gitdb
stevedore==3.2.0 # via bandit
toml==0.10.1 # via black, pre-commit, pylint
typed-ast==1.4.1 # via black, mypy
typing-extensions==3.7.4.2 # via mypy
virtualenv==20.0.30 # via pre-commit
wrapt==1.12.1 # via astroid

# The following packages are considered to be unsafe in a requirements file:
# setuptools
4 changes: 4 additions & 0 deletions scripts/service_rename.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
#!/usr/bin/env bash
# Use to change service related names in the complete project
# Define service name
# Define environment name
6 changes: 2 additions & 4 deletions service_master.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,7 @@


if __name__ == "__main__":
log.info(f"Created app instance. Initiating run . . .")
log.info("Created app instance. Initiating run . . .")
app.run(
host=settings.API.SERVER.url,
port=settings.API.SERVER.port,
debug=settings.DEBUG,
host=settings.API.SERVER.url, port=settings.API.SERVER.port, debug=settings.DEBUG,
)
33 changes: 33 additions & 0 deletions setup.cfg
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
[flake8]
max-line-length = 127
max-complexity = 10
# https://www.flake8rules.com/
ignore =
E501, # Line too long (82 > 79 characters)
W503, # Line break occurred before a binary operator
select = B,C,E,F,W,T4,B9


# Global options:
[mypy]
python_version = 3.6
warn_return_any = True
warn_unused_configs = True
ignore_missing_imports = True

# Per-module options:
[*.py]
ignore_missing_imports = True

[src]
ignore_missing_imports = True

[test]
ignore_missing_imports = True


[isort]
multi_line_output=3
include_trailing_comma=True
force_grid_wrap=0
use_parentheses=True
5 changes: 2 additions & 3 deletions src/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,8 @@

log = Logger()

log.info(f"Creating app instance . . .")
log.info("Creating app instance . . .")
server = Server() # Generate singleton instance of server
app = server.get_app() # Get Flask app reference from server instance
log.info(f"Registering blueprints . . .")
log.info("Registering blueprints . . .")
register_blueprints(app) # Register all blueprints to app reference

6 changes: 3 additions & 3 deletions src/core/__init__.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
from src.core.logger import Logger
from src.core.namespace import Namespace
from src.core.singleton import Singleton
from src.core.logger import Logger # noqa: F401
from src.core.namespace import Namespace # noqa: F401
from src.core.singleton import Singleton # noqa: F401
1 change: 1 addition & 0 deletions src/core/logger.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import os
import sys
from logging.handlers import TimedRotatingFileHandler

from dynaconf import settings

from src.core.singleton import Singleton
Expand Down
2 changes: 1 addition & 1 deletion src/core/namespace.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
from flask import Blueprint
from dynaconf import settings
from flask import Blueprint


class Namespace(object):
Expand Down
5 changes: 4 additions & 1 deletion src/core/singleton.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
from typing import Dict


class Singleton(type):
_instances = {}
_instances: Dict = {}

def __call__(cls, *args, **kwargs):
if cls not in cls._instances:
Expand Down
Loading