diff --git a/.github/workflows/bumpversion.yaml b/.github/workflows/bump_version.yaml similarity index 55% rename from .github/workflows/bumpversion.yaml rename to .github/workflows/bump_version.yaml index b58ac46..70ed123 100644 --- a/.github/workflows/bumpversion.yaml +++ b/.github/workflows/bump_version.yaml @@ -4,11 +4,6 @@ on: push: branches: - master - tags-ignore: - - '*' - pull_request: - branches: - - master workflow_dispatch: jobs: @@ -17,13 +12,22 @@ jobs: runs-on: ubuntu-latest name: "Bump version and create changelog with commitizen" steps: + - name: Load secret + uses: 1password/load-secrets-action@v2 + with: + export-env: true + env: + OP_SERVICE_ACCOUNT_TOKEN: ${{ secrets.OP_SERVICE_ACCOUNT_TOKEN }} + PERSONAL_ACCESS_TOKEN: op://shawndengdev/github_access_token/credential + - name: Check out uses: actions/checkout@v4 with: fetch-depth: 0 - token: '${{ secrets.PERSONAL_ACCESS_TOKEN }}' + token: '${{ env.PERSONAL_ACCESS_TOKEN }}' + - name: Create bump and changelog uses: commitizen-tools/commitizen-action@master with: - github_token: ${{ secrets.PERSONAL_ACCESS_TOKEN }} + github_token: ${{ env.PERSONAL_ACCESS_TOKEN }} branch: master diff --git a/.github/workflows/lint.yaml b/.github/workflows/lint.yaml new file mode 100644 index 0000000..909b494 --- /dev/null +++ b/.github/workflows/lint.yaml @@ -0,0 +1,40 @@ +name: lint_and_unittest + +on: [ push, pull_request ] + +jobs: + lint_and_unittest: + runs-on: ubuntu-latest + steps: + - name: Load secret + uses: 1password/load-secrets-action@v2 + with: + export-env: true + env: + OP_SERVICE_ACCOUNT_TOKEN: ${{ secrets.OP_SERVICE_ACCOUNT_TOKEN }} + PERSONAL_ACCESS_TOKEN: op://shawndengdev/github_access_token/credential + + - name: Check out + uses: actions/checkout@v4 + with: + fetch-depth: 0 + token: '${{ env.PERSONAL_ACCESS_TOKEN }}' + + - uses: actions/setup-python@v5 + with: + python-version: "3.12" + + - uses: abatilo/actions-poetry@v2 + with: + poetry-version: "latest" + + - name: install depends + run: | + pip install nox + poetry install + + - name: Run lint checks + run: poetry run nox -s lint + + - name: Run tests + run: poetry run nox -s test diff --git a/.github/workflows/release-build.yaml b/.github/workflows/release-build.yaml deleted file mode 100644 index 4213ec7..0000000 --- a/.github/workflows/release-build.yaml +++ /dev/null @@ -1,39 +0,0 @@ -name: release-build -on: - push: - tags: - - '*.*.*' - workflow_dispatch: - -jobs: - release-build: - runs-on: windows-latest - steps: - - uses: actions/checkout@v4 - - uses: actions/setup-python@v5 - with: - python-version: "3.12" - - uses: abatilo/actions-poetry@v2 - with: - poetry-version: "latest" - - - name: setup-pypi - run: | - poetry self add poetry-pyinstaller-plugin - poetry self add poetry-plugin-taskipy - - - name: build - run: | - poetry config pypi-token.pypi ${{ secrets.PYPI_TOKEN }} - poetry publish --build - - - name: Release - uses: softprops/action-gh-release@v2 - with: - files: | - dist/**/*.exe - dist/*.tar.gz - dist/*.whl - generate_release_notes: true - env: - GITHUB_TOKEN: ${{ secrets.PERSONAL_ACCESS_TOKEN }} diff --git a/.github/workflows/release_build.yaml b/.github/workflows/release_build.yaml new file mode 100644 index 0000000..4eaa23a --- /dev/null +++ b/.github/workflows/release_build.yaml @@ -0,0 +1,52 @@ +name: release-build +on: + workflow_dispatch: + push: + tags: + - '*.*.*' + +jobs: + release-build: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - name: Load secret + uses: 1password/load-secrets-action@v2 + with: + export-env: true + env: + OP_SERVICE_ACCOUNT_TOKEN: ${{ secrets.OP_SERVICE_ACCOUNT_TOKEN }} + PERSONAL_ACCESS_TOKEN: op://shawndengdev/github_access_token/credential + PYPI_TOKEN: op://shawndengdev/pypi_token/credential + + - uses: actions/setup-python@v5 + with: + python-version: "3.12" + + - uses: abatilo/actions-poetry@v2 + with: + poetry-version: "latest" + + - name: Install nox + run: pip install nox + + - name: build and publish + run: | + poetry config pypi-token.pypi ${{ env.PYPI_TOKEN }} + poetry install + poetry run nox -s lint + poetry run nox -s test + poetry run nox -s build + poetry publish + + - name: Release + uses: softprops/action-gh-release@v2 + with: + files: | + dist/**/*.exe + dist/*.tar.gz + dist/*.whl + generate_release_notes: true + env: + GITHUB_TOKEN: ${{ env.PERSONAL_ACCESS_TOKEN }} diff --git a/.gitignore b/.gitignore index a09c56d..2d9539c 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,8 @@ /.idea +# Coverage output +.coverage +/.nox/ +/build/ +/coverage.xml +/.zip/ +/venv/ \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md index a1841f5..57b6331 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,7 +2,5 @@ ### Feat -- update `project.toml` readme type -- update `project.toml` readme type - update template config - update github action,and update config diff --git a/cookiecutter.json b/cookiecutter.json index 41705c7..1b99955 100644 --- a/cookiecutter.json +++ b/cookiecutter.json @@ -3,7 +3,7 @@ "template-python": { "path": "./template-python", "title": "python", - "description": "A cookiecutter template for python project" + "description": "template for python project" } } } \ No newline at end of file diff --git a/noxfile.py b/noxfile.py new file mode 100644 index 0000000..1f2fc82 --- /dev/null +++ b/noxfile.py @@ -0,0 +1,95 @@ +"""Nox automation file for github-action-test project. + +This module contains nox sessions for automating development tasks including: +- Code linting and formatting +- Unit testing with coverage reporting +- Package building +- Executable creation + +Typical usage example: + nox -s lint # Run linting + nox -s test # Run tests + nox -s build # Build package + nox -s build_exe # Build package with standalone executable +""" +import nox + + +@nox.session(reuse_venv=True) +def lint(session: nox.Session) -> None: + """Run code quality checks using ruff. + + Performs linting and formatting checks on the codebase using ruff. + Fixes auto-fixable issues and shows formatting differences. + + Args: + session: Nox session object for running commands + """ + session.install("poetry") + session.install("ruff") + session.run("poetry", "install", "--only", "dev") + session.run( + "ruff", + "check", + ".", + "--fix", + "--verbose" + ) + session.run( + "ruff", + "format", + "--verbose", + "--diff" + ) + +@nox.session(reuse_venv=True) +def test(session: nox.Session) -> None: + """Run the test suite with coverage reporting. + + Executes pytest with coverage reporting for the github_action_test package. + Generates both terminal and XML coverage reports. + + Args: + session: Nox session object for running commands + """ + session.install("poetry") + session.run("poetry", "install") + session.run( + "pytest", + "--cov=repo_scaffold", + "--cov-report=term-missing", + "--cov-report=xml", + "-v", + "tests" + ) + + +@nox.session(reuse_venv=True) +def build(session: nox.Session) -> None: + """Build the Python package. + + Creates a distributable package using poetry build command + with verbose output and excluding dev dependencies. + + Args: + session: Nox session object for running commands + """ + session.install("poetry") + session.run("poetry", "install", "--without", "dev") + session.run("poetry", "build", "-vvv") + + +@nox.session(reuse_venv=True) +def build_exe(session: nox.Session) -> None: + """Build the Python package with standalone executable. + + Creates an executable using poetry-pyinstaller-plugin. + Installs required plugin and builds without dev dependencies. + + Args: + session: Nox session object for running commands + """ + session.install("poetry") + session.install("poetry", "self", "add", "poetry-pyinstaller-plugin") + session.run("poetry", "install", "--without", "dev") + session.run("poetry", "build", "-vvv") diff --git a/poetry.lock b/poetry.lock index 03fd506..d7d246a 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1,37 +1,5 @@ # This file is automatically @generated by Poetry 1.8.5 and should not be changed by hand. -[[package]] -name = "annotated-types" -version = "0.7.0" -description = "Reusable constraint types to use with typing.Annotated" -optional = false -python-versions = ">=3.8" -files = [ - {file = "annotated_types-0.7.0-py3-none-any.whl", hash = "sha256:1f02e8b43a8fbbc3f3e0d4f0f4bfc8131bcb4eebe8849b8e5c773f3a1c582a53"}, - {file = "annotated_types-0.7.0.tar.gz", hash = "sha256:aff07c09a53a08bc8cfccb9c85b05f1aa9a2a6f23728d790723543408344ce89"}, -] - -[[package]] -name = "anyio" -version = "4.7.0" -description = "High level compatibility layer for multiple asynchronous event loop implementations" -optional = false -python-versions = ">=3.9" -files = [ - {file = "anyio-4.7.0-py3-none-any.whl", hash = "sha256:ea60c3723ab42ba6fff7e8ccb0488c898ec538ff4df1f1d5e642c3601d07e352"}, - {file = "anyio-4.7.0.tar.gz", hash = "sha256:2f834749c602966b7d456a7567cafcb309f96482b5081d14ac93ccd457f9dd48"}, -] - -[package.dependencies] -idna = ">=2.8" -sniffio = ">=1.1" -typing_extensions = {version = ">=4.5", markers = "python_version < \"3.13\""} - -[package.extras] -doc = ["Sphinx (>=7.4,<8.0)", "packaging", "sphinx-autodoc-typehints (>=1.2.0)", "sphinx_rtd_theme"] -test = ["anyio[trio]", "coverage[toml] (>=7)", "exceptiongroup (>=1.2.0)", "hypothesis (>=4.0)", "psutil (>=5.9)", "pytest (>=7.0)", "pytest-mock (>=3.6.1)", "trustme", "truststore (>=0.9.1)", "uvloop (>=0.21)"] -trio = ["trio (>=0.26.1)"] - [[package]] name = "argcomplete" version = "3.5.2" @@ -90,17 +58,6 @@ files = [ {file = "certifi-2024.12.14.tar.gz", hash = "sha256:b650d30f370c2b724812bee08008be0c4163b163ddaec3f2546c1caf65f191db"}, ] -[[package]] -name = "cfgv" -version = "3.4.0" -description = "Validate configuration and produce human readable error messages." -optional = false -python-versions = ">=3.8" -files = [ - {file = "cfgv-3.4.0-py2.py3-none-any.whl", hash = "sha256:b7265b1f29fd3316bfcd2b330d63d024f2bfd8bcb8b0272f8e19a504856c48f9"}, - {file = "cfgv-3.4.0.tar.gz", hash = "sha256:e52591d4c5f5dead8e0f673fb16db7949d2cfb3f7da4582893288f0ded8fe560"}, -] - [[package]] name = "chardet" version = "5.2.0" @@ -238,6 +195,23 @@ files = [ {file = "colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44"}, ] +[[package]] +name = "colorlog" +version = "6.9.0" +description = "Add colours to the output of Python's logging module." +optional = false +python-versions = ">=3.6" +files = [ + {file = "colorlog-6.9.0-py3-none-any.whl", hash = "sha256:5906e71acd67cb07a71e779c47c4bcb45fb8c2993eebe9e5adcd6a6f1b283eff"}, + {file = "colorlog-6.9.0.tar.gz", hash = "sha256:bfba54a1b93b94f54e1f4fe48395725a3d92fd2a4af702f6bd70946bdc0c6ac2"}, +] + +[package.dependencies] +colorama = {version = "*", markers = "sys_platform == \"win32\""} + +[package.extras] +development = ["black", "flake8", "mypy", "pytest", "types-colorama"] + [[package]] name = "commitizen" version = "4.1.0" @@ -282,6 +256,80 @@ pyyaml = ">=5.3.1" requests = ">=2.23.0" rich = "*" +[[package]] +name = "coverage" +version = "7.6.10" +description = "Code coverage measurement for Python" +optional = false +python-versions = ">=3.9" +files = [ + {file = "coverage-7.6.10-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:5c912978f7fbf47ef99cec50c4401340436d200d41d714c7a4766f377c5b7b78"}, + {file = "coverage-7.6.10-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:a01ec4af7dfeb96ff0078ad9a48810bb0cc8abcb0115180c6013a6b26237626c"}, + {file = "coverage-7.6.10-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a3b204c11e2b2d883946fe1d97f89403aa1811df28ce0447439178cc7463448a"}, + {file = "coverage-7.6.10-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:32ee6d8491fcfc82652a37109f69dee9a830e9379166cb73c16d8dc5c2915165"}, + {file = "coverage-7.6.10-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:675cefc4c06e3b4c876b85bfb7c59c5e2218167bbd4da5075cbe3b5790a28988"}, + {file = "coverage-7.6.10-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:f4f620668dbc6f5e909a0946a877310fb3d57aea8198bde792aae369ee1c23b5"}, + {file = "coverage-7.6.10-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:4eea95ef275de7abaef630c9b2c002ffbc01918b726a39f5a4353916ec72d2f3"}, + {file = "coverage-7.6.10-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:e2f0280519e42b0a17550072861e0bc8a80a0870de260f9796157d3fca2733c5"}, + {file = "coverage-7.6.10-cp310-cp310-win32.whl", hash = "sha256:bc67deb76bc3717f22e765ab3e07ee9c7a5e26b9019ca19a3b063d9f4b874244"}, + {file = "coverage-7.6.10-cp310-cp310-win_amd64.whl", hash = "sha256:0f460286cb94036455e703c66988851d970fdfd8acc2a1122ab7f4f904e4029e"}, + {file = "coverage-7.6.10-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:ea3c8f04b3e4af80e17bab607c386a830ffc2fb88a5484e1df756478cf70d1d3"}, + {file = "coverage-7.6.10-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:507a20fc863cae1d5720797761b42d2d87a04b3e5aeb682ef3b7332e90598f43"}, + {file = "coverage-7.6.10-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d37a84878285b903c0fe21ac8794c6dab58150e9359f1aaebbeddd6412d53132"}, + {file = "coverage-7.6.10-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a534738b47b0de1995f85f582d983d94031dffb48ab86c95bdf88dc62212142f"}, + {file = "coverage-7.6.10-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0d7a2bf79378d8fb8afaa994f91bfd8215134f8631d27eba3e0e2c13546ce994"}, + {file = "coverage-7.6.10-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:6713ba4b4ebc330f3def51df1d5d38fad60b66720948112f114968feb52d3f99"}, + {file = "coverage-7.6.10-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:ab32947f481f7e8c763fa2c92fd9f44eeb143e7610c4ca9ecd6a36adab4081bd"}, + {file = "coverage-7.6.10-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:7bbd8c8f1b115b892e34ba66a097b915d3871db7ce0e6b9901f462ff3a975377"}, + {file = "coverage-7.6.10-cp311-cp311-win32.whl", hash = "sha256:299e91b274c5c9cdb64cbdf1b3e4a8fe538a7a86acdd08fae52301b28ba297f8"}, + {file = "coverage-7.6.10-cp311-cp311-win_amd64.whl", hash = "sha256:489a01f94aa581dbd961f306e37d75d4ba16104bbfa2b0edb21d29b73be83609"}, + {file = "coverage-7.6.10-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:27c6e64726b307782fa5cbe531e7647aee385a29b2107cd87ba7c0105a5d3853"}, + {file = "coverage-7.6.10-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:c56e097019e72c373bae32d946ecf9858fda841e48d82df7e81c63ac25554078"}, + {file = "coverage-7.6.10-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c7827a5bc7bdb197b9e066cdf650b2887597ad124dd99777332776f7b7c7d0d0"}, + {file = "coverage-7.6.10-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:204a8238afe787323a8b47d8be4df89772d5c1e4651b9ffa808552bdf20e1d50"}, + {file = "coverage-7.6.10-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e67926f51821b8e9deb6426ff3164870976fe414d033ad90ea75e7ed0c2e5022"}, + {file = "coverage-7.6.10-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:e78b270eadb5702938c3dbe9367f878249b5ef9a2fcc5360ac7bff694310d17b"}, + {file = "coverage-7.6.10-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:714f942b9c15c3a7a5fe6876ce30af831c2ad4ce902410b7466b662358c852c0"}, + {file = "coverage-7.6.10-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:abb02e2f5a3187b2ac4cd46b8ced85a0858230b577ccb2c62c81482ca7d18852"}, + {file = "coverage-7.6.10-cp312-cp312-win32.whl", hash = "sha256:55b201b97286cf61f5e76063f9e2a1d8d2972fc2fcfd2c1272530172fd28c359"}, + {file = "coverage-7.6.10-cp312-cp312-win_amd64.whl", hash = "sha256:e4ae5ac5e0d1e4edfc9b4b57b4cbecd5bc266a6915c500f358817a8496739247"}, + {file = "coverage-7.6.10-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:05fca8ba6a87aabdd2d30d0b6c838b50510b56cdcfc604d40760dae7153b73d9"}, + {file = "coverage-7.6.10-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:9e80eba8801c386f72e0712a0453431259c45c3249f0009aff537a517b52942b"}, + {file = "coverage-7.6.10-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a372c89c939d57abe09e08c0578c1d212e7a678135d53aa16eec4430adc5e690"}, + {file = "coverage-7.6.10-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ec22b5e7fe7a0fa8509181c4aac1db48f3dd4d3a566131b313d1efc102892c18"}, + {file = "coverage-7.6.10-cp313-cp313-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:26bcf5c4df41cad1b19c84af71c22cbc9ea9a547fc973f1f2cc9a290002c8b3c"}, + {file = "coverage-7.6.10-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:4e4630c26b6084c9b3cb53b15bd488f30ceb50b73c35c5ad7871b869cb7365fd"}, + {file = "coverage-7.6.10-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:2396e8116db77789f819d2bc8a7e200232b7a282c66e0ae2d2cd84581a89757e"}, + {file = "coverage-7.6.10-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:79109c70cc0882e4d2d002fe69a24aa504dec0cc17169b3c7f41a1d341a73694"}, + {file = "coverage-7.6.10-cp313-cp313-win32.whl", hash = "sha256:9e1747bab246d6ff2c4f28b4d186b205adced9f7bd9dc362051cc37c4a0c7bd6"}, + {file = "coverage-7.6.10-cp313-cp313-win_amd64.whl", hash = "sha256:254f1a3b1eef5f7ed23ef265eaa89c65c8c5b6b257327c149db1ca9d4a35f25e"}, + {file = "coverage-7.6.10-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:2ccf240eb719789cedbb9fd1338055de2761088202a9a0b73032857e53f612fe"}, + {file = "coverage-7.6.10-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:0c807ca74d5a5e64427c8805de15b9ca140bba13572d6d74e262f46f50b13273"}, + {file = "coverage-7.6.10-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2bcfa46d7709b5a7ffe089075799b902020b62e7ee56ebaed2f4bdac04c508d8"}, + {file = "coverage-7.6.10-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4e0de1e902669dccbf80b0415fb6b43d27edca2fbd48c74da378923b05316098"}, + {file = "coverage-7.6.10-cp313-cp313t-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3f7b444c42bbc533aaae6b5a2166fd1a797cdb5eb58ee51a92bee1eb94a1e1cb"}, + {file = "coverage-7.6.10-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:b330368cb99ef72fcd2dc3ed260adf67b31499584dc8a20225e85bfe6f6cfed0"}, + {file = "coverage-7.6.10-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:9a7cfb50515f87f7ed30bc882f68812fd98bc2852957df69f3003d22a2aa0abf"}, + {file = "coverage-7.6.10-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:6f93531882a5f68c28090f901b1d135de61b56331bba82028489bc51bdd818d2"}, + {file = "coverage-7.6.10-cp313-cp313t-win32.whl", hash = "sha256:89d76815a26197c858f53c7f6a656686ec392b25991f9e409bcef020cd532312"}, + {file = "coverage-7.6.10-cp313-cp313t-win_amd64.whl", hash = "sha256:54a5f0f43950a36312155dae55c505a76cd7f2b12d26abeebbe7a0b36dbc868d"}, + {file = "coverage-7.6.10-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:656c82b8a0ead8bba147de9a89bda95064874c91a3ed43a00e687f23cc19d53a"}, + {file = "coverage-7.6.10-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:ccc2b70a7ed475c68ceb548bf69cec1e27305c1c2606a5eb7c3afff56a1b3b27"}, + {file = "coverage-7.6.10-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a5e37dc41d57ceba70956fa2fc5b63c26dba863c946ace9705f8eca99daecdc4"}, + {file = "coverage-7.6.10-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0aa9692b4fdd83a4647eeb7db46410ea1322b5ed94cd1715ef09d1d5922ba87f"}, + {file = "coverage-7.6.10-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:aa744da1820678b475e4ba3dfd994c321c5b13381d1041fe9c608620e6676e25"}, + {file = "coverage-7.6.10-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:c0b1818063dc9e9d838c09e3a473c1422f517889436dd980f5d721899e66f315"}, + {file = "coverage-7.6.10-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:59af35558ba08b758aec4d56182b222976330ef8d2feacbb93964f576a7e7a90"}, + {file = "coverage-7.6.10-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:7ed2f37cfce1ce101e6dffdfd1c99e729dd2ffc291d02d3e2d0af8b53d13840d"}, + {file = "coverage-7.6.10-cp39-cp39-win32.whl", hash = "sha256:4bcc276261505d82f0ad426870c3b12cb177752834a633e737ec5ee79bbdff18"}, + {file = "coverage-7.6.10-cp39-cp39-win_amd64.whl", hash = "sha256:457574f4599d2b00f7f637a0700a6422243b3565509457b2dbd3f50703e11f59"}, + {file = "coverage-7.6.10-pp39.pp310-none-any.whl", hash = "sha256:fd34e7b3405f0cc7ab03d54a334c17a9e802897580d964bd8c2001f4b9fd488f"}, + {file = "coverage-7.6.10.tar.gz", hash = "sha256:7fb105327c8f8f0682e29843e2ff96af9dcbe5bab8eeb4b398c6a33a16d80a23"}, +] + +[package.extras] +toml = ["tomli"] + [[package]] name = "decli" version = "0.6.2" @@ -320,120 +368,6 @@ docs = ["furo (>=2024.8.6)", "sphinx (>=8.0.2)", "sphinx-autodoc-typehints (>=2. testing = ["covdefaults (>=2.3)", "coverage (>=7.6.1)", "diff-cover (>=9.2)", "pytest (>=8.3.3)", "pytest-asyncio (>=0.24)", "pytest-cov (>=5)", "pytest-mock (>=3.14)", "pytest-timeout (>=2.3.1)", "virtualenv (>=20.26.4)"] typing = ["typing-extensions (>=4.12.2)"] -[[package]] -name = "githubkit" -version = "0.12.2" -description = "GitHub SDK for Python" -optional = false -python-versions = "<4.0,>=3.9" -files = [ - {file = "githubkit-0.12.2-py3-none-any.whl", hash = "sha256:be37fb2258311362c8398fd26eb7c0370b475cc413237de791dc9e510062a67d"}, - {file = "githubkit-0.12.2.tar.gz", hash = "sha256:d83f5f2418b0ead3e2a13d7e2a2a3a58f2a3e54eb6e7703a09c0161aad66ef58"}, -] - -[package.dependencies] -anyio = ">=3.6.1,<5.0.0" -hishel = ">=0.0.21,<=0.2.0" -httpx = ">=0.23.0,<1.0.0" -pydantic = ">=1.9.1,<2.5.0 || >2.5.0,<2.5.1 || >2.5.1,<3.0.0" -typing-extensions = ">=4.11.0,<5.0.0" - -[package.extras] -all = ["PyJWT[crypto] (>=2.4.0,<3.0.0)"] -auth = ["PyJWT[crypto] (>=2.4.0,<3.0.0)"] -auth-app = ["PyJWT[crypto] (>=2.4.0,<3.0.0)"] -jwt = ["PyJWT[crypto] (>=2.4.0,<3.0.0)"] - -[[package]] -name = "h11" -version = "0.14.0" -description = "A pure-Python, bring-your-own-I/O implementation of HTTP/1.1" -optional = false -python-versions = ">=3.7" -files = [ - {file = "h11-0.14.0-py3-none-any.whl", hash = "sha256:e3fe4ac4b851c468cc8363d500db52c2ead036020723024a109d37346efaa761"}, - {file = "h11-0.14.0.tar.gz", hash = "sha256:8f19fbbe99e72420ff35c00b27a34cb9937e902a8b810e2c88300c6f0a3b699d"}, -] - -[[package]] -name = "hishel" -version = "0.1.1" -description = "Persistent cache implementation for httpx and httpcore" -optional = false -python-versions = ">=3.9" -files = [ - {file = "hishel-0.1.1-py3-none-any.whl", hash = "sha256:5b51acc340303faeef2f5cfc1658acb1db1fdc3e3ad76406265a485f9707c5d6"}, - {file = "hishel-0.1.1.tar.gz", hash = "sha256:1f6421b78cc23fc43c610f651b7848c9b8eee2d29551d64a2ab0d45b319b6559"}, -] - -[package.dependencies] -httpx = ">=0.22.0" - -[package.extras] -redis = ["redis (==5.0.1)"] -s3 = ["boto3 (>=1.15.0,<=1.15.3)", "boto3 (>=1.15.3)"] -sqlite = ["anysqlite (>=0.0.5)"] -yaml = ["pyyaml (==6.0.1)"] - -[[package]] -name = "httpcore" -version = "1.0.7" -description = "A minimal low-level HTTP client." -optional = false -python-versions = ">=3.8" -files = [ - {file = "httpcore-1.0.7-py3-none-any.whl", hash = "sha256:a3fff8f43dc260d5bd363d9f9cf1830fa3a458b332856f34282de498ed420edd"}, - {file = "httpcore-1.0.7.tar.gz", hash = "sha256:8551cb62a169ec7162ac7be8d4817d561f60e08eaa485234898414bb5a8a0b4c"}, -] - -[package.dependencies] -certifi = "*" -h11 = ">=0.13,<0.15" - -[package.extras] -asyncio = ["anyio (>=4.0,<5.0)"] -http2 = ["h2 (>=3,<5)"] -socks = ["socksio (==1.*)"] -trio = ["trio (>=0.22.0,<1.0)"] - -[[package]] -name = "httpx" -version = "0.28.1" -description = "The next generation HTTP client." -optional = false -python-versions = ">=3.8" -files = [ - {file = "httpx-0.28.1-py3-none-any.whl", hash = "sha256:d909fcccc110f8c7faf814ca82a9a4d816bc5a6dbfea25d6591d6985b8ba59ad"}, - {file = "httpx-0.28.1.tar.gz", hash = "sha256:75e98c5f16b0f35b567856f597f06ff2270a374470a5c2392242528e3e3e42fc"}, -] - -[package.dependencies] -anyio = "*" -certifi = "*" -httpcore = "==1.*" -idna = "*" - -[package.extras] -brotli = ["brotli", "brotlicffi"] -cli = ["click (==8.*)", "pygments (==2.*)", "rich (>=10,<14)"] -http2 = ["h2 (>=3,<5)"] -socks = ["socksio (==1.*)"] -zstd = ["zstandard (>=0.18.0)"] - -[[package]] -name = "identify" -version = "2.6.3" -description = "File identification library for Python" -optional = false -python-versions = ">=3.9" -files = [ - {file = "identify-2.6.3-py2.py3-none-any.whl", hash = "sha256:9edba65473324c2ea9684b1f944fe3191db3345e50b6d04571d10ed164f8d7bd"}, - {file = "identify-2.6.3.tar.gz", hash = "sha256:62f5dae9b5fef52c84cc188514e9ea4f3f636b1d8799ab5ebc475471f9e47a02"}, -] - -[package.extras] -license = ["ukkonen"] - [[package]] name = "idna" version = "3.10" @@ -448,6 +382,17 @@ files = [ [package.extras] all = ["flake8 (>=7.1.1)", "mypy (>=1.11.2)", "pytest (>=8.3.2)", "ruff (>=0.6.2)"] +[[package]] +name = "iniconfig" +version = "2.0.0" +description = "brain-dead simple config-ini parsing" +optional = false +python-versions = ">=3.7" +files = [ + {file = "iniconfig-2.0.0-py3-none-any.whl", hash = "sha256:b6a85871a79d2e3b22d2d1b94ac2824226a63c6b741c88f7ae975f18b6778374"}, + {file = "iniconfig-2.0.0.tar.gz", hash = "sha256:2d91e135bf72d31a410b17c16da610a82cb55f6b0477d1a902134b24a455b8b3"}, +] + [[package]] name = "jinja2" version = "3.1.5" @@ -571,16 +516,26 @@ files = [ ] [[package]] -name = "nodeenv" -version = "1.9.1" -description = "Node.js virtual environment builder" +name = "nox" +version = "2024.10.9" +description = "Flexible test automation." optional = false -python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7" +python-versions = ">=3.8" files = [ - {file = "nodeenv-1.9.1-py2.py3-none-any.whl", hash = "sha256:ba11c9782d29c27c70ffbdda2d7415098754709be8a7056d79a737cd901155c9"}, - {file = "nodeenv-1.9.1.tar.gz", hash = "sha256:6ec12890a2dab7946721edbfbcd91f3319c6ccc9aec47be7c7e6b7011ee6645f"}, + {file = "nox-2024.10.9-py3-none-any.whl", hash = "sha256:1d36f309a0a2a853e9bccb76bbef6bb118ba92fa92674d15604ca99adeb29eab"}, + {file = "nox-2024.10.9.tar.gz", hash = "sha256:7aa9dc8d1c27e9f45ab046ffd1c3b2c4f7c91755304769df231308849ebded95"}, ] +[package.dependencies] +argcomplete = ">=1.9.4,<4" +colorlog = ">=2.6.1,<7" +packaging = ">=20.9" +virtualenv = ">=20.14.1" + +[package.extras] +tox-to-nox = ["jinja2", "tox"] +uv = ["uv (>=0.1.6)"] + [[package]] name = "packaging" version = "24.2" @@ -609,22 +564,19 @@ test = ["appdirs (==1.4.4)", "covdefaults (>=2.3)", "pytest (>=8.3.2)", "pytest- type = ["mypy (>=1.11.2)"] [[package]] -name = "pre-commit" -version = "4.0.1" -description = "A framework for managing and maintaining multi-language pre-commit hooks." +name = "pluggy" +version = "1.5.0" +description = "plugin and hook calling mechanisms for python" optional = false -python-versions = ">=3.9" +python-versions = ">=3.8" files = [ - {file = "pre_commit-4.0.1-py2.py3-none-any.whl", hash = "sha256:efde913840816312445dc98787724647c65473daefe420785f885e8ed9a06878"}, - {file = "pre_commit-4.0.1.tar.gz", hash = "sha256:80905ac375958c0444c65e9cebebd948b3cdb518f335a091a670a89d652139d2"}, + {file = "pluggy-1.5.0-py3-none-any.whl", hash = "sha256:44e1ad92c8ca002de6377e165f3e0f1be63266ab4d554740532335b9d75ea669"}, + {file = "pluggy-1.5.0.tar.gz", hash = "sha256:2cffa88e94fdc978c4c574f15f9e59b7f4201d439195c3715ca9e2486f1d0cf1"}, ] -[package.dependencies] -cfgv = ">=2.0.0" -identify = ">=1.0.0" -nodeenv = ">=0.11.1" -pyyaml = ">=5.1" -virtualenv = ">=20.10.0" +[package.extras] +dev = ["pre-commit", "tox"] +testing = ["pytest", "pytest-benchmark"] [[package]] name = "prompt-toolkit" @@ -641,150 +593,73 @@ files = [ wcwidth = "*" [[package]] -name = "pydantic" -version = "2.10.4" -description = "Data validation using Python type hints" +name = "pygments" +version = "2.18.0" +description = "Pygments is a syntax highlighting package written in Python." +optional = false +python-versions = ">=3.8" +files = [ + {file = "pygments-2.18.0-py3-none-any.whl", hash = "sha256:b8e6aca0523f3ab76fee51799c488e38782ac06eafcf95e7ba832985c8e7b13a"}, + {file = "pygments-2.18.0.tar.gz", hash = "sha256:786ff802f32e91311bff3889f6e9a86e81505fe99f2735bb6d60ae0c5004f199"}, +] + +[package.extras] +windows-terminal = ["colorama (>=0.4.6)"] + +[[package]] +name = "pytest" +version = "8.3.4" +description = "pytest: simple powerful testing with Python" optional = false python-versions = ">=3.8" files = [ - {file = "pydantic-2.10.4-py3-none-any.whl", hash = "sha256:597e135ea68be3a37552fb524bc7d0d66dcf93d395acd93a00682f1efcb8ee3d"}, - {file = "pydantic-2.10.4.tar.gz", hash = "sha256:82f12e9723da6de4fe2ba888b5971157b3be7ad914267dea8f05f82b28254f06"}, + {file = "pytest-8.3.4-py3-none-any.whl", hash = "sha256:50e16d954148559c9a74109af1eaf0c945ba2d8f30f0a3d3335edde19788b6f6"}, + {file = "pytest-8.3.4.tar.gz", hash = "sha256:965370d062bce11e73868e0335abac31b4d3de0e82f4007408d242b4f8610761"}, ] [package.dependencies] -annotated-types = ">=0.6.0" -pydantic-core = "2.27.2" -typing-extensions = ">=4.12.2" +colorama = {version = "*", markers = "sys_platform == \"win32\""} +iniconfig = "*" +packaging = "*" +pluggy = ">=1.5,<2" [package.extras] -email = ["email-validator (>=2.0.0)"] -timezone = ["tzdata"] +dev = ["argcomplete", "attrs (>=19.2)", "hypothesis (>=3.56)", "mock", "pygments (>=2.7.2)", "requests", "setuptools", "xmlschema"] [[package]] -name = "pydantic-core" -version = "2.27.2" -description = "Core functionality for Pydantic validation and serialization" +name = "pytest-cov" +version = "6.0.0" +description = "Pytest plugin for measuring coverage." optional = false -python-versions = ">=3.8" +python-versions = ">=3.9" files = [ - {file = "pydantic_core-2.27.2-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:2d367ca20b2f14095a8f4fa1210f5a7b78b8a20009ecced6b12818f455b1e9fa"}, - {file = "pydantic_core-2.27.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:491a2b73db93fab69731eaee494f320faa4e093dbed776be1a829c2eb222c34c"}, - {file = "pydantic_core-2.27.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7969e133a6f183be60e9f6f56bfae753585680f3b7307a8e555a948d443cc05a"}, - {file = "pydantic_core-2.27.2-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:3de9961f2a346257caf0aa508a4da705467f53778e9ef6fe744c038119737ef5"}, - {file = "pydantic_core-2.27.2-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e2bb4d3e5873c37bb3dd58714d4cd0b0e6238cebc4177ac8fe878f8b3aa8e74c"}, - {file = "pydantic_core-2.27.2-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:280d219beebb0752699480fe8f1dc61ab6615c2046d76b7ab7ee38858de0a4e7"}, - {file = "pydantic_core-2.27.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:47956ae78b6422cbd46f772f1746799cbb862de838fd8d1fbd34a82e05b0983a"}, - {file = "pydantic_core-2.27.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:14d4a5c49d2f009d62a2a7140d3064f686d17a5d1a268bc641954ba181880236"}, - {file = "pydantic_core-2.27.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:337b443af21d488716f8d0b6164de833e788aa6bd7e3a39c005febc1284f4962"}, - {file = "pydantic_core-2.27.2-cp310-cp310-musllinux_1_1_armv7l.whl", hash = "sha256:03d0f86ea3184a12f41a2d23f7ccb79cdb5a18e06993f8a45baa8dfec746f0e9"}, - {file = "pydantic_core-2.27.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:7041c36f5680c6e0f08d922aed302e98b3745d97fe1589db0a3eebf6624523af"}, - {file = "pydantic_core-2.27.2-cp310-cp310-win32.whl", hash = "sha256:50a68f3e3819077be2c98110c1f9dcb3817e93f267ba80a2c05bb4f8799e2ff4"}, - {file = "pydantic_core-2.27.2-cp310-cp310-win_amd64.whl", hash = "sha256:e0fd26b16394ead34a424eecf8a31a1f5137094cabe84a1bcb10fa6ba39d3d31"}, - {file = "pydantic_core-2.27.2-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:8e10c99ef58cfdf2a66fc15d66b16c4a04f62bca39db589ae8cba08bc55331bc"}, - {file = "pydantic_core-2.27.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:26f32e0adf166a84d0cb63be85c562ca8a6fa8de28e5f0d92250c6b7e9e2aff7"}, - {file = "pydantic_core-2.27.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8c19d1ea0673cd13cc2f872f6c9ab42acc4e4f492a7ca9d3795ce2b112dd7e15"}, - {file = "pydantic_core-2.27.2-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:5e68c4446fe0810e959cdff46ab0a41ce2f2c86d227d96dc3847af0ba7def306"}, - {file = "pydantic_core-2.27.2-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d9640b0059ff4f14d1f37321b94061c6db164fbe49b334b31643e0528d100d99"}, - {file = "pydantic_core-2.27.2-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:40d02e7d45c9f8af700f3452f329ead92da4c5f4317ca9b896de7ce7199ea459"}, - {file = "pydantic_core-2.27.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1c1fd185014191700554795c99b347d64f2bb637966c4cfc16998a0ca700d048"}, - {file = "pydantic_core-2.27.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:d81d2068e1c1228a565af076598f9e7451712700b673de8f502f0334f281387d"}, - {file = "pydantic_core-2.27.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:1a4207639fb02ec2dbb76227d7c751a20b1a6b4bc52850568e52260cae64ca3b"}, - {file = "pydantic_core-2.27.2-cp311-cp311-musllinux_1_1_armv7l.whl", hash = "sha256:3de3ce3c9ddc8bbd88f6e0e304dea0e66d843ec9de1b0042b0911c1663ffd474"}, - {file = "pydantic_core-2.27.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:30c5f68ded0c36466acede341551106821043e9afaad516adfb6e8fa80a4e6a6"}, - {file = "pydantic_core-2.27.2-cp311-cp311-win32.whl", hash = "sha256:c70c26d2c99f78b125a3459f8afe1aed4d9687c24fd677c6a4436bc042e50d6c"}, - {file = "pydantic_core-2.27.2-cp311-cp311-win_amd64.whl", hash = "sha256:08e125dbdc505fa69ca7d9c499639ab6407cfa909214d500897d02afb816e7cc"}, - {file = "pydantic_core-2.27.2-cp311-cp311-win_arm64.whl", hash = "sha256:26f0d68d4b235a2bae0c3fc585c585b4ecc51382db0e3ba402a22cbc440915e4"}, - {file = "pydantic_core-2.27.2-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:9e0c8cfefa0ef83b4da9588448b6d8d2a2bf1a53c3f1ae5fca39eb3061e2f0b0"}, - {file = "pydantic_core-2.27.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:83097677b8e3bd7eaa6775720ec8e0405f1575015a463285a92bfdfe254529ef"}, - {file = "pydantic_core-2.27.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:172fce187655fece0c90d90a678424b013f8fbb0ca8b036ac266749c09438cb7"}, - {file = "pydantic_core-2.27.2-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:519f29f5213271eeeeb3093f662ba2fd512b91c5f188f3bb7b27bc5973816934"}, - {file = "pydantic_core-2.27.2-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:05e3a55d124407fffba0dd6b0c0cd056d10e983ceb4e5dbd10dda135c31071d6"}, - {file = "pydantic_core-2.27.2-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9c3ed807c7b91de05e63930188f19e921d1fe90de6b4f5cd43ee7fcc3525cb8c"}, - {file = "pydantic_core-2.27.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6fb4aadc0b9a0c063206846d603b92030eb6f03069151a625667f982887153e2"}, - {file = "pydantic_core-2.27.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:28ccb213807e037460326424ceb8b5245acb88f32f3d2777427476e1b32c48c4"}, - {file = "pydantic_core-2.27.2-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:de3cd1899e2c279b140adde9357c4495ed9d47131b4a4eaff9052f23398076b3"}, - {file = "pydantic_core-2.27.2-cp312-cp312-musllinux_1_1_armv7l.whl", hash = "sha256:220f892729375e2d736b97d0e51466252ad84c51857d4d15f5e9692f9ef12be4"}, - {file = "pydantic_core-2.27.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:a0fcd29cd6b4e74fe8ddd2c90330fd8edf2e30cb52acda47f06dd615ae72da57"}, - {file = "pydantic_core-2.27.2-cp312-cp312-win32.whl", hash = "sha256:1e2cb691ed9834cd6a8be61228471d0a503731abfb42f82458ff27be7b2186fc"}, - {file = "pydantic_core-2.27.2-cp312-cp312-win_amd64.whl", hash = "sha256:cc3f1a99a4f4f9dd1de4fe0312c114e740b5ddead65bb4102884b384c15d8bc9"}, - {file = "pydantic_core-2.27.2-cp312-cp312-win_arm64.whl", hash = "sha256:3911ac9284cd8a1792d3cb26a2da18f3ca26c6908cc434a18f730dc0db7bfa3b"}, - {file = "pydantic_core-2.27.2-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:7d14bd329640e63852364c306f4d23eb744e0f8193148d4044dd3dacdaacbd8b"}, - {file = "pydantic_core-2.27.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:82f91663004eb8ed30ff478d77c4d1179b3563df6cdb15c0817cd1cdaf34d154"}, - {file = "pydantic_core-2.27.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:71b24c7d61131bb83df10cc7e687433609963a944ccf45190cfc21e0887b08c9"}, - {file = "pydantic_core-2.27.2-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:fa8e459d4954f608fa26116118bb67f56b93b209c39b008277ace29937453dc9"}, - {file = "pydantic_core-2.27.2-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ce8918cbebc8da707ba805b7fd0b382816858728ae7fe19a942080c24e5b7cd1"}, - {file = "pydantic_core-2.27.2-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:eda3f5c2a021bbc5d976107bb302e0131351c2ba54343f8a496dc8783d3d3a6a"}, - {file = "pydantic_core-2.27.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bd8086fa684c4775c27f03f062cbb9eaa6e17f064307e86b21b9e0abc9c0f02e"}, - {file = "pydantic_core-2.27.2-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:8d9b3388db186ba0c099a6d20f0604a44eabdeef1777ddd94786cdae158729e4"}, - {file = "pydantic_core-2.27.2-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:7a66efda2387de898c8f38c0cf7f14fca0b51a8ef0b24bfea5849f1b3c95af27"}, - {file = "pydantic_core-2.27.2-cp313-cp313-musllinux_1_1_armv7l.whl", hash = "sha256:18a101c168e4e092ab40dbc2503bdc0f62010e95d292b27827871dc85450d7ee"}, - {file = "pydantic_core-2.27.2-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:ba5dd002f88b78a4215ed2f8ddbdf85e8513382820ba15ad5ad8955ce0ca19a1"}, - {file = "pydantic_core-2.27.2-cp313-cp313-win32.whl", hash = "sha256:1ebaf1d0481914d004a573394f4be3a7616334be70261007e47c2a6fe7e50130"}, - {file = "pydantic_core-2.27.2-cp313-cp313-win_amd64.whl", hash = "sha256:953101387ecf2f5652883208769a79e48db18c6df442568a0b5ccd8c2723abee"}, - {file = "pydantic_core-2.27.2-cp313-cp313-win_arm64.whl", hash = "sha256:ac4dbfd1691affb8f48c2c13241a2e3b60ff23247cbcf981759c768b6633cf8b"}, - {file = "pydantic_core-2.27.2-cp38-cp38-macosx_10_12_x86_64.whl", hash = "sha256:d3e8d504bdd3f10835468f29008d72fc8359d95c9c415ce6e767203db6127506"}, - {file = "pydantic_core-2.27.2-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:521eb9b7f036c9b6187f0b47318ab0d7ca14bd87f776240b90b21c1f4f149320"}, - {file = "pydantic_core-2.27.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:85210c4d99a0114f5a9481b44560d7d1e35e32cc5634c656bc48e590b669b145"}, - {file = "pydantic_core-2.27.2-cp38-cp38-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:d716e2e30c6f140d7560ef1538953a5cd1a87264c737643d481f2779fc247fe1"}, - {file = "pydantic_core-2.27.2-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f66d89ba397d92f840f8654756196d93804278457b5fbede59598a1f9f90b228"}, - {file = "pydantic_core-2.27.2-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:669e193c1c576a58f132e3158f9dfa9662969edb1a250c54d8fa52590045f046"}, - {file = "pydantic_core-2.27.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9fdbe7629b996647b99c01b37f11170a57ae675375b14b8c13b8518b8320ced5"}, - {file = "pydantic_core-2.27.2-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:d262606bf386a5ba0b0af3b97f37c83d7011439e3dc1a9298f21efb292e42f1a"}, - {file = "pydantic_core-2.27.2-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:cabb9bcb7e0d97f74df8646f34fc76fbf793b7f6dc2438517d7a9e50eee4f14d"}, - {file = "pydantic_core-2.27.2-cp38-cp38-musllinux_1_1_armv7l.whl", hash = "sha256:d2d63f1215638d28221f664596b1ccb3944f6e25dd18cd3b86b0a4c408d5ebb9"}, - {file = "pydantic_core-2.27.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:bca101c00bff0adb45a833f8451b9105d9df18accb8743b08107d7ada14bd7da"}, - {file = "pydantic_core-2.27.2-cp38-cp38-win32.whl", hash = "sha256:f6f8e111843bbb0dee4cb6594cdc73e79b3329b526037ec242a3e49012495b3b"}, - {file = "pydantic_core-2.27.2-cp38-cp38-win_amd64.whl", hash = "sha256:fd1aea04935a508f62e0d0ef1f5ae968774a32afc306fb8545e06f5ff5cdf3ad"}, - {file = "pydantic_core-2.27.2-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:c10eb4f1659290b523af58fa7cffb452a61ad6ae5613404519aee4bfbf1df993"}, - {file = "pydantic_core-2.27.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:ef592d4bad47296fb11f96cd7dc898b92e795032b4894dfb4076cfccd43a9308"}, - {file = "pydantic_core-2.27.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c61709a844acc6bf0b7dce7daae75195a10aac96a596ea1b776996414791ede4"}, - {file = "pydantic_core-2.27.2-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:42c5f762659e47fdb7b16956c71598292f60a03aa92f8b6351504359dbdba6cf"}, - {file = "pydantic_core-2.27.2-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:4c9775e339e42e79ec99c441d9730fccf07414af63eac2f0e48e08fd38a64d76"}, - {file = "pydantic_core-2.27.2-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:57762139821c31847cfb2df63c12f725788bd9f04bc2fb392790959b8f70f118"}, - {file = "pydantic_core-2.27.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0d1e85068e818c73e048fe28cfc769040bb1f475524f4745a5dc621f75ac7630"}, - {file = "pydantic_core-2.27.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:097830ed52fd9e427942ff3b9bc17fab52913b2f50f2880dc4a5611446606a54"}, - {file = "pydantic_core-2.27.2-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:044a50963a614ecfae59bb1eaf7ea7efc4bc62f49ed594e18fa1e5d953c40e9f"}, - {file = "pydantic_core-2.27.2-cp39-cp39-musllinux_1_1_armv7l.whl", hash = "sha256:4e0b4220ba5b40d727c7f879eac379b822eee5d8fff418e9d3381ee45b3b0362"}, - {file = "pydantic_core-2.27.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:5e4f4bb20d75e9325cc9696c6802657b58bc1dbbe3022f32cc2b2b632c3fbb96"}, - {file = "pydantic_core-2.27.2-cp39-cp39-win32.whl", hash = "sha256:cca63613e90d001b9f2f9a9ceb276c308bfa2a43fafb75c8031c4f66039e8c6e"}, - {file = "pydantic_core-2.27.2-cp39-cp39-win_amd64.whl", hash = "sha256:77d1bca19b0f7021b3a982e6f903dcd5b2b06076def36a652e3907f596e29f67"}, - {file = "pydantic_core-2.27.2-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:2bf14caea37e91198329b828eae1618c068dfb8ef17bb33287a7ad4b61ac314e"}, - {file = "pydantic_core-2.27.2-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:b0cb791f5b45307caae8810c2023a184c74605ec3bcbb67d13846c28ff731ff8"}, - {file = "pydantic_core-2.27.2-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:688d3fd9fcb71f41c4c015c023d12a79d1c4c0732ec9eb35d96e3388a120dcf3"}, - {file = "pydantic_core-2.27.2-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3d591580c34f4d731592f0e9fe40f9cc1b430d297eecc70b962e93c5c668f15f"}, - {file = "pydantic_core-2.27.2-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:82f986faf4e644ffc189a7f1aafc86e46ef70372bb153e7001e8afccc6e54133"}, - {file = "pydantic_core-2.27.2-pp310-pypy310_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:bec317a27290e2537f922639cafd54990551725fc844249e64c523301d0822fc"}, - {file = "pydantic_core-2.27.2-pp310-pypy310_pp73-musllinux_1_1_armv7l.whl", hash = "sha256:0296abcb83a797db256b773f45773da397da75a08f5fcaef41f2044adec05f50"}, - {file = "pydantic_core-2.27.2-pp310-pypy310_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:0d75070718e369e452075a6017fbf187f788e17ed67a3abd47fa934d001863d9"}, - {file = "pydantic_core-2.27.2-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:7e17b560be3c98a8e3aa66ce828bdebb9e9ac6ad5466fba92eb74c4c95cb1151"}, - {file = "pydantic_core-2.27.2-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:c33939a82924da9ed65dab5a65d427205a73181d8098e79b6b426bdf8ad4e656"}, - {file = "pydantic_core-2.27.2-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:00bad2484fa6bda1e216e7345a798bd37c68fb2d97558edd584942aa41b7d278"}, - {file = "pydantic_core-2.27.2-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c817e2b40aba42bac6f457498dacabc568c3b7a986fc9ba7c8d9d260b71485fb"}, - {file = "pydantic_core-2.27.2-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:251136cdad0cb722e93732cb45ca5299fb56e1344a833640bf93b2803f8d1bfd"}, - {file = "pydantic_core-2.27.2-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:d2088237af596f0a524d3afc39ab3b036e8adb054ee57cbb1dcf8e09da5b29cc"}, - {file = "pydantic_core-2.27.2-pp39-pypy39_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:d4041c0b966a84b4ae7a09832eb691a35aec90910cd2dbe7a208de59be77965b"}, - {file = "pydantic_core-2.27.2-pp39-pypy39_pp73-musllinux_1_1_armv7l.whl", hash = "sha256:8083d4e875ebe0b864ffef72a4304827015cff328a1be6e22cc850753bfb122b"}, - {file = "pydantic_core-2.27.2-pp39-pypy39_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:f141ee28a0ad2123b6611b6ceff018039df17f32ada8b534e6aa039545a3efb2"}, - {file = "pydantic_core-2.27.2-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:7d0c8399fcc1848491f00e0314bd59fb34a9c008761bcb422a057670c3f65e35"}, - {file = "pydantic_core-2.27.2.tar.gz", hash = "sha256:eb026e5a4c1fee05726072337ff51d1efb6f59090b7da90d30ea58625b1ffb39"}, + {file = "pytest-cov-6.0.0.tar.gz", hash = "sha256:fde0b595ca248bb8e2d76f020b465f3b107c9632e6a1d1705f17834c89dcadc0"}, + {file = "pytest_cov-6.0.0-py3-none-any.whl", hash = "sha256:eee6f1b9e61008bd34975a4d5bab25801eb31898b032dd55addc93e96fcaaa35"}, ] [package.dependencies] -typing-extensions = ">=4.6.0,<4.7.0 || >4.7.0" +coverage = {version = ">=7.5", extras = ["toml"]} +pytest = ">=4.6" + +[package.extras] +testing = ["fields", "hunter", "process-tests", "pytest-xdist", "virtualenv"] [[package]] -name = "pygments" -version = "2.18.0" -description = "Pygments is a syntax highlighting package written in Python." +name = "pytest-mock" +version = "3.14.0" +description = "Thin-wrapper around the mock package for easier use with pytest" optional = false python-versions = ">=3.8" files = [ - {file = "pygments-2.18.0-py3-none-any.whl", hash = "sha256:b8e6aca0523f3ab76fee51799c488e38782ac06eafcf95e7ba832985c8e7b13a"}, - {file = "pygments-2.18.0.tar.gz", hash = "sha256:786ff802f32e91311bff3889f6e9a86e81505fe99f2735bb6d60ae0c5004f199"}, + {file = "pytest-mock-3.14.0.tar.gz", hash = "sha256:2719255a1efeceadbc056d6bf3df3d1c5015530fb40cf347c0f9afac88410bd0"}, + {file = "pytest_mock-3.14.0-py3-none-any.whl", hash = "sha256:0b72c38033392a5f4621342fe11e9219ac11ec9d375f8e2a0c164539e0d70f6f"}, ] +[package.dependencies] +pytest = ">=6.2.5" + [package.extras] -windows-terminal = ["colorama (>=0.4.6)"] +dev = ["pre-commit", "pytest-asyncio", "tox"] [[package]] name = "python-dateutil" @@ -970,17 +845,6 @@ files = [ {file = "six-1.17.0.tar.gz", hash = "sha256:ff70335d468e7eb6ec65b95b99d3a2836546063f63acc5171de367e834932a81"}, ] -[[package]] -name = "sniffio" -version = "1.3.1" -description = "Sniff out which async library your code is running under" -optional = false -python-versions = ">=3.7" -files = [ - {file = "sniffio-1.3.1-py3-none-any.whl", hash = "sha256:2f6da418d1f1e0fddd844478f41680e794e6051915791a034ff65e5f100525a2"}, - {file = "sniffio-1.3.1.tar.gz", hash = "sha256:f4324edc670a0f49750a81b895f35c3adb843cca46f0530f79fc1babb23789dc"}, -] - [[package]] name = "termcolor" version = "2.5.0" @@ -1028,17 +892,6 @@ files = [ {file = "types_python_dateutil-2.9.0.20241206.tar.gz", hash = "sha256:18f493414c26ffba692a72369fea7a154c502646301ebfe3d56a04b3767284cb"}, ] -[[package]] -name = "typing-extensions" -version = "4.12.2" -description = "Backported and Experimental Type Hints for Python 3.8+" -optional = false -python-versions = ">=3.8" -files = [ - {file = "typing_extensions-4.12.2-py3-none-any.whl", hash = "sha256:04e5ca0351e0f3f85c6853954072df659d0d13fac324d0072316b67d7794700d"}, - {file = "typing_extensions-4.12.2.tar.gz", hash = "sha256:1a7ead55c7e559dd4dee8856e3a88b41225abfe1ce8df57b7c13915fe121ffb8"}, -] - [[package]] name = "urllib3" version = "2.3.0" @@ -1090,4 +943,4 @@ files = [ [metadata] lock-version = "2.0" python-versions = "^3.12" -content-hash = "3eab762e7bb54c35e96285429be51a431ab863db33ee080872080e5df8a04415" +content-hash = "4b4dff4d64e2c3e0888dbc4241074869d7bd039351a5f7b3c60d407723a86ef6" diff --git a/pyproject.toml b/pyproject.toml index a9f59a0..adb5f69 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,8 +1,8 @@ [tool.poetry] name = "repo-scaffold" -version = "0.1.0" +version = "0.2.0" description = "shawn deng repo temple project" -authors = ["colyerdeng "] +authors = ["shawndeng "] license = "MIT" readme = "README.md" include = [ @@ -16,7 +16,10 @@ click = "^8.1.8" [tool.poetry.group.dev.dependencies] ruff = "^0.8.4" -pre-commit = "^4.0.1" +nox = "^2024.10.9" +pytest = "^8.3.4" +pytest-mock = "^3.14.0" +pytest-cov = "^6.0.0" commitizen = "^4.1.0" [tool.poetry.scripts] @@ -25,6 +28,7 @@ repo-scaffold = "repo_scaffold.cli:cli" [tool.ruff] line-length = 120 include = ["pyproject.toml", "repo_scaffold/*.py"] +exclude = ["template-python/**/*"] [tool.ruff.lint] select = [ diff --git a/repo_scaffold/cli.py b/repo_scaffold/cli.py index f36d598..3b3ed45 100644 --- a/repo_scaffold/cli.py +++ b/repo_scaffold/cli.py @@ -23,10 +23,9 @@ @click.group() def cli(): - """CLI tool for project creation. + """Repository scaffolding CLI tool. - This function serves as the main command group for the CLI application. - It groups all subcommands and provides the base entry point for the tool. + A tool for creating new projects from templates. """ ... @@ -35,25 +34,26 @@ def cli(): @click.option( "--template", "-t", - default="https://github.com/ShawnDen-coder/repo-template.git", + default="https://github.com/ShawnDen-coder/repo-scaffold.git", help="Cookiecutter template URL or path", ) @click.option("--output-dir", "-o", default=".", help="Where to output the generated project dir") @click.option("--local", "-l", is_flag=True, help="Use local template in ./template-python") def create(template, output_dir, local): - """Create a new project from a Cookiecutter template. - - Args: - template (str): URL or path to the cookiecutter template. - output_dir (str): Directory where the generated project will be created. - local (bool): Flag to use local template instead of remote. - - Returns: - None - - Example: - $ repo_scaffold create --template https://github.com/user/template.git - $ repo_scaffold create --local --output-dir ./projects + r"""Create a new project from template. + + \b + Usage: + repo-scaffold create [OPTIONS] + + \b + Examples: + $ repo-scaffold create + $ repo-scaffold create --local + $ repo-scaffold create -o ./my-projects + $ repo-scaffold create -t https://github.com/user/custom-template.git + $ repo-scaffold create -t ../path/to/local/template + $ repo-scaffold create -t gh:user/template-name """ if local: template = os.path.abspath(os.path.join(os.path.dirname(__file__), os.pardir)) diff --git a/repo_scaffold/utils.py b/repo_scaffold/utils.py deleted file mode 100644 index d7fdf4a..0000000 --- a/repo_scaffold/utils.py +++ /dev/null @@ -1,17 +0,0 @@ -"""Utility functions module for common operations. - -This module contains reusable utility functions that can be used across the application. -It provides helper methods, convenience functions, and shared functionality to promote -code reuse and maintainability. - -Typical usage example: - - from repo_scaffold.utils import validate_input, format_output - - cleaned_data = validate_input(raw_data) - result = format_output(cleaned_data) - -Note: - All utility functions should be stateless and follow single responsibility principle. - New utility functions should be well documented with type hints and docstrings. -""" diff --git a/template-python/{{cookiecutter.project_slug}}/.github/workflows/bumpversion.yaml b/template-python/{{cookiecutter.project_slug}}/.github/workflows/bump_version.yaml similarity index 51% rename from template-python/{{cookiecutter.project_slug}}/.github/workflows/bumpversion.yaml rename to template-python/{{cookiecutter.project_slug}}/.github/workflows/bump_version.yaml index bbc9c71..ee94982 100644 --- a/template-python/{{cookiecutter.project_slug}}/.github/workflows/bumpversion.yaml +++ b/template-python/{{cookiecutter.project_slug}}/.github/workflows/bump_version.yaml @@ -1,7 +1,7 @@ name: Bump version on: - pull_request: + push: branches: - master workflow_dispatch: @@ -12,13 +12,22 @@ jobs: runs-on: ubuntu-latest name: "Bump version and create changelog with commitizen" steps: + - name: Load secret + uses: 1password/load-secrets-action@v2 + with: + export-env: true + env: + OP_SERVICE_ACCOUNT_TOKEN: {% raw %}${{ secrets.OP_SERVICE_ACCOUNT_TOKEN }}{% endraw %} + PERSONAL_ACCESS_TOKEN: op://shawndengdev/github_access_token/credential + - name: Check out uses: actions/checkout@v4 with: fetch-depth: 0 - token: '${{ secrets.GITHUB_TOKEN }}' + token: '{% raw %}${{ env.PERSONAL_ACCESS_TOKEN }}{% endraw %}' + - name: Create bump and changelog uses: commitizen-tools/commitizen-action@master with: - github_token: ${{ secrets.GITHUB_TOKEN }} + github_token: {% raw %}${{ env.PERSONAL_ACCESS_TOKEN }}{% endraw %} branch: master diff --git a/template-python/{{cookiecutter.project_slug}}/.github/workflows/lint.yaml b/template-python/{{cookiecutter.project_slug}}/.github/workflows/lint.yaml new file mode 100644 index 0000000..94d565f --- /dev/null +++ b/template-python/{{cookiecutter.project_slug}}/.github/workflows/lint.yaml @@ -0,0 +1,40 @@ +name: lint_and_unittest + +on: [ push, pull_request ] + +jobs: + lint_and_unittest: + runs-on: ubuntu-latest + steps: + - name: Load secret + uses: 1password/load-secrets-action@v2 + with: + export-env: true + env: + OP_SERVICE_ACCOUNT_TOKEN: {% raw %}${{ secrets.OP_SERVICE_ACCOUNT_TOKEN }}{% endraw %} + PERSONAL_ACCESS_TOKEN: op://shawndengdev/github_access_token/credential + + - name: Check out + uses: actions/checkout@v4 + with: + fetch-depth: 0 + token: '{% raw %}${{ env.PERSONAL_ACCESS_TOKEN }}{% endraw %}' + + - uses: actions/setup-python@v5 + with: + python-version: "3.12" + + - uses: abatilo/actions-poetry@v2 + with: + poetry-version: "latest" + + - name: install depends + run: | + pip install nox + poetry install + + - name: Run lint checks + run: poetry run nox -s lint + + - name: Run tests + run: poetry run nox -s test diff --git a/template-python/{{cookiecutter.project_slug}}/.github/workflows/release-build.yaml b/template-python/{{cookiecutter.project_slug}}/.github/workflows/release-build.yaml deleted file mode 100644 index 82448c4..0000000 --- a/template-python/{{cookiecutter.project_slug}}/.github/workflows/release-build.yaml +++ /dev/null @@ -1,38 +0,0 @@ -name: release-build -on: - push: - tags: - - '*.*.*' - workflow_dispatch: - -jobs: - release-build: - runs-on: windows-latest - steps: - - uses: actions/checkout@v4 - - uses: actions/setup-python@v5 - with: - python-version: "3.12" - - uses: abatilo/actions-poetry@v2 - with: - poetry-version: "latest" - - - name: setup-pypi - run: | - poetry config pypi-token.pypi ${{ secrets.PYPI_TOKEN }} - poetry self add poetry-pyinstaller-plugin - poetry self add poetry-plugin-taskipy - - - name: build - run: poetry publish --build - - - name: Release - uses: softprops/action-gh-release@v2 - with: - files: | - dist/**/*.exe - dist/*.tar.gz - dist/*.whl - generate_release_notes: true - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/template-python/{{cookiecutter.project_slug}}/.github/workflows/release_build.yaml b/template-python/{{cookiecutter.project_slug}}/.github/workflows/release_build.yaml new file mode 100644 index 0000000..fa7a37f --- /dev/null +++ b/template-python/{{cookiecutter.project_slug}}/.github/workflows/release_build.yaml @@ -0,0 +1,54 @@ +name: release-build +on: + workflow_dispatch: + push: + tags: + - '*.*.*' + +jobs: + release-build: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - name: Load secret + uses: 1password/load-secrets-action@v2 + with: + export-env: true + env: + OP_SERVICE_ACCOUNT_TOKEN: {% raw %}${{ secrets.OP_SERVICE_ACCOUNT_TOKEN }}{% endraw %} + PERSONAL_ACCESS_TOKEN: op://shawndengdev/github_access_token/credential + PYPI_TOKEN: op://shawndengdev/pypi_token/credential + + - uses: actions/setup-python@v5 + with: + python-version: "3.12" + + - uses: abatilo/actions-poetry@v2 + with: + poetry-version: "latest" + + - name: Install nox + run: pip install nox + + - name: build and publish + run: | + poetry config pypi-token.pypi {% raw %}${{ env.PYPI_TOKEN }}{% endraw %} + poetry install + poetry run nox -s lint + poetry run nox -s test + {% if cookiecutter.include_cli == 'y' -%} + poetry run nox -s build_exe + {% endif -%} + poetry publish + + - name: Release + uses: softprops/action-gh-release@v2 + with: + files: | + dist/**/*.exe + dist/*.tar.gz + dist/*.whl + generate_release_notes: true + env: + GITHUB_TOKEN: {% raw %}${{ env.PERSONAL_ACCESS_TOKEN }}{% endraw %} diff --git a/template-python/{{cookiecutter.project_slug}}/.gitignore b/template-python/{{cookiecutter.project_slug}}/.gitignore new file mode 100644 index 0000000..2d9539c --- /dev/null +++ b/template-python/{{cookiecutter.project_slug}}/.gitignore @@ -0,0 +1,8 @@ +/.idea +# Coverage output +.coverage +/.nox/ +/build/ +/coverage.xml +/.zip/ +/venv/ \ No newline at end of file diff --git a/template-python/{{cookiecutter.project_slug}}/noxfile.py b/template-python/{{cookiecutter.project_slug}}/noxfile.py new file mode 100644 index 0000000..0279edc --- /dev/null +++ b/template-python/{{cookiecutter.project_slug}}/noxfile.py @@ -0,0 +1,96 @@ +"""Nox automation file for github-action-test project. + +This module contains nox sessions for automating development tasks including: +- Code linting and formatting +- Unit testing with coverage reporting +- Package building +- Executable creation + +Typical usage example: + nox -s lint # Run linting + nox -s test # Run tests + nox -s build # Build package + nox -s build_exe # Build package with standalone executable +""" +import nox + + +@nox.session(reuse_venv=True) +def lint(session: nox.Session) -> None: + """Run code quality checks using ruff. + + Performs linting and formatting checks on the codebase using ruff. + Fixes auto-fixable issues and shows formatting differences. + + Args: + session: Nox session object for running commands + """ + session.install("poetry") + session.install("ruff") + session.run("poetry", "install", "--only", "dev") + session.run( + "ruff", + "check", + ".", + "--fix", + "--verbose" + ) + session.run( + "ruff", + "format", + "--verbose", + "--diff" + ) + + +@nox.session(reuse_venv=True) +def test(session: nox.Session) -> None: + """Run the test suite with coverage reporting. + + Executes pytest with coverage reporting for the github_action_test package. + Generates both terminal and XML coverage reports. + + Args: + session: Nox session object for running commands + """ + session.install("poetry") + session.run("poetry", "install") + session.run( + "pytest", + "--cov={{cookiecutter.project_slug}}", + "--cov-report=term-missing", + "--cov-report=xml", + "-v", + "tests" + ) + + +@nox.session(reuse_venv=True) +def build(session: nox.Session) -> None: + """Build the Python package. + + Creates a distributable package using poetry build command + with verbose output and excluding dev dependencies. + + Args: + session: Nox session object for running commands + """ + session.install("poetry") + session.run("poetry", "install", "--without", "dev") + session.run("poetry", "build", "-vvv") + + +@nox.session(reuse_venv=True) +def build_exe(session: nox.Session) -> None: + """Build the Python package with standalone executable. + + Creates an executable using poetry-pyinstaller-plugin. + Installs required plugin and builds without dev dependencies. + + Args: + session: Nox session object for running commands + """ + session.install("poetry") + session.install("poetry", "self", "add", "poetry-pyinstaller-plugin") + session.run("poetry", "install", "--without", "dev") + session.run("poetry", "build", "-vvv") diff --git a/template-python/{{cookiecutter.project_slug}}/pyproject.toml b/template-python/{{cookiecutter.project_slug}}/pyproject.toml index 68de72a..7a729d1 100644 --- a/template-python/{{cookiecutter.project_slug}}/pyproject.toml +++ b/template-python/{{cookiecutter.project_slug}}/pyproject.toml @@ -4,7 +4,7 @@ version = "0.1.0" description = "shawn deng repo temple project" authors = ["{{cookiecutter.full_name}} <{{cookiecutter.email}}>"] license = "MIT" -readme = {file = "README.md", content-type = "text/markdown"} +readme = "README.md" [tool.poetry.dependencies] python = "^3.12" @@ -14,14 +14,12 @@ click = "^8.1.7" [tool.poetry.group.dev.dependencies] ruff = "^0.8.4" -pre-commit = "^4.0.1" +nox = "^2024.10.9" +pytest = "^8.3.4" +pytest-mock = "^3.14.0" +pytest-cov = "^6.0.0" commitizen = "^4.1.0" -[tool.poetry.group.test.dependencies] -pytest = "^8.0.0" -pytest-cov = "^4.1.0" -pytest-mock = "^3.12.0" - {% if cookiecutter.include_cli == 'y' %} [tool.poetry.scripts] {{cookiecutter.project_slug}} = "{{cookiecutter.project_slug}}.cli:cli" diff --git a/template-python/{{cookiecutter.project_slug}}/tests/__init__.py b/template-python/{{cookiecutter.project_slug}}/tests/__init__.py index e69de29..5df8916 100644 --- a/template-python/{{cookiecutter.project_slug}}/tests/__init__.py +++ b/template-python/{{cookiecutter.project_slug}}/tests/__init__.py @@ -0,0 +1 @@ +"""Test package for {{cookiecutter.project_slug}}.""" diff --git a/tests/__init__.py b/tests/__init__.py new file mode 100644 index 0000000..e0f36dd --- /dev/null +++ b/tests/__init__.py @@ -0,0 +1 @@ +"""Test package for github-action-test.""" diff --git a/tests/test_import.py b/tests/test_import.py new file mode 100644 index 0000000..a48524f --- /dev/null +++ b/tests/test_import.py @@ -0,0 +1,17 @@ +"""Import Test.""" + +import importlib +import pkgutil + +import repo_scaffold + +def test_imports(): + """Test import modules.""" + prefix = "{}.".format(repo_scaffold.__name__) # noqa + iter_packages = pkgutil.walk_packages( + repo_scaffold.__path__, # noqa + prefix, + ) + for _, name, _ in iter_packages: + module_name = name if name.startswith(prefix) else prefix + name + importlib.import_module(module_name) \ No newline at end of file