diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md new file mode 100644 index 0000000..2b26835 --- /dev/null +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -0,0 +1,20 @@ +# Description + +Jira Ticket: https://yexttest.atlassian.net/browse/[ TICKET_NUMBER ] + + + +# Screenshots/GIFS + + + +# Checklist + + + +- [ ] My code follows the style guidelines of this project +- [ ] I have performed a self-review of my code +- [ ] I have made corresponding changes to any relevant documentation +- [ ] I have added tests that prove my fix is effective or that my feature works +- [ ] New and existing unit tests pass locally with my changes +- [ ] Any dependent changes have been merged and published in downstream modules diff --git a/.gitignore b/.gitignore index dae0c87..4add5ec 100644 --- a/.gitignore +++ b/.gitignore @@ -37,3 +37,7 @@ nosetests.xml # Virtualenv .venv + +# Other +.pypirc +.git diff --git a/AUTHORS.rst b/AUTHORS.rst index 1fe1fae..5d4a1c3 100644 --- a/AUTHORS.rst +++ b/AUTHORS.rst @@ -8,6 +8,7 @@ Contributors | `Akshay Shah `_ | `Dale Hui `_ | `Istvan Nemeth `_ +| `Lachlan Imel `_ | `Robert MacCloy `_ | `Sam Vilain `_ | `Wyatt Paul `_ diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..7b54e85 --- /dev/null +++ b/Makefile @@ -0,0 +1,35 @@ +REPO = $(shell git rev-parse --show-toplevel) +POETRY = poetry + +hooks: + ${REPO}/githooks/update_githooks.sh + +install-build: + ${POETRY} install --only=main + +install-dev: + ${POETRY} install + +poetry: + curl -sSL https://install.python-poetry.org | POETRY_VERSION=2.1.3 python3 - + poetry cache clear pypi --all + poetry config virtualenvs.in-project true + +quickstart: poetry install-dev hooks + +quickstart-build: poetry install-build hooks + +clean: + # Delete all .pyc and .pyo files. + find ${REPO} \( -name "*~" -o -name "*.py[co]" -o -name ".#*" -o -name "#*#" \) -exec rm '{}' + + rm -rf .pytest_cache + +lint: clean + ${POETRY} run flake8 --config=${REPO}/.flake8 ${REPO}/src/richenum + ${POETRY} run pylint --rcfile=${REPO}/pylint.rc ${REPO}/src/richenum + +test: clean + ${POETRY} run pytest + +build: + ${POETRY} build \ No newline at end of file diff --git a/githooks/pre-commit b/githooks/pre-commit new file mode 100755 index 0000000..932798a --- /dev/null +++ b/githooks/pre-commit @@ -0,0 +1,77 @@ +#!/usr/bin/env bash + +# Pre-commit linting. +# +# To skip any of these checks touch any of these bypass_* files in the +# project root. +# bypass_flake8 +# bypass_tabs +# +# To bypass Flake8 checking for a particular line, add '# noqa' as an +# inline comment. + +REPO_ROOT=$(git rev-parse --show-toplevel) + +function get_temp_file { + export TMPDIR=/tmp # OSX compat + echo `mktemp tmp.pre-commit.XXXXXXXXXX` +} + +function flake8_check { + local temp_file + temp_file=$1 + poetry run flake8 --config="${REPO_ROOT}/.flake8" "$temp_file" + return $? +} + +function tab_check { + local temp_file + temp_file=$1 + if grep -q $'\t' $temp_file; then + return 1 + else + return 0 + fi +} + +function run_check { + local run_type + local display_name + local file_ext + local callback + run_type=$1 + display_name=$2 + file_ext=$3 # the file extension to check against + callback=$4 # callback should take the (temporary) file to check + + if [ -e $REPO_ROOT/bypass_$run_type ]; then + echo "Bypassed $display_name check." + rm $REPO_ROOT/bypass_$run_type 2> /dev/null # don't bypass the check next time. + else + # Only check staged files that match the extension. + # The --diff-filter option matches everything except for (D)eleted files. + echo "Running $display_name checker..." + local files + files=`git diff --staged --name-only --diff-filter=ACMRTUXB | grep "\.${file_ext}\$"` + for file in $files; do + local temp_file + temp_file=$(get_temp_file) + git show :0:$file > $temp_file # check the staged version of the file + + local ret + $callback $temp_file + ret=$? + + rm $temp_file # clean up the temp file, the callback should never exit + if [ $ret -ne 0 ] + then + echo "Not committing since there are ${display_name} errors in $file." + exit 1 + fi + done + fi +} + +# Flake8 checks for tab indentation in Python. +run_check flake8 Flake8 py flake8_check +run_check tabs TabCharacter sh tab_check \ No newline at end of file diff --git a/githooks/update_githooks.sh b/githooks/update_githooks.sh new file mode 100755 index 0000000..ba26cf4 --- /dev/null +++ b/githooks/update_githooks.sh @@ -0,0 +1,8 @@ +#!/usr/bin/env bash +# Update our githooks. + +REPO_ROOT=$(git rev-parse --show-toplevel) +src_dir="${REPO_ROOT}/githooks/" +dest_dir="${REPO_ROOT}/.git/hooks" + +cp $src_dir/* $dest_dir \ No newline at end of file diff --git a/poetry.lock b/poetry.lock index e938678..4525d49 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1,5 +1,34 @@ # This file is automatically @generated by Poetry 2.1.3 and should not be changed by hand. +[[package]] +name = "astroid" +version = "3.2.4" +description = "An abstract syntax tree for Python with inference support." +optional = false +python-versions = ">=3.8.0" +groups = ["dev"] +markers = "python_version < \"3.11\"" +files = [ + {file = "astroid-3.2.4-py3-none-any.whl", hash = "sha256:413658a61eeca6202a59231abb473f932038fbcbf1666587f66d482083413a25"}, + {file = "astroid-3.2.4.tar.gz", hash = "sha256:0e14202810b30da1b735827f78f5157be2bbd4a7a59b7707ca0bfc2fb4c0063a"}, +] + +[package.dependencies] +typing-extensions = {version = ">=4.0.0", markers = "python_version < \"3.11\""} + +[[package]] +name = "astroid" +version = "4.0.4" +description = "An abstract syntax tree for Python with inference support." +optional = false +python-versions = ">=3.10.0" +groups = ["dev"] +markers = "python_version >= \"3.11\"" +files = [ + {file = "astroid-4.0.4-py3-none-any.whl", hash = "sha256:52f39653876c7dec3e3afd4c2696920e05c83832b9737afc21928f2d2eb7a753"}, + {file = "astroid-4.0.4.tar.gz", hash = "sha256:986fed8bcf79fb82c78b18a53352a0b287a73817d6dbcfba3162da36667c49a0"}, +] + [[package]] name = "colorama" version = "0.4.6" @@ -13,6 +42,40 @@ files = [ {file = "colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44"}, ] +[[package]] +name = "dill" +version = "0.4.0" +description = "serialize all of Python" +optional = false +python-versions = ">=3.8" +groups = ["dev"] +markers = "python_version < \"3.11\"" +files = [ + {file = "dill-0.4.0-py3-none-any.whl", hash = "sha256:44f54bf6412c2c8464c14e8243eb163690a9800dbe2c367330883b19c7561049"}, + {file = "dill-0.4.0.tar.gz", hash = "sha256:0633f1d2df477324f53a895b02c901fb961bdbf65a17122586ea7019292cbcf0"}, +] + +[package.extras] +graph = ["objgraph (>=1.7.2)"] +profile = ["gprof2dot (>=2022.7.29)"] + +[[package]] +name = "dill" +version = "0.4.1" +description = "serialize all of Python" +optional = false +python-versions = ">=3.9" +groups = ["dev"] +markers = "python_version >= \"3.11\"" +files = [ + {file = "dill-0.4.1-py3-none-any.whl", hash = "sha256:1e1ce33e978ae97fcfcff5638477032b801c46c7c65cf717f95fbc2248f79a9d"}, + {file = "dill-0.4.1.tar.gz", hash = "sha256:423092df4182177d4d8ba8290c8a5b640c66ab35ec7da59ccfa00f6fa3eea5fa"}, +] + +[package.extras] +graph = ["objgraph (>=1.7.2)"] +profile = ["gprof2dot (>=2022.7.29)"] + [[package]] name = "exceptiongroup" version = "1.3.0" @@ -61,6 +124,38 @@ files = [ {file = "iniconfig-2.1.0.tar.gz", hash = "sha256:3abbd2e30b36733fee78f9c7f7308f2d0050e88f0087fd25c2645f63c773e1c7"}, ] +[[package]] +name = "isort" +version = "5.13.2" +description = "A Python utility / library to sort Python imports." +optional = false +python-versions = ">=3.8.0" +groups = ["dev"] +markers = "python_version < \"3.11\"" +files = [ + {file = "isort-5.13.2-py3-none-any.whl", hash = "sha256:8ca5e72a8d85860d5a3fa69b8745237f2939afe12dbf656afbcb47fe72d947a6"}, + {file = "isort-5.13.2.tar.gz", hash = "sha256:48fdfcb9face5d58a4f6dde2e72a1fb8dcaf8ab26f95ab49fab84c2ddefb0109"}, +] + +[package.extras] +colors = ["colorama (>=0.4.6)"] + +[[package]] +name = "isort" +version = "8.0.0" +description = "A Python utility / library to sort Python imports." +optional = false +python-versions = ">=3.10.0" +groups = ["dev"] +markers = "python_version >= \"3.11\"" +files = [ + {file = "isort-8.0.0-py3-none-any.whl", hash = "sha256:184916a933041c7cf718787f7e52064f3c06272aff69a5cb4dc46497bd8911d9"}, + {file = "isort-8.0.0.tar.gz", hash = "sha256:fddea59202f231e170e52e71e3510b99c373b6e571b55d9c7b31b679c0fed47c"}, +] + +[package.extras] +colors = ["colorama"] + [[package]] name = "mccabe" version = "0.7.0" @@ -85,6 +180,37 @@ files = [ {file = "packaging-25.0.tar.gz", hash = "sha256:d443872c98d677bf60f6a1f2f8c1cb748e8fe762d2bf9d3148b5599295b0fc4f"}, ] +[[package]] +name = "platformdirs" +version = "4.3.6" +description = "A small Python package for determining appropriate platform-specific dirs, e.g. a `user data dir`." +optional = false +python-versions = ">=3.8" +groups = ["dev"] +markers = "python_version < \"3.11\"" +files = [ + {file = "platformdirs-4.3.6-py3-none-any.whl", hash = "sha256:73e575e1408ab8103900836b97580d5307456908a03e92031bab39e4554cc3fb"}, + {file = "platformdirs-4.3.6.tar.gz", hash = "sha256:357fb2acbc885b0419afd3ce3ed34564c13c9b95c89360cd9563f73aa5e2b907"}, +] + +[package.extras] +docs = ["furo (>=2024.8.6)", "proselint (>=0.14)", "sphinx (>=8.0.2)", "sphinx-autodoc-typehints (>=2.4)"] +test = ["appdirs (==1.4.4)", "covdefaults (>=2.3)", "pytest (>=8.3.2)", "pytest-cov (>=5)", "pytest-mock (>=3.14)"] +type = ["mypy (>=1.11.2)"] + +[[package]] +name = "platformdirs" +version = "4.9.2" +description = "A small Python package for determining appropriate platform-specific dirs, e.g. a `user data dir`." +optional = false +python-versions = ">=3.10" +groups = ["dev"] +markers = "python_version >= \"3.11\"" +files = [ + {file = "platformdirs-4.9.2-py3-none-any.whl", hash = "sha256:9170634f126f8efdae22fb58ae8a0eaa86f38365bc57897a6c4f781d1f5875bd"}, + {file = "platformdirs-4.9.2.tar.gz", hash = "sha256:9a33809944b9db043ad67ca0db94b14bf452cc6aeaac46a88ea55b26e2e9d291"}, +] + [[package]] name = "pluggy" version = "1.5.0" @@ -125,6 +251,63 @@ files = [ {file = "pyflakes-3.2.0.tar.gz", hash = "sha256:1c61603ff154621fb2a9172037d84dca3500def8c8b630657d1701f026f8af3f"}, ] +[[package]] +name = "pylint" +version = "3.2.7" +description = "python code static checker" +optional = false +python-versions = ">=3.8.0" +groups = ["dev"] +markers = "python_version < \"3.11\"" +files = [ + {file = "pylint-3.2.7-py3-none-any.whl", hash = "sha256:02f4aedeac91be69fb3b4bea997ce580a4ac68ce58b89eaefeaf06749df73f4b"}, + {file = "pylint-3.2.7.tar.gz", hash = "sha256:1b7a721b575eaeaa7d39db076b6e7743c993ea44f57979127c517c6c572c803e"}, +] + +[package.dependencies] +astroid = ">=3.2.4,<=3.3.0-dev0" +colorama = {version = ">=0.4.5", markers = "sys_platform == \"win32\""} +dill = {version = ">=0.2", markers = "python_version < \"3.11\""} +isort = ">=4.2.5,<5.13.0 || >5.13.0,<6" +mccabe = ">=0.6,<0.8" +platformdirs = ">=2.2.0" +tomli = {version = ">=1.1.0", markers = "python_version < \"3.11\""} +tomlkit = ">=0.10.1" +typing-extensions = {version = ">=3.10.0", markers = "python_version < \"3.10\""} + +[package.extras] +spelling = ["pyenchant (>=3.2,<4.0)"] +testutils = ["gitpython (>3)"] + +[[package]] +name = "pylint" +version = "4.0.5" +description = "python code static checker" +optional = false +python-versions = ">=3.10.0" +groups = ["dev"] +markers = "python_version >= \"3.11\"" +files = [ + {file = "pylint-4.0.5-py3-none-any.whl", hash = "sha256:00f51c9b14a3b3ae08cff6b2cdd43f28165c78b165b628692e428fb1f8dc2cf2"}, + {file = "pylint-4.0.5.tar.gz", hash = "sha256:8cd6a618df75deb013bd7eb98327a95f02a6fb839205a6bbf5456ef96afb317c"}, +] + +[package.dependencies] +astroid = ">=4.0.2,<=4.1.dev0" +colorama = {version = ">=0.4.5", markers = "sys_platform == \"win32\""} +dill = [ + {version = ">=0.3.7", markers = "python_version >= \"3.12\""}, + {version = ">=0.3.6", markers = "python_version == \"3.11\""}, +] +isort = ">=5,<5.13 || >5.13,<9" +mccabe = ">=0.6,<0.8" +platformdirs = ">=2.2" +tomlkit = ">=0.10.1" + +[package.extras] +spelling = ["pyenchant (>=3.2,<4.0)"] +testutils = ["gitpython (>3)"] + [[package]] name = "pytest" version = "8.3.5" @@ -191,6 +374,32 @@ files = [ {file = "tomli-2.2.1.tar.gz", hash = "sha256:cd45e1dc79c835ce60f7404ec8119f2eb06d38b1deba146f07ced3bbc44505ff"}, ] +[[package]] +name = "tomlkit" +version = "0.13.3" +description = "Style preserving TOML library" +optional = false +python-versions = ">=3.8" +groups = ["dev"] +markers = "python_version < \"3.11\"" +files = [ + {file = "tomlkit-0.13.3-py3-none-any.whl", hash = "sha256:c89c649d79ee40629a9fda55f8ace8c6a1b42deb912b2a8fd8d942ddadb606b0"}, + {file = "tomlkit-0.13.3.tar.gz", hash = "sha256:430cf247ee57df2b94ee3fbe588e71d362a941ebb545dec29b53961d61add2a1"}, +] + +[[package]] +name = "tomlkit" +version = "0.14.0" +description = "Style preserving TOML library" +optional = false +python-versions = ">=3.9" +groups = ["dev"] +markers = "python_version >= \"3.11\"" +files = [ + {file = "tomlkit-0.14.0-py3-none-any.whl", hash = "sha256:592064ed85b40fa213469f81ac584f67a4f2992509a7c3ea2d632208623a3680"}, + {file = "tomlkit-0.14.0.tar.gz", hash = "sha256:cf00efca415dbd57575befb1f6634c4f42d2d87dbba376128adb42c121b87064"}, +] + [[package]] name = "typing-extensions" version = "4.13.2" @@ -207,4 +416,4 @@ files = [ [metadata] lock-version = "2.1" python-versions = "^3.8.1" -content-hash = "f63543f27200097265b09b8d7f31f9f6d6290e1c0d2f511996b762674e8644ea" +content-hash = "24165690f6947ec500a9db5a4734e3b163be0671d7b37bece1ce95673a341307" diff --git a/pylint.rc b/pylint.rc new file mode 100644 index 0000000..daea4cd --- /dev/null +++ b/pylint.rc @@ -0,0 +1,12 @@ +[MESSAGES CONTROL] +# Errors only. +disable=all +enable=E + +[REPORTS] +# Don't display the complete report. +reports=no + +[TYPECHECK] +# Dynamically-set members missed by the inference system. +# generated-members= diff --git a/pyproject.toml b/pyproject.toml index d9a62cf..1e3c8b9 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -30,6 +30,7 @@ python = "^3.8.1" [tool.poetry.group.dev.dependencies] pytest = "^8.0.0" flake8 = "^7.0.0" +pylint = "*" [build-system] requires = ["poetry-core"]