commit 53b7c05b0734b40e8b3067d7c0ad2f4cf8940d6a Author: Jack Hadrill Date: Wed Aug 31 00:54:17 2022 +0100 Initial commit diff --git a/.drone.yml b/.drone.yml new file mode 100644 index 0000000..46e1eab --- /dev/null +++ b/.drone.yml @@ -0,0 +1,49 @@ +kind: pipeline +type: docker +name: lint-test +steps: + - name: lint + image: python:3-slim + commands: + - echo "Installing lint dependencies..." + - pip install --no-cache-dir '.[lint]' > /dev/null + - echo "Running flake8..." + - flake8 src + - echo "Running pylint..." + - pylint src + - name: test + image: python:3-slim + commands: + - echo "Installing test dependencies..." + - pip install --no-cache-dir '.[test]' > /dev/null + - echo "Running tests..." + - pytest +--- +kind: pipeline +type: docker +name: build-deploy +trigger: + branch: + - main +depends_on: + - lint-test +steps: + - name: build + image: python:3-slim + commands: + - pip install --no-cache-dir build + - python -m build --wheel + - name: publish + image: plugins/pypi + when: + branch: + - main + event: + - push + settings: + username: + from_secret: username + password: + from_secret: password + repository: https://git.jacknet.io/api/packages/jackhadrill/pypi + skip_build: true diff --git a/.flake8 b/.flake8 new file mode 100644 index 0000000..6deafc2 --- /dev/null +++ b/.flake8 @@ -0,0 +1,2 @@ +[flake8] +max-line-length = 120 diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..3227e2a --- /dev/null +++ b/.gitignore @@ -0,0 +1,126 @@ +# ---> VisualStudioCode +.vscode +!.vscode/settings.json +!.vscode/tasks.json +!.vscode/launch.json +!.vscode/extensions.json + +# ---> Python +# Byte-compiled / optimized / DLL files +__pycache__/ +*.py[cod] +*$py.class + +# C extensions +*.so + +# Distribution / packaging +.Python +develop-eggs/ +dist/ +downloads/ +eggs/ +.eggs/ +lib/ +lib64/ +parts/ +sdist/ +var/ +wheels/ +*.egg-info/ +.installed.cfg +*.egg +MANIFEST + +# PyInstaller +# Usually these files are written by a python script from a template +# before PyInstaller builds the exe, so as to inject date/other infos into it. +*.manifest +*.spec + +# Installer logs +pip-log.txt +pip-delete-this-directory.txt + +# Unit test / coverage reports +htmlcov/ +.tox/ +.nox/ +.coverage +.coverage.* +.cache +nosetests.xml +coverage.xml +*.cover +.hypothesis/ +.pytest_cache/ + +# Translations +*.mo +*.pot + +# Django stuff: +*.log +local_settings.py +db.sqlite3 + +# Flask stuff: +instance/ +.webassets-cache + +# Scrapy stuff: +.scrapy + +# Sphinx documentation +docs/_build/ + +# PyBuilder +target/ + +# Jupyter Notebook +.ipynb_checkpoints + +# IPython +profile_default/ +ipython_config.py + +# pyenv +.python-version + +# celery beat schedule file +celerybeat-schedule + +# SageMath parsed files +*.sage.py + +# Environments +.env +.venv +env/ +venv/ +ENV/ +env.bak/ +venv.bak/ + +# Spyder project settings +.spyderproject +.spyproject + +# Rope project settings +.ropeproject + +# mkdocs documentation +/site + +# mypy +.mypy_cache/ +.dmypy.json +dmypy.json + +# Pyre type checker +.pyre/ + +# pycharm +.idea + +.vscode/launch.json diff --git a/.pylintrc b/.pylintrc new file mode 100644 index 0000000..7615b86 --- /dev/null +++ b/.pylintrc @@ -0,0 +1,2 @@ +[FORMAT] +max-line-length=120 diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..8e09124 --- /dev/null +++ b/LICENSE @@ -0,0 +1,23 @@ +Butlersaurus License (Extends ISC License) + +Copyright (c) 2017-2022 by Butlersaurus + +Definitions: + * This software - All source files, issues, comments and intellectual + propety contained within this repository. + * Butlersarus - Members of Discord Guild <506852356281991208>, + hereby known as Butlersaurus. + * Employer - Any company, subsidiary or affiliated organisation which + directly or indirectly employs a Butlersaurus member. + +Permission to use, copy, modify, and /or distribute this software for any +purpose with or without fee is hereby granted to all except the employer of +each contributor to this software, provided that the above copyright notice +and this permission notice appear in all copies. + +THE SOFTWARE IS PROVIDED "AS IS" AND BUTLERSAURUS DISCLAIMS ALL WARRANTIES WITH +REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND +FITNESS. IN NO EVENT SHALL BUTLERSAURUS BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, +OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA +OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, +ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..323be92 --- /dev/null +++ b/README.md @@ -0,0 +1,111 @@ +# Python Template + +This is a basic Python template which uses the new `pyproject.toml` in +conjunction with `setup.cfg` (and legacy support for older Python versions with +`setup.py`). + +It contains pylint and flake8 rules for an increased line length of 120 +characters, in addition to support for unit tests and CI via Drone. + +## Development + +The package should be located in a subdirectory within `src/`. For example, +`src/foobar/`. + +This directory should contain an `__init__.py` and a `__main__.py`, the latter +of which allows this package to be called as a Python module. + +To install an editable version (such that you don't need to keep +re-installing), create a new virtual environment and use pip's editable flag. + +```bash +$ python -m venv venv +$ . venv/bin/activate +(venv)$ pip install -e . +``` + +### Lint + +Pylint and flake8 rules can be found in `.pylintrc` and `.flake8` respectively. +By default, the default rulesets are followed with overrides specified in these +files. + +To install, use the following command: +```bash +(venv)$ pip install -e '.[lint]' +``` + +To run, use the following commands: +```bash +(venv)$ flake8 src +(venv)$ pylint src +``` + +It should be noted that flake8 is much quicker than pylint, so should run first +when used in a CI pipeline. + +### Test + +This package is setup to support Python unittest and pytest, although in +practice I've only really used it with pytest. + +To install the test dependencies, issue the following command: +```bash +(venv)$ pip install -e '.[test]' +``` + +To run the tests, run the following command: +```bash +(venv)$ pytest +``` + +Tests should be stored in the `test/` directory. + +### Build + +To build a wheel for this package, use the following commands: +```bash +(venv)$ pip install --no-cache-dir build +(venv)$ python -m build --wheel +``` + +This will output a wheel to the `dist/` directory. + +## Installation + +Installation can be performed from source or using the previously built wheel. + +### Source + +To install from source, navigate to the root directory and run the following +command: +```bash +(venv)$ pip install . +``` + +### Wheel + +To install using the wheel, run the following command: +```bash +(venv)$ pip install dist/foobar*.whl +``` + +## Running + +The `[project.scripts]` directive in `pyproject.toml` lists the commands which +should be installed as part of this package. The included example runs the +`main()` function in `__main__.py`, and allows for the user to run the package +with the following command: +```bash +(venv)$ foobar +Hello, World! +42 +``` + +Alternatively, because `__main__.py` was used, the user can achieve the same by +using the following: +```bash +(venv)$ python -m foobar +Hello, World! +42 +``` diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 0000000..947c40e --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,26 @@ +[build-system] +requires = ["setuptools", "wheel"] +build-backend = "setuptools.build_meta" + +[project] +name = "foobar" +description = "A boilerplate template for Python projects." +readme = "README.md" +requires-python = ">=3.9" +license = {text = "Butlersaurus License"} +dynamic = ["version"] +dependencies = [ + # "dependency>=0.0.1" +] + +[project.optional-dependencies] +lint = [ + "pylint>=2.14.5", + "flake8>=5.0.4" +] +test = [ + "pytest>=7.1.2" +] + +[project.scripts] +foobar = "foobar.__main__:main" diff --git a/setup.cfg b/setup.cfg new file mode 100644 index 0000000..41a0ee7 --- /dev/null +++ b/setup.cfg @@ -0,0 +1,3 @@ +[metadata] +name = foobar +version = 0.0.1 diff --git a/setup.py b/setup.py new file mode 100644 index 0000000..430fb1f --- /dev/null +++ b/setup.py @@ -0,0 +1,10 @@ +#!/usr/bin/env python3 + +# N.B. This is here for legacy support in order to support editable installs. Please see: +# https://setuptools.pypa.io/en/latest/userguide/pyproject_config.html#pep660-status +# https://setuptools.pypa.io/en/latest/userguide/pyproject_config.html#setupcfg-caveats + +from setuptools import setup + + +setup() diff --git a/src/foobar/__init__.py b/src/foobar/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/src/foobar/__main__.py b/src/foobar/__main__.py new file mode 100644 index 0000000..f69dd22 --- /dev/null +++ b/src/foobar/__main__.py @@ -0,0 +1,13 @@ +"""Entrypoint for application.""" + +from foobar.example import add_numbers + + +def main() -> None: + """Prints example strings to stdout.""" + print("Hello, World!") + print(add_numbers(40, 2)) + + +if __name__ == "__main__": + main() diff --git a/src/foobar/example.py b/src/foobar/example.py new file mode 100644 index 0000000..10ffa15 --- /dev/null +++ b/src/foobar/example.py @@ -0,0 +1,11 @@ +"""Contains some example functions.""" + + +def add_numbers(first: int, second: int) -> int: + """Adds two integers. + + :param first: The first integer. + :param second: The second integer. + :returns: The sum of the first and second integer. + """ + return first + second diff --git a/tests/test_example.py b/tests/test_example.py new file mode 100644 index 0000000..52f999d --- /dev/null +++ b/tests/test_example.py @@ -0,0 +1,17 @@ +"""Tests for example.py.""" + +from foobar.example import add_numbers + + +def test_add() -> None: + """Assert that two integers add together correctly.""" + # Arrange + first = 40 + second = 2 + expected = 42 + + # Act + ret = add_numbers(first, second) + + # Assert + assert ret == expected