├── .coveragerc ├── .github ├── ISSUE_TEMPLATE │ ├── bug.md │ ├── discussion.md │ ├── documentation.md │ ├── feature.md │ ├── post-mortem.md │ ├── question.md │ ├── refactor.md │ └── task.md ├── dependabot.yml ├── pull_request_template.md └── workflows │ ├── codeql.yml │ ├── continuous-integration.yml │ ├── dependency-review.yml │ ├── scorecard.yml │ └── semantic-release.yml ├── .gitignore ├── .pre-commit-config.yaml ├── .readthedocs.yaml ├── .vscode └── settings.json ├── CHANGELOG.md ├── CODE_OF_CONDUCT.md ├── CONTRIBUTING.md ├── COPYRIGHT.md ├── LICENSE.md ├── README.md ├── SECURITY.md ├── doc ├── .gitignore ├── Makefile ├── make-html.bash ├── requirements.txt └── source │ ├── _static │ └── .gitkeep │ ├── conf.py │ ├── examples.rst │ ├── index.rst │ ├── motivation.rst │ ├── reference.rst │ └── spelling_wordlist.txt ├── example ├── basic.py ├── default_values.py ├── post_processing.py ├── pretty_printing.py ├── relative_references.py ├── requirements.txt ├── run-all.bash ├── subparsers.py └── test_examples.py ├── pyproject.toml ├── requirements.txt ├── reverse_argparse ├── __init__.py ├── py.typed └── reverse_argparse.py ├── setup.py ├── templates ├── .release_notes.md.j2 └── CHANGELOG.md.j2 └── test ├── __init__.py ├── requirements.txt └── test_reverse_argparse.py /.coveragerc: -------------------------------------------------------------------------------- 1 | [run] 2 | omit = 3 | test/* 4 | */.vscode/* 5 | branch = True 6 | dynamic_context = test_function 7 | relative_files = True 8 | 9 | [paths] 10 | source = reverse_argparse 11 | 12 | [report] 13 | skip_covered = False 14 | fail_under = 90 15 | show_missing = True 16 | exclude_lines = 17 | pragma: no cover 18 | if 0: 19 | if False: 20 | 21 | [html] 22 | directory = test/htmlcov 23 | title = reverse_argparse Coverage Report 24 | show_contexts = True 25 | 26 | [xml] 27 | output = test/coverage.xml 28 | 29 | [json] 30 | output = test/coverage.json 31 | pretty_print = True 32 | show_contexts = True 33 | 34 | [lcov] 35 | output = test/coverage.lcov 36 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug 3 | about: What went wrong? 4 | title: '' 5 | labels: 'Type: Bug' 6 | assignees: '' 7 | 8 | --- 9 | 10 | ## Description 11 | * What went wrong? 12 | * What should have happened? 13 | * Do you have an idea what might fix things? 14 | * How has this bug affected you? 15 | * What are you trying to accomplish? 16 | 17 | ## Steps to Reproduce 18 | 1. Machine/OS: [insert here] 19 | 2. Python reproducer: 20 | ```python 21 | # Insert minimal example script here. 22 | ``` 23 | 3. Output from running the script: 24 | ``` 25 | # Paste all output from the terminal here. 26 | ``` 27 | 28 | ## Screenshots 29 | If applicable, add screenshots to help explain your problem. 30 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/discussion.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Discussion 3 | about: What do we need to talk through? 4 | title: '' 5 | labels: 'Type: Discussion' 6 | assignees: '' 7 | 8 | --- 9 | 10 | * What do we need to talk through? 11 | * Why do we need to talk through it? 12 | * What is needed for us to consider this discussion complete? 13 | * Be sure to @mention whoever should be involved in the discussion. 14 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/documentation.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Documentation 3 | about: What's wrong with the docs? 4 | title: '' 5 | labels: 'Type: Documentation' 6 | assignees: '' 7 | 8 | --- 9 | 10 | * What would you like to see in the documentation? 11 | * How does our current documentation not meet your needs? 12 | * How has this lack of documentation affected you? 13 | * What are you trying to accomplish? 14 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature 3 | about: What new functionality is needed? 4 | title: '' 5 | labels: 'Type: Feature' 6 | assignees: '' 7 | 8 | --- 9 | 10 | * What feature change/addition is needed? 11 | * How does this differ from what we currently have? 12 | * Do you have suggestions on implementation? 13 | * What alternative solutions have you considered? 14 | * How has the lack of this feature affected you? 15 | * What are you trying to accomplish? 16 | * What specifically must we demonstrate to call this work complete? 17 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/post-mortem.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Post-Mortem 3 | about: Let's track down the root cause of a failure 4 | title: '' 5 | labels: 'Type: Post-Mortem' 6 | assignees: '' 7 | 8 | --- 9 | 10 | ## What Went Wrong? 11 | Gather information and construct a detailed timeline of what contributed to the problem. 12 | 13 | ## Why Did It Go Wrong? 14 | This is not for the purpose of blame, but to educate the team such that we can learn from our mistakes. 15 | 16 | ## Proposed Countermeasures 17 | What changes can we implement to increase the likelihood that similar problems will not happen in the future? 18 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/question.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Question 3 | about: What do you need to know? 4 | title: '' 5 | labels: 'Type: Question' 6 | assignees: '' 7 | 8 | --- 9 | 10 | ## Question 11 | * What can we help you with? 12 | * What is it you're trying to accomplish? 13 | * Why do you need to do what you're trying to do? 14 | 15 | ## Checklist 16 | * [ ] Have you read through the [README](README.md)? 17 | * [ ] Have you searched through [our documentation](https://reverse-argparse.readthedocs.io)? 18 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/refactor.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Refactor 3 | about: What needs rework? 4 | title: '' 5 | labels: 'Type: Refactor' 6 | assignees: '' 7 | 8 | --- 9 | 10 | * What needs to be cleaned up? 11 | * How would the refactored implementation differ from what we have now? 12 | * What are the potential downsides to not dealing with the technical debt now and leaving it for later? 13 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/task.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Task 3 | about: What needs to be done? 4 | title: '' 5 | labels: 'Type: Task' 6 | assignees: '' 7 | 8 | --- 9 | 10 | ## Description 11 | * What needs to happen? 12 | * Why does it need to happen? 13 | * How does it relate to the rest of the project? 14 | * What specifically must we demonstrate to call this work complete 15 | 16 | ## Tasks 17 | * [ ] First do this. 18 | * [ ] Then do that. 19 | * [ ] Also this other thing. 20 | -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | updates: 3 | - package-ecosystem: github-actions 4 | directory: / 5 | schedule: 6 | interval: weekly 7 | groups: 8 | github-actions-dependencies: 9 | applies-to: version-updates 10 | patterns: 11 | - "*" 12 | 13 | - package-ecosystem: pip 14 | directories: 15 | - / 16 | - /doc 17 | - /example 18 | - /test 19 | schedule: 20 | interval: weekly 21 | groups: 22 | python-dependencies: 23 | applies-to: version-updates 24 | patterns: 25 | - "*" 26 | -------------------------------------------------------------------------------- /.github/pull_request_template.md: -------------------------------------------------------------------------------- 1 | 9 | 10 | ## Description 11 | 14 | 15 | ## Related Issues/PRs 16 | 22 | 23 | ## Motivation 24 | 28 | 29 | ## Implementation Details 30 | 35 | 36 | ## Screenshots/Recordings 37 | 40 | 41 | 42 | ## Testing 43 | 47 | 48 | 49 | ## Documentation 50 | 53 | -------------------------------------------------------------------------------- /.github/workflows/codeql.yml: -------------------------------------------------------------------------------- 1 | name: "CodeQL" 2 | 3 | on: 4 | push: 5 | branches: ["master"] 6 | pull_request: 7 | branches: ["master"] 8 | schedule: 9 | - cron: "0 0 * * 1" 10 | 11 | permissions: 12 | contents: read 13 | 14 | jobs: 15 | analyze: 16 | name: Analyze 17 | runs-on: ubuntu-latest 18 | permissions: 19 | actions: read 20 | contents: read 21 | security-events: write 22 | 23 | strategy: 24 | fail-fast: false 25 | 26 | steps: 27 | - name: Harden Runner 28 | uses: step-security/harden-runner@0634a2670c59f64b4a01f0f96f84700a4088b9f0 # v2.12.0 29 | with: 30 | egress-policy: audit 31 | 32 | - name: Checkout repository 33 | uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 34 | 35 | - name: Initialize CodeQL 36 | uses: github/codeql-action/init@ff0a06e83cb2de871e5a09832bc6a81e7276941f # v3.28.18 37 | with: 38 | languages: python 39 | 40 | - name: Perform CodeQL Analysis 41 | uses: github/codeql-action/analyze@ff0a06e83cb2de871e5a09832bc6a81e7276941f # v3.28.18 42 | with: 43 | category: "/language:python" 44 | -------------------------------------------------------------------------------- /.github/workflows/continuous-integration.yml: -------------------------------------------------------------------------------- 1 | name: Continuous Integration 2 | 3 | on: 4 | push: 5 | branches: 6 | - master 7 | pull_request: 8 | workflow_dispatch: 9 | 10 | defaults: 11 | run: 12 | shell: bash 13 | 14 | permissions: 15 | contents: read 16 | 17 | jobs: 18 | test: 19 | runs-on: ubuntu-latest 20 | strategy: 21 | matrix: 22 | version: ["3.9", "3.10", "3.11", "3.12", "3.13"] 23 | steps: 24 | 25 | - name: Harden Runner 26 | uses: step-security/harden-runner@0634a2670c59f64b4a01f0f96f84700a4088b9f0 # v2.12.0 27 | with: 28 | egress-policy: audit 29 | 30 | - name: Check out the commit 31 | uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 32 | 33 | - name: Set up Python 34 | uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5.6.0 35 | with: 36 | python-version: ~${{ matrix.version }} 37 | 38 | - name: Install development dependencies 39 | run: | 40 | python3 -m pip install --upgrade pip 41 | python3 -m pip install \ 42 | -r doc/requirements.txt \ 43 | -r example/requirements.txt \ 44 | -r test/requirements.txt 45 | 46 | - name: Test install 47 | run: python3 -m pip install . 48 | 49 | - name: Test with pytest 50 | run: python3 -m pytest --cov=reverse_argparse example/ test/ 51 | 52 | - name: Upload coverage reports to Codecov 53 | uses: codecov/codecov-action@18283e04ce6e62d37312384ff67231eb8fd56d24 # v5.4.3 54 | env: 55 | CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} 56 | 57 | - name: Check documentation spelling 58 | run: make spelling 59 | working-directory: ./doc 60 | 61 | - name: Check documentation coverage 62 | run: | 63 | make coverage 64 | mv build/coverage/python.txt ../docs-coverage-report-${{ matrix.version }}.txt 65 | working-directory: ./doc 66 | 67 | - name: Archive documentation coverage results 68 | uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 69 | with: 70 | name: docs-coverage-report-${{ matrix.version }} 71 | path: docs-coverage-report-${{ matrix.version }}.txt 72 | 73 | - name: Test uninstall 74 | run: python3 -m pip uninstall -y reverse_argparse 75 | 76 | commits: 77 | runs-on: ubuntu-latest 78 | steps: 79 | - name: Harden Runner 80 | uses: step-security/harden-runner@0634a2670c59f64b4a01f0f96f84700a4088b9f0 # v2.12.0 81 | with: 82 | egress-policy: audit 83 | 84 | - name: Conventional Commits 85 | uses: taskmedia/action-conventional-commits@a708bda25c04fc82b2acd5eeeb88d97f9a19beb9 # v1.1.20 86 | with: 87 | types: > 88 | build|chore|ci|docs|feat|fix|minor|patch|perf|style|refactor|test 89 | -------------------------------------------------------------------------------- /.github/workflows/dependency-review.yml: -------------------------------------------------------------------------------- 1 | name: 'Dependency Review' 2 | on: [pull_request] 3 | 4 | permissions: 5 | contents: read 6 | 7 | jobs: 8 | dependency-review: 9 | runs-on: ubuntu-latest 10 | steps: 11 | - name: Harden Runner 12 | uses: step-security/harden-runner@0634a2670c59f64b4a01f0f96f84700a4088b9f0 # v2.12.0 13 | with: 14 | egress-policy: audit 15 | 16 | - name: 'Checkout Repository' 17 | uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 18 | 19 | - name: 'Dependency Review' 20 | uses: actions/dependency-review-action@da24556b548a50705dd671f47852072ea4c105d9 # v4.7.1 21 | -------------------------------------------------------------------------------- /.github/workflows/scorecard.yml: -------------------------------------------------------------------------------- 1 | name: Scorecard supply-chain security 2 | on: 3 | branch_protection_rule: 4 | schedule: 5 | - cron: "22 6 * * 2" 6 | push: 7 | branches: [ "master" ] 8 | 9 | # Declare default permissions as read only. 10 | permissions: read-all 11 | 12 | jobs: 13 | analysis: 14 | name: Scorecard analysis 15 | runs-on: ubuntu-latest 16 | permissions: 17 | 18 | # Needed to upload the results to the code-scanning dashboard. 19 | security-events: write 20 | 21 | # Needed to publish the results and get a badge (see 22 | # `publish_results` below). 23 | id-token: write 24 | 25 | steps: 26 | - name: Harden Runner 27 | uses: step-security/harden-runner@0634a2670c59f64b4a01f0f96f84700a4088b9f0 # v2.12.0 28 | with: 29 | egress-policy: audit 30 | 31 | - name: "Checkout code" 32 | uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 33 | with: 34 | persist-credentials: false 35 | 36 | - name: "Run analysis" 37 | uses: ossf/scorecard-action@f49aabe0b5af0936a0987cfb85d86b75731b0186 # v2.4.1 38 | with: 39 | results_file: results.sarif 40 | results_format: sarif 41 | # (Optional) "write" PAT token. Uncomment the `repo_token` line below if: 42 | # - you want to enable the Branch-Protection check on a *public* repository, or 43 | # - you are installing Scorecard on a *private* repository 44 | # To create the PAT, follow the steps in https://github.com/ossf/scorecard-action?tab=readme-ov-file#authentication-with-fine-grained-pat-optional. 45 | # repo_token: ${{ secrets.SCORECARD_TOKEN }} 46 | publish_results: true 47 | 48 | - name: "Upload artifact" 49 | uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 50 | with: 51 | name: SARIF file 52 | path: results.sarif 53 | retention-days: 5 54 | 55 | - name: "Upload to code-scanning dashboard" 56 | uses: github/codeql-action/upload-sarif@ff0a06e83cb2de871e5a09832bc6a81e7276941f # v3.28.18 57 | with: 58 | sarif_file: results.sarif 59 | -------------------------------------------------------------------------------- /.github/workflows/semantic-release.yml: -------------------------------------------------------------------------------- 1 | name: Semantic Release 2 | 3 | on: 4 | push: 5 | branches: 6 | - master 7 | 8 | permissions: 9 | contents: read 10 | 11 | jobs: 12 | release: 13 | runs-on: ubuntu-latest 14 | concurrency: release 15 | environment: release 16 | permissions: 17 | id-token: write 18 | 19 | steps: 20 | - name: Harden Runner 21 | uses: step-security/harden-runner@0634a2670c59f64b4a01f0f96f84700a4088b9f0 # v2.12.0 22 | with: 23 | egress-policy: audit 24 | 25 | - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 26 | with: 27 | fetch-depth: 0 28 | token: ${{ secrets.GH_TOKEN }} 29 | 30 | - name: Python Semantic Release 31 | id: release 32 | uses: python-semantic-release/python-semantic-release@917a2c730cb8f6c8cd3d00f23c876d724a4a844c # v10.0.1 33 | with: 34 | github_token: ${{ secrets.GH_TOKEN }} 35 | 36 | - name: Publish to PyPI 37 | uses: pypa/gh-action-pypi-publish@76f52bc884231f62b9a034ebfe128415bbaabdfc # release/v1 38 | if: steps.release.outputs.released == 'true' 39 | 40 | - name: Publish to GitHub Releases 41 | uses: python-semantic-release/publish-action@d3a9934c4fff57f0d4df24450566d3dba7e7082a # v10.0.1 42 | if: steps.release.outputs.released == 'true' 43 | with: 44 | github_token: ${{ secrets.GH_TOKEN }} 45 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .coverage 2 | .pytest_cache 3 | __pycache__ 4 | test/coverage.json 5 | test/coverage.xml 6 | test/htmlcov 7 | -------------------------------------------------------------------------------- /.pre-commit-config.yaml: -------------------------------------------------------------------------------- 1 | # See https://pre-commit.com for more information 2 | # See https://pre-commit.com/hooks.html for more hooks 3 | ci: 4 | autofix_prs: false 5 | autoupdate_commit_msg: "ci: pre-commit auto-update" 6 | 7 | repos: 8 | 9 | - repo: https://github.com/astral-sh/ruff-pre-commit 10 | rev: v0.11.11 11 | hooks: 12 | - id: ruff 13 | - id: ruff-format 14 | 15 | - repo: https://github.com/gitleaks/gitleaks 16 | rev: v8.26.0 17 | hooks: 18 | - id: gitleaks 19 | 20 | - repo: https://github.com/pre-commit/mirrors-mypy 21 | rev: v1.15.0 22 | hooks: 23 | - id: mypy 24 | additional_dependencies: ["dateparser", "types-dateparser"] 25 | 26 | - repo: https://github.com/pre-commit/pre-commit-hooks 27 | rev: v5.0.0 28 | hooks: 29 | - id: check-added-large-files 30 | - id: check-ast 31 | - id: check-case-conflict 32 | - id: check-merge-conflict 33 | - id: end-of-file-fixer 34 | - id: mixed-line-ending 35 | - id: trailing-whitespace 36 | 37 | - repo: https://github.com/pre-commit/pygrep-hooks 38 | rev: v1.10.0 39 | hooks: 40 | - id: python-use-type-annotations 41 | - id: rst-backticks 42 | - id: rst-directive-colons 43 | - id: rst-inline-touching-normal 44 | 45 | - repo: https://github.com/PyCQA/doc8 46 | rev: v1.1.2 47 | hooks: 48 | - id: doc8 49 | 50 | - repo: https://github.com/regebro/pyroma 51 | rev: "4.2" 52 | hooks: 53 | - id: pyroma 54 | additional_dependencies: ["poetry"] 55 | 56 | - repo: https://github.com/shellcheck-py/shellcheck-py 57 | rev: v0.10.0.1 58 | hooks: 59 | - id: shellcheck 60 | -------------------------------------------------------------------------------- /.readthedocs.yaml: -------------------------------------------------------------------------------- 1 | # Read the Docs configuration file for Sphinx projects. 2 | # See https://docs.readthedocs.io/en/stable/config-file/v2.html for 3 | # details. 4 | 5 | # Required. 6 | version: 2 7 | 8 | # Set the OS, Python version, and other tools you need. 9 | build: 10 | os: "ubuntu-22.04" 11 | tools: 12 | python: "3.9" 13 | 14 | # Build documentation in the "doc/" directory with Sphinx. 15 | sphinx: 16 | fail_on_warning: true 17 | configuration: doc/source/conf.py 18 | 19 | # Declare Python requirements for building the documentation. 20 | python: 21 | install: 22 | - method: pip 23 | path: . 24 | - requirements: requirements.txt 25 | - requirements: doc/requirements.txt 26 | - requirements: example/requirements.txt 27 | -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "python.testing.pytestArgs": [ 3 | "-v", 4 | "--cov", 5 | "--cov-report=html", 6 | "--cov-report=json", 7 | "--cov-report=xml", 8 | "." 9 | ], 10 | "python.testing.unittestEnabled": false, 11 | "python.testing.pytestEnabled": true 12 | } 13 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # CHANGELOG 2 | 3 | 4 | 5 | ## v2.0.5 (2025-05-27) 6 | 7 | ### Patch 8 | * patch: Omit pre-commit updates from CHANGELOG ([`b6298d8`](https://github.com/sandialabs/reverse_argparse/commit/b6298d8eda0b0b5cc03c7c2be8bcd0d76931df46)) 9 | 10 | I thought 1aa9022a7c7796e85e342382f67b02434d4b544b was sufficient for 11 | this, but apparently not. Trying again. 12 | 13 | ## v2.0.4 (2025-05-27) 14 | 15 | ### Patch 16 | * patch: Omit dependency auto-updates from CHANGELOG ([`1aa9022`](https://github.com/sandialabs/reverse_argparse/commit/1aa9022a7c7796e85e342382f67b02434d4b544b)) 17 | 18 | This is marked at a patch release to ensure the change works, and 19 | regenerate the CHANGELOG without the noisy entries. 20 | 21 | ## v2.0.3 (2025-05-22) 22 | 23 | ### Chores 24 | * chore: Update security notice ([`4d51098`](https://github.com/sandialabs/reverse_argparse/commit/4d51098cf5cdc0b72bab35318183f88d920a5df4)) 25 | 26 | The Best Practices Badge App suggests we should document what users can 27 | expect from our project in terms of security. 28 | 29 | ### Documentation 30 | * docs: Switch to `project_copyright` ([`d0a21d5`](https://github.com/sandialabs/reverse_argparse/commit/d0a21d5ea5a1ed9a3988bf73f290a19ab3ae8786)) 31 | 32 | Using this alias means we're no longer overshadowing the `copyright` 33 | built-in, so we can remove the comment to ignore that Ruff linting rule. 34 | 35 | ### Patch 36 | * patch: Replace deprecated GitHub Action ([`e5f4256`](https://github.com/sandialabs/reverse_argparse/commit/e5f4256e2467b8e1a9919ef97e0e026ea8724a6c)) 37 | 38 | Marking this as a patch release to test out the new action and make sure 39 | it works. 40 | 41 | Closes #255. 42 | 43 | ## v2.0.2 (2024-12-17) 44 | 45 | ### Bug fixes 46 | * fix: Switch import location ([`7948fc2`](https://github.com/sandialabs/reverse_argparse/commit/7948fc2b0e1e9cdb6444be1d931e7f5a92ac26aa)) 47 | 48 | In Python 3.9, `typing.Sequence` was deprecated in favor of 49 | `collections.abc.Sequence` (see PEP 585). 50 | 51 | ## v2.0.1 (2024-12-17) 52 | 53 | ### Patch 54 | * patch: Support Python 3.13 ([`453fd05`](https://github.com/sandialabs/reverse_argparse/commit/453fd05415f7580240996e8dcbfbf29842986822)) 55 | 56 | ## v2.0.0 (2024-12-03) 57 | 58 | ### Chores 59 | * chore!: Drop support for Python 3.8 ([`5c448ec`](https://github.com/sandialabs/reverse_argparse/commit/5c448ec9e02cbb61d7f9872730b7c9b40a731035)) 60 | 61 | * Use the type-hinting provided out of the box in 3.9. 62 | * Remove version guards around `argparse.BooleanOptionalAction`. 63 | * Update documentation and CI accordingly. 64 | * chore: Tweak dependabot again ([`1af1398`](https://github.com/sandialabs/reverse_argparse/commit/1af139888af3580b53bef3f3a5c2f7bbfc47728a)) 65 | * chore: Tweak dependabot ([`c4c9252`](https://github.com/sandialabs/reverse_argparse/commit/c4c9252c6f060c8eee3b4ea5878710d2a96243e6)) 66 | 67 | Run weekly instead of daily, and group updates into a single PR for each 68 | packaging ecosystem. 69 | * chore: Update LICENSE/COPYRIGHT info ([`aae82e5`](https://github.com/sandialabs/reverse_argparse/commit/aae82e52fccd0a40dba7fa23e73129b172f63ae7)) 70 | 71 | ### Continuous integration 72 | * ci: Change documentation coverage file name ([`c487d94`](https://github.com/sandialabs/reverse_argparse/commit/c487d94f28f3a160e8d764cc5a7529fe42d3e744)) 73 | * ci: Restrict token permissions ([`dfb85fd`](https://github.com/sandialabs/reverse_argparse/commit/dfb85fdc512526ad4c4513849a3839cb344af369)) 74 | 75 | https://github.com/sandialabs/reverse_argparse/security/code-scanning/21 76 | * ci: Tweak automated suggestions ([`3a73bda`](https://github.com/sandialabs/reverse_argparse/commit/3a73bdabda6608d9bbc2b7f53c94cd12a3282848)) 77 | * ci: Apply security best practices ([`27fd558`](https://github.com/sandialabs/reverse_argparse/commit/27fd5585e7629efed20650c3f134125ccc2efee6)) 78 | 79 | Signed-off-by: StepSecurity Bot 80 | * ci: Don't fix Ruff issues ([`6fb3b58`](https://github.com/sandialabs/reverse_argparse/commit/6fb3b58069d381099d07df0ac4c82d039e2f6e28)) 81 | 82 | Remove the `--fix` argument from the `ruff` check in the pre-commit 83 | configuration. We don't want automated commits pushed to PRs, because 84 | we want to encourage contributors to clean up their branches before 85 | merging. Additionally, when pre-commit doesn't automatically fix files, 86 | it shows the user what the issues are, thereby training them to avoid 87 | them in the future. 88 | 89 | ### Documentation 90 | * docs: Fix highlighting in examples ([`149e48c`](https://github.com/sandialabs/reverse_argparse/commit/149e48c6ef8adabbc11027da17cf88338f3d6318)) 91 | 92 | I never noticed when we added the license and copyright information to 93 | the top of all the source files that we didn't account for the 94 | lines highlighted in the included examples. This adjusts things such 95 | that (1) we don't include all that header stuff when generating the 96 | docs, and only include the lines of code that are really relevant to 97 | share on the examples page, and (2) the appropriate lines are 98 | highlighted. 99 | * docs: Slight tweaks to contributing guidelines ([`6e2ddc9`](https://github.com/sandialabs/reverse_argparse/commit/6e2ddc91c8467d7d6fd58cac13a7c630247348df)) 100 | 101 | ### Testing 102 | * test: Remove unnecessary parentheses ([`7c7d39a`](https://github.com/sandialabs/reverse_argparse/commit/7c7d39a3af7775fe1653bfdb5b6591f28f3b14bf)) 103 | 104 | To align with updated ruff rules. 105 | * test: Ignore subprocess warning in test file ([`90e3cad`](https://github.com/sandialabs/reverse_argparse/commit/90e3cad5799f79cc67ef8fe915b5f0f4fd14542b)) 106 | 107 | This test file uses `subprocess.run()` to run the examples and check 108 | their output. The input to `run()` has been verified and is not a 109 | security vulnerability. 110 | 111 | ## v1.0.8 (2024-05-13) 112 | 113 | ### Chores 114 | * chore: Remove commitizen configuration ([`73ceec1`](https://github.com/sandialabs/reverse_argparse/commit/73ceec1bdb5385744c29cef4eb85385603839ee7)) 115 | * chore: Remove commitizen pre-commit hook ([`18c274f`](https://github.com/sandialabs/reverse_argparse/commit/18c274f5b42764b8bca3527bd49841ae7bc920da)) 116 | 117 | In order to enable a faster development workflow, remove the commitizen 118 | pre-commit hook to allow commits messages that don't adhere to the 119 | Conventional Commits specification. Commit messages are still checked 120 | in the Continuous Integration workflow, though, so a branch will need to 121 | be clean before merging. 122 | 123 | ### Documentation 124 | * docs: Fix license/copyright text in file ([`1d496c1`](https://github.com/sandialabs/reverse_argparse/commit/1d496c1b20da8ee373f41dd08863db222a15876c)) 125 | 126 | Should have been included in b3553415da40949f9ce496ca1363cb69424da791, 127 | but was overlooked. 128 | * docs: Reword Conventional Commits guidelines ([`6659b11`](https://github.com/sandialabs/reverse_argparse/commit/6659b11ea4d855ec48667c5d0fc904ca9f027dbe)) 129 | * docs: Add code lines badge ([`9e4953d`](https://github.com/sandialabs/reverse_argparse/commit/9e4953d7fd43d2f325bfdc66cd6c0c71f5fc454e)) 130 | 131 | ### Patch 132 | * patch: Indicate that the package is typed ([`bd89c55`](https://github.com/sandialabs/reverse_argparse/commit/bd89c55ded9b8d7982ff52b46155e4427ddf629e)) 133 | 134 | According to PEP 561, we need to add this file to static type checkers 135 | can infer the types from the package. 136 | 137 | ### Testing 138 | * test: Ignore assert warnings in test files ([`01f97d0`](https://github.com/sandialabs/reverse_argparse/commit/01f97d037707378cf2fd7c86390c635dfbd5387b)) 139 | 140 | ## v1.0.7 (2024-04-22) 141 | 142 | ### Chores 143 | * chore: Ignore security findings in tests/examples ([`f18ece4`](https://github.com/sandialabs/reverse_argparse/commit/f18ece4a69291b96b84a80bd8eea0a5f51697026)) 144 | * chore: Switch to Ruff ([`6112943`](https://github.com/sandialabs/reverse_argparse/commit/6112943ca3f2a74c0419d8d2452884dd144c8309)) 145 | 146 | Use Ruff to replace a variety of linters/formatters. 147 | * chore: Fix badge URLs ([`2c8dda1`](https://github.com/sandialabs/reverse_argparse/commit/2c8dda1315e1d1297acea0f41a827736258d1950)) 148 | 149 | Somehow it looks like some hidden character wound up copy/pasted in the 150 | middle of the `https`. 151 | * chore: Add PR template ([`eb0b3b8`](https://github.com/sandialabs/reverse_argparse/commit/eb0b3b8da57b0c2a67b4928f4d3ae67890aa5bff)) 152 | 153 | ### Continuous integration 154 | * ci: Add OpenSSF Scorecard workflow ([`5f8f3cf`](https://github.com/sandialabs/reverse_argparse/commit/5f8f3cf299ff64890cbcbc9d0a780095edb337da)) 155 | * ci: auto fixes from pre-commit.com hooks ([`2d05e81`](https://github.com/sandialabs/reverse_argparse/commit/2d05e818be047a42cae0fabd0e42b77b2688c87e)) 156 | 157 | for more information, see https://pre-commit.ci 158 | 159 | ### Documentation 160 | * docs: Add docstrings to test/example files ([`f0b7eb9`](https://github.com/sandialabs/reverse_argparse/commit/f0b7eb96cff1cd6a6360b1e9eba0b66c614c6ac1)) 161 | * docs: Add OpenSSF Scorecard badge to ReadTheDocs ([`91c5557`](https://github.com/sandialabs/reverse_argparse/commit/91c5557f90b3f4ebd3eb71bd6d030133f4085376)) 162 | * docs: Add CodeFactor badge ([`105a394`](https://github.com/sandialabs/reverse_argparse/commit/105a3948b4913ad83e38d718db23e4fecec17150)) 163 | * docs: Adopt Conventional Comments ([`9d16c0c`](https://github.com/sandialabs/reverse_argparse/commit/9d16c0cef5b291710e32a57c788dc06669eee1e2)) 164 | 165 | Try to encourage effective communication via issues/PRs. 166 | * docs: Update link to latest GMS release ([`af2ce45`](https://github.com/sandialabs/reverse_argparse/commit/af2ce4549133ceb306d3f7516bc58a92b6656817)) 167 | * docs: Move copyright/license text to comments ([`b355341`](https://github.com/sandialabs/reverse_argparse/commit/b3553415da40949f9ce496ca1363cb69424da791)) 168 | 169 | In all source files, move the copyright and license text from the module 170 | docstring to comments immediately below it. This is to avoid processing 171 | this text when Sphinx is automatically generating documentation from 172 | docstrings. 173 | * docs: Add contributor license agreement ([`9531c94`](https://github.com/sandialabs/reverse_argparse/commit/9531c944fed6acd3e5a6264343078a97c9e5f581)) 174 | * docs: Update copyright text in source files ([`4cba3d0`](https://github.com/sandialabs/reverse_argparse/commit/4cba3d06877911ce93c7ae95b2fbb37960e10111)) 175 | 176 | Per guidance from Sandia Technology Transfer, the recommended text from 177 | the Linux Foundation is insufficient for our purposes. 178 | * docs: Update copyright/license info ([`4d1d42a`](https://github.com/sandialabs/reverse_argparse/commit/4d1d42a140834293289c8cf7123a3230802935bb)) 179 | 180 | Update the copyright years in the `LICENSE.md` file and add copyright 181 | and license information to all source files (part of the Gold level 182 | OpenSSF Best Practices). 183 | * docs: Add coverage job steps ([`3b20a84`](https://github.com/sandialabs/reverse_argparse/commit/3b20a844bb4912e092d466ec1068726cbf989d56)) 184 | 185 | Add steps to the CI job to compute the documentation coverage for the 186 | package and archive the results. 187 | 188 | ### Patch 189 | * patch: Force `prefer_short` to be keyword-only ([`f02c7f2`](https://github.com/sandialabs/reverse_argparse/commit/f02c7f2eee4861904d3505fd7a6d2cc0fbc5cfc8)) 190 | 191 | Turning on `flake8-boolean-trap` linting via Ruff resulted in the 192 | following findings: 193 | 194 | reverse_argparse/reverse_argparse.py:242:31: 195 | FBT002 Boolean default positional argument in function definition 196 | reverse_argparse/reverse_argparse.py:242:31: 197 | FBT001 Boolean-typed positional argument in function definition 198 | Found 2 errors. 199 | 200 | Switching `prefer_short` from a positional to a keyword-only argument 201 | addresses the problem. 202 | 203 | Note that this is technically a breaking change, but only for a 204 | "private" method, not in the package's public API. Therefore the change 205 | is not registered as a breaking change via Conventional Commit syntax, 206 | and no major version update will be created. Instead, this commit will 207 | force the creation of a patch release. If users were relying on the 208 | prior behavior of this internal method, they can simply switch to the 209 | keyword syntax when calling it. 210 | 211 | ### Refactoring 212 | * refactor: Address Ruff-specific lint findings ([`076e199`](https://github.com/sandialabs/reverse_argparse/commit/076e19951c8fb2241c85d4da063d166292054f25)) 213 | * refactor: Address Pylint findings ([`862bc62`](https://github.com/sandialabs/reverse_argparse/commit/862bc62bee7a61659cb69e668f4a1f1d1e9c0c1f)) 214 | * refactor: Ignore particular type error ([`9d412dd`](https://github.com/sandialabs/reverse_argparse/commit/9d412ddc83a6b0ad5ad3acfb5a520eb0df20086b)) 215 | * refactor: Remove unnecessary shebang lines ([`a7ae1f6`](https://github.com/sandialabs/reverse_argparse/commit/a7ae1f6813797f48f3889d6b362217c55a853079)) 216 | * refactor: Assign exception messages to variables ([`844c71a`](https://github.com/sandialabs/reverse_argparse/commit/844c71ab25ce20ebb22b111524740b2c991f3f29)) 217 | 218 | Running `flake8-errmsg` via Ruff yielded the following findings: 219 | 220 | reverse_argparse/reverse_argparse.py:143:17: 221 | EM102 Exception must not use an f-string literal, assign to variable 222 | first 223 | reverse_argparse/reverse_argparse.py:461:17: 224 | EM102 Exception must not use an f-string literal, assign to variable 225 | first 226 | Found 2 errors. 227 | 228 | This changes resolves the issues. 229 | * refactor: Don't override Python builtins ([`9006adb`](https://github.com/sandialabs/reverse_argparse/commit/9006adbeefdbd08237325d91fbdf7ecf952b386d)) 230 | 231 | ### Testing 232 | * test: Use tuples for parametrize variables ([`25d9be8`](https://github.com/sandialabs/reverse_argparse/commit/25d9be8d014f0159c4328594af84fc723fdad6f9)) 233 | * test: Use UTC timezone with datetime ([`25ff30f`](https://github.com/sandialabs/reverse_argparse/commit/25ff30ff9c19378108db1cc31f367e0a98e189d9)) 234 | 235 | Running `flake8-datetimez` via Ruff yielded the following findings: 236 | 237 | example/test_examples.py:88:25: 238 | DTZ005 `datetime.datetime.now()` called without a `tz` argument 239 | example/test_examples.py:89:25: 240 | DTZ007 Naive datetime constructed using 241 | `datetime.datetime.strptime()` without %z 242 | example/test_examples.py:125:13: 243 | DTZ005 `datetime.datetime.now()` called without a `tz` argument 244 | example/test_examples.py:126:25: 245 | DTZ007 Naive datetime constructed using 246 | `datetime.datetime.strptime()` without %z 247 | Found 4 errors. 248 | 249 | Specifying timezone info resolves the issues. 250 | 251 | ## v1.0.6 (2024-01-15) 252 | 253 | ### Documentation 254 | * docs: Add more badges ([`629857d`](https://github.com/sandialabs/reverse_argparse/commit/629857dc1c926be7cb0aa41b155be42d502822ef)) 255 | 256 | Add additional badges to capture things like contributions, the 257 | conda-forge release channel, etc. 258 | * docs: Include badges in ReadTheDocs ([`e30fc68`](https://github.com/sandialabs/reverse_argparse/commit/e30fc68c9d9ae8dc7a35b016b4024604e23ec5e5)) 259 | 260 | Include the badges from the README in the index page of our 261 | documentation so this information is visible on ReadTheDocs in addition 262 | to GitHub and PyPI. 263 | 264 | Closes #81. 265 | * docs: Private vulnerability reporting ([`9d6a758`](https://github.com/sandialabs/reverse_argparse/commit/9d6a758a95f47922f57eac814ba28e9046ee08e2)) 266 | 267 | Remove the security issue template and instead direct people to file a 268 | private security advisory. 269 | 270 | ### Patch 271 | * patch: Add a badge for the CodeQL action ([`2d77837`](https://github.com/sandialabs/reverse_argparse/commit/2d77837998ca69a46dd7579cbb89e9aa298b0ae4)) 272 | 273 | Create a patch release to push all these new badges out to PyPI. 274 | 275 | ## v1.0.5 (2023-10-24) 276 | 277 | ### Chores 278 | * chore: Update python-semantic-release config ([`9972341`](https://github.com/sandialabs/reverse_argparse/commit/997234115d3ad715ad2adb6b3a092193163a91f8)) 279 | 280 | * Add commit types to automatically bump the minor or patch version 281 | numbers via a commit message. 282 | * Update commitizen configuration to allow the new commit types. 283 | * chore: Add Python 3.12 to pyproject.toml ([`ef59c2d`](https://github.com/sandialabs/reverse_argparse/commit/ef59c2d76c9f51dcae6736dbe91436c647780245)) 284 | 285 | This was accidentally omitted in 286 | 6642a176e3591f3ef8ed0c04dbcbc4a257c5b127. 287 | * chore: Remove YAPF configuration ([`ad02127`](https://github.com/sandialabs/reverse_argparse/commit/ad02127423354c1f42aff78728b9429c24647031)) 288 | 289 | We switched to `black` back in #5. 290 | 291 | ### Continuous integration 292 | * ci: Add Python 3.12 to CI ([`f03f4dc`](https://github.com/sandialabs/reverse_argparse/commit/f03f4dccde7188b8ea545d8bf3b626fefe652745)) 293 | 294 | Also update the version badge to specify particular versions. 295 | * ci: pre-commit autoupdate ([`08fe531`](https://github.com/sandialabs/reverse_argparse/commit/08fe531db0d29044440649a5fee7787ba691858c)) 296 | 297 | updates: 298 | - [github.com/commitizen-tools/commitizen: 3.5.3 → 3.6.0](https://github.com/commitizen-tools/commitizen/compare/3.5.3...3.6.0) 299 | - [github.com/pre-commit/mirrors-mypy: v1.4.1 → v1.5.0](https://github.com/pre-commit/mirrors-mypy/compare/v1.4.1...v1.5.0) 300 | - [github.com/PyCQA/flake8: 6.0.0 → 6.1.0](https://github.com/PyCQA/flake8/compare/6.0.0...6.1.0) 301 | 302 | ### Documentation 303 | * docs: Remove dependency pinning ([`b14034f`](https://github.com/sandialabs/reverse_argparse/commit/b14034fb44f39fec6e9db847053233bd10a24ccd)) 304 | 305 | I should be the case that the bugs that kept us on an older version of 306 | Sphinx have been resolved at this point, so remove the version pinning. 307 | * docs: Add sphinx-copybutton ([`2122825`](https://github.com/sandialabs/reverse_argparse/commit/2122825d7c31ebb91b7dd76af74c5cf61a4bd897)) 308 | 309 | Automatically add a button to all code boxes to copy the contents to the 310 | clipboard. 311 | * docs: Special thanks to @mjsumpter ([`6cc3054`](https://github.com/sandialabs/reverse_argparse/commit/6cc3054bd573da56c57505bcb11d057e38440dcb)) 312 | 313 | Include @mjsumpter in the **Credits** section at the bottom of the 314 | README, as he put together a prior iteration of this concept under my 315 | guidance. His earlier implementation informed the eventual creation of 316 | this package. 317 | * docs: Fix typos ([`eb05c2c`](https://github.com/sandialabs/reverse_argparse/commit/eb05c2ca0b9bca8ada937d382d10185bc03e66e0)) 318 | * docs: Add CI details to contributing guidelines ([`b8269bf`](https://github.com/sandialabs/reverse_argparse/commit/b8269bf0c74a95bf65cddf1fb29eccf6db7b9cf8)) 319 | * docs: Check spelling ([`b72ee11`](https://github.com/sandialabs/reverse_argparse/commit/b72ee11874ae3b03280f623dbe08614aa023d689)) 320 | 321 | Add sphinxcontrib-spelling extension to check the spelling in our 322 | documentation, and add a step to the CI job to ensure all is well. 323 | * docs: Add OpenSSF Best Practices badge ([`604fb61`](https://github.com/sandialabs/reverse_argparse/commit/604fb6127229606c8e36dae4199b538e0ec12248)) 324 | * docs: Fix copy/paste issue ([`2f6517a`](https://github.com/sandialabs/reverse_argparse/commit/2f6517a9ad62412ea246d500170b0de7fe7e0e2f)) 325 | * docs: pre-commit install instructions ([`063d8f9`](https://github.com/sandialabs/reverse_argparse/commit/063d8f977d513f966d10889f7fc14386731a1c80)) 326 | 327 | ### Patch 328 | * patch: Add release notes template ([`a447eac`](https://github.com/sandialabs/reverse_argparse/commit/a447eac820ac9cadf081f1fdfeda1c4d5027552c)) 329 | 330 | * Create a template to govern the generation of release notes by 331 | python-semantic-release. 332 | * Bump the patch version number to test that this works as expected. 333 | 334 | ### Testing 335 | * test: Run examples in CI ([`6642a17`](https://github.com/sandialabs/reverse_argparse/commit/6642a176e3591f3ef8ed0c04dbcbc4a257c5b127)) 336 | 337 | Create `example/test_examples.py` so `pytest` runs all the examples and 338 | checks their output. 339 | 340 | ## v1.0.4 (2023-07-25) 341 | 342 | ### Bug fixes 343 | * fix: PyPI badge ([`1581e2a`](https://github.com/sandialabs/reverse_argparse/commit/1581e2a322caf39bd7a670c5c3f059713b4a43eb)) 344 | 345 | ## v1.0.3 (2023-07-25) 346 | 347 | ### Bug fixes 348 | * fix: Semantic release configuration ([`a73688c`](https://github.com/sandialabs/reverse_argparse/commit/a73688c434c203df0efde316bfdd5934a9ddee63)) 349 | 350 | ## v1.0.2 (2023-07-24) 351 | 352 | ### Bug fixes 353 | * fix: Release notes template ([`1ac839a`](https://github.com/sandialabs/reverse_argparse/commit/1ac839a5bf1a252830dd9bf9267bd049031b7f9b)) 354 | * fix: Semantic release configuration ([`0325dc0`](https://github.com/sandialabs/reverse_argparse/commit/0325dc0cd5dacee541f495652857fe43c9e1a3fe)) 355 | 356 | * Add `__init__.py` to the files modified. 357 | * Fix the `__version__` in that file. 358 | * Remove trailing space in CHANGELOG template. 359 | * Add build command. 360 | * Make release commit match conventional standard. 361 | * Add release notes template. 362 | * Publish releases to PyPI and GitHub Releases. 363 | 364 | ### Continuous integration 365 | * ci: Remove `-vv` for `semantic-release` ([`d83ae5d`](https://github.com/sandialabs/reverse_argparse/commit/d83ae5d1063a43de2822ba513b574745eed5a2e9)) 366 | 367 | ## v1.0.1 (2023-07-20) 368 | 369 | ### Bug fixes 370 | * fix: Include version in __init__.py ([`b7b369e`](https://github.com/sandialabs/reverse_argparse/commit/b7b369ec7ad3e8d58fbe0dd39b4acf2bc17bd568)) 371 | 372 | ### Continuous integration 373 | * ci: Rename workflow file ([`1cfed2d`](https://github.com/sandialabs/reverse_argparse/commit/1cfed2d0bd8833e633f684e717745ac65997d7ad)) 374 | * ci: Add conventional commits job ([`c683d7a`](https://github.com/sandialabs/reverse_argparse/commit/c683d7a9adf415f71816b190954cec4f4be3162d)) 375 | * ci: Set up semantice-release ([`9f233be`](https://github.com/sandialabs/reverse_argparse/commit/9f233bea255a44c5bb8470330c746ca6a951377e)) 376 | 377 | Add a semantic-release configuration to `pyproject.toml`, with a custom 378 | `CHANGELOG.md` template. Also add a GitHub Actions workflow. 379 | 380 | ### Documentation 381 | * docs: Fix PyPI badge ([`edcc3d4`](https://github.com/sandialabs/reverse_argparse/commit/edcc3d4bb77a1b0c6a1ce22928e8a1965f015897)) 382 | 383 | ### Unknown 384 | * 1.0.1 ([`92bdc1a`](https://github.com/sandialabs/reverse_argparse/commit/92bdc1ade70d4b808f3be5a80e20ed6cb65517aa)) 385 | 386 | Automatically generated by python-semantic-release. 387 | 388 | ## v1.0.0 (2023-07-18) 389 | 390 | ### Bug fixes 391 | * fix: Move __init__.py ([`324f3e5`](https://github.com/sandialabs/reverse_argparse/commit/324f3e5b0dbb45144ca2b8afe258f8879b2fe6aa)) 392 | 393 | Part of extracting this package from the repository it was initially 394 | developed in. 395 | * fix: Correct method call ([`27fb201`](https://github.com/sandialabs/reverse_argparse/commit/27fb20153e46ad219a9f532f478f04391d3fb947)) 396 | 397 | Should have been part of 398 | 509fafb33329128ba8985578d66ab1bffe3fdbfb. 399 | * fix: Omit suppressed arguments ([`9484360`](https://github.com/sandialabs/reverse_argparse/commit/948436060be2bfc53c6a1836b806d2c43438772a)) 400 | 401 | If an argument's help text has been suppressed, and the value of the 402 | argument matches the default value, that indicated that a parser author 403 | has hidden an argument from users, and the user hasn't modified it on 404 | the command line. To match the parser author's intent, such arguments 405 | should be omitted from the effective command line invocation. 406 | 407 | ### Chores 408 | * chore: Enable Pyroma ([`124fa62`](https://github.com/sandialabs/reverse_argparse/commit/124fa629790976e0f5a0dcd3813d2aca34ad4cd1)) 409 | * chore: Enable Bandit ([`80e5bbe`](https://github.com/sandialabs/reverse_argparse/commit/80e5bbebf62361e54e53cfe41d55ee0e148ac4fb)) 410 | * chore: Add pre-commit hooks ([`1c2a015`](https://github.com/sandialabs/reverse_argparse/commit/1c2a01524adce4aecb55c7f6b636cdbe81c3e655)) 411 | * chore: Add pre-commit configuration ([`93ba0e7`](https://github.com/sandialabs/reverse_argparse/commit/93ba0e73b748a6b199d5f46f8b22873b6d39d14a)) 412 | * chore: Add VS Code settings ([`cc4edb2`](https://github.com/sandialabs/reverse_argparse/commit/cc4edb2611ed25a8a90751c03c8f69c8221db642)) 413 | * chore: Add __pycache__ to .gitignore ([`48a8acd`](https://github.com/sandialabs/reverse_argparse/commit/48a8acd77bad6b83a735b0540b5b184920715da9)) 414 | 415 | ### Code style 416 | * style: Address black issues ([`f2a8622`](https://github.com/sandialabs/reverse_argparse/commit/f2a86228680942d9b03d231e1d751c8e1aea2094)) 417 | 418 | ### Continuous integration 419 | * ci: Remove documentation jobs ([`81ab9c2`](https://github.com/sandialabs/reverse_argparse/commit/81ab9c230c3a19c8268b878c6e9364e3e1882266)) 420 | 421 | Let ReadTheDocs test the PR instead. 422 | * ci: Add Sphinx job to build the docs ([`671ac18`](https://github.com/sandialabs/reverse_argparse/commit/671ac18a9d6d83c3db4b1ccbe6fd0ca7b9180eb6)) 423 | * ci: Install all development dependencies ([`d8e7cf6`](https://github.com/sandialabs/reverse_argparse/commit/d8e7cf62f07157b8c6786755ed3818c371870526)) 424 | * ci: Switch to CodeCov ([`5899e2f`](https://github.com/sandialabs/reverse_argparse/commit/5899e2fcd3d1132097e05ff8e95f784d9b00cfd9)) 425 | 426 | Abandon Coveralls, as it doesn't seem to integrate well with GitHub 427 | Actions. 428 | * ci: Add Coveralls integration ([`7b19390`](https://github.com/sandialabs/reverse_argparse/commit/7b193900b0d1f20a24845b7a6ad02a784c0e8551)) 429 | * ci: Don't auto-fix PRs ([`cab73e9`](https://github.com/sandialabs/reverse_argparse/commit/cab73e90f4e41e24baae6a1634926e924fb4700c)) 430 | * ci: Switch flake8 ([`477646b`](https://github.com/sandialabs/reverse_argparse/commit/477646b2377bec35370e6f858e57bf2f0a03c5b5)) 431 | 432 | Instead of running `flake8` in our GitHub Actions workflow, run it via 433 | pre-commit.ci. 434 | * ci: Add initial workflow ([`9e42fcd`](https://github.com/sandialabs/reverse_argparse/commit/9e42fcdf0ccc5c7363528d110f0c7e331da30453)) 435 | 436 | Create initial GitHub Actions workflow to lint and test the package. 437 | 438 | ### Documentation 439 | * docs: Prepare for PyPI ([`511e859`](https://github.com/sandialabs/reverse_argparse/commit/511e85998ada5aae0bd61da7e127cfce81a28f51)) 440 | * docs: Fix punctuation. ([`cfc1279`](https://github.com/sandialabs/reverse_argparse/commit/cfc1279b9d614a601886042b905ec562d572f636)) 441 | * docs: Tweak badge ([`369b154`](https://github.com/sandialabs/reverse_argparse/commit/369b1542afd37b53ad0ea32275aa37174ca2e44d)) 442 | * docs: Sort badges in README ([`9db52fe`](https://github.com/sandialabs/reverse_argparse/commit/9db52fe8217eb3f09919b2898de6a816cebe0c62)) 443 | * docs: Add ReadTheDocs badge to README ([`df7e2db`](https://github.com/sandialabs/reverse_argparse/commit/df7e2dbd12a6dd1167448d8f035a503e633b849d)) 444 | * docs: Correct links ([`df1bde3`](https://github.com/sandialabs/reverse_argparse/commit/df1bde3befa88ecda2cbc9f76acca77c5a9099f0)) 445 | 446 | Correct the URL for the documentation hosting on ReadTheDocs. 447 | * docs: Create `_static` directory ([`6d83328`](https://github.com/sandialabs/reverse_argparse/commit/6d833282683190bce42932243f55fc6839e76a8f)) 448 | * docs: Install the package first ([`c00c692`](https://github.com/sandialabs/reverse_argparse/commit/c00c69288e8ef9b9ce49e3d72dbb9db2f7daf2a1)) 449 | 450 | Try to `pip install .` as part of creating the environment for 451 | ReadTheDocs. 452 | * docs: Add ReadTheDocs configuration ([`32e84f1`](https://github.com/sandialabs/reverse_argparse/commit/32e84f16820bb9bcc5ae0769104f408f1866a1ae)) 453 | * docs: Add Sphinx documentation ([`4595541`](https://github.com/sandialabs/reverse_argparse/commit/4595541e4f3fff5809147850294a881696716347)) 454 | 455 | Create the Sphinx-based documentation for the package, including: 456 | 457 | * Getting started guidelines 458 | * The motivation for the package 459 | * Example use cases 460 | * Reference documentation for developers 461 | * docs: Add CI badge to README ([`b14c7dd`](https://github.com/sandialabs/reverse_argparse/commit/b14c7ddd59bfb8f48f8ec0c81e294f7d8cf87a41)) 462 | * docs: Fix contributing guidelines ([`87afd52`](https://github.com/sandialabs/reverse_argparse/commit/87afd52e60b2416407d53c9a8373ec7eceee8381)) 463 | * docs: Address pydocstyle issues ([`1c1d2e2`](https://github.com/sandialabs/reverse_argparse/commit/1c1d2e2f50cdac418d46be231acaa6b5cf349484)) 464 | * docs: Update contributing guidelines ([`7f41b8d`](https://github.com/sandialabs/reverse_argparse/commit/7f41b8dd461d27a7d1bbe33718b6fa225117014b)) 465 | 466 | Translate from GitLab to GitHub. 467 | * docs: Add issue template ([`9e8cfc0`](https://github.com/sandialabs/reverse_argparse/commit/9e8cfc01d6132707ed30d707a78cecf8bb868384)) 468 | * docs: Update Markdown files ([`62c9115`](https://github.com/sandialabs/reverse_argparse/commit/62c9115ae7b2f3ecd888f15fdba165943710ec19)) 469 | 470 | Tweaks to link syntax, etc. 471 | * docs: Update README.md ([`1d69674`](https://github.com/sandialabs/reverse_argparse/commit/1d696743f2c8e4fe9c3858d97c5baffb33d04cf9)) 472 | * docs: Add LICENSE.md ([`72de284`](https://github.com/sandialabs/reverse_argparse/commit/72de2849d5a492a05d083e7f628ed434dd95e578)) 473 | * docs: Make unparse grammar consistent ([`bb55e4d`](https://github.com/sandialabs/reverse_argparse/commit/bb55e4d8d0e36e8376bac30f6b57e030800ac983)) 474 | 475 | Make the spelling of unparse and its derivatives consistent (no 476 | hyphenation, not quoted) in all docstrings and text printed to the 477 | terminal. 478 | 479 | ### Features 480 | * feat: Make private method public ([`509fafb`](https://github.com/sandialabs/reverse_argparse/commit/509fafb33329128ba8985578d66ab1bffe3fdbfb)) 481 | 482 | Since classes/scripts using `reverse_argparse` may also need the ability 483 | to quote a command line argument if there are spaces in it, transition 484 | `quote_arg_if_necessary` from a private to a public method. This will 485 | avoid code duplication outside `reverse_argparse`, and ensure classes 486 | and scripts that are using it are quoting arguments consistently. 487 | * feat: Handle subparsers ([`b2262d5`](https://github.com/sandialabs/reverse_argparse/commit/b2262d561926f3aa75e70fa37e1bd6ad71c5b71a)) 488 | 489 | Enable the unparsing of subparser actions by recursively pushing them 490 | onto the stack of parsers, unparsing them, and popping them back off the 491 | stack. 492 | 493 | Note: This also makes it such that optional arguments are unparsed 494 | before positional ones, as this is required when dealing with 495 | subparsers. 496 | 497 | ### Refactoring 498 | * refactor: Only support Python 3.8+ ([`8d15f4a`](https://github.com/sandialabs/reverse_argparse/commit/8d15f4ab124bb067f5422538050dd7c70b414aa8)) 499 | 500 | Changes that can be undone when we remove 3.8 support: 501 | * Change certain type hints to work for 3.8 502 | * Use version guard around `BooleanOptionalAction` 503 | 504 | Changes that can be undone when we remove 3.9 support: 505 | * Switch match-case statement to if block. 506 | * refactor: Address pylint issues ([`b4555dc`](https://github.com/sandialabs/reverse_argparse/commit/b4555dce7f91278145d2d1ee14bbdd25f8155e77)) 507 | * refactor: Address isort issues ([`fd6242d`](https://github.com/sandialabs/reverse_argparse/commit/fd6242dd5b25261aca064e5d380f4b930970ac60)) 508 | * refactor: Address mypy issues ([`403e53d`](https://github.com/sandialabs/reverse_argparse/commit/403e53da9d1b84e00f8814c90784dcae3f3158cb)) 509 | * refactor!: Build up `args` consecutively ([`d9a5639`](https://github.com/sandialabs/reverse_argparse/commit/d9a5639005824f0fdfb7e8570f2156179998cc71)) 510 | 511 | Rework the class such that: 512 | 513 | * We initialize the `args` to a list of strings containing only the 514 | program name. 515 | * Each `_unparse_*` method appends a list of strings corresponding to 516 | the action to the `args`. 517 | * The `get_*_command_line_invocation` methods appropriately concatenate 518 | the elements in `args` into a single string. 519 | 520 | This sets us up for being able to handle sub-parser actions. 521 | 522 | Note that this is a breaking change, as it removes the `get_*_args` 523 | public methods. 524 | * refactor: Display positional arguments first ([`ccf644d`](https://github.com/sandialabs/reverse_argparse/commit/ccf644daf915b86e82dae4637ed8ff75efbcbd9d)) 525 | 526 | Display positional rather than optional arguments first in the effective 527 | command line. This is necessary to prepare for the ability to handle 528 | sub-parsers. 529 | * refactor: Prepare for nested parsers ([`ec3a7d8`](https://github.com/sandialabs/reverse_argparse/commit/ec3a7d832acc8903bf162792f62ab063175620a2)) 530 | 531 | Change the `parser` attribute to be a list of parsers to prepare for 532 | processing nested parsers. 533 | 534 | ### Testing 535 | * test: Adjust code coverage ([`b7aa09e`](https://github.com/sandialabs/reverse_argparse/commit/b7aa09ec6bd7d2ca09fec1bbce6914f9db5afdfc)) 536 | * test: Rework tests for calling program name ([`8c21452`](https://github.com/sandialabs/reverse_argparse/commit/8c21452ac0909536060828a6a3e3420a64244b01)) 537 | 538 | As part of the transition from GitLab CI/CD to GitHub Actions, the 539 | program name used when running the tests has shifted from `__main__.py` 540 | to `pytest`. This commits adjusts the tests to ignore the program name, 541 | and only pay attention to the arguments that come after it, such that 542 | the tests will work in both contexts. 543 | * test: Fix import ([`65e57ba`](https://github.com/sandialabs/reverse_argparse/commit/65e57bad7a070bbbe7165caec709478d787b27f0)) 544 | 545 | Rework how the tests import the class, given the package reorganization 546 | after pulling it out of the repository it was initially developed in. 547 | 548 | ### Unknown 549 | * [pre-commit.ci] pre-commit autoupdate ([`a88839f`](https://github.com/sandialabs/reverse_argparse/commit/a88839f47b42d84cc24fda1ddf3501d7d9ed0628)) 550 | 551 | updates: 552 | - [github.com/commitizen-tools/commitizen: 3.5.2 → 3.5.3](https://github.com/commitizen-tools/commitizen/compare/3.5.2...3.5.3) 553 | - [github.com/psf/black: 23.3.0 → 23.7.0](https://github.com/psf/black/compare/23.3.0...23.7.0) 554 | * [pre-commit.ci] pre-commit autoupdate ([`f0df3d3`](https://github.com/sandialabs/reverse_argparse/commit/f0df3d32a3d85429e9cc57ac55774292f9613e24)) 555 | 556 | updates: 557 | - [github.com/commitizen-tools/commitizen: 3.3.0 → 3.5.2](https://github.com/commitizen-tools/commitizen/compare/3.3.0...3.5.2) 558 | - [github.com/pre-commit/mirrors-mypy: v1.3.0 → v1.4.1](https://github.com/pre-commit/mirrors-mypy/compare/v1.3.0...v1.4.1) 559 | * [pre-commit.ci] pre-commit autoupdate ([`fd58d13`](https://github.com/sandialabs/reverse_argparse/commit/fd58d135f92fc227c37cdd908bf9acacaca246eb)) 560 | 561 | updates: 562 | - [github.com/commitizen-tools/commitizen: 3.2.2 → 3.3.0](https://github.com/commitizen-tools/commitizen/compare/3.2.2...3.3.0) 563 | * Add more issue templates ([`234b562`](https://github.com/sandialabs/reverse_argparse/commit/234b562299a42cb4eb1aa003b76a6fb9e8be3a2b)) 564 | * Add CHANGELOG.md ([`7bcc39d`](https://github.com/sandialabs/reverse_argparse/commit/7bcc39d3dc1691243f3af4bab16d9f188173b215)) 565 | * Add CONTRIBUTING.md ([`2b6dfc0`](https://github.com/sandialabs/reverse_argparse/commit/2b6dfc0b7c27666a672f370e978d8dae38395bd8)) 566 | * Add CODE_OF_CONDUCT.md ([`acbac7d`](https://github.com/sandialabs/reverse_argparse/commit/acbac7d6d40ec3771d6c009f0fc6488c2036a370)) 567 | * Add SECURITY.md ([`4ef978c`](https://github.com/sandialabs/reverse_argparse/commit/4ef978c7f221071d85e062fb16ce1430f696233a)) 568 | * Add README.md ([`4a0580c`](https://github.com/sandialabs/reverse_argparse/commit/4a0580cc0cbbdb7334a19d392ffd61cea252a3c5)) 569 | * Move __init__.py ([`c50bcd2`](https://github.com/sandialabs/reverse_argparse/commit/c50bcd27ad916376eb9d6fd11fa6236af69dca52)) 570 | * Add setup.py ([`1de083b`](https://github.com/sandialabs/reverse_argparse/commit/1de083b532f1aac92b692e304a0f3a4c579dd660)) 571 | * Add requirements.txt ([`75aa526`](https://github.com/sandialabs/reverse_argparse/commit/75aa52698241ff7ade31cfad6d3fc5269d24e92a)) 572 | * Add pyproject.toml ([`e833969`](https://github.com/sandialabs/reverse_argparse/commit/e8339695aee00086d0361475adc8b374106adcd8)) 573 | * Add .style.yapf ([`13d6301`](https://github.com/sandialabs/reverse_argparse/commit/13d63014fbbc999d1d11a235273f45c5b5ec9126)) 574 | * Add .gitignore ([`1c329cf`](https://github.com/sandialabs/reverse_argparse/commit/1c329cff71cc4c6e443539d3dcb3e65878af5530)) 575 | * Add .coveragerc ([`b43be41`](https://github.com/sandialabs/reverse_argparse/commit/b43be411421851129b3b022fbd79eb9a71a727cf)) 576 | * Unparse `BooleanOptionalAction` ([`cd82066`](https://github.com/sandialabs/reverse_argparse/commit/cd82066fbd080a48d8ae4e87d0ef23379234bbdd)) 577 | * Unparse `extend` action ([`3e9fbd3`](https://github.com/sandialabs/reverse_argparse/commit/3e9fbd380c5eade477d4cec2572397c451274cc7)) 578 | * Unparse `count` action ([`224b23b`](https://github.com/sandialabs/reverse_argparse/commit/224b23baa583d0581714906ef35d60fed5f8b724)) 579 | * Unparse `append_const` action ([`b22390a`](https://github.com/sandialabs/reverse_argparse/commit/b22390a3a854a92f31a14fd65a9844173c5dbb99)) 580 | * Unparse `store_const` action ([`64cc273`](https://github.com/sandialabs/reverse_argparse/commit/64cc2738ff6aceb66d814f588678c17b5085e46a)) 581 | * Create `reverse_argparse` module (#1873) ([`1ab310c`](https://github.com/sandialabs/reverse_argparse/commit/1ab310c697a31689dd52f97fcc26f05c00dcfb21)) 582 | 583 | Create a module that is able to generate the effective command line 584 | invocation of a script, given the `ArgumentParser` that was used to 585 | parse the command line options, and the `Namespace` of those parsed 586 | options. This makes it such that users can know exactly what was run, 587 | including all default values, and any transformations that might've been 588 | made to the arguments after parsing. 589 | 590 | This commit only implements the functionality we care about at the 591 | moment, which includes the following "actions": 592 | * store 593 | * store_true 594 | * store_false 595 | * append 596 | * help 597 | * version 598 | 599 | The remaining actions are stubbed out but not yet implemented: 600 | * store_const 601 | * append_const 602 | * count 603 | * extend 604 | * BooleanOptionalAction 605 | 606 | Also how sub-parsers are handled remains to be determined in the future. 607 | -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Contributor Covenant Code of Conduct 2 | 3 | ## Our Pledge 4 | 5 | We as members, contributors, and leaders pledge to make participation in our 6 | community a harassment-free experience for everyone. We pledge to act and 7 | interact in ways that contribute to an open, welcoming, and healthy community. 8 | 9 | ## Our Standards 10 | 11 | Examples of behavior that contributes to a positive environment for our 12 | community include: 13 | 14 | * Demonstrating understanding and kindness toward other people 15 | * Being respectful of differing opinions, viewpoints, and experiences 16 | * Giving and gracefully accepting constructive feedback 17 | * Accepting responsibility and apologizing to those affected by our mistakes, 18 | and learning from the experience 19 | * Focusing on what is best not just for us as individuals, but for the overall 20 | community 21 | 22 | Examples of unacceptable behavior include: 23 | 24 | * The use of sexualized language or imagery, and sexual attention or advances of 25 | any kind 26 | * Trolling, insulting or derogatory comments, and personal or political attacks 27 | * Public or private harassment 28 | * Publishing others' private information, such as a physical or email address, 29 | without their explicit permission 30 | * Other conduct which could reasonably be considered inappropriate in a 31 | professional setting 32 | 33 | ## Enforcement Responsibilities 34 | 35 | Community leaders are responsible for clarifying and enforcing our standards of 36 | acceptable behavior and will take appropriate and fair corrective action in 37 | response to any behavior that they deem inappropriate, threatening, offensive, 38 | or harmful. 39 | 40 | Community leaders have the right and responsibility to remove, edit, or reject 41 | comments, commits, code, wiki edits, issues, and other contributions that are 42 | not aligned to this Code of Conduct, and will communicate reasons for moderation 43 | decisions when appropriate. 44 | 45 | ## Scope 46 | 47 | This Code of Conduct applies within all community spaces, and also applies when 48 | an individual is officially representing the community in public spaces. 49 | Examples of representing our community include using an official e-mail address, 50 | posting via an official social media account, or acting as an appointed 51 | representative at an online or offline event. 52 | 53 | ## Enforcement 54 | 55 | Instances of abusive, harassing, or otherwise unacceptable behavior may be 56 | reported to the community leaders responsible for enforcement by emailing 57 | jmgate@sandia.gov. All complaints will be reviewed and investigated promptly 58 | and fairly. 59 | 60 | All community leaders are obligated to respect the privacy and security of the 61 | reporter of any incident. 62 | 63 | ## Enforcement Guidelines 64 | 65 | Community leaders will follow these Community Impact Guidelines in determining 66 | the consequences for any action they deem in violation of this Code of Conduct: 67 | 68 | ### 1. Correction 69 | 70 | **Community Impact**: Use of inappropriate language or other behavior deemed 71 | unprofessional or unwelcome in the community. 72 | 73 | **Consequence**: A private, written warning from community leaders, providing 74 | clarity around the nature of the violation and an explanation of why the 75 | behavior was inappropriate. A public apology may be requested. 76 | 77 | ### 2. Warning 78 | 79 | **Community Impact**: A violation through a single incident or series of 80 | actions. 81 | 82 | **Consequence**: A warning with consequences for continued behavior. No 83 | interaction with the people involved, including unsolicited interaction with 84 | those enforcing the Code of Conduct, for a specified period of time. This 85 | includes avoiding interactions in community spaces as well as external channels 86 | like social media. Violating these terms may lead to a temporary or permanent 87 | ban. 88 | 89 | ### 3. Temporary Ban 90 | 91 | **Community Impact**: A serious violation of community standards, including 92 | sustained inappropriate behavior. 93 | 94 | **Consequence**: A temporary ban from any sort of interaction or public 95 | communication with the community for a specified period of time. No public or 96 | private interaction with the people involved, including unsolicited interaction 97 | with those enforcing the Code of Conduct, is allowed during this period. 98 | Violating these terms may lead to a permanent ban. 99 | 100 | ### 4. Permanent Ban 101 | 102 | **Community Impact**: Demonstrating a pattern of violation of community 103 | standards, including sustained inappropriate behavior, harassment of an 104 | individual, or aggression toward or disparagement of classes of individuals. 105 | 106 | **Consequence**: A permanent ban from any sort of public interaction within the 107 | community. 108 | 109 | ## Attribution 110 | 111 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], 112 | version 2.1, available at 113 | [https://www.contributor-covenant.org/version/2/1/code_of_conduct.html][v2.1]. 114 | 115 | Community Impact Guidelines were inspired by 116 | [Mozilla's code of conduct enforcement ladder][Mozilla CoC]. 117 | 118 | For answers to common questions about this code of conduct, see the FAQ at 119 | [https://www.contributor-covenant.org/faq][FAQ]. Translations are available at 120 | [https://www.contributor-covenant.org/translations][translations]. 121 | 122 | [homepage]: https://www.contributor-covenant.org 123 | [v2.1]: https://www.contributor-covenant.org/version/2/1/code_of_conduct.html 124 | [Mozilla CoC]: https://github.com/mozilla/diversity 125 | [FAQ]: https://www.contributor-covenant.org/faq 126 | [translations]: https://www.contributor-covenant.org/translations 127 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing to reverse_argparse 2 | 3 | Thanks so much for your willingness to help out with `reverse_argparse`'s 4 | development :grinning: Here's everything you need to know. 5 | 6 | 7 | 8 | ## Contributor License Agreement 9 | 10 | By contributing to this software project, you are agreeing to the following 11 | terms and conditions for your contributions: 12 | 13 | * You agree your contributions are submitted under the 14 | [license used by this project](LICENSE.md). 15 | * You represent you are authorized to make the contributions and grant the 16 | license. If your employer has rights to intellectual property that includes 17 | your contributions, you represent that you have received permission to make 18 | contributions and grant the required license on behalf of that employer. 19 | 20 | 21 | 22 | ## Setting Up Your Environment 23 | 24 | Before you begin hacking on `reverse_argparse`, you'll need to do four things: 25 | 26 | 1. **Fork the Repository:** On [`reverse_argparse`'s main page][homepage], in 27 | the top-right corner, you'll see a button to [fork the repository][fork]. 28 | Do so, and then clone your fork and set it up with 29 | ```bash 30 | git clone git@github.com:${USER}/reverse_argparse 31 | cd reverse_argparse 32 | git remote add upstream git@github.com:sandialabs/reverse_argparse 33 | git fetch upstream 34 | ``` 35 | 2. **Set Up your Environment:** Install the requirements with 36 | ```bash 37 | cd /path/to/reverse_argparse 38 | python3 -m pip install \ 39 | -r requirements.txt \ 40 | -r doc/requirements.txt \ 41 | -r example/requirements.txt \ 42 | -r test/requirements.txt 43 | ``` 44 | 3. **Run the Examples:** Ensure you can run all the examples with 45 | ```bash 46 | cd /path/to/reverse_argparse/example 47 | ./run-all.bash 48 | ``` 49 | 4. **Build the Documentation:** Ensure you can build the documentation with 50 | ```bash 51 | cd /path/to/reverse_argparse/doc 52 | ./make-html.bash 53 | ``` 54 | 55 | [homepage]: https://github.com/sandialabs/reverse_argparse 56 | [fork]: https://docs.github.com/en/get-started/quickstart/fork-a-repo 57 | 58 | ### Pre-Commit 59 | 60 | We use [pre-commit][precommit] to ensure adherence to Python best practices, 61 | enforce our style guide, etc. To set yourself up with it, ensure you have your 62 | development environment activated, and then run 63 | ```bash 64 | cd /path/to/reverse_argparse 65 | pre-commit install 66 | pre-commit install --hook-type commit-msg --hook-type pre-push 67 | ``` 68 | 69 | [precommit]: https://pre-commit.com/ 70 | 71 | The checks we perform are the following: 72 | * Use [ruff][ruff] to lint and format the code and docstrings. 73 | * Use [mypy][mypy] to run static type checking on our type-hinted code. 74 | * Ensure no large files are added to the repository. 75 | * Ensure files parse as valid Python. 76 | * Check for files that would conflict in case-sensitive filesystems. 77 | * Ensure files don't contain merge conflict strings. 78 | * Ensure files end with a single blank line. 79 | * Ensure we only use Unix line endings. 80 | * Trim trailing whitespace. 81 | * Ensure we use [type-hinting][typing]. 82 | * Check for common mistakes in [reStructuredText][rest] in our documentation. 83 | * Use [doc8][doc8] to enforce our style for our documentation. 84 | * Use [pyroma][pyroma] to ensure our package complies with the best practices 85 | of the Python packaging ecosystem. 86 | 87 | [ruff]: https://docs.astral.sh/ruff/ 88 | [mypy]: https://github.com/python/mypy 89 | [typing]: https://docs.python.org/3/library/typing.html 90 | [rest]: https://www.sphinx-doc.org/en/master/usage/restructuredtext/basics.html 91 | [doc8]: https://github.com/PyCQA/doc8 92 | [pyroma]: https://github.com/regebro/pyroma 93 | 94 | ### VS Code 95 | 96 | Our IDE of choice is [VS Code][vscode]. Download and install it, and then 97 | follow the instructions below to get it set up. 98 | 99 | [vscode]: https://code.visualstudio.com/ 100 | 101 | #### Getting Started 102 | 103 | For getting up and running with VS Code, check out the following resources: 104 | 105 | * [Visual Studio Code: Introductory Videos][videos] 106 | * [Visual Studio Code: Getting Started][gettingstarted] documentation 107 | * [Python Development in Visual Studio Code][pyvscode] from 108 | [RealPython.com][realpython] 109 | * [Advanced Visual Studio Code for Python Developers][advanced] from 110 | [RealPython.com][realpython] 111 | * One-page reference of keyboard shortcuts for [Linux][linux], [MacOS][mac], 112 | and [Windows][win] 113 | 114 | [videos]: https://code.visualstudio.com/docs/getstarted/introvideos 115 | [gettingstarted]: https://code.visualstudio.com/docs 116 | [pyvscode]: https://realpython.com/python-development-visual-studio-code/ 117 | [realpython]: http://realpython.com/ 118 | [advanced]: https://realpython.com/advanced-visual-studio-code-python/ 119 | [linux]: https://code.visualstudio.com/shortcuts/keyboard-shortcuts-linux.pdf 120 | [mac]: https://code.visualstudio.com/shortcuts/keyboard-shortcuts-macos.pdf 121 | [win]: https://code.visualstudio.com/shortcuts/keyboard-shortcuts-windows.pdf 122 | 123 | #### Extensions 124 | 125 | VS Code is highly customizable through the use of extensions. Click on the 126 | building blocks icon on the left-hand side to open the **EXTENSIONS** panel to 127 | search for and install them. These are the ones we recommend: 128 | 129 | **General** 130 | * **Better Comments:** Style comments in a more human-friendly manner. 131 | * **Code Spell Checker:** Catch spelling mistakes in code and comments. 132 | * **Conventional Commits:** Adhere to the [Conventional Commits][conventional] 133 | specification for commit messages. 134 | * **Coverage Gutters:** Display test coverage in the editor. 135 | * **GitLens — Git supercharged:** Integrate some of the powerful features of 136 | [GitKraken][kraken] into VS Code. 137 | * **IntelliCode:** AI-assisted development features. 138 | * **Pre-Commit:** Commands and helpers for executing pre-commit hooks. 139 | * **Test Adapter Converter:** Converts from the Test Explorer UI (below) API 140 | to native VS Code testing. 141 | * **Test Explorer UI:** Extensible user interface for running your tests in VS 142 | Code. 143 | * **Vim:** For when you can't truly leave vi behind (and who would want to?). 144 | * **vscode-icons:** Icons for the file explorer. 145 | 146 | [conventional]: https://www.conventionalcommits.org/en/v1.0.0/ 147 | [kraken]: https://www.gitkraken.com/ 148 | 149 | **Python-Specific** 150 | * **AREPL for python:** Automatically evaluate Python code as you type in the 151 | editor. 152 | * **autoDocstring - Python Docstring Generator:** Quickly generate docstrings 153 | for Python functions. 154 | * **Mpy Type Checker:** Type checking support for Python. 155 | * **Pylance:** Fast, feature-rich language support for Python. 156 | * **Pytest IntelliSense:** Adds IntelliSense support for [pytest][pytest] 157 | fixtures. 158 | * **Python:** Rich support for the Python language. 159 | * **Python Indent:** Correct Python indentation. 160 | * **Python Test Explorer:** Run your [unittest][unittest], [pytest][pytest], 161 | or [testplan][testplan] tests with the Test Explorer UI (see **General** 162 | above). 163 | * **Python Type Hint:** Type hint autocompletion. 164 | * **Ruff:** Automatic linting and formatting. 165 | * **Sourcery:** Automatic code review and refactoring. 166 | 167 | [unittest]: https://docs.python.org/3/library/unittest.html 168 | [testplan]: https://github.com/morganstanley/testplan 169 | 170 | #### Settings 171 | 172 | After installing the various extensions, you'll also want to customize your 173 | **Settings**. Some things can be set in the [Settings editor][settings]: 174 | 175 | [settings]: https://code.visualstudio.com/docs/getstarted/settings#_settings-editor 176 | 177 | * Text Editor 178 | * Font 179 | * **Font Family:** Add "'Hack FC Ligatured', " to the beginning of the 180 | list. You'll also want to install the [Ligatured Hack fonts][hack] on 181 | your system. 182 | * Files 183 | * **Auto Save:** Set to "onFocusChange". 184 | * **Trim Trailing Whitespace:** Check. 185 | * Extensions 186 | * Conventional Commits 187 | * **Show Editor:** Check. 188 | * **Silent Auto Commit:** Check. 189 | * coverage-gutters 190 | * **Coverage-gutters: Show Line Coverage:** Check. 191 | * **Coverage-gutters: Show Ruler Coverage:** Check. 192 | * Git 193 | * **Allow Force Push:** Check. 194 | * **Autofetch:** Set to "true". 195 | * **Enable Smart Commit:** Check. 196 | * **Fetch On Pull:** Check. 197 | * **Prune On Fetch:** Check. 198 | * **Rebase When Sync:** Check. This makes it such that you use `git pull 199 | --rebase` when pulling. 200 | * **Show Push Success Notification:** Check. 201 | * **Terminal Git Editor:** Check. 202 | * pre-commit-helper 203 | * **Run On Save:** Select "all hooks". 204 | * Python Docstring Generator configuration 205 | * **Docstring Format:** Select "google-notypes". 206 | * **Start On New Line:** Check. 207 | * Sourcery Configuration: 208 | * **Token:** [Create a free Sourcery account][sourcery], generate a token, 209 | and paste it here. 210 | * Vim 211 | * **Vimrc:** Enable: Check. 212 | 213 | [hack]: https://github.com/gaplo917/Ligatured-Hack 214 | [sourcery]: https://sourcery.ai/ 215 | 216 | Other items can be customized in the [`settings.json` file][settingsjson]. 217 | Consider adding the following snippets: 218 | 219 | [settingsjson]: https://code.visualstudio.com/docs/getstarted/settings#_settingsjson 220 | 221 | * To use ligatures to make multi-character symbols in code more readable, add 222 | ```json 223 | "editor.fontLigatures": true, 224 | ``` 225 | * To add vertical rulers to the editor window, add 226 | ```json 227 | "editor.rulers": [ 228 | 72, 229 | 79 230 | ], 231 | ``` 232 | The line at 79 characters is to remind you of the maximum line length, and 233 | the one at 72 characters is to remind you of the maximum line length for 234 | comments and docstrings (see [PEP8][pep8]). 235 | * If you'd like the UI to preserve the scope that you're currently editing at 236 | the top of the file as you scroll through it, you can add 237 | ```json 238 | "editor.experimental.stickyScroll.enabled": true, 239 | ``` 240 | * To turn on search highlighting when using the Vim extension, add 241 | ```json 242 | "vim.hlsearch": true, 243 | ``` 244 | * To set up `pytest`, such that it produces coverage information, add 245 | ```json 246 | "python.testing.unittestEnabled": false, 247 | "python.testing.pytestEnabled": true, 248 | "python.testing.pytestArgs": [ 249 | "-v", 250 | "--cov", 251 | "--cov-report=html", 252 | "--cov-report=json", 253 | "--cov-report=xml", 254 | "." 255 | ], 256 | ``` 257 | 258 | [pep8]: https://peps.python.org/pep-0008/#maximum-line-length 259 | 260 | A final setting needs to be configured in the [`launch.json` file][launchjson]. 261 | You'll need to add the following to the list of configurations: 262 | ```json 263 | "configurations": [ 264 | { 265 | ... # Existing configuration. 266 | }, 267 | { 268 | "name": "Python: Debug Tests", 269 | "type": "python", 270 | "request": "launch", 271 | "program": "${file}", 272 | "purpose": ["debug-test"], 273 | "console": "integratedTerminal", 274 | "env": { 275 | "PYTEST_ADDOPTS": "--no-cov" 276 | }, 277 | "justMyCode": false 278 | } 279 | ] 280 | ``` 281 | This will make it such that when debugging unit testing, the debugger doesn't 282 | restrict itself to only your code. 283 | 284 | [launchjson]: https://code.visualstudio.com/docs/editor/debugging#_launch-configurations 285 | 286 | #### Choosing a Python Interpreter 287 | 288 | Once you've taken care of all the settings above, you're almost ready to start 289 | Python development with VS Code. Before you do, though, you'll need to select 290 | your Python interpreter. Open the command palette, start typing "python 291 | interpreter," and select **Python: Select Interpreter**. It will pop up a list 292 | of Python installations it could find on your system. Pick the one that 293 | corresponds to your development environment (see 294 | [above](#setting-up-your-environment)). 295 | 296 | #### Setting Up PyTest 297 | 298 | The last step in setting up VS Code for Python development is to ensure 299 | `pytest` is working. Click on the flask icon on the left-hand side to open the 300 | **TESTING** panel on the left. There will be two collapsible sections labeled 301 | **TEST EXPLORER**. Collapse the top one (it comes from an extension that 302 | doesn't quite work for Python testing), and expand the bottom one. You should 303 | be able to hover over a test file, click the play button, and see the tests 304 | pass. If so, go ahead and click the three dots at the top-right of the 305 | **TESTING** panel and deselect the top **Test Explorer**. 306 | 307 | Running your test suite will generate code coverage information, which you can 308 | then view in the editor. After you've run your tests, open up one of your code 309 | files, open the command palette, type "coverage," and select 310 | **Coverage-Gutters: Toggle Coverage**. This will highlight covered and 311 | uncovered lines in green and red, respectively. You can also view the full 312 | coverage report by opening `test/htmlcov/index.html`. 313 | 314 | 315 | 316 | ## Coding Standards 317 | 318 | Many of our coding standards are applied and enforced using 319 | [pre-commit][precommit] (see [above](#pre-commit)). In addition to what's 320 | handled automatically, we have the following. 321 | 322 | ### Documentation 323 | 324 | Classes and functions should be documented with [docstrings][docstrings] using 325 | the [Google-style][google] format. The contents of docstrings should use 326 | [reStructuredText][rest] formatting. This is so we can use [Sphinx][sphinx] to 327 | generate [our documentation][docs]. Additionally, function definitions should 328 | utilize [type-hinting][typing] wherever possible for clarity's sake. 329 | 330 | [docstrings]: https://www.python.org/dev/peps/pep-0257 331 | [google]: https://github.com/google/styleguide/blob/gh-pages/pyguide.md#38-comments-and-docstrings 332 | [docs]: https://reverse-argparse.readthedocs.io 333 | [sphinx]: https://www.sphinx-doc.org/en/master/ 334 | 335 | ### Testing 336 | 337 | We use [pytest][pytest] for our unit test suite. To get up-to-speed with what 338 | it does and how it works, check out [this RealPython tutorial][tutorial]. Also 339 | highly recommended is [Python Testing with pytest, by Brian Okken][okken]. 340 | 341 | [pytest]: https://docs.pytest.org/ 342 | [tutorial]: https://realpython.com/pytest-python-testing/ 343 | [okken]: https://www.amazon.com/Python-Testing-pytest-Effective-Scalable/dp/1680502409/ref=sr_1_2?keywords=pytest&qid=1637712723&sr=8-2 344 | 345 | Please add tests to cover any new functions you create, and adhere to the 346 | following guidelines: 347 | * Each module (`module_name.py`) should have a corresponding test file 348 | (`test_module_name.py`). 349 | * Each function/method in a module should have at least one corresponding test. 350 | * The test order should match the ordering of the functions/methods being 351 | tested in the module, such that users can easily scroll through the two files 352 | side-by-side. 353 | * Prefer parametrizing a test function over creating a separate test function. 354 | * But don't go too crazy with that—use your judgment. 355 | * Place any fixture definitions at the top of the test file. 356 | 357 | ### Best Practices 358 | 359 | * Docstrings and comments should be grammatically correct English 360 | (capitalization, punctuation, full sentences, etc.). 361 | * Prefer double quotes over single quotes. 362 | * Use `pathlib.Path` and associated methods to represent all path-like objects. 363 | * Use [f-strings][fstrings] for formatting strings. 364 | * Alphabetize class attributes in the docstring and `__init__()` to ease 365 | readability/maintainability/extensibility. 366 | * Prefer alphabetizing keyword arguments to functions, unless a different 367 | ordering would be more logical in a specific situation. 368 | * Blank lines in functions should be avoided unless preceding a comment 369 | indicating a section of code. However, if your function is broken up into 370 | sections via comments, consider subdividing it into smaller functions. 371 | * Prefer imports of the form 372 | ```python 373 | from package import Class 374 | ``` 375 | as opposed to 376 | ```python 377 | import package 378 | ``` 379 | if only using a small handful of things from the package. 380 | 381 | [fstrings]: https://peps.python.org/pep-0498/ 382 | 383 | 384 | 385 | ## Creating Issues 386 | 387 | Create [issues][issues] in GitHub for any work that needs to be done. 388 | 389 | [issues]: https://github.com/sandialabs/reverse_argparse/issues 390 | 391 | ### Markdown 392 | 393 | [Markdown][markdown] is a lightweight markup language with plain text 394 | formatting syntax. GitHub uses a form of it for rendering issue and pull 395 | request descriptions and comments, wiki pages, and any files in your 396 | repositories with a `.md` extension (such as this one). For more details on 397 | what's possible with GitHub-flavored Markdown, [see the documentation][gfm]. 398 | 399 | [markdown]: https://en.wikipedia.org/wiki/Markdown 400 | [gfm]: https://docs.github.com/en/get-started/writing-on-github/getting-started-with-writing-and-formatting-on-github/basic-writing-and-formatting-syntax 401 | 402 | ### Issue Templates 403 | 404 | When creating an issue, select one of the available issue templates, and then 405 | follow the instructions that appear in the template. 406 | 407 | ### Labels 408 | 409 | The [reverse_argparse > Labels][labels] page shows you all the labels we use, 410 | along with their descriptions. "Type" labels will be applied automatically 411 | when an issue is created via the issue template. "Stage" labels are used to 412 | keep track of what work is being done at any given time. Other labels can be 413 | added as appropriate. 414 | 415 | [labels]: https://github.com/sandialabs/reverse_argparse/labels 416 | 417 | 418 | 419 | ## Working Issues 420 | 421 | ### Planning Work 422 | 423 | Depending on the needs of the `reverse_argparse` user base, a project 424 | maintainer will schedule issues to be tackled in the near future by applying 425 | the "Stage: Soon" label. An issue can then be grabbed by a member of the 426 | development team when they have some time available to work on it. 427 | 428 | > **Note:** If you're working on something that hasn't been 429 | > scheduled—e.g., you're tackling a quick bug fix, or are tinkering with 430 | > a feature you'd like to see added—don't worry about the "Stage: Soon" 431 | > label; just work on it as per the rest of the guidelines below. 432 | 433 | ### When Work Begins 434 | 435 | First switch the label from "Stage: Soon" to "Stage: Development". Next make 436 | sure your local `master` branch is up-to-date with 437 | ```bash 438 | git checkout master 439 | git pull --ff-only upstream master 440 | ``` 441 | 442 | > **Note:** You should never be making commits on your `master` branch. The 443 | > `--ff-only` ensures you only update your local `master` branch if it can be 444 | > fast-forwarded. 445 | 446 | Once `master` is updated, you then create a feature branch off of it with 447 | ```bash 448 | git checkout -b 449 | ``` 450 | 451 | The recommended branch naming convention is to use the issue number, followed 452 | by a hyphen, followed by the issue title, all lowercase, omitting special 453 | characters, and replacing spaces with hyphens. For instance, if issue number 454 | 123 has "Implement Awesome New Feature" as the title, the corresponding branch 455 | name would be `123-implement-awesome-new-feature`. 456 | 457 | ### As Work Continues 458 | 459 | Do whatever work is necessary to address the issue you're tackling. Break your 460 | work into logical, working commits. Use the **Conventional Commits** extension 461 | for VS Code (or something similar) to ensure your commit messages adhere to the 462 | [Conventional Commits specification][conventional]. 463 | 464 | Feel free to commit and push small chunks early and often and then use 465 | interactive rebase to reorganize your commits before sharing. 466 | 467 | > **Note:** If you rebase a branch that's already been pushed to a remote, 468 | > you'll wind up changing the history, which will require a force push. That 469 | > is permissible (even encouraged), but if you've had one or more reviewers or 470 | > collaborators working with you on the branch, *get their buy-in first* before 471 | > doing a force push. 472 | 473 | ### When Work is Complete 474 | 475 | While working on your feature in your local `` branch, other 476 | commits will likely make it into the upstream `master` branch. There are a 477 | variety of ways to merge these changes into your local feature branch. One 478 | possibility is 479 | ```bash 480 | git checkout master 481 | git pull --ff-only upstream master 482 | git checkout 483 | git rebase master 484 | ``` 485 | 486 | though there are others that are equally valid. Once all is well, create a 487 | pull request (see below). 488 | 489 | ### Closing Old Issues 490 | 491 | If at any point you encounter an issue that will not be worked in the 492 | foreseeable future, it is worthwhile to close the issue such that we can 493 | maintain a reasonable backlog of upcoming work. Do be sure to include in the 494 | comments some explanation as to why the issue won't be addressed. 495 | 496 | 497 | 498 | ## Pull Requests 499 | 500 | The only way changes get into `master` is through pull requests. When you've 501 | completed work on an issue, push your branch to your fork with `git push -u 502 | origin `, and then create a pull request. Apply the same "Type" 503 | label as the issue, and then return to the issue and swap "Stage: Development" 504 | for "Stage: Review". 505 | 506 | ### Reviews 507 | 508 | A project maintainer will review your pull request. Work with them to get your 509 | changes into an acceptable state. 510 | 511 | ### Drafts 512 | 513 | You may wish to have your changes reviewed by colleagues before they are ready 514 | to be merged into `master`. To do so, create a [draft pull request][drafts]. 515 | GitHub will not allow you to merge a draft request. When it's ready for 516 | review, you can [mark it as ready][ready]. 517 | 518 | [drafts]: https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/proposing-changes-to-your-work-with-pull-requests/about-pull-requests#draft-pull-requests 519 | [ready]: https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/proposing-changes-to-your-work-with-pull-requests/changing-the-stage-of-a-pull-request#marking-a-pull-request-as-ready-for-review 520 | 521 | ### Continuous Integration 522 | 523 | GitHub Actions is GitHub's continuous integration and delivery (CI/CD) 524 | mechanism. The configurations for our workflows can be found in the `*.yml` 525 | files in [the `.github/workflows` directory](.github/workflows) in the 526 | repository root: 527 | * **Continuous Integration:** This workflow runs a `test` job, parametrized 528 | across the currently maintained versions of Python, to ensure unit testing 529 | passes, and a `commits` job to ensure we're adhering to the [Conventional 530 | Commits specification][conventional]. 531 | * **Semantic Release:** This workflow runs on merges to `master` to 532 | automatically generate and publish new releases, based on the commits just 533 | merged. 534 | 535 | In addition to the GitHub Actions workflows, we also integrate with the 536 | following services: 537 | * [Codecov][codecov]: We calculate and publish code coverage details for all 538 | PRs and merged into `master`, and the service comments on PRs indicating any 539 | changes in coverage compared to the base branch. 540 | * [ReadTheDocs][readthedocs]: We ensure our documentation builds for all PRs, 541 | and the documentation is published for `master` and all release tags. 542 | * [pre-commit.ci][precommitci]: We ensure all the `pre-commit` checks we 543 | encourage developers to run locally also run in CI. 544 | 545 | [codecov]: https://about.codecov.io/ 546 | [readthedocs]: https://about.readthedocs.com/?ref=readthedocs.org 547 | [precommitci]: https://pre-commit.ci/ 548 | 549 | ### Merging 550 | 551 | When the review is finished and changes are ready to be merged into `master`: 552 | 1. Rebase your feature branch on top of the latest `master`. 553 | 2. Clean up your branch with an interactive rebase, squashing down to the 554 | smallest number of commits that makes sense. If there are successive 555 | distinct changes in a pull request, it's fine for those to be preserved in 556 | separate commits. 557 | 3. Notify your reviewers that the request is ready to merge. 558 | 4. Wait for them to merge the request. 559 | 5. Ensure the post-merge CI pipeline also succeeds. 560 | 561 | 562 | 563 | ## Conventional Comments 564 | 565 | When commenting on issues and pull requests, we endeavor to adhere to the 566 | [Conventional Comments specification][conventionalcomments] wherever 567 | applicable. Comments should have the form 568 | ``` 569 |