diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 0000000..5ace460 --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,6 @@ +version: 2 +updates: + - package-ecosystem: "github-actions" + directory: "/" + schedule: + interval: "weekly" diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml new file mode 100644 index 0000000..b4a2cc5 --- /dev/null +++ b/.github/workflows/release.yaml @@ -0,0 +1,42 @@ +on: + push: + branches: + - master + tags: + - "v*" + pull_request: +name: Build and release to pypi +jobs: + release-build: + name: Build and upload distributions + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - name: Set up uv + run: curl -LsSf https://astral.sh/uv/install.sh | sh + - name: Build dist + run: uv tool run --with build[uv] --from build python -m build --installer uv + - name: Upload release distributions + uses: actions/upload-artifact@v4 + with: + name: release-dists + path: dist/ + pypi-publish: + name: Release to pypi + runs-on: ubuntu-latest + environment: + name: pypi_publish + url: https://pypi.org/p/python-template + if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags/v') + needs: + - release-build + permissions: + id-token: write + steps: + - name: Retrieve release distributions + uses: actions/download-artifact@v4 + with: + name: release-dists + path: dist/ + - name: Publish release distributions to PyPI + uses: pypa/gh-action-pypi-publish@release/v1 diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml new file mode 100644 index 0000000..72ba3fa --- /dev/null +++ b/.github/workflows/test.yaml @@ -0,0 +1,43 @@ +name: Test Python package + +on: + push: + branches: + - master + pull_request: + +env: + UV_SYSTEM_PYTHON: 1 + # Configure a constant location for the uv cache + UV_CACHE_DIR: /tmp/.uv-cache +jobs: + build: + runs-on: ubuntu-latest + permissions: + id-token: write + steps: + - uses: actions/checkout@v4 + - name: Set up uv + run: curl -LsSf https://astral.sh/uv/install.sh | sh + - name: Set up Python + uses: actions/setup-python@v5 + with: + python-version: 3.12 + - name: Restore uv cache + uses: actions/cache@v4 + with: + path: ${{ env.UV_CACHE_DIR }} + key: uv-${{ runner.os }}-${{ hashFiles('pyproject.toml') }} + restore-keys: | + uv-${{ runner.os }}-${{ hashFiles('pyproject.toml') }} + uv-${{ runner.os }} + - name: Install dependencies + run: uv pip install nox[uv] + - name: Test with pytest + run: nox -db uv + - name: Upload coverage reports to Codecov + uses: codecov/codecov-action@v4 + with: + use_oidc: true + - name: Minimize uv cache + run: uv cache prune --ci diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..b0c9139 --- /dev/null +++ b/.gitignore @@ -0,0 +1,164 @@ +# Byte-compiled / optimized / DLL files +__pycache__/ +*.py[cod] +*$py.class + +# C extensions +*.so + +# Distribution / packaging +.Python +build/ +develop-eggs/ +dist/ +downloads/ +eggs/ +.eggs/ +lib/ +lib64/ +parts/ +sdist/ +var/ +wheels/ +share/python-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 +*.py,cover +.hypothesis/ +.pytest_cache/ +cover/ + +# Translations +*.mo +*.pot + +# Django stuff: +*.log +local_settings.py +db.sqlite3 +db.sqlite3-journal + +# Flask stuff: +instance/ +.webassets-cache + +# Scrapy stuff: +.scrapy + +# Sphinx documentation +docs/_build/ + +# PyBuilder +.pybuilder/ +target/ + +# Jupyter Notebook +.ipynb_checkpoints + +# IPython +profile_default/ +ipython_config.py + +# pyenv +# For a library or package, you might want to ignore these files since the code is +# intended to run in multiple environments; otherwise, check them in: +# .python-version + +# pipenv +# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. +# However, in case of collaboration, if having platform-specific dependencies or dependencies +# having no cross-platform support, pipenv may install dependencies that don't work, or not +# install all needed dependencies. +#Pipfile.lock + +# poetry +# Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control. +# This is especially recommended for binary packages to ensure reproducibility, and is more +# commonly ignored for libraries. +# https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control +#poetry.lock + +# pdm +# Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control. +#pdm.lock +# pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it +# in version control. +# https://pdm.fming.dev/latest/usage/project/#working-with-version-control +.pdm.toml +.pdm-python +.pdm-build/ + +# PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm +__pypackages__/ + +# Celery stuff +celerybeat-schedule +celerybeat.pid + +# 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/ + +# pytype static type analyzer +.pytype/ + +# Cython debug symbols +cython_debug/ + +# PyCharm +# JetBrains specific template is maintained in a separate JetBrains.gitignore that can +# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore +# and can be added to the global gitignore or merged into this file. For a more nuclear +# option (not recommended) you can uncomment the following to ignore the entire idea folder. +#.idea/ +.ruff_cache/ +node_modules/ diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml new file mode 100644 index 0000000..ded8f46 --- /dev/null +++ b/.pre-commit-config.yaml @@ -0,0 +1,37 @@ +# See https://pre-commit.com for more information +# See https://pre-commit.com/hooks.html for more hooks +repos: + - repo: https://github.com/pre-commit/pre-commit-hooks + rev: v4.6.0 + hooks: + - id: trailing-whitespace + - id: end-of-file-fixer + - id: check-yaml + - id: check-json + - id: check-added-large-files + - id: check-merge-conflict + - id: check-symlinks + - id: check-toml + - id: mixed-line-ending + # Python + - repo: https://github.com/astral-sh/ruff-pre-commit + rev: v0.5.7 + hooks: + - id: ruff + args: ["--fix"] + - id: ruff-format + - repo: https://github.com/pre-commit/mirrors-mypy + rev: "v1.11.1" + hooks: + - id: mypy + additional_dependencies: [] + - repo: https://github.com/pre-commit/mirrors-prettier + rev: v4.0.0-alpha.8 + hooks: + - id: prettier + types_or: [javascript, css, html, markdown, json, yaml] + - repo: https://github.com/abravalheri/validate-pyproject + rev: v0.19 + hooks: + - id: validate-pyproject + additional_dependencies: ["validate-pyproject-schema-store[all]"] diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..0a04128 --- /dev/null +++ b/LICENSE @@ -0,0 +1,165 @@ + GNU LESSER GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + + This version of the GNU Lesser General Public License incorporates +the terms and conditions of version 3 of the GNU General Public +License, supplemented by the additional permissions listed below. + + 0. Additional Definitions. + + As used herein, "this License" refers to version 3 of the GNU Lesser +General Public License, and the "GNU GPL" refers to version 3 of the GNU +General Public License. + + "The Library" refers to a covered work governed by this License, +other than an Application or a Combined Work as defined below. + + An "Application" is any work that makes use of an interface provided +by the Library, but which is not otherwise based on the Library. +Defining a subclass of a class defined by the Library is deemed a mode +of using an interface provided by the Library. + + A "Combined Work" is a work produced by combining or linking an +Application with the Library. The particular version of the Library +with which the Combined Work was made is also called the "Linked +Version". + + The "Minimal Corresponding Source" for a Combined Work means the +Corresponding Source for the Combined Work, excluding any source code +for portions of the Combined Work that, considered in isolation, are +based on the Application, and not on the Linked Version. + + The "Corresponding Application Code" for a Combined Work means the +object code and/or source code for the Application, including any data +and utility programs needed for reproducing the Combined Work from the +Application, but excluding the System Libraries of the Combined Work. + + 1. Exception to Section 3 of the GNU GPL. + + You may convey a covered work under sections 3 and 4 of this License +without being bound by section 3 of the GNU GPL. + + 2. Conveying Modified Versions. + + If you modify a copy of the Library, and, in your modifications, a +facility refers to a function or data to be supplied by an Application +that uses the facility (other than as an argument passed when the +facility is invoked), then you may convey a copy of the modified +version: + + a) under this License, provided that you make a good faith effort to + ensure that, in the event an Application does not supply the + function or data, the facility still operates, and performs + whatever part of its purpose remains meaningful, or + + b) under the GNU GPL, with none of the additional permissions of + this License applicable to that copy. + + 3. Object Code Incorporating Material from Library Header Files. + + The object code form of an Application may incorporate material from +a header file that is part of the Library. You may convey such object +code under terms of your choice, provided that, if the incorporated +material is not limited to numerical parameters, data structure +layouts and accessors, or small macros, inline functions and templates +(ten or fewer lines in length), you do both of the following: + + a) Give prominent notice with each copy of the object code that the + Library is used in it and that the Library and its use are + covered by this License. + + b) Accompany the object code with a copy of the GNU GPL and this license + document. + + 4. Combined Works. + + You may convey a Combined Work under terms of your choice that, +taken together, effectively do not restrict modification of the +portions of the Library contained in the Combined Work and reverse +engineering for debugging such modifications, if you also do each of +the following: + + a) Give prominent notice with each copy of the Combined Work that + the Library is used in it and that the Library and its use are + covered by this License. + + b) Accompany the Combined Work with a copy of the GNU GPL and this license + document. + + c) For a Combined Work that displays copyright notices during + execution, include the copyright notice for the Library among + these notices, as well as a reference directing the user to the + copies of the GNU GPL and this license document. + + d) Do one of the following: + + 0) Convey the Minimal Corresponding Source under the terms of this + License, and the Corresponding Application Code in a form + suitable for, and under terms that permit, the user to + recombine or relink the Application with a modified version of + the Linked Version to produce a modified Combined Work, in the + manner specified by section 6 of the GNU GPL for conveying + Corresponding Source. + + 1) Use a suitable shared library mechanism for linking with the + Library. A suitable mechanism is one that (a) uses at run time + a copy of the Library already present on the user's computer + system, and (b) will operate properly with a modified version + of the Library that is interface-compatible with the Linked + Version. + + e) Provide Installation Information, but only if you would otherwise + be required to provide such information under section 6 of the + GNU GPL, and only to the extent that such information is + necessary to install and execute a modified version of the + Combined Work produced by recombining or relinking the + Application with a modified version of the Linked Version. (If + you use option 4d0, the Installation Information must accompany + the Minimal Corresponding Source and Corresponding Application + Code. If you use option 4d1, you must provide the Installation + Information in the manner specified by section 6 of the GNU GPL + for conveying Corresponding Source.) + + 5. Combined Libraries. + + You may place library facilities that are a work based on the +Library side by side in a single library together with other library +facilities that are not Applications and are not covered by this +License, and convey such a combined library under terms of your +choice, if you do both of the following: + + a) Accompany the combined library with a copy of the same work based + on the Library, uncombined with any other library facilities, + conveyed under the terms of this License. + + b) Give prominent notice with the combined library that part of it + is a work based on the Library, and explaining where to find the + accompanying uncombined form of the same work. + + 6. Revised Versions of the GNU Lesser General Public License. + + The Free Software Foundation may publish revised and/or new versions +of the GNU Lesser General Public License from time to time. Such new +versions will be similar in spirit to the present version, but may +differ in detail to address new problems or concerns. + + Each version is given a distinguishing version number. If the +Library as you received it specifies that a certain numbered version +of the GNU Lesser General Public License "or any later version" +applies to it, you have the option of following the terms and +conditions either of that published version or of any later version +published by the Free Software Foundation. If the Library as you +received it does not specify a version number of the GNU Lesser +General Public License, you may choose any version of the GNU Lesser +General Public License ever published by the Free Software Foundation. + + If the Library as you received it specifies that a proxy can decide +whether future versions of the GNU Lesser General Public License shall +apply, that proxy's public statement of acceptance of any version is +permanent authorization for you to choose that version for the +Library. diff --git a/README.md b/README.md new file mode 100644 index 0000000..52e1501 --- /dev/null +++ b/README.md @@ -0,0 +1,5 @@ +# Python template + + + +`python-template` is a template to start a new Python project quickly. diff --git a/noxfile.py b/noxfile.py new file mode 100644 index 0000000..3350e04 --- /dev/null +++ b/noxfile.py @@ -0,0 +1,21 @@ +"""Nox configuration file.""" + +from __future__ import annotations + +import nox + + +@nox.session +def tests(session: nox.Session) -> None: + """Run test suite with pytest.""" + session.install("-e.[test]") + session.run( + "pytest", + "--cov", + "--cov-config", + "pyproject.toml", + "--cov-report", + "term", + "--cov-report", + "xml", + ) diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 0000000..deb1a84 --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,71 @@ +[build-system] +requires = [ + "setuptools>=61", + "setuptools_scm[toml]>=7", +] +build-backend = "setuptools.build_meta" + +[project] +name = "python-template" # Please revise this line. +dynamic = ["version"] +description = "A Python template." # Please revise this line. +authors = [ + { name = "Jinzhe Zeng", email = "jinzhe.zeng@rutgers.edu"}, +] +license = { file = "LICENSE" } +classifiers = [ + "Programming Language :: Python :: 3.9", + "Programming Language :: Python :: 3.10", + "Programming Language :: Python :: 3.11", + "Programming Language :: Python :: 3.12", + "Operating System :: POSIX :: Linux", + "Operating System :: MacOS :: MacOS X", + "Operating System :: Microsoft :: Windows", + "License :: OSI Approved :: GNU Lesser General Public License v3 (LGPLv3)", +] +dependencies = [ +] +requires-python = ">=3.9" +readme = "README.md" +keywords = [ +] + +[project.scripts] + +[project.urls] +repository = "https://github.com/njzjz/python-template" # Please revise this line. + +[project.optional-dependencies] +test = [ + 'pytest', + 'pytest-cov', +] + +[tool.setuptools.packages.find] +include = ["python_template*"] # Please revise this line. + +[tool.setuptools_scm] +version_file = "python_template/_version.py" # Please revise this line. + +[tool.ruff.lint] +select = [ + "ALL", +] +ignore = [ +] + +[tool.ruff.lint.pydocstyle] +convention = "numpy" + +[tool.ruff.lint.isort] +required-imports = [ + "from __future__ import annotations", +] + +[tool.ruff.lint.extend-per-file-ignores] +"tests/**/*.py" = [ + "S101", # asserts allowed in tests... +] + +[tool.coverage.report] +include = ["python_template/*"] # Please revise this line. diff --git a/python_template/__init__.py b/python_template/__init__.py new file mode 100644 index 0000000..12b1796 --- /dev/null +++ b/python_template/__init__.py @@ -0,0 +1,11 @@ +"""A Python template (please revise this docstring).""" + +from __future__ import annotations + +from ._version import __version__ + +__email__ = "jinzhe.zeng@rutgers.edu" + +__all__ = [ + "__version__", +] diff --git a/python_template/__main__.py b/python_template/__main__.py new file mode 100644 index 0000000..bcad6d9 --- /dev/null +++ b/python_template/__main__.py @@ -0,0 +1,7 @@ +"""Main entry point for the command line interface.""" + +from __future__ import annotations + +if __name__ == "__main__": + msg = "This module is not meant to be executed directly." + raise NotImplementedError(msg) diff --git a/python_template/py.typed b/python_template/py.typed new file mode 100644 index 0000000..e69de29 diff --git a/renovate.json b/renovate.json new file mode 100644 index 0000000..4bf8589 --- /dev/null +++ b/renovate.json @@ -0,0 +1,4 @@ +{ + "$schema": "https://docs.renovatebot.com/renovate-schema.json", + "extends": ["local>njzjz/renovate-config"] +} diff --git a/tests/__init__.py b/tests/__init__.py new file mode 100644 index 0000000..d420712 --- /dev/null +++ b/tests/__init__.py @@ -0,0 +1 @@ +"""Tests.""" diff --git a/tests/test_version.py b/tests/test_version.py new file mode 100644 index 0000000..80d94de --- /dev/null +++ b/tests/test_version.py @@ -0,0 +1,12 @@ +"""Test version.""" + +from __future__ import annotations + +from importlib.metadata import version + +from python_template import __version__ + + +def test_version() -> None: + """Test version.""" + assert version("python-template") == __version__