diff --git a/.cookiecutter.json b/.cookiecutter.json index e64afb6..0e8c1df 100644 --- a/.cookiecutter.json +++ b/.cookiecutter.json @@ -1,5 +1,5 @@ { - "_commit": "410906d2e116f1c177c9c873bb79d2809df08c75", + "_commit": "1460377e7f5ce48155c22f32b6845546d5097664", "_template": "C:\\Users\\56kyl\\source\\repos\\cookiecutter-robust-python", "add_rust_extension": false, "author": "Kyle Oliver", @@ -7,11 +7,13 @@ "development_status": "Development Status :: 1 - Planning", "email": "56kyleoliver+cookiecutter-robust-python@gmail.com", "friendly_name": "Robust Python Demo", - "github_user": "56kyle", "license": "MIT", "max_python_version": "3.13", "min_python_version": "3.9", "package_name": "robust_python_demo", "project_name": "robust-python-demo", + "repository_host": "github.com", + "repository_path": "56kyle/robust-python-demo", + "repository_provider": "github", "version": "0.0.0" } diff --git a/.cruft.json b/.cruft.json index 5fb2ec7..9603a77 100644 --- a/.cruft.json +++ b/.cruft.json @@ -1,6 +1,6 @@ { "template": "C:\\Users\\56kyl\\source\\repos\\cookiecutter-robust-python", - "commit": "410906d2e116f1c177c9c873bb79d2809df08c75", + "commit": "1460377e7f5ce48155c22f32b6845546d5097664", "checkout": null, "context": { "cookiecutter": { @@ -12,13 +12,15 @@ "add_rust_extension": false, "author": "Kyle Oliver", "email": "56kyleoliver+cookiecutter-robust-python@gmail.com", - "github_user": "56kyle", + "repository_provider": "github", + "repository_host": "github.com", + "repository_path": "56kyle/robust-python-demo", "version": "0.0.0", "copyright_year": "2025", "license": "MIT", "development_status": "Development Status :: 1 - Planning", "_template": "C:\\Users\\56kyl\\source\\repos\\cookiecutter-robust-python", - "_commit": "410906d2e116f1c177c9c873bb79d2809df08c75" + "_commit": "1460377e7f5ce48155c22f32b6845546d5097664" } }, "directory": null diff --git a/.github/workflows/lint-python.yml b/.github/workflows/lint-python.yml index 6acae86..eadd3e0 100644 --- a/.github/workflows/lint-python.yml +++ b/.github/workflows/lint-python.yml @@ -11,7 +11,6 @@ on: - "noxfile.py" - "pyproject.toml" - ".ruff.toml" - - ".pydocstyle" - ".github/workflows/lint-python.yml" push: branches: @@ -23,7 +22,6 @@ on: - "noxfile.py" - "pyproject.toml" - ".ruff.toml" - - ".pydocstyle" - ".github/workflows/lint-python.yml" workflow_dispatch: @@ -45,8 +43,5 @@ jobs: with: python-version-file: ".github/workflows/.python-version" - - name: Run formatting checks - run: uvx nox -s format-python - - - name: Run linting checks - run: uvx nox -s lint-python + - name: Run Python quality checks + run: uvx nox -t quality diff --git a/.github/workflows/security-python.yml b/.github/workflows/security-python.yml index f5aed7b..37db8d0 100644 --- a/.github/workflows/security-python.yml +++ b/.github/workflows/security-python.yml @@ -10,7 +10,7 @@ on: - "tests/**/*.py" - "noxfile.py" - "pyproject.toml" - - ".bandit" + - "bandit.yml" - ".ruff.toml" - ".github/workflows/security-python.yml" push: @@ -22,7 +22,7 @@ on: - "tests/**/*.py" - "noxfile.py" - "pyproject.toml" - - ".bandit" + - "bandit.yml" - ".ruff.toml" - ".github/workflows/security-python.yml" diff --git a/CHANGELOG.md b/CHANGELOG.md index 3c60b14..28c2dfc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,5 @@ +## v0.22.0 (2025-07-29) + ## v0.21.0 (2025-07-27) ## v0.20.0 (2025-07-27) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index f56f408..d78db7d 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,44 +1,205 @@ -# Contributing to cookiecutter-robust-python +# Contributing to robust-python-demo -Thank you for considering contributing to the `cookiecutter-robust-python` template! We welcome contributions that help improve the template, keep its tooling current, and enhance its documentation. +Thank you for your interest in contributing to `robust_python_demo`! We welcome bug reports, feature requests, and code contributions that help improve this project. -By participating in this project, you are expected to uphold our [Code of Conduct]. +By participating in this project, you are expected to uphold our [Code of Conduct][code-of-conduct]. ## How to Contribute -There are several ways to contribute: +### Reporting Bugs -1. **Reporting Bugs:** If you find an issue with the template itself (e.g., it doesn't generate correctly, the generated project's workflow doesn't work on a specific OS, a tool is misconfigured), please open an issue on the [issue tracker](https://github.com/56kyle/cookiecutter-robust-python/issues). Provide clear steps to reproduce the bug. -2. **Suggesting Enhancements:** Have an idea for a new feature, a different tool choice you think is better, or an improvement to the template structure or documentation? Open an issue on the [issue tracker](https://github.com/56kyle/cookiecutter-robust-python/issues) to discuss your suggestion. Clearly articulate the proposed change and the rationale behind it, ideally referencing the template's philosophy and criteria ([Template Philosophy](https://56kyle.github.io/cookiecutter-robust-python/philosophy.html), [Criteria for Tool Selection](https://56kyle.github.io/cookiecutter-robust-python/criteria.html)). -3. **Submitting Code Contributions:** Ready to contribute code (e.g., fix a bug, implement a suggested enhancement, update a tool version)? Please fork the repository and submit a Pull Request. +If you find a bug, please open an issue on our [issue tracker][issues] with: -## Setting Up Your Development Environment +- A clear description of the bug +- Steps to reproduce the issue +- Expected vs. actual behavior +- Your environment details (Python version, OS, etc.) +- Relevant error messages or logs -Refer to the **[Getting Started: Contributing to the Template](https://56kyle.github.io/cookiecutter-robust-python/getting-started-template-contributing.html)** section in the template documentation for instructions on cloning the repository, installing template development dependencies (using uv), setting up the template's pre-commit hooks, and running template checks/tests. +### Suggesting Features -## Contribution Workflow +For feature requests, please open an issue with: -1. **Fork** the repository and **clone** your fork. -2. Create a **new branch** for your contribution based on the main branch. Use a descriptive name (e.g., `fix/ci-workflow-on-windows`, `feat/update-uv-version`). -3. Set up your development environment following the [Getting Started](https://56kyle.github.io/cookiecutter-robust-python/getting-started-template-contributing.html) guide (clone, `uv sync`, `uvx nox -s pre-commit -- install`). -4. Make your **code or documentation changes**. -5. Ensure your changes adhere to the template's **code quality standards** (configured in the template's `.pre-commit-config.yaml`, `.ruff.toml`, etc.). The pre-commit hooks will help with this. Run `uvx nox -s lint`, `uvx nox -s check` in the template repository for more comprehensive checks. -6. Ensure your changes **do not break existing functionality**. Run the template's test suite: `uvx nox -s test`. Ideally, add tests for new functionality or bug fixes. -7. Ensure the **template documentation builds correctly** with your changes: `uvx nox -s docs`. -8. Write clear, concise **commit messages** following the [Conventional Commits](https://www.conventionalcommits.org/en/v1.0.0/) specification where possible, especially for significant changes (fixes, features, chore updates, etc.). -9. **Push** your branch to your fork. -10. **Open a Pull Request** from your branch to the main branch of the main template repository. Provide a clear description of your changes. Link to any relevant issues. +- A clear description of the proposed feature +- The problem it would solve or use case it would address +- Any relevant examples or mockups +- Consideration of potential alternatives -## Updating Tool Evaluations +### Contributing Code -If your contribution involves updating a major tool version or suggesting a different tool entirely, you **must** update the relevant sections in the template's documentation (`docs/topics/` files) to reflect the changes in configuration, behavior, or re-justify the choice based on the current state of the tools and criteria. This is crucial for keeping the documentation accurate and useful over time. +We welcome pull requests! For significant changes, it's best to open an issue first to discuss the approach. -## Communication +## Development Setup -For questions or discussion about contributions, open an issue or a discussion on the [GitHub repository](https://github.com/56kyle/cookiecutter-robust-python). +### Prerequisites ---- +- Python 3.9+ (this project supports Python 3.9-3.13) +- [uv][uv-documentation] for dependency management +- Git for version control + +### Setting Up Your Development Environment + +1. **Fork and clone the repository:** + ```bash + git clone https://github.com/56kyle/robust-python-demo.git + cd robust-python-demo + ``` + +2. **Install dependencies:** + ```bash + uv sync + ``` + +3. **Set up pre-commit hooks:** + ```bash + uvx nox -s pre-commit -- install + ``` + +4. **Verify your setup:** + ```bash + uvx nox -l # List available development tasks + ``` + +## Development Workflow + +### Making Changes + +1. **Create a feature branch:** + ```bash + git checkout -b feature/your-feature-name + # or + git checkout -b fix/your-bug-fix + ``` + +2. **Make your changes** following our coding standards (see below) + +3. **Test your changes:** + ```bash + # Run the full test suite + uvx nox -s tests-python + + # Run tests for a specific Python version + uvx nox -s tests-python-313 + + # Run a specific test file + uvx nox -s tests-python -- tests/unit_tests/test_specific.py + ``` + +4. **Check code quality:** + ```bash + # Format code + uvx nox -s format-python + + # Lint code + uvx nox -s lint-python + + # Type check + uvx nox -s typecheck + + # Security checks + uvx nox -s security-python + + # Or run all checks at once + uvx nox -t ci + ``` + +5. **Update documentation if needed:** + ```bash + # Build docs locally + uvx nox -s build-docs + ``` + +### Coding Standards + +This project follows these standards: - +- **Code formatting:** [Ruff][ruff-documentation] (automatically applied by pre-commit) +- **Linting:** Ruff with comprehensive rule set +- **Type checking:** [Pyright][pyright-documentation] +- **Security:** [Bandit][bandit-documentation] for security linting +- **Commit messages:** [Conventional Commits][conventional-commits] format preferred +- **Testing:** [pytest][pytest-documentation] with good coverage + +### Testing Guidelines + +- Write tests for new functionality in the appropriate test directory: + - `tests/unit_tests/` - Fast, isolated unit tests + - `tests/integration_tests/` - Tests that involve multiple components + - `tests/acceptance_tests/` - End-to-end behavior tests +- Aim for good test coverage (check with `uvx nox -s coverage`) +- Use descriptive test names and docstrings +- Mock external dependencies appropriately + +## Submitting Changes + +### Pull Request Process + +1. **Push your branch** to your fork +2. **Open a pull request** with: + - Clear title describing the change + - Description explaining what and why + - Link to any relevant issues + - Note any breaking changes + +3. **Ensure CI passes** - all automated checks must pass +4. **Respond to review feedback** if requested +5. **Squash commits** if requested before merge + +### Pull Request Guidelines + +- Keep changes focused and atomic +- Update documentation for user-facing changes +- Add tests for new functionality +- Follow the existing code style +- Ensure all CI checks pass + +## Development Tasks Reference + +Common Nox sessions for development: + +```bash +# Code quality +uvx nox -s format-python # Format with Ruff +uvx nox -s lint-python # Lint with Ruff +uvx nox -s typecheck # Type check with Pyright +uvx nox -s security-python # Security checks + +# Testing +uvx nox -s tests-python # Run full test suite +uvx nox -s coverage # Generate coverage report + +# Documentation +uvx nox -s build-docs # Build documentation + +# Building +uvx nox -s build-python # Build package + +# Run everything CI runs +uvx nox -t ci # All CI checks +``` + +## Getting Help + +- Check existing [issues][issues] and [discussions][discussions] +- Open a new issue for bugs or feature requests +- Start a discussion for questions or ideas + +## Recognition + +Contributors will be recognized in our release notes and documentation. Thank you for helping make this project better! + +--- -[code of conduct]: CODE_OF_CONDUCT.md +*This project was generated from the [cookiecutter-robust-python][cookiecutter-robust-python] template.* + + +[code-of-conduct]: CODE_OF_CONDUCT.md +[issues]: https://github.com/56kyle/robust-python-demo/issues +[discussions]: https://github.com/56kyle/robust-python-demo/discussions +[uv-documentation]: https://docs.astral.sh/uv/ +[ruff-documentation]: https://docs.astral.sh/ruff/ +[pyright-documentation]: https://github.com/microsoft/pyright +[bandit-documentation]: https://bandit.readthedocs.io/ +[conventional-commits]: https://www.conventionalcommits.org/ +[pytest-documentation]: https://docs.pytest.org/ +[cookiecutter-robust-python]: https://github.com/56kyle/cookiecutter-robust-python diff --git a/README.md b/README.md index 4c8e7d4..e74ee9a 100644 --- a/README.md +++ b/README.md @@ -59,7 +59,7 @@ If your project defines command-line entry points in `pyproject.toml`: # robust-python-demo do-something --input file.txt ``` -For detailed API documentation and CLI command references, see the **[Documentation](https://robust-python-demo.readthedocs.io/)**. +For detailed API documentation and CLI command references, see the **[Documentation][documentation]**. ## Development Workflow @@ -87,4 +87,9 @@ Distributed under the terms of the **MIT** license. See [LICENSE](LICENSE) for d --- -**This project was generated from the [cookiecutter-robust-python template](https://github.com/56kyle/cookiecutter-robust-python).** +**This project was generated from the [cookiecutter-robust-python template][cookiecutter-robust-python].** + + +[cookiecutter-robust-python]: https://github.com/56kyle/cookiecutter-robust-python + +[documentation]: https://robust-python-demo.readthedocs.io/ diff --git a/noxfile.py b/noxfile.py index fcf6aa8..09310bb 100644 --- a/noxfile.py +++ b/noxfile.py @@ -29,7 +29,8 @@ PROJECT_NAME: str = "robust-python-demo" PACKAGE_NAME: str = "robust_python_demo" -GITHUB_USER: str = "56kyle" +REPOSITORY_HOST: str = "github.com" +REPOSITORY_PATH: str = "56kyle/robust-python-demo" ENV: str = "env" FORMAT: str = "format" @@ -42,7 +43,7 @@ DOCS: str = "docs" BUILD: str = "build" RELEASE: str = "release" -CI: str = "ci" +QUALITY: str = "quality" PYTHON: str = "python" RUST: str = "rust" @@ -59,7 +60,16 @@ def setup_venv(session: Session) -> None: session.run("python", SCRIPTS_FOLDER / "setup-venv.py", REPO_ROOT, "-p", PYTHON_VERSIONS[0], external=True) -@nox.session(python=DEFAULT_PYTHON_VERSION, name="pre-commit", tags=[CI]) +@nox.session(python=False, name="setup-remote") +def setup_remote(session: Session) -> None: + """Set up the remote repository for the current project.""" + command: list[str] = [ + "python", SCRIPTS_FOLDER / "setup-remote.py", REPO_ROOT, "--host", REPOSITORY_HOST, "--path", REPOSITORY_PATH + ] + session.run(*command, external=True) + + +@nox.session(python=DEFAULT_PYTHON_VERSION, name="pre-commit", tags=[QUALITY]) def precommit(session: Session) -> None: """Lint using pre-commit.""" args: list[str] = session.posargs or ["run", "--all-files", "--show-diff-on-failure"] @@ -72,21 +82,21 @@ def precommit(session: Session) -> None: activate_virtualenv_in_precommit_hooks(session) -@nox.session(python=False, name="format-python", tags=[FORMAT, PYTHON]) +@nox.session(python=False, name="format-python", tags=[FORMAT, PYTHON, QUALITY]) def format_python(session: Session) -> None: """Run Python code formatter (Ruff format).""" session.log(f"Running Ruff formatter check with py{session.python}.") session.run("uvx", "ruff", "format", *session.posargs) -@nox.session(python=False, name="lint-python", tags=[LINT, PYTHON]) +@nox.session(python=False, name="lint-python", tags=[LINT, PYTHON, QUALITY]) def lint_python(session: Session) -> None: """Run Python code linters (Ruff check, Pydocstyle rules).""" session.log(f"Running Ruff check with py{session.python}.") session.run("uvx", "ruff", "check", "--fix", "--verbose") -@nox.session(python=PYTHON_VERSIONS, name="typecheck", tags=[TYPE, PYTHON, CI]) +@nox.session(python=PYTHON_VERSIONS, name="typecheck", tags=[TYPE, PYTHON]) def typecheck(session: Session) -> None: """Run static type checking (Pyright) on Python code.""" session.log("Installing type checking dependencies...") @@ -96,7 +106,7 @@ def typecheck(session: Session) -> None: session.run("pyright", "--pythonversion", session.python) -@nox.session(python=False, name="security-python", tags=[SECURITY, PYTHON, CI]) +@nox.session(python=False, name="security-python", tags=[SECURITY, PYTHON]) def security_python(session: Session) -> None: """Run code security checks (Bandit) on Python code.""" session.log(f"Running Bandit static security analysis with py{session.python}.") @@ -106,7 +116,7 @@ def security_python(session: Session) -> None: session.run("uvx", "pip-audit") -@nox.session(python=PYTHON_VERSIONS, name="tests-python", tags=[TEST, PYTHON, CI]) +@nox.session(python=PYTHON_VERSIONS, name="tests-python", tags=[TEST, PYTHON]) def tests_python(session: Session) -> None: """Run the Python test suite (pytest with coverage).""" session.log("Installing test dependencies...") diff --git a/pyproject.toml b/pyproject.toml index 73ae412..4b83aa7 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "robust-python-demo" -version = "0.21.0" +version = "0.22.0" description = "robust-python-demo" authors = [ { name = "Kyle Oliver", email = "56kyleoliver+cookiecutter-robust-python@gmail.com" }, diff --git a/scripts/setup-remote.py b/scripts/setup-remote.py index c77fe43..06b5056 100644 --- a/scripts/setup-remote.py +++ b/scripts/setup-remote.py @@ -15,15 +15,15 @@ def main() -> None: """Parses command line input and passes it through to setup_git.""" parser: argparse.ArgumentParser = get_parser() args: argparse.Namespace = parser.parse_args() - setup_remote(path=args.path, github_user=args.github_user, repo_name=args.repo_name) + setup_remote(path=args.path, repository_host=args.repository_host, repository_path=args.repository_path) -def setup_remote(path: Path, github_user: str, repo_name: str) -> None: +def setup_remote(path: Path, repository_host: str, repository_path: str) -> None: """Set up the provided cookiecutter-robust-python project's git repo.""" commands: list[list[str]] = [ ["git", "fetch", "origin"], - ["git", "remote", "add", "origin", f"https://github.com/{github_user}/{repo_name}.git"], - ["git", "remote", "set-url", "origin", f"https://github.com/{github_user}/{repo_name}.git"], + ["git", "remote", "add", "origin", f"https://{repository_host}/{repository_path}.git"], + ["git", "remote", "set-url", "origin", f"https://{repository_host}/{repository_path}.git"], ["git", "pull"], ["git", "checkout", "main"], ["git", "push", "-u", "origin", "main"], @@ -40,7 +40,7 @@ def get_parser() -> argparse.ArgumentParser: """Creates the argument parser for setup-git.""" parser: argparse.ArgumentParser = argparse.ArgumentParser( prog="setup-git", - usage="python ./scripts/setup-remote.py . -u 56kyle -n robust-python-demo", + usage="python ./scripts/setup-remote.py . -h github.com -p 56kyle/robust-python-demo", description="Set up the provided cookiecutter-robust-python project's remote repo connection.", ) parser.add_argument( @@ -49,8 +49,8 @@ def get_parser() -> argparse.ArgumentParser: metavar="PATH", help="Path to the repo's root directory (must already exist).", ) - parser.add_argument("-u", "--user", dest="github_user", help="GitHub user name.") - parser.add_argument("-n", "--name", dest="repo_name", help="Name of the repo.") + parser.add_argument("-h", "--host", dest="repository_host", help="Repository host (e.g., github.com, gitlab.com).") + parser.add_argument("-p", "--path", dest="repository_path", help="Repository path (e.g., user/repo, group/subgroup/repo).") return parser diff --git a/uv.lock b/uv.lock index 3ebfaa2..4679448 100644 --- a/uv.lock +++ b/uv.lock @@ -1092,7 +1092,7 @@ wheels = [ [[package]] name = "robust-python-demo" -version = "0.21.0" +version = "0.22.0" source = { editable = "." } dependencies = [ { name = "loguru" },