diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md new file mode 100644 index 0000000..4d5380c --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -0,0 +1,32 @@ +--- +name: Bug report +about: Create a report to help us improve. +title: '' +labels: '' +assignees: '' + +--- + +## Describe the bug +A clear and concise description of what the bug is. + +## To Reproduce +Steps to reproduce the behavior: +1. Go to '...' +2. Click on '....' +3. Scroll down to '....' +4. See error + +## Expected behavior +A clear and concise description of what you expected to happen. + +## Screenshots +If applicable, add screenshots to help explain your problem. + +## Environment (please complete the following information): + - OS: [e.g. iOS] + - Python Version: [e.g. 3.12, 3.11, etc.] + - PythonProjectBootstrapper Version [e.g. 1.2.3] + +## Additional context +Add any other context about the problem here. diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml new file mode 100644 index 0000000..ac2e8b4 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -0,0 +1 @@ +blank_issues_enabled: false diff --git a/.github/ISSUE_TEMPLATE/custom.md b/.github/ISSUE_TEMPLATE/custom.md new file mode 100644 index 0000000..a8cf75b --- /dev/null +++ b/.github/ISSUE_TEMPLATE/custom.md @@ -0,0 +1,8 @@ +--- +name: Custom issue template +about: Create an issue that isn't a bug or feature request. +title: '' +labels: '' +assignees: '' + +--- diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md new file mode 100644 index 0000000..fb1765f --- /dev/null +++ b/.github/ISSUE_TEMPLATE/feature_request.md @@ -0,0 +1,20 @@ +--- +name: Feature request +about: Suggest an idea for this PythonProjectBootstrapper. +title: '' +labels: '' +assignees: '' + +--- + +## Is your feature request related to a problem? Please describe. +A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] + +## Describe the solution you'd like +A clear and concise description of what you want to happen. + +## Describe alternatives you've considered +A clear and concise description of any alternative solutions or features you've considered. + +## Additional context +Add any other context or screenshots about the feature request here. diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md new file mode 100644 index 0000000..f26ff1f --- /dev/null +++ b/.github/pull_request_template.md @@ -0,0 +1,8 @@ +## :pencil: Description +Please include a summary of the change and the work item associated with it. + +## :gear: Work Item +Please include link to the corresponding GitHub Issue or Project work item. + +## :movie_camera: Demo +Please provide any images, GIFs, or videos that show the effect of your changes (if applicable). A picture is worth a thousand words. diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index 736f635..82dd2bf 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -17,7 +17,7 @@ on: pull_request: branches: [ "main" ] schedule: - - cron: '32 17 * * 0' + - cron: '0 0 * * *' workflow_dispatch: permissions: {} diff --git a/.github/workflows/standard.yaml b/.github/workflows/standard.yaml index 2fc2eee..18167ac 100644 --- a/.github/workflows/standard.yaml +++ b/.github/workflows/standard.yaml @@ -1,8 +1,8 @@ # ---------------------------------------------------------------------- -# -# Copyright (c) 2024 Scientific Software Engineering Center at Georgia Tech -# Distributed under the MIT License. -# +# | +# | Copyright (c) 2024 Scientific Software Engineering Center at Georgia Tech +# | Distributed under the MIT License. +# | # ---------------------------------------------------------------------- name: "Standard" @@ -183,7 +183,9 @@ jobs: with: operating_system: ${{ matrix.os }} python_version: ${{ matrix.python_version }} - validation_command: PythonProjectBootstrapper package this_value_is_ignored --version + validation_command: PythonProjectBootstrapper package --version + + # ---------------------------------------------------------------------- publish: @@ -191,6 +193,7 @@ jobs: - validate_package - validate_binary + name: Publish permissions: @@ -201,3 +204,5 @@ jobs: release_sources_configuration_filename: .github/release_sources.yaml secrets: PYPI_TOKEN: ${{ secrets.PYPI_TOKEN }} + + MINISIGN_PRIVATE_KEY: ${{ secrets.MINISIGN_PRIVATE_KEY }} diff --git a/.python_project_bootstrapper_config.yml b/.python_project_bootstrapper_config.yml new file mode 100644 index 0000000..b248747 --- /dev/null +++ b/.python_project_bootstrapper_config.yml @@ -0,0 +1,22 @@ +############################################################################################################# +# This file is used by PythonProjectBootstrapper (https://github.com/gt-sse-center/PythonProjectBootstrapper) +# to rerun generation on this python package. To use this file, run the following command from within this +# working directory: +# +# PythonProjectBootstrapper package . --configuration .python_project_bootstrapper_config.yml +# +############################################################################################################# +default_context: + name: Scientific Software Engineering Center at Georgia Tech + email: sse-center@gatech.edu + project_description: Tool that helps in the creation of python projects. + license: MIT + github_url: https://github.com + github_username: gt-sse-center + github_project_name: PythonProjectBootstrapper + pypi_project_name: PythonProjectBootstrapper + gist_id: 2f9d770d13e3a148424f374f74d41f4b + gist_username: davidbrownell + minisign_public_key: RWRkzrG0tznlEpemQ9U4aCQU/TO1TXipqycs7G9pRrm/9ab9HBcV/EIf + openssf_best_practices_badge_id: 9132 + create_docker_image: False diff --git a/.python_project_bootstrapper_manifest.yml b/.python_project_bootstrapper_manifest.yml new file mode 100644 index 0000000..10637cd --- /dev/null +++ b/.python_project_bootstrapper_manifest.yml @@ -0,0 +1,38 @@ +############################################################################################################# +# This file is used by PythonProjectBootstrapper (https://github.com/gt-sse-center/PythonProjectBootstrapper) +# to determine whether changes have been made to any files in the project. These values are saved in case the +# project is regenerated so we can avoid overwriting any user changes. Please do not change the contents :) +############################################################################################################# + +.github/CODEOWNERS: 42bdd9797e12e16d0fe3e10f798da519189b41eeca25da34ce3bab44cb04aa68 +.github/ISSUE_TEMPLATE/bug_report.md: 0d0cac487c4b348cf88f29e0a7e446aff6e3b1f3fd8c3fc791312069f0939c43 +.github/ISSUE_TEMPLATE/config.yml: d6d81427cbfd6fb2c87462698c241fd6c31e47025c137498e50b8a01b228cb95 +.github/ISSUE_TEMPLATE/custom.md: 14e93edcf3acd7351957a11551565a3d03317eb9246a46bbbd9e01b8f28cf843 +.github/ISSUE_TEMPLATE/feature_request.md: 84fca7a1f0095afb8de52af8a03fc6f3f62b42b30365547992ad83a4b638cf41 +.github/pull_request_template.md: 6a7736d2a3ed6154e3f84462b483d7640709abe7f42e7caff63354eec84788af +.github/release_sources.yaml: c2241d25423ec6e22afa41c6caed30162438af803e6de74ee466479ca6cd8246 +.github/workflows/codeql.yml: 5e6e94a06f17ebbd8d3042467327837bb2076c29a1414b794800a3c1b09cca7d +.github/workflows/standard.yaml: 67d46981413db61fa435984c505db98513047848d71a268ca830ce5c368bf62b +.gitignore: 5898ee882c89a06ac046fb91b791950cb095157fccab17f31e9c5f6d0ed722da +.python_project_bootstrapper_config.yml: fdb86c64cb7cc5927ae227138440af9e54fda901026625d2370f33e87caf280f +ActivateEpilog.py: 102bb407fb3efcdbb697c4c5ea0d98236d43490ff9297bfa00b37ffaed66501d +Bootstrap.cmd: 48a673262f121c847d924d9b4b1db2a7ee01ef46d0aca8912d0c90f1f1d464c1 +Bootstrap.sh: c68ba07e6ab2df55c54a0285becf8c510cba9d0738f7c1b59b24a6188bb486f8 +BootstrapEpilog.py: bb93ebafd101e6434c3342bb9d9e337254b199e3cfff6035a3f33c16b4db7188 +Build.py: 711c112b877fb5a3fd71a7942f2b572a0546ff62bd65acaa91b9da16de685717 +CODE_OF_CONDUCT.md: 4b1e95a3ab0841adc68d4b43064c4021e423d2efe37e80ba2c74e18c0959d1cb +CONTRIBUTING.md: 8bdfa4f1c635965e1d8cc008e95b4562afa096a1d2d9b5f794955970c2cfc725 +DEVELOPMENT.md: b053ad0fe1c507e4fb1ebe950f36796d5083f85adbb435f5fefb32f0c5220486 +GOVERNANCE.md: 20e9812c403a41ba86aaf95e1efde35c94f195109f0da2632a7fde6c0562916b +LICENSE.txt: cdcedfdd3d9071859f7902f300b73f3cd1573de80a9086317c5bdf0863ad5458 +MAINTAINERS.md: deeb3c59f9ea4638cde04690e0b4ceb68ada72ab2c5cf99fec8139b4ba262d9e +README.md: 93b3bc9474594c3be11cbcde28bc5d342c847d7aec5bc232bafb118721771cd6 +SECURITY.md: baac87b1d8ca9981d01299679d039f06fed99f9fdc59c0f9ed723122aaaeabff +pyproject.toml: 5f07c159ea6a829ff62ae0273878fc25ad5c08bde1ff5ec47f654ab64539ac82 +src/AutoGitSemVer.yaml: 8829c49a62fcfba1bb17b03ac0f8a9e38a3777e49f058b16a79e4f4c782ddd7b +src/BuildBinary.py: bf736a35211fd68b2d1d8f9323e59d42c778bb0173cf18baa55dc439c18dea9b +src/PythonProjectBootstrapper/EntryPoint.py: e384c323ce48c2b768a12274dc0d7fbd13b1a60fb5790d0b60602b571138f57f +src/PythonProjectBootstrapper/Math.py: c339e168155404407d1196fb822df748f638fc7be5544a0add5aa6814e27c177 +src/PythonProjectBootstrapper/__init__.py: 455ff824b13e41ce2cfc5e9cccac234d1e8e1958e065e2af5ff8799c5c9cc73e +tests/EntryPoint_UnitTest.py: a32616e9bb6bbf10e9cb4b63e54c8013357a8988087c5f95f216e74d5b61ec15 +tests/Math_UnitTest.py: c9901514bf4ca017fc3c62dc1854c77e52fe5ac61dd3d4358d70faeebdff8422 diff --git a/ActivateEpilog.py b/ActivateEpilog.py index a32ad80..9a47b2a 100644 --- a/ActivateEpilog.py +++ b/ActivateEpilog.py @@ -1,11 +1,3 @@ -# ---------------------------------------------------------------------- -# | -# | Copyright (c) 2024 Scientific Software Engineering Center at Georgia Tech -# | Distributed under the MIT License. -# | -# ---------------------------------------------------------------------- -# pylint: disable=missing-module-docstring - import json import os import sys diff --git a/BootstrapEpilog.py b/BootstrapEpilog.py index f9101bf..943ed4b 100644 --- a/BootstrapEpilog.py +++ b/BootstrapEpilog.py @@ -12,6 +12,7 @@ from pathlib import Path + # Parse the arguments is_debug = False is_force = False @@ -21,9 +22,8 @@ display_flags: list[str] = [] -for arg in sys.argv[ - 2: -]: # First arg is the script name, second arg is the name of the shell script to write to +# First arg is the script name, second arg is the name of the shell script to write to +for arg in sys.argv[2:]: if arg == "--debug": is_debug = True elif arg == "--force": @@ -36,7 +36,7 @@ elif arg == "--no-cache": no_cache = True else: - raise Exception("Unrecognized argument: {}".format(arg)) + raise Exception("'{}' is not a recognized argument.".format(arg)) if is_debug: is_verbose = True @@ -50,7 +50,6 @@ shell=True, ) - with ( Path(__file__).parent / os.environ["PYTHON_BOOTSTRAPPER_GENERATED_DIR"] / "bootstrap_flags.json" ).open("w") as f: diff --git a/Build.py b/Build.py index 7022f1a..410f20a 100644 --- a/Build.py +++ b/Build.py @@ -4,7 +4,7 @@ # | Distributed under the MIT License. # | # ---------------------------------------------------------------------- -"""Build tasks for this python module.""" +"""Build tasks for this python project.""" import sys @@ -13,9 +13,8 @@ import typer from dbrownell_Common import PathEx -from typer.core import TyperGroup - from dbrownell_DevTools.RepoBuildTools import Python as RepoBuildTools +from typer.core import TyperGroup # ---------------------------------------------------------------------- @@ -74,11 +73,14 @@ def list_commands(self, *args, **kwargs): # pylint: disable=unused-argument BuildBinary = RepoBuildTools.BuildBinaryFuncFactory( this_dir, - src_dir / "BuildBinary.py", + PathEx.EnsureFile(src_dir / "BuildBinary.py"), app, ) -CreateDockerImage = RepoBuildTools.CreateDockerImageFuncFactory(this_dir, app) +CreateDockerImage = RepoBuildTools.CreateDockerImageFuncFactory( + this_dir, + app, +) # ---------------------------------------------------------------------- diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md new file mode 100644 index 0000000..8236fc8 --- /dev/null +++ b/CODE_OF_CONDUCT.md @@ -0,0 +1,25 @@ +# PythonProjectBootstrapper Open Source Code of Conduct + +## Principles +These principles guide our data, product, and process decisions, architecture, and approach. + +- Open means transparent and participatory. +- We take a modular and modern approach to software development. +- We build open-source software and open-source process. +- We value ease of implementation. +- Fostering community includes building capacity and making our software and processes accessible to participants with diverse backgrounds and skillsets. +- Data (and data science) is as important as software and process. We build open data sets where possible. +- We strive for transparency for algorithms and places we might be introducing bias. + +## Community Guidelines +Information on contributing to this repository is available in our [Contributing file](CONTRIBUTING.md). + +When participating in PythonProjectBootstrapper open source community conversations and spaces, we ask individuals to follow the following guidelines: + +- Embrace a culture of learning, and educate each other. We are all entering this conversation from different starting points and with different backgrounds. There are no dumb questions. +- Take space and give space. We strive to create an equitable environment in which all are welcome and able to participate. We hope individuals feel comfortable voicing their opinions and providing contributions and will do our best to recognize and make space for individuals who may be struggling to find space here. Likewise, we expect individuals to recognize when they are taking up significant space and take a step back to allow room for others. +- Be respectful. +- Default to positive. Assume others' contributions are legitimate and valuable and that they are made with good intention. + +## Acknowledgements +This Community Guidelines was adapted from the [United States Digital Service](https://usds.gov) [Justice40](https://thejustice40.com) open source [repository](https://github.com/usds/justice40-tool). diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000..f92f34d --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,39 @@ +# Contribution Guidelines + +## Contributor Code of Conduct +As contributors and maintainers of this project, we pledge to respect all people who contribute through reporting issues, posting feature requests, updating documentation, submitting pull requests or patches, and other activities. + +We are committed to making participation in this project a harassment-free experience for everyone, regardless of the level of experience, gender, gender identity, expression, sexual orientation, disability, personal appearance, body size, race, ethnicity, age, or religion. + +Examples of unacceptable behavior by participants include the use of sexual language or imagery, derogatory comments or personal attacks, trolling, public or private harassment, insults, or other unprofessional conduct. + +[Project maintainers](MAINTAINERS.md) have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned with this Code of Conduct. + +Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by opening an issue or contacting one or more of the [project maintainers](MAINTAINERS.md). + +## General information +For specific proposals, please provide them as [pull requests](https://github.com/coreinfrastructure/best-practices-badge/pulls) or [issues](https://github.com/coreinfrastructure/best-practices-badge/issues) via our [GitHub site](https://github.com/gt-sse-center/PythonProjectBootstrapper). + +The [DEVELOPMENT.md](DEVELOPMENT.md) file explains how to install the program locally (highly recommended if you're going to make code changes). It also provides information useful for making changes and validating them locally before submitting a pull request. + +### Pull requests and different branches recommended +Pull requests are preferred, since they are specific. For more about how to create a pull request, see https://help.github.com/articles/using-pull-requests/. + +We recommend creating different branches for different (logical) changes, and creating a pull request into the `main` branch when you're done. See the GitHub documentation on [creating branches](https://help.github.com/articles/creating-and-deleting-branches-within-your-repository/) and [using pull requests](https://help.github.com/articles/using-pull-requests/). + +### How we handle proposals +We use GitHub to track proposed changes via its [issue tracker](https://github.com/coreinfrastructure/best-practices-badge/issues) and [pull requests](https://github.com/coreinfrastructure/best-practices-badge/pulls). Specific changes are proposed using those mechanisms. Issues are assigned to an individual, who works and then marks it complete. If there are questions or objections, the conversation of that issue or pull request is used to resolve it. + +### We are proactive +In general we try to be proactive to detect and eliminate mistakes and vulnerabilities as soon as possible, and to reduce their impact when they do happen. We use a defensive design and coding style to reduce the likelihood of mistakes, a variety of tools that try to detect mistakes early, and an automatic test suite with significant coverage. We also release the software as open source software so others can review it. + +Since early detection and impact reduction can never be perfect, we also try to detect and repair problems during deployment as quickly as possible. This is especially true for security issues; see our [security information](#vulnerability-reporting-security-issues) for more information. + +## Vulnerability reporting (security issues) +Please privately report vulnerabilities you find so we can fix them! + +See [SECURITY.md](SECURITY.md) for information on how to privately report vulnerabilities. + +## Acknowledgements + +This Code of Conduct is adapted from the [Contributor Covenant](http://contributor-covenant.org), version 1.0.0, available at [http://contributor-covenant.org/version/1/0/0/](http://contributor-covenant.org/version/1/0/0/) diff --git a/DEVELOPMENT.md b/DEVELOPMENT.md index b355ed4..b84721a 100644 --- a/DEVELOPMENT.md +++ b/DEVELOPMENT.md @@ -1,6 +1,28 @@ -# Python Project Bootstrapper +# Local Development -This page contains information associated with the content generated by `PythonProjectBootstrapper`. Please see [README.md](https://github.com/gt-sse-center/PythonProjectBootstrapper/blob/main/README.md) for information about `PythonProjectBootstrapper` itself. +## Enlistment +Enlistment in this repository involves these steps. + +| Step | Command Line | Description | +| --- | --- | --- | +| 1. Clone the repository locally | `git clone https://github.com/gt-sse-center/PythonProjectBootstrapper` | https://git-scm.com/docs/git-clone | +| 2. Bootstrap the repository |
Linux / MacOS:./Bootstrap.sh [--python-version <python version>] [--package]
Windows:Bootstrap.cmd [--python-version <python version>] [--package]
|

Prepares the repository for local development by enlisting in all dependencies.

The `--package` argument is required to run the [Python Package Creation](#python-package-creation) and [Python Package Publising](#python-package-publishing) steps below. | +| 3. Activate the environment |
Linux / MacOS:. ./Activate.sh
Windows:Activate.cmd
|

Activates the terminal for development. Each new terminal window must be activated.

`Activate.sh/.cmd` is actually a shortcut to the most recently bootstrapped version of python (e.g. `Activate3.11.sh/.cmd`). With this functionality, it is possible to support multiple python versions in the same repository and activate each in a terminal using the python-specific activation script.

| +| 4. [Optional] Deactivate the environment |
Linux / MacOS:. ./Deactivate.sh
Windows:Deactivate.cmd
| Deactivates the terminal environment. Deactivating is optional, as the terminal window itself may be closed when development activities are complete. | + +## Development Activities + +Each of these activities can be invoked from an activated terminal on your local machine. + +| Activity | Command Line | Description | Invoked by [Continuous Integration](https://github.com/gt-sse-center/PythonProjectBootstrapper/blob/main/.github/workflows/standard.yaml) | +| --- | --- | --- | :---: | +| Code Formatting | `python Build.py black [--format]` | Format source code using [black](https://github.com/psf/black) based on settings in [pyproject.toml](https://github.com/gt-sse-center/PythonProjectBootstrapper/blob/main/pyproject.toml). | :white_check_mark: | +| Static Code Analysis | `python Build pylint` | Validate source code using [pylint](https://github.com/pylint-dev/pylint) based on settings in [pyproject.toml](https://github.com/gt-sse-center/PythonProjectBootstrapper/blob/main/pyproject.toml). | :white_check_mark: | +| Automated Testing | `python Build pytest [--code-coverage]` | Run automated tests using [pytest](https://docs.pytest.org/) and (optionally) extract code coverage information using [coverage](https://coverage.readthedocs.io/) based on settings in [pyproject.toml](https://github.com/gt-sse-center/PythonProjectBootstrapper/blob/main/pyproject.toml). | :white_check_mark: | +| Semantic Version Generation | `python Build.py update_version` | Generate a new [Semantic Version](https://semver.org) based on git commits using [AutoGitSemVer](https://github.com/davidbrownell/AutoGitSemVer). Version information is stored [here](https://github.com/gt-sse-center/PythonProjectBootstrapper/blob/main/src/PythonProjectBootstrapper/__init__.py). | :white_check_mark: | +| Python Package Creation |

`python Build.py package`

Requires that the repository was bootstrapped with the `--package` flag.

| Create a python package using [setuptools](https://github.com/pypa/setuptools) based on settings in [pyproject.toml](https://github.com/gt-sse-center/PythonProjectBootstrapper/blob/main/pyproject.toml). |

:white_check_mark:

Packages are built for all supported python versions.

| +| Python Package Publishing |

`python Build.py publish`

Requires that the repository was bootstrapped with the `--package` flag.

| Publish a python package to [PyPi](https://pypi.org). | :white_check_mark: | +| Build Binaries | `python Build.py build_binaries` | Create a python binary for your current operating system using [cx_Freeze](https://cx-freeze.readthedocs.io/) based on settings in [BuildBinary.py](https://github.com/gt-sse-center/PythonProjectBootstrapper/blob/main/src/BuildBinary.py). |

:white_check_mark:

Binaries are built for Linux, MacOS, and Windows.

## Generated Content diff --git a/GOVERNANCE.md b/GOVERNANCE.md new file mode 100644 index 0000000..9256d60 --- /dev/null +++ b/GOVERNANCE.md @@ -0,0 +1,2 @@ +# Governance +This project is governed by our [Code of Conduct](CODE_OF_CONDUCT.md) and [Contribution Guidelines](CONTRIBUTING.md). diff --git a/LICENSE.txt b/LICENSE.txt index da51da0..34a8b01 100644 --- a/LICENSE.txt +++ b/LICENSE.txt @@ -1,4 +1,6 @@ -Copyright (c) 2024 Scientific Software Engineering Center +MIT LICENSE + +Copyright (c) 2024 Scientific Software Engineering Center at Georgia Tech Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/MAINTAINERS.md b/MAINTAINERS.md new file mode 100644 index 0000000..9a8d022 --- /dev/null +++ b/MAINTAINERS.md @@ -0,0 +1,14 @@ +# Maintainers + +This page lists all active maintainers of this repository. If you were a maintainer and would like to add your name to the Emeritus list, please send us a pull request. + +See [Code of Conduct](CODE_OF_CONDUCT.md) and [Contributing](CONTRIBUTING.md) for general contribution guidelines. + +## Current Maintainers +| Maintainer | GitHub ID | Affiliation | +| --- | --- | --- | +TODO: Add maintainers + +## Emeritus +| Maintainer | GitHub ID | Affiliation | +| --- | --- | --- | diff --git a/README.md b/README.md index 48bc17d..abce314 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,6 @@ +# PythonProjectBootstrapper + + [![CI](https://github.com/gt-sse-center/PythonProjectBootstrapper/actions/workflows/standard.yaml/badge.svg?event=push)](https://github.com/gt-sse-center/PythonProjectBootstrapper/actions/workflows/standard.yaml) [![Code Coverage](https://img.shields.io/endpoint?url=https://gist.githubusercontent.com/davidbrownell/2f9d770d13e3a148424f374f74d41f4b/raw/PythonProjectBootstrapper_coverage.json)](https://github.com/gt-sse-center/PythonProjectBootstrapper/actions) [![License](https://img.shields.io/github/license/gt-sse-center/PythonProjectBootstrapper?color=dark-green)](https://github.com/gt-sse-center/PythonProjectBootstrapper/blob/master/LICENSE.txt) @@ -5,16 +8,22 @@ [![PyPI - Python Version](https://img.shields.io/pypi/pyversions/PythonProjectBootstrapper?color=dark-green)](https://pypi.org/project/pythonprojectbootstrapper/) [![PyPI - Version](https://img.shields.io/pypi/v/PythonProjectBootstrapper?color=dark-green)](https://pypi.org/project/pythonprojectbootstrapper/) [![PyPI - Downloads](https://img.shields.io/pypi/dm/PythonProjectBootstrapper)](https://pypistats.org/packages/pythonprojectbootstrapper) +[![OpenSSF Best Practices](https://www.bestpractices.dev/projects/9132/badge)](https://www.bestpractices.dev/projects/9132) + Tool that helps in the creation of python projects. -### Quick Start - -1. Install via [executable](#installation-via-executable), [pip](#installation-via-pip), or [local development](#local-development) -2. [Run the executable](#running-the-executable) + +## Contents +- [Overview](#overview) +- [Installation](#installation) +- [Development](#development) +- [Additional Information](#additional-information) +- [License](#license) + -### Overview +## Overview `PythonProjectBootstrapper` creates a python project that adheres to modern best practices for python package development. It also generates Continuous Integration / Delivery / Deployment workflows that maximize the free functionality offered by GitHub for open-source solutions. @@ -87,15 +96,16 @@ Enter 'yes' to continue or 'no' to exit: │ * output_dir DIRECTORY Directory to populate. [default: None] [required] │ └─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘ ┌─ Options ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐ -│ --configuration-filename FILE Filename that contains template configuration values; see │ -│ https://cookiecutter.readthedocs.io/en/stable/advanced/user_config.html for more info. │ -│ [default: None] │ -│ --replay Do not prompt for input, instead read from saved json. │ -│ --yes Answer yes to all prompts. │ -│ --version Display the current version and exit. │ -│ --install-completion [bash|zsh|fish|powershell|pwsh] Install completion for the specified shell. [default: None] │ -│ --show-completion [bash|zsh|fish|powershell|pwsh] Show completion for the specified shell, to copy it or customize the installation. [default: None] │ -│ --help Show this message and exit. │ +│ --configuration FILE Filename that contains template configuration values; see https://cookiecutter.readthedocs.io/en/stable/advanced/user_config.html for more │ +│ info. │ +│ [default: None] │ +│ --replay Do not prompt for input, instead read from saved json. │ +│ --yes Answer yes to all prompts. │ +│ --skip-prompts Do not display prompts after generating content. │ +│ --version Display the current version and exit. │ +│ --install-completion Install completion for the current shell. │ +│ --show-completion Show completion for the current shell, to copy it or customize the installation. │ +│ --help Show this message and exit. │ └─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘ @@ -108,72 +118,60 @@ Enter 'yes' to continue or 'no' to exit: -## Installation via Executable + +## Installation + +PythonProjectBootstrapper can be installed via one of these methods: + +- [Installation via Executable](#installation-via-executable) +- [Installation via pip](#installation-via-pip) + +### Installation via Executable Download an executable for Linux, MacOS, or Windows to use the functionality provided by this repository without a dependency on [Python](https://www.python.org). 1. Download the archive for the latest release [here](https://github.com/gt-sse-center/PythonProjectBootstrapper/releases/latest); the files will begin with `exe.` and contain the name of your operating system. 2. Decompress the archive -## Installation via pip + +#### Verifying Signed Executables + +Executables are signed and validated using [Minisign](https://jedisct1.github.io/minisign/). + +The public key for executables in this repository is `RWRkzrG0tznlEpemQ9U4aCQU/TO1TXipqycs7G9pRrm/9ab9HBcV/EIf`. + +To verify that the executable is valid, download the corresponding `.minisig` file [here](https://github.com/gt-sse-center/PythonProjectBootstrapper/releases/latest) and run this command, replacing `` with the name of your file. + +`docker run -i --rm -v .:/host jedisct1/minisign -V -P RWRkzrG0tznlEpemQ9U4aCQU/TO1TXipqycs7G9pRrm/9ab9HBcV/EIf -m /host/` + +Instructions for installing [docker](https://docker.com) are available at https://docs.docker.com/engine/install/. + + + +### Installation via pip Install the PythonProjectBootstrapper package via [pip](https://pip.pypa.io/en/stable/) (Package Installer for Python) to use it with your python code. `pip install PythonProjectBootstrapper` -## Local Development - -Follow these steps to prepare the repository for local development activities. - -1) Clone this repository -2) Bootstrap the local repository by running... - | Operating System | Command | - | --- | --- | - | Linux / MacOS |

Standard:
`Bootstrap.sh`

Standard + packaging:
`Bootstrap.sh --package`

| - | Windows |

Standard:
`Bootstrap.cmd`

Standard + packaging:
`Bootstrap.cmd --package`

| -3) Activate the development environment by running... - | Operating System | Command | - | --- | --- | - | Linux / MacOS | `. ./Activate.sh` | - | Windows | `Activate.cmd` | -4) Invoke `Build.py` - | Command | Description | Example | Notes | - | --- | --- | --- | --- | - | `black` | Validates that the source code is formatted by [black](https://github.com/psf/black). |

Validation:
`python Build.py black`

Perform formatting:
`python Build.py black --format`

| | - | `pylint` | Validates the source code using [pylint](https://github.com/pylint-dev/pylint). | `python Build.py pylint` | | - | `pytest` | Runs automated tests using [pytest](https://docs.pytest.org/). |

Without Code Coverage:
`python Build.py pytest`

With Code Coverage:
`python Build.py pytest --code-coverage`

| | - | `update_version` | Updates the [semantic version](https://semver.org/) of the package based on git commits using [AutoGitSemVer](https://github.com/davidbrownell/AutoGitSemVer). | `python Build.py update_version` | | - | `package` | Creates a Python wheel package for distribution; outputs to the `/dist` directory. | `python Build.py package` | Requires `--package` when bootstrapping in step #2. | - | `publish` | Publishes a Python wheel package to [PyPi](https://pypi.org/). |

https://test.pypi.org:
`python Build.py publish`

https://pypi.org:
`python Build.py publish --production`

| Requires `--package` when bootstrapping in step #2. | - | `build_binary` | Builds an executable for your package that can be run on machines without a python installation; outputs to the `/build` directory. | `python Build.py build_binary` | Requires `--package` when bootstrapping in step #2. | - -5) \[Optional] Deactivate the development environment by running... - | Operating System | Command | - | --- | --- | - | Linux / MacOS | `. ./Deactivate.sh` | - | Windows | `Deactivate.cmd` | - -## Similar Tools - -There are other tools available that offer similar functionality, each emphasizing different domains, conventions, or workflows. They are listed here in the event that one of them is a better fit for the specifics of your scenario. - -| Tool | Description | -| --- | --- | -| [Scientific Python: guide, cookie, & sp-repo-review](https://github.com/scientific-python/cookie) | A copier/cookiecutter template for new Python projects based on the Scientific Python Developer Guide. | -| [cookiecutter-cms](https://github.com/MolSSI/cookiecutter-cms) | A cookiecutter template for those interested in developing computational molecular packages in Python. | -| [LINCC Frameworks Python Project Template](https://github.com/lincc-frameworks/python-project-template) | This project template codifies LINCC-Framework's best practices for python code organization, testing, documentation, and automation. | -| [Cookiecutter Django](https://github.com/cookiecutter/cookiecutter-django) | Cookiecutter Django is a framework for jumpstarting production-ready Django projects quickly. | -| [cookiecutter-pylibrary](https://github.com/ionelmc/cookiecutter-pylibrary) | Enhanced cookiecutter template for Python libraries. | -| [repo-scaffolder](https://github.com/DSACMS/repo-scaffolder) | Templates and commandline tools for creating repositories for US Federal open source projects | - -### Templating Systems - -PythonProjectBootstrapper uses cookiecutter as its underlying templating engine, but others are available within python. Some are listed here if you want to use them directly. - -| Tool | Description | -| --- | --- | -| [cookiecutter](https://github.com/cookiecutter/cookiecutter) | A cross-platform command-line utility that creates projects from cookiecutters (project templates), e.g. Python package projects, C projects. | -| [copier](https://github.com/copier-org/copier) | A library and CLI app for rendering project templates. | +## Development + +Please visit [Contributing](https://github.com/gt-sse-center/PythonProjectBootstrapper/blob/main/CONTRIBUTING.md) and [Development](https://github.com/gt-sse-center/PythonProjectBootstrapper/blob/main/DEVELOPMENT.md) for information on contributing to this project. + + + +## Additional Information + +Additional information can be found at these locations. + +| Title | Document | Description | +| --- | --- | --- | +| Code of Conduct | [CODE_OF_CONDUCT.md](https://github.com/gt-sse-center/PythonProjectBootstrapper/blob/main/CODE_OF_CONDUCT.md) | Information about the the norms, rules, and responsibilities we adhere to when participating in this open source community. | +| Contributing | [CONTRIBUTING.md](https://github.com/gt-sse-center/PythonProjectBootstrapper/blob/main/CONTRIBUTING.md) | Information about contributing code changes to this project. | +| Development | [DEVELOPMENT.md](https://github.com/gt-sse-center/PythonProjectBootstrapper/blob/main/DEVELOPMENT.md) | Information about development activities involved in making changes to this project. | +| Governance | [GOVERNANCE.md](https://github.com/gt-sse-center/PythonProjectBootstrapper/blob/main/GOVERNANCE.md) | Information about how this project is governed. | +| Maintainers | [MAINTAINERS.md](https://github.com/gt-sse-center/PythonProjectBootstrapper/blob/main/MAINTAINERS.md) | Information about individuals who maintain this project. | +| Security | [SECURITY.md](https://github.com/gt-sse-center/PythonProjectBootstrapper/blob/main/SECURITY.md) | Information about how to privately report security issues associated with this project. | ## License diff --git a/SECURITY.md b/SECURITY.md new file mode 100644 index 0000000..fdd12f2 --- /dev/null +++ b/SECURITY.md @@ -0,0 +1,9 @@ +# Security + +If you find a significant vulnerability, or evidence of one, please report it privately. + +We prefer that you use the [GitHub mechanism for privately reporting a vulnerability](https://docs.github.com/en/code-security/security-advisories/guidance-on-reporting-and-writing/privately-reporting-a-security-vulnerability#privately-reporting-a-security-vulnerability). Under the [main repository's security tab](https://github.com/gt-sse-center/PythonProjectBootstrapper/security), in the left sidebar, under "Reporting", click "Advisories", click the "New draft security advisory" button to open the advisory form. + +We will gladly give credit to anyone who reports a vulnerability so that we can fix it. If you want to remain anonymous or pseudonymous instead, please let us know that; we will gladly respect your wishes. + +We gladly welcome patches to fix such vulnerabilities! See [CONTRIBUTING.md](CONTRIBUTING.md) for information about contributions. diff --git a/pyproject.toml b/pyproject.toml index 4f2ceb9..20a7427 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,4 +1,11 @@ +# ---------------------------------------------------------------------- +# | +# | Copyright (c) 2024 Scientific Software Engineering Center at Georgia Tech +# | Distributed under the MIT License. +# | +# ---------------------------------------------------------------------- # https://packaging.python.org/en/latest/specifications/declaring-project-metadata/ + [build-system] requires = ["setuptools >= 63.0"] build-backend = "setuptools.build_meta" @@ -10,12 +17,12 @@ build-backend = "setuptools.build_meta" # ---------------------------------------------------------------------- [project] name = "PythonProjectBootstrapper" -description = "Bootstraps a python project." +description = "Tool that helps in the creation of python projects." license = { text = "MIT" } authors = [ - { name = "Scientific Software Engineering Center", email = "ssec-dev@gatech.edu" }, + { name = "Scientific Software Engineering Center at Georgia Tech", email = "sse-center@gatech.edu" }, ] keywords = [ @@ -39,7 +46,7 @@ dependencies = [ "cookiecutter ~= 2.6", "dbrownell_Common", "rich ~= 13.7", - "typer ~= 0.9", + "typer ~= 0.9" ] dynamic = [ @@ -68,7 +75,6 @@ Repository = "https://github.com/gt-sse-center/PythonProjectBootstrapper" [project.scripts] PythonProjectBootstrapper = "PythonProjectBootstrapper:EntryPoint.app" - # ---------------------------------------------------------------------- # | # | black @@ -103,7 +109,7 @@ max-args = 10 max-parents = 15 [tool.pylint.main] -ignore-patterns = [ +ignore-paths = [ # Note that the pylint vscode extension has trouble with wrapping these patterns in quotes # (which is required to parse the file correctly). Because of this, each pattern must be # converted to a glob pattern and specified in the pylint vscode settings as well. diff --git a/src/AutoGitSemVer.yaml b/src/AutoGitSemVer.yaml index 7d6e277..1fa7d2f 100644 --- a/src/AutoGitSemVer.yaml +++ b/src/AutoGitSemVer.yaml @@ -1,3 +1,6 @@ +# This file is used by AutoGitSemVer to configure the semantic version of the PythonProjectBootstrapper package. +# It indicates that AutoGitSemVer should only look at changes in this directory, its descendants, and files specified in +# additional_dependencies when calculating the semantic version for the package. additional_dependencies: - "../pyproject.toml" - "../README.md" diff --git a/src/BuildBinary.py b/src/BuildBinary.py index 4f6ad28..1f72c50 100644 --- a/src/BuildBinary.py +++ b/src/BuildBinary.py @@ -8,112 +8,84 @@ import datetime import importlib -import os import textwrap -from pathlib import Path, PurePath +from functools import cache +from pathlib import Path from cx_Freeze import setup, Executable from dbrownell_Common import PathEx # ---------------------------------------------------------------------- -_this_dir = Path(__file__).parent - -_name = "PythonProjectBootstrapper" -_initial_year: int = 2024 -_entry_point_script = PathEx.EnsureFile( - _this_dir / "PythonProjectBootstrapper" / "EntryPoint.py", -) -_copyright_template = textwrap.dedent( - """\ - -Copyright (c) {year}{year_suffix} Scientific Software Engineering Center - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. - -""", -).strip() +@cache +def _GetName() -> str: + return "PythonProjectBootstrapper" # ---------------------------------------------------------------------- -# Get the version and docstring -mod = importlib.import_module(_name) -_version = mod.__version__ - -mod = importlib.import_module("{}.{}".format(_name, _entry_point_script.stem)) -_docstring = mod.__doc__ - -del mod +@cache +def _GetVersionAndDocstring() -> tuple[str, str]: + mod = importlib.import_module(_GetName()) + return mod.__version__, mod.__doc__ or "" # ---------------------------------------------------------------------- -# Create the year suffix -_year = datetime.datetime.now().year - -if _year == _initial_year: - _year_suffix = "" -elif _year // 100 != _initial_year // 100: - _year_suffix = str(_year) -else: - _year_suffix = "-{}".format(_year % 100) +@cache +def _GetEntryPoint() -> Path: + return PathEx.EnsureFile(Path(__file__).parent / _GetName() / "EntryPoint.py") # ---------------------------------------------------------------------- -_include_files: list[tuple[str, str]] = [] - -_project_root = PathEx.EnsureDir(_this_dir / "PythonProjectBootstrapper" / "package") -_lib_path = PurePath("lib") - -for root, _, filenames in os.walk(_project_root): - if not filenames: - continue - - root_path = Path(root) - relative_path = PurePath(*root_path.parts[len(_this_dir.parts) :]) - - for filename in filenames: - fullpath = root_path / filename - - _include_files.append( - ( - (relative_path / filename).as_posix(), - (_lib_path / relative_path / filename).as_posix(), - ) - ) +@cache +def _GetCopyright() -> str: + initial_year = 2024 + current_year = datetime.datetime.now().year + + if current_year == initial_year: + year_suffix = "" + elif current_year // 100 != initial_year // 100: + year_suffix = str(current_year) + else: + year_suffix = "-{}".format(current_year % 100) + + return textwrap.dedent( + f"""\ + Copyright (c) {initial_year}{year_suffix} Scientific Software Engineering Center at Georgia Tech + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. + """, + ) # ---------------------------------------------------------------------- setup( - name=_name, - version=_version, - description=_docstring, + name=_GetName(), + version=_GetVersionAndDocstring()[0], + description=_GetVersionAndDocstring()[1], executables=[ Executable( - _entry_point_script, + _GetEntryPoint(), base="console", - copyright=_copyright_template.format( - year=str(_initial_year), - year_suffix=_year_suffix, - ), + copyright=_GetCopyright(), # icon=, - target_name=_name, + target_name=_GetName(), # trademarks=, ), ], @@ -125,11 +97,8 @@ ], "no_compress": False, "optimize": 0, - "packages": [ - "cookiecutter.extensions", - "rich", - ], - "include_files": _include_files, + # "packages": [], + # "include_files": [], }, }, ) diff --git a/src/PythonProjectBootstrapper/EntryPoint.py b/src/PythonProjectBootstrapper/EntryPoint.py index fed1f24..88b0110 100644 --- a/src/PythonProjectBootstrapper/EntryPoint.py +++ b/src/PythonProjectBootstrapper/EntryPoint.py @@ -73,6 +73,9 @@ def _CreateProjectType(): if not file_item.is_dir(): continue + if file_item.name.startswith("."): + continue + project_types.append(file_item.name) assert project_types diff --git a/src/PythonProjectBootstrapper/__init__.py b/src/PythonProjectBootstrapper/__init__.py index c92b44b..3e2f695 100644 --- a/src/PythonProjectBootstrapper/__init__.py +++ b/src/PythonProjectBootstrapper/__init__.py @@ -1,6 +1,12 @@ +# ---------------------------------------------------------------------- +# | +# | Copyright (c) 2024 Scientific Software Engineering Center at Georgia Tech +# | Distributed under the MIT License. +# | +# ---------------------------------------------------------------------- # pylint: disable=missing-module-docstring,invalid-name # Note that this value will be overwritten by calls to `python ../../Build.py update_version` based # on changes observed in the git repository. The default value below will be used until the value -# here is explicitly updated by the Continuous Integration system as part of a commit. +# here is explicitly updated by the Continuous Integration system. __version__ = "0.1.0" diff --git a/src/PythonProjectBootstrapper/package/{{ cookiecutter.__empty_dir }}/.python_project_bootstrapper_config.yml b/src/PythonProjectBootstrapper/package/{{ cookiecutter.__empty_dir }}/.python_project_bootstrapper_config.yml index 83ac77b..4b85309 100644 --- a/src/PythonProjectBootstrapper/package/{{ cookiecutter.__empty_dir }}/.python_project_bootstrapper_config.yml +++ b/src/PythonProjectBootstrapper/package/{{ cookiecutter.__empty_dir }}/.python_project_bootstrapper_config.yml @@ -3,7 +3,7 @@ # to rerun generation on this python package. To use this file, run the following command from within this # working directory: # -# PythonProjectBootstrapper package . --config .python_project_bootstrapper_config.yml +# PythonProjectBootstrapper package . --configuration .python_project_bootstrapper_config.yml # ############################################################################################################# default_context: