├── version ├── requirements.txt ├── linux-packages.txt ├── project-packages.txt ├── tests └── requirements.txt ├── Dockerfile ├── setup.cfg ├── .vscode-settings └── settings.json ├── Makefile ├── setup.py ├── README-template.md ├── .gitignore └── .dockerignore /version: -------------------------------------------------------------------------------- 1 | 0.0.1 2 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | # Add project requirements here 2 | -------------------------------------------------------------------------------- /linux-packages.txt: -------------------------------------------------------------------------------- 1 | # Add any dependecies below 2 | make 3 | -------------------------------------------------------------------------------- /project-packages.txt: -------------------------------------------------------------------------------- 1 | # Add all Python project packages down below, the first one is main 2 | -------------------------------------------------------------------------------- /tests/requirements.txt: -------------------------------------------------------------------------------- 1 | build 2 | flake8 3 | pylint 4 | mypy 5 | pycodestyle 6 | autopep8 7 | coverage 8 | ipython 9 | twine 10 | safety 11 | pytest 12 | pytest_cov 13 | 14 | # add custom test requirements BELOW this line 15 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM python:3.10.0-slim 2 | ENTRYPOINT ["python"] 3 | ARG ENV 4 | 5 | # install dependencies 6 | WORKDIR /tmp 7 | COPY linux-packages.txt linux-packages.txt 8 | RUN apt-get update && \ 9 | apt-get install -yq --no-install-recommends \ 10 | $(grep -vE '^#' linux-packages.txt) && \ 11 | rm -rf /var/lib/apt/lists/* 12 | 13 | COPY requirements.txt requirements.txt 14 | RUN pip install -r requirements.txt --no-input && rm requirements.txt 15 | COPY tests/requirements.txt requirements-test.txt 16 | RUN if [ "$ENV" = "TEST" ] ; then pip install -r requirements-test.txt --no-input && rm requirements-test.txt ; fi 17 | 18 | WORKDIR /app 19 | 20 | COPY . . 21 | RUN if [ "$ENV" = "TEST" ] ; then make install-test; else make install ; fi 22 | 23 | # edit below this line 24 | -------------------------------------------------------------------------------- /setup.cfg: -------------------------------------------------------------------------------- 1 | [isort] 2 | atomic=true 3 | force_grid_wrap=0 4 | include_trailing_comma=true 5 | lines_after_imports=2 6 | multi_line_output=3 7 | use_parentheses=true 8 | 9 | known_first_party=attr 10 | known_third_party=hypothesis,pytest,setuptools,six,zope 11 | 12 | [mypy] 13 | ignore_missing_imports = True 14 | follow_imports = silent 15 | strict_optional = False 16 | warn_unused_configs = True 17 | warn_redundant_casts = True 18 | warn_unused_ignores = True 19 | warn_no_return = True 20 | warn_unreachable = True 21 | show_error_context = True 22 | show_column_numbers = True 23 | show_error_codes = True 24 | pretty = True 25 | 26 | [flake8] 27 | import-order-style=pycharm 28 | extend-select=W504 29 | ignore=R504,W503,T101 30 | 31 | [tool:pytest] 32 | filterwarnings = 33 | error 34 | 35 | # add custom configuration below this line 36 | -------------------------------------------------------------------------------- /.vscode-settings/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "[python]": { 3 | "editor.tabSize": 4, 4 | "editor.rulers": [ 5 | 79 6 | ], 7 | "editor.wordWrap": "wordWrapColumn", 8 | "editor.formatOnSave": true, 9 | "editor.insertSpaces": true, 10 | "editor.codeActionsOnSave": { 11 | "source.organizeImports": true 12 | } 13 | }, 14 | "[json]": { 15 | "editor.quickSuggestions": { 16 | "strings": true 17 | }, 18 | "editor.suggest.insertMode": "replace", 19 | "editor.formatOnSave": true 20 | }, 21 | "python.linting.pylintArgs": [], 22 | "editor.formatOnSave": true, 23 | "editor.tabSize": 2, 24 | "files.insertFinalNewline": true, 25 | "files.trimTrailingWhitespace": true, 26 | "files.watcherExclude": { 27 | "**/.output/**": true 28 | }, 29 | "files.exclude": { 30 | "**/.git": true, 31 | "**/.svn": true, 32 | "**/.hg": true, 33 | "**/CVS": true, 34 | "**/.DS_Store": true, 35 | "**/__pycache__": true 36 | }, 37 | "git.ignoreLimitWarning": true, 38 | "[markdown]": { 39 | "files.trimTrailingWhitespace": false 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env make -f 2 | 3 | # Find all PY files except those in hidden folders. TODO: make this list extendable 4 | FILES_PY = $(shell find $(CURDIR) -type f -name "*.py" -not -path "$(CURDIR)/.**/**" -not -path "$(CURDIR)/build/**") 5 | 6 | install: 7 | python -m pip install -e . && \ 8 | python setup.py build_ext --inplace 9 | 10 | install-test: 11 | pip install -e . && \ 12 | pip install -r $(CURDIR)/tests/requirements.txt && \ 13 | python setup.py build_ext --inplace 14 | 15 | run-test: 16 | @pytest $(CURDIR)/tests/ -vv --color=yes || [ $$? -eq 5 ] && exit 0 || exit $$? 17 | 18 | validate: 19 | @echo "Running flake8" 20 | @flake8 $(FILES_PY) 21 | @echo "Running mypy" 22 | @mypy $(FILES_PY) 23 | @echo "Running isort" 24 | @isort -c $(FILES_PY) 25 | @echo "Running safety" 26 | @safety check --bare 27 | 28 | build-package: 29 | @python setup.py bdist_wheel 30 | 31 | coverage: 32 | @pytest --cov-report=html --cov=$(CURDIR)/tests/ -vv --color=yes || [ $$? -eq 5 ] && exit 0 || exit $$? 33 | 34 | run-test-full: validate run-test 35 | 36 | docker-validate: 37 | @docker build -t test-build --build-arg ENV=TEST $(CURDIR) 38 | @docker run --rm --entrypoint /usr/bin/make test-build:latest run-test-full 39 | @docker image rm test-build 40 | -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | import os 2 | 3 | from setuptools import setup 4 | 5 | 6 | HERE = os.path.abspath(os.path.dirname(__file__)) 7 | 8 | 9 | with open(os.path.join(HERE, 'README.md')) as f: 10 | long_description = f.read() 11 | 12 | requirements = list() 13 | with open(os.path.join(HERE, 'requirements.txt')) as f: 14 | for line in f: 15 | line = line.strip() 16 | if not line.startswith('#'): 17 | requirements.append(line) 18 | 19 | package_names = list() 20 | with open(os.path.join(HERE, "project-packages.txt")) as f: 21 | package_names = [line for line in f.read().split("\n") 22 | if line and not line.startswith('#')] 23 | package_name = package_names[0] 24 | 25 | with open(os.path.join(HERE, 'version')) as f: 26 | version = f.read().strip() 27 | 28 | setup( 29 | name=package_name, 30 | version=version, 31 | description=long_description, 32 | long_description=long_description, 33 | packages=package_names, 34 | include_package_data=True, 35 | install_requires=requirements, 36 | setup_requires=[ 37 | 38 | ], 39 | tests_require=[ 40 | 41 | ], 42 | data_files=[ 43 | 44 | ], 45 | entry_points={ 46 | 'console_scripts': [ 47 | ], 48 | }, 49 | scripts=[ 50 | ], 51 | ) 52 | -------------------------------------------------------------------------------- /README-template.md: -------------------------------------------------------------------------------- 1 | # Template base Python project 2 | 3 | This template contains most of the stuff you might need for a Python project. 4 | 5 | ## How to initialize 6 | 1. Make a new repo and use this one as a template (Follow how to marge changes section below) 7 | 2. Create your project package directory 8 | 3. Add project package name to the `project-packages.txt` 9 | 4. Set virtualenv (if you want to create directory for env inside project directory make sure to make it hidden, with `.`, like e.g. `.my-env` that way it won't trigger MyPy validation on dependecies). I used 3.10, but should be fine with 3.7+. 10 | 5. Run `make install-test` 11 | 6. (Optional) - Copy [https://github.com/overfitted-cat/pybase/blob/main/.vscode-settings/settings.json](settings.json) into `.vscode/settgins.json` 12 | 7. (Optional) - Set env for the vscode 13 | 8. (Optional) - Set github hooks, e.g. add `make docker-validate` in `.git/hooks/pre-commit` - This will run docker build, ptest, isort, mypy, flake8 and safety validations. 14 | 15 | ## How to merge changes 16 | You can synchronize all your repoes with this base by setting: 17 | 1. `git remote add base git@github.com:overfitted-cat/pybase.git` - this need to be ran once, it sets another remote (`base`) to point to this template 18 | 2. (Optional) - `git remote -v` - One of the outputs should be `base git@github.com:overfitted-cat/pybase.git (fetch)` 19 | 3. `git fetch base` - this will fetch all new commits from this template repo 20 | 4. `git merge --no-ff base/main --allow-unrelated-histories` 21 | 5. `git config remote.base.pushurl "Push to the template repo is not allowed"` - just to make sure you don't update the template repo from your repo 22 | 23 | ## Makefile commands 24 | 1. `make install` - installs a project with dependecies 25 | 2. `make install-test` - installs dev version with dependecies to validation and test 26 | 3. `make run-test`- Runs all tests from `tests` 27 | 4. `make validate` - Runs `mypy`, `flake8`, `isort` and `safety` checks 28 | 5. `make coverage` - Generates coverage HTML report 29 | 6. `make run-test-full` - Runs tests + validations 30 | 7. `make run-docker-validate` - Runs validation and tests inside the docker container 31 | -------------------------------------------------------------------------------- /.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 | # Edit below this line 132 | -------------------------------------------------------------------------------- /.dockerignore: -------------------------------------------------------------------------------- 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 | # Editors 132 | .vscode 133 | .idea 134 | 135 | # Edit Below this LINE: 136 | --------------------------------------------------------------------------------