├── requirements.txt ├── create_flask_service ├── template │ ├── __init__.py │ ├── model │ │ └── __init__.py │ ├── schema │ │ └── __init__.py │ ├── utils │ │ └── __init__.py │ ├── database │ │ └── __init__.py │ ├── interface │ │ └── __init__.py │ ├── scripts │ │ └── __init__.py │ ├── service │ │ └── __init__.py │ ├── .env │ ├── README.md │ ├── requirements.txt │ ├── controller │ │ └── __init__.py │ ├── app.py │ └── .gitignore ├── GlobalEnum.py ├── __init__.py └── Service.py ├── MANIFEST.in ├── demo.gif ├── LICENSE ├── setup.py ├── .gitignore └── README.md /requirements.txt: -------------------------------------------------------------------------------- 1 | halo 2 | requests -------------------------------------------------------------------------------- /create_flask_service/template/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /create_flask_service/template/model/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /create_flask_service/template/schema/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /create_flask_service/template/utils/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /create_flask_service/template/database/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /create_flask_service/template/interface/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /create_flask_service/template/scripts/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /create_flask_service/template/service/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /MANIFEST.in: -------------------------------------------------------------------------------- 1 | recursive-include create_flask_service/template * -------------------------------------------------------------------------------- /demo.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amickael/create-flask-service/HEAD/demo.gif -------------------------------------------------------------------------------- /create_flask_service/template/.env: -------------------------------------------------------------------------------- 1 | FLASK_ENV=development 2 | 3 | YOUR_CONN_STRING_ENV=YOUR_CONN_STRING -------------------------------------------------------------------------------- /create_flask_service/template/README.md: -------------------------------------------------------------------------------- 1 | # {{ %SERVICE_NAME% }} 2 | An awesome Flask-powered microservice -------------------------------------------------------------------------------- /create_flask_service/GlobalEnum.py: -------------------------------------------------------------------------------- 1 | from enum import Enum 2 | 3 | 4 | class GlobalEnum(Enum): 5 | TEMPLATE_DIR = "template" 6 | PLACEHOLDER = "{{ %SERVICE_NAME% }}" 7 | -------------------------------------------------------------------------------- /create_flask_service/template/requirements.txt: -------------------------------------------------------------------------------- 1 | flask 2 | flask-restx 3 | flask-sqlalchemy 4 | flask_accepts 5 | flask-compress 6 | flask-cors 7 | python-dotenv 8 | marshmallow 9 | python-jose 10 | werkzeug 11 | pyodbc 12 | pytest 13 | typing-extensions -------------------------------------------------------------------------------- /create_flask_service/template/controller/__init__.py: -------------------------------------------------------------------------------- 1 | import os 2 | 3 | from flask_restx import Api 4 | from marshmallow import ValidationError 5 | 6 | 7 | ######################################################################################################################## 8 | # Config 9 | ######################################################################################################################## 10 | 11 | VERSION = "v1" 12 | api = Api( 13 | title="{{ %SERVICE_NAME% }}", 14 | version=VERSION, 15 | prefix=f"/api/{VERSION}", 16 | doc="/" if os.getenv("FLASK_ENV") == "development" else False, 17 | ) 18 | 19 | 20 | @api.errorhandler(ValidationError) 21 | def handle_validation_error(error: ValidationError): 22 | del error.data 23 | return {"message": error.messages}, 400 24 | 25 | 26 | ######################################################################################################################## 27 | # Namespaces 28 | ######################################################################################################################## 29 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 Andrew Mickael 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | from setuptools import setup, find_packages 2 | 3 | import create_flask_service 4 | 5 | with open("README.md", "r") as f: 6 | readme = f.read() 7 | 8 | with open("requirements.txt", "r") as f: 9 | requirements = [i.rstrip() for i in f.readlines()] 10 | 11 | setup( 12 | name="create-flask-service", 13 | version=create_flask_service.__version__, 14 | description=create_flask_service.__description__, 15 | long_description=readme, 16 | long_description_content_type="text/markdown", 17 | author=create_flask_service.__author__, 18 | author_email="andrew.mickael@gmail.com", 19 | license="MIT", 20 | platforms=["NT", "POSIX"], 21 | url="https://github.com/amickael/create-flask-service", 22 | packages=find_packages(exclude=("create_flask_service.template",)), 23 | include_package_data=True, 24 | zip_safe=False, 25 | entry_points={ 26 | "console_scripts": ["create-flask-service = create_flask_service:main"] 27 | }, 28 | install_requires=requirements, 29 | classifiers=[ 30 | "Programming Language :: Python :: 3", 31 | "License :: OSI Approved :: MIT License", 32 | "Operating System :: MacOS :: MacOS X", 33 | "Operating System :: POSIX", 34 | "Operating System :: Microsoft :: Windows", 35 | "Environment :: Console", 36 | ], 37 | python_requires=">=3.6", 38 | ) 39 | -------------------------------------------------------------------------------- /create_flask_service/template/app.py: -------------------------------------------------------------------------------- 1 | import os 2 | 3 | from flask import Flask 4 | from flask_compress import Compress 5 | from flask_cors import CORS 6 | from flask_sqlalchemy import SQLAlchemy 7 | from werkzeug.middleware.proxy_fix import ProxyFix 8 | 9 | # Set working directory to project root 10 | os.chdir(os.path.abspath(os.path.dirname(__file__))) 11 | 12 | # If available, load environment variables from .env before rest of the package 13 | if os.path.isfile(".env"): 14 | from dotenv import load_dotenv 15 | 16 | load_dotenv() 17 | 18 | from controller import api 19 | 20 | 21 | ######################################################################################################################## 22 | # Setup / Configuration 23 | ######################################################################################################################## 24 | 25 | # Instantiate app 26 | app = Flask(__name__) 27 | app.config["SQLALCHEMY_DATABASE_URI"] = os.environ["YOUR_CONN_STRING_ENV"] 28 | app.config["SQLALCHEMY_TRACK_MODIFICATIONS"] = False 29 | app.wsgi_app = ProxyFix(app.wsgi_app) # Fixes Swagger UI issues over HTTPS 30 | 31 | # Add extensions 32 | db = SQLAlchemy(app) 33 | CORS(app) 34 | api.init_app(app) 35 | Compress(app) 36 | 37 | 38 | ######################################################################################################################## 39 | # Run / Debug 40 | ######################################################################################################################## 41 | 42 | if __name__ == "__main__": 43 | if os.getenv("FLASK_ENV") == "development": 44 | app.run() 45 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Byte-compiled / optimized / DLL files 2 | __pycache__/ 3 | *.py[cod] 4 | *$py.class 5 | 6 | # C extensions 7 | *.so 8 | 9 | # Distribution / packaging 10 | .Python 11 | build/ 12 | develop-eggs/ 13 | dist/ 14 | downloads/ 15 | eggs/ 16 | .eggs/ 17 | lib/ 18 | lib64/ 19 | parts/ 20 | sdist/ 21 | var/ 22 | wheels/ 23 | pip-wheel-metadata/ 24 | share/python-wheels/ 25 | *.egg-info/ 26 | .installed.cfg 27 | *.egg 28 | MANIFEST 29 | 30 | # PyInstaller 31 | # Usually these files are written by a python script from a template 32 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 33 | *.manifest 34 | *.spec 35 | 36 | # Installer logs 37 | pip-log.txt 38 | pip-delete-this-directory.txt 39 | 40 | # Unit test / coverage reports 41 | htmlcov/ 42 | .tox/ 43 | .nox/ 44 | .coverage 45 | .coverage.* 46 | .cache 47 | nosetests.xml 48 | coverage.xml 49 | *.cover 50 | *.py,cover 51 | .hypothesis/ 52 | .pytest_cache/ 53 | 54 | # Translations 55 | *.mo 56 | *.pot 57 | 58 | # Django stuff: 59 | *.log 60 | local_settings.py 61 | db.sqlite3 62 | db.sqlite3-journal 63 | 64 | # Flask stuff: 65 | instance/ 66 | .webassets-cache 67 | 68 | # Scrapy stuff: 69 | .scrapy 70 | 71 | # Sphinx documentation 72 | docs/_build/ 73 | 74 | # PyBuilder 75 | target/ 76 | 77 | # Jupyter Notebook 78 | .ipynb_checkpoints 79 | 80 | # IPython 81 | profile_default/ 82 | ipython_config.py 83 | 84 | # pyenv 85 | .python-version 86 | 87 | # pipenv 88 | # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. 89 | # However, in case of collaboration, if having platform-specific dependencies or dependencies 90 | # having no cross-platform support, pipenv may install dependencies that don't work, or not 91 | # install all needed dependencies. 92 | #Pipfile.lock 93 | 94 | # PEP 582; used by e.g. github.com/David-OConnor/pyflow 95 | __pypackages__/ 96 | 97 | # Celery stuff 98 | celerybeat-schedule 99 | celerybeat.pid 100 | 101 | # SageMath parsed files 102 | *.sage.py 103 | 104 | # Environments 105 | .venv 106 | env/ 107 | venv/ 108 | ENV/ 109 | env.bak/ 110 | venv.bak/ 111 | 112 | # Spyder project settings 113 | .spyderproject 114 | .spyproject 115 | 116 | # Rope project settings 117 | .ropeproject 118 | 119 | # mkdocs documentation 120 | /site 121 | 122 | # mypy 123 | .mypy_cache/ 124 | .dmypy.json 125 | dmypy.json 126 | 127 | # Pyre type checker 128 | .pyre/ 129 | 130 | .idea 131 | -------------------------------------------------------------------------------- /create_flask_service/template/.gitignore: -------------------------------------------------------------------------------- 1 | # Byte-compiled / optimized / DLL files 2 | __pycache__/ 3 | *.py[cod] 4 | *$py.class 5 | 6 | # C extensions 7 | *.so 8 | 9 | # Distribution / packaging 10 | .Python 11 | build/ 12 | develop-eggs/ 13 | dist/ 14 | downloads/ 15 | eggs/ 16 | .eggs/ 17 | lib/ 18 | lib64/ 19 | parts/ 20 | sdist/ 21 | var/ 22 | wheels/ 23 | pip-wheel-metadata/ 24 | share/python-wheels/ 25 | *.egg-info/ 26 | .installed.cfg 27 | *.egg 28 | MANIFEST 29 | 30 | # PyInstaller 31 | # Usually these files are written by a python script from a template 32 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 33 | *.manifest 34 | *.spec 35 | 36 | # Installer logs 37 | pip-log.txt 38 | pip-delete-this-directory.txt 39 | 40 | # Unit test / coverage reports 41 | htmlcov/ 42 | .tox/ 43 | .nox/ 44 | .coverage 45 | .coverage.* 46 | .cache 47 | nosetests.xml 48 | coverage.xml 49 | *.cover 50 | *.py,cover 51 | .hypothesis/ 52 | .pytest_cache/ 53 | 54 | # Translations 55 | *.mo 56 | *.pot 57 | 58 | # Django stuff: 59 | *.log 60 | local_settings.py 61 | db.sqlite3 62 | db.sqlite3-journal 63 | 64 | # Flask stuff: 65 | instance/ 66 | .webassets-cache 67 | 68 | # Scrapy stuff: 69 | .scrapy 70 | 71 | # Sphinx documentation 72 | docs/_build/ 73 | 74 | # PyBuilder 75 | target/ 76 | 77 | # Jupyter Notebook 78 | .ipynb_checkpoints 79 | 80 | # IPython 81 | profile_default/ 82 | ipython_config.py 83 | 84 | # pyenv 85 | .python-version 86 | 87 | # pipenv 88 | # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. 89 | # However, in case of collaboration, if having platform-specific dependencies or dependencies 90 | # having no cross-platform support, pipenv may install dependencies that don't work, or not 91 | # install all needed dependencies. 92 | #Pipfile.lock 93 | 94 | # PEP 582; used by e.g. github.com/David-OConnor/pyflow 95 | __pypackages__/ 96 | 97 | # Celery stuff 98 | celerybeat-schedule 99 | celerybeat.pid 100 | 101 | # SageMath parsed files 102 | *.sage.py 103 | 104 | # Environments 105 | .env 106 | .venv 107 | env/ 108 | venv/ 109 | ENV/ 110 | env.bak/ 111 | venv.bak/ 112 | 113 | # Spyder project settings 114 | .spyderproject 115 | .spyproject 116 | 117 | # Rope project settings 118 | .ropeproject 119 | 120 | # mkdocs documentation 121 | /site 122 | 123 | # mypy 124 | .mypy_cache/ 125 | .dmypy.json 126 | dmypy.json 127 | 128 | # Pyre type checker 129 | .pyre/ 130 | 131 | .idea 132 | -------------------------------------------------------------------------------- /create_flask_service/__init__.py: -------------------------------------------------------------------------------- 1 | import argparse 2 | 3 | from halo import Halo 4 | import requests 5 | 6 | from create_flask_service.Service import Service 7 | 8 | 9 | __author__ = "Andrew Mickael" 10 | __version__ = "0.1.6" 11 | __description__ = "Create a Flask microservice with a few keystrokes" 12 | 13 | 14 | def check_version(verbose: bool = False): 15 | resp = requests.get("https://pypi.org/pypi/create-flask-service/json") 16 | if resp.ok: 17 | latest_version = resp.json().get("info", {}).get("version", "") 18 | if latest_version != __version__ or verbose: 19 | print( 20 | f"A newer version of create-flask-service is available on PyPI ({__version__} => {latest_version})", 21 | 'Run "pip install --upgrade create-flask-service" to update', 22 | sep="\r\n", 23 | ) 24 | 25 | 26 | def run(): 27 | # Prompt input 28 | while True: 29 | service_name = input("Service name: ").strip().replace(" ", "-") 30 | if service_name: 31 | break 32 | else: 33 | print("Please enter a service name") 34 | root_dir = input("Root directory (blank for current directory): ") 35 | service = Service(service_name, root_dir) 36 | 37 | # Create file structure 38 | spinner = Halo(text="Creating file structure") 39 | spinner.start() 40 | service.create_tree() 41 | spinner.succeed() 42 | 43 | # Generate venv 44 | spinner.start("Generating virtual environment") 45 | service.generate_venv() 46 | spinner.succeed() 47 | 48 | # Activate venv and install requirements 49 | spinner.start("Installing requirements") 50 | service.install_requirements() 51 | spinner.succeed() 52 | 53 | # Initialize git 54 | spinner.start("Initializing git repository") 55 | service.initialize_git() 56 | spinner.succeed() 57 | 58 | # Personalize 59 | spinner.start("Personalizing") 60 | service.personalize() 61 | spinner.succeed() 62 | 63 | # Done! 64 | spinner.stop_and_persist("🎂".encode("utf-8"), "All done!") 65 | print("Your new project is located in:", service.cwd, sep="\t") 66 | 67 | 68 | def main(): 69 | # Set up args 70 | parser = argparse.ArgumentParser(description=__description__) 71 | parser.add_argument("-V", action="store_true", help="Display version") 72 | args = parser.parse_args() 73 | 74 | # Run 75 | if args.V is True: 76 | print("create-flask-service", __version__, sep="==") 77 | else: 78 | try: 79 | run() 80 | except (KeyboardInterrupt, SystemExit): 81 | pass 82 | check_version() 83 | 84 | 85 | if __name__ == "__main__": 86 | main() 87 | -------------------------------------------------------------------------------- /create_flask_service/Service.py: -------------------------------------------------------------------------------- 1 | import os 2 | import subprocess 3 | import shutil 4 | import sys 5 | import stat 6 | 7 | import requests 8 | 9 | from create_flask_service.GlobalEnum import GlobalEnum 10 | 11 | 12 | class Service: 13 | def __init__(self, service_name: str, root_dir: str): 14 | self.service_name = service_name 15 | self.root_dir = root_dir 16 | self.executable = "/bin/bash" if os.name == "posix" else None 17 | self.template_dir = os.path.join( 18 | os.path.dirname(os.path.abspath(__file__)), GlobalEnum.TEMPLATE_DIR.value 19 | ) 20 | 21 | # Check if service directory already exists, if it does then prompt for overwrite 22 | self.cwd = os.path.abspath(os.path.join(self.root_dir, self.service_name)) 23 | if os.path.exists(self.cwd): 24 | proceed = input("Directory already exists, overwrite? [y/N]: ") 25 | if proceed.lower() == "y": 26 | try: 27 | shutil.rmtree(self.cwd) 28 | except (PermissionError, WindowsError): 29 | for root, dirs, files in os.walk(self.cwd): 30 | for directory in dirs: 31 | os.chmod(os.path.join(root, directory), stat.S_IWUSR) 32 | for file in files: 33 | os.chmod(os.path.join(root, file), stat.S_IWUSR) 34 | shutil.rmtree(self.cwd) 35 | else: 36 | print("Stopping") 37 | exit() 38 | 39 | def create_tree(self): 40 | # Copy file structure 41 | shutil.copytree( 42 | self.template_dir, self.cwd, ignore=shutil.ignore_patterns("__pycache__") 43 | ) 44 | 45 | return self 46 | 47 | def generate_venv(self): 48 | # Generate venv 49 | subprocess.run([sys.executable, "-m", "venv", os.path.join(self.cwd, "venv")]) 50 | 51 | return self 52 | 53 | def __version_requirements(self): 54 | # Read requirements 55 | req_path = os.path.join(self.cwd, "requirements.txt") 56 | with open(req_path, "r") as f: 57 | requirements = [req.rstrip() for req in f.readlines()] 58 | 59 | # Get latest requirement version 60 | # Make this check cross-dependencies in the future? 61 | versioned_requirements = [] 62 | for requirement in requirements: 63 | resp = requests.get(f"https://pypi.org/pypi/{requirement}/json") 64 | if resp.ok: 65 | version = resp.json().get("info", {}).get("version") 66 | versioned_requirements.append(f"{requirement}=={version}") 67 | else: 68 | versioned_requirements.append(requirement) 69 | 70 | # Write back to requirements 71 | with open(req_path, "w") as f: 72 | f.writelines([f"{req}\n" for req in versioned_requirements]) 73 | 74 | def install_requirements(self): 75 | # Replace requirements with versioned ones 76 | self.__version_requirements() 77 | 78 | # Install requirements 79 | subprocess.Popen( 80 | " && ".join( 81 | [ 82 | f"source {self.cwd}/venv/bin/activate" 83 | if os.name == "posix" 84 | else fr"{self.cwd}\venv\Scripts\activate.bat", 85 | f"pip install -r {self.cwd}{os.path.sep}requirements.txt", 86 | "deactivate", 87 | ] 88 | ), 89 | stdout=subprocess.DEVNULL, 90 | stderr=subprocess.DEVNULL, 91 | shell=True, 92 | executable=self.executable, 93 | ).communicate() 94 | 95 | return self 96 | 97 | def initialize_git(self): 98 | subprocess.Popen( 99 | f"cd {self.cwd} && git init && git add .", 100 | stdout=subprocess.DEVNULL, 101 | stderr=subprocess.DEVNULL, 102 | shell=True, 103 | executable=self.executable, 104 | ).communicate() 105 | 106 | return self 107 | 108 | def __placeholder(self, file_name: str): 109 | file_path = os.path.join(self.cwd, file_name) 110 | with open(file_path, "r", encoding="utf-8") as f: 111 | text = f.read().replace(GlobalEnum.PLACEHOLDER.value, self.service_name) 112 | with open(file_path, "w", encoding="utf-8") as f: 113 | f.write(text) 114 | 115 | def personalize(self): 116 | self.__placeholder("README.md") 117 | self.__placeholder(os.path.join("controller", "__init__.py")) 118 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [![GitHub issues](https://img.shields.io/github/issues/amickael/create-flask-service)](https://github.com/amickael/create-flask-service/issues) 2 | ![PyPI](https://img.shields.io/pypi/v/create-flask-service?color=blue) 3 | ![PyPI - Downloads](https://img.shields.io/pypi/dw/create-flask-service?color=red) 4 | [![GitHub license](https://img.shields.io/github/license/amickael/create-flask-service?color=purple)](https://github.com/amickael/create-flask-service/blob/master/LICENSE) 5 | [![Code style](https://img.shields.io/badge/code%20style-black-black)](https://github.com/psf/black) 6 | 7 | # create-flask-service 8 | Set up a Flask service with a few keystrokes 9 | 10 | ![create-flask-service](https://repository-images.githubusercontent.com/252598272/c0646200-75c6-11ea-90dd-94cb96cbb2de) 11 | 12 | ## 👶 Dependencies 13 | * [Python 3.6 or higher](https://www.python.org/downloads/) 14 | * [Git SCM](https://git-scm.com/downloads) 15 | 16 | ## 🛠️ Installation 17 | Install from PyPI using `pip`, you may need to use `pip3` depending on your installation 18 | ```sh 19 | pip install create-flask-service 20 | ``` 21 | 22 | ## 🚀 Usage 23 | ![Demo](https://github.com/amickael/create-flask-service/blob/master/demo.gif) 24 | 25 | 1. Run the `create-flask-service` command 26 | 2. Enter your new project name, note that spaces will be converted to dashes 27 | 3. Enter the root directory for your new project, if none is supplied then the current directory is used 28 | 4. Watch the magic happen 29 | 30 | To start the application run `app.py` and navigate to http://127.0.0.1:5000, you should see a blank Swagger UI page. Note that in certain IDEs like PyCharm you may need to set your working directory to the project root, this will ensure that the .env file is loaded before runtime. 31 | 32 | ## ⚙️ Command Line Arguments 33 | > Note that supplying arguments will not run the main program 34 | 35 | | Name | Argument | Description | Default | 36 | |---------|----------|----------------------------------|---------| 37 | | Version | -V | Display installed version number | False | 38 | 39 | ## 📦 What's in the box 40 | * Boilerplate directory structure. Adapted from [a guide by AJ Pryor](http://alanpryorjr.com/2019-05-20-flask-api-example/), author of the excellent [flask_accepts](https://github.com/apryor6/flask_accepts) library (included) 41 | ``` 42 | . 43 | ├── README.md 44 | ├── __init__.py 45 | ├── app.py 46 | ├── controller 47 | │   └── __init__.py 48 | ├── database 49 | │   └── __init__.py 50 | ├── interface 51 | │   └── __init__.py 52 | ├── model 53 | │   └── __init__.py 54 | ├── requirements.txt 55 | ├── schema 56 | │   └── __init__.py 57 | ├── scripts 58 | │   └── __init__.py 59 | ├── service 60 | │   └── __init__.py 61 | └── utils 62 | └── __init__.py 63 | ``` 64 | 65 | * Python virtual environment with the following libraries installed, remember to activate the environment before developing 66 | * [flask](https://github.com/pallets/flask) - The Python micro framework for building web applications 67 | * [flask-restx](https://github.com/python-restx/flask-restx) - Fully featured framework for fast, easy and documented API development with Flask 68 | * [flask_accepts](https://github.com/apryor6/flask_accepts) - Easy, opinionated Flask input/output handling mixing Marshmallow with flask-restx 69 | * [flask-compress](https://github.com/colour-science/flask-compress) - Compress responses in your Flask app with gzip 70 | * [flask-cors](https://github.com/corydolphin/flask-cors) - Cross Origin Resource Sharing ( CORS ) support for Flask 71 | * [python-dotenv](https://github.com/theskumar/python-dotenv) - Get and set values in your .env file in local and production servers 72 | * [marshmallow](https://github.com/marshmallow-code/marshmallow) - A lightweight library for converting complex objects to and from simple Python datatypes 73 | * [python-jose](https://github.com/mpdavis/python-jose) - A JOSE implementation in Python 74 | * [werkzeug](https://github.com/pallets/werkzeug) - The comprehensive WSGI web application library 75 | * [flask-sqlalchemy](https://github.com/pallets/flask-sqlalchemy) - The Database Toolkit for Python 76 | * [pyodbc](https://github.com/mkleehammer/pyodbc) - Python ODBC bridge 77 | * [pytest](https://github.com/pytest-dev/pytest) - The pytest framework makes it easy to write small tests, yet scales to support complex functional testing 78 | * [typing-extensions](https://github.com/python/typing/tree/master/typing_extensions) 79 | * Note that this is only needed for Python <3.7 80 | * Basic Flask and Flask-RestX configuration 81 | * app.py contains basic configuration setting up Flask, Flask-SQLAlchemy, CORS, and gzip compression 82 | * controller/\_\_init\_\_.py contains basic Flask-RestX configuration based on the [Flask-RestX guidelines](https://flask-restx.readthedocs.io/en/latest/scaling.html) 83 | * Boilerplate code style is formatted with [Black](https://github.com/psf/black), but you may use whatever style suits you 84 | * Initialized git repository with a Python-specific .gitignore file 85 | * Nothing will be committed automatically 86 | * Basic README.md file 87 | 88 | ## ⚖️ License 89 | [MIT © 2020 Andrew Mickael](https://github.com/amickael/create-flask-service/blob/master/LICENSE) 90 | --------------------------------------------------------------------------------