pax_global_header00006660000000000000000000000064145230517760014524gustar00rootroot0000000000000052 comment=750485ed3f446d3a431905d4a0f0c31347700be7 sphinxcontrib-towncrier-0.4.0a0/000077500000000000000000000000001452305177600166525ustar00rootroot00000000000000sphinxcontrib-towncrier-0.4.0a0/.codecov.yml000066400000000000000000000007311452305177600210760ustar00rootroot00000000000000--- # yamllint disable rule:truthy codecov: bot: codecov notify: require_ci_to_pass: yes coverage: precision: 2 round: down range: "70...100" status: # Only consider coverage of the code snippet changed in PR project: no patch: yes changes: no parsers: gcov: branch_detection: conditional: yes loop: yes method: no macro: no comment: layout: "header, diff" behavior: default require_changes: no ... sphinxcontrib-towncrier-0.4.0a0/.coveragerc000066400000000000000000000010071452305177600207710ustar00rootroot00000000000000[paths] source = src/sphinxcontrib/towncrier */src/sphinxcontrib/towncrier .tox/*/lib/python*/site-packages/sphinxcontrib/towncrier [report] skip_covered = true show_missing = true exclude_lines = \#\s*pragma: no cover ^\s*raise AssertionError\b ^\s*raise NotImplementedError\b ^\s*return NotImplemented\b ^\s*raise$ ^if __name__ == ['"]__main__['"]:$ [run] branch = true cover_pylib = false parallel = true relative_files = true source = tests source_pkgs = sphinxcontrib.towncrier sphinxcontrib-towncrier-0.4.0a0/.darglint000066400000000000000000000001061452305177600204540ustar00rootroot00000000000000[darglint] docstring_style = sphinx enable = DAR104 strictness = long sphinxcontrib-towncrier-0.4.0a0/.flake8000066400000000000000000000063261452305177600200340ustar00rootroot00000000000000[flake8] # Print the total number of errors: count = true # Don't even try to analyze these: extend-exclude = # No need to traverse egg info dir *.egg-info, # GitHub configs .github, # Cache files of MyPy .mypy_cache, # Cache files of pytest .pytest_cache, # Temp dir of pytest-testmon .tmontmp, # Countless third-party libs in venvs .tox, # Occasional virtualenv dir .venv, # VS Code .vscode, # Temporary build dir build, # This contains sdists and wheels of pylibsshext that we don't want to check dist, # Metadata of `pip wheel` cmd is autogenerated pip-wheel-metadata, # IMPORTANT: avoid using ignore option, always use extend-ignore instead # Completely and unconditionally ignore the following errors: extend-ignore = # Legitimate cases, no need to "fix" these violations: # E501: "line too long", its function is replaced by `flake8-length` E501, # W505: "doc line too long", its function is replaced by `flake8-length` W505, # I: flake8-isort is drunk + we have isort integrated into pre-commit I, # S101: MyPy requires `asserts`, plus they're not bad if cooked well S101, # WPS300: local folder imports are needed WPS300, # WPS305: "Found f string" -- nothing bad about this WPS305, # WPS317 enforces weird indents WPS317, # WPS318 enforces weird indents too WPS318, # WPS326: "Found implicit string concatenation" -- nothing bad about this WPS326, # IMPORTANT: avoid using select option, always use select-ignore instead # Enable the following errors: extend-select = # B950: "line too long", longer than `max-line-length` + 10% B950, # https://wemake-python-stylegui.de/en/latest/pages/usage/formatter.html format = wemake # Let's not overcomplicate the code: max-complexity = 10 # Accessibility/large fonts and PEP8 friendly. # This is being flexibly extended through the `flake8-length`: max-line-length = 79 # Allow certain violations in certain files: per-file-ignores = # WPS412 logic of an extension is in __init__.py file # F401 imported but unused src/sphinxcontrib/towncrier/__init__.py: F401, WPS412 # FIXME: WPS201 too many imports # FIXME: WPS402 too many `noqa`s src/sphinxcontrib/towncrier/ext.py: WPS201, WPS402 # There are multiple `assert`s (S101) # and subprocesses (import – S404; call – S603) in tests; # also, using fixtures looks like shadowing the outer scope (WPS442); # furthermore, we should be able to import and test private attributes # (WPS450) and modules (WPS436) and finally it's impossible to # have <= members in tests (WPS202): tests/**.py: S101, S404, S603, WPS202, WPS436, WPS442, WPS450 # Count the number of occurrences of each error/warning code and print a report: statistics = true # flake8-pytest-style # PT001: pytest-fixture-no-parentheses = true # PT006: pytest-parametrize-names-type = tuple # PT007: pytest-parametrize-values-type = tuple pytest-parametrize-values-row-type = tuple # PT023: pytest-mark-no-parentheses = true # flake8-rst-docstrings rst-directives = spelling rst-roles = # Built-in Sphinx roles: class, file, exc, meth, term, py:class, py:data, py:exc, py:meth, py:term, # Sphinx's internal role: event, # wemake-python-styleguide show-source = true sphinxcontrib-towncrier-0.4.0a0/.git_archival.txt000066400000000000000000000002251452305177600221240ustar00rootroot00000000000000node: 750485ed3f446d3a431905d4a0f0c31347700be7 node-date: 2023-11-09T04:37:34+01:00 describe-name: v0.4.0a0 ref-names: HEAD -> master, tag: v0.4.0a0 sphinxcontrib-towncrier-0.4.0a0/.gitattributes000066400000000000000000000001101452305177600215350ustar00rootroot00000000000000# Needed for setuptools-scm-git-archive .git_archival.txt export-subst sphinxcontrib-towncrier-0.4.0a0/.github/000077500000000000000000000000001452305177600202125ustar00rootroot00000000000000sphinxcontrib-towncrier-0.4.0a0/.github/FUNDING.yml000066400000000000000000000004051452305177600220260ustar00rootroot00000000000000--- custom: - https://www.comebackalive.in.ua/donate - https://github.com/vshymanskyy/StandWithUkraine#for-maintainers-and-authors - https://www.paypal.me/webknjazCZ - https://webknjaz.me github: - slsh1o - webknjaz ko_fi: webknjaz liberapay: webknjaz ... sphinxcontrib-towncrier-0.4.0a0/.github/workflows/000077500000000000000000000000001452305177600222475ustar00rootroot00000000000000sphinxcontrib-towncrier-0.4.0a0/.github/workflows/ci-cd.yml000066400000000000000000000640721452305177600237620ustar00rootroot00000000000000--- name: πŸ‘·tests on: # yamllint disable-line rule:truthy merge_group: push: branches-ignore: - dependabot/** - gh-readonly-queue/** # Temporary merge queue-related GH-made branches - pre-commit-ci-update-config pull_request: schedule: - cron: 1 0 * * * # Run daily at 0:01 UTC workflow_dispatch: inputs: release-version: # github.event_name == 'workflow_dispatch' # && github.event.inputs.release-version description: >- Target PEP440-compliant version to release. Please, don't prepend `v`. type: string required: true release-committish: # github.event_name == 'workflow_dispatch' # && github.event.inputs.release-committish default: '' description: >- The commit to be released to PyPI and tagged in Git as `release-version`. Normally, you should keep this empty. type: string required: false YOLO: default: false description: >- Set this flag to disregard the outcome of the test stage. The test results will block the release otherwise. Only use this under extraordinary circumstances to ignore the test failures and cut the release regardless. type: boolean required: false concurrency: group: >- ${{ github.workflow }}-${{ github.ref_type }}-${{ github.event.pull_request.number || github.sha }} cancel-in-progress: true env: FORCE_COLOR: 1 # Request colored output from CLI tools supporting it MYPY_FORCE_COLOR: 1 # MyPy's color enforcement PIP_DISABLE_PIP_VERSION_CHECK: 1 # Hide "there's a newer pip" message PIP_NO_PYTHON_VERSION_WARNING: 1 # Hide "this Python is deprecated" message PIP_NO_WARN_SCRIPT_LOCATION: 1 # Hide "script dir is not in $PATH" message PRE_COMMIT_COLOR: 1 PY_COLORS: 1 # Recognized by the `py` package, dependency of `pytest` PYTHONIOENCODING: utf-8 PYTHONLEGACYWINDOWSSTDIO: 1 # Python 3.6 hack PYTHONUTF8: 1 TOX_PARALLEL_NO_SPINNER: 1 # Disable tox's parallel run spinner animation TOX_TESTENV_PASSENV: >- FORCE_COLOR MYPY_FORCE_COLOR NO_COLOR PY_COLORS PYTEST_THEME PYTEST_THEME_MODE jobs: pre-setup: name: βš™οΈ Pre-set global build settings runs-on: ubuntu-latest defaults: run: shell: python outputs: dist-version: >- ${{ steps.request-check.outputs.release-requested == 'true' && github.event.inputs.release-version || steps.scm-version.outputs.dist-version }} is-untagged-devel: >- ${{ steps.untagged-check.outputs.is-untagged-devel || false }} release-requested: >- ${{ steps.request-check.outputs.release-requested || false }} is-yolo-mode: >- ${{ ( steps.request-check.outputs.release-requested == 'true' && github.event.inputs.YOLO ) && true || false }} cache-key-files: >- ${{ steps.calc-cache-key-files.outputs.files-hash-key }} git-tag: ${{ steps.git-tag.outputs.tag }} sdist-artifact-name: ${{ steps.artifact-name.outputs.sdist }} wheel-artifact-name: ${{ steps.artifact-name.outputs.wheel }} steps: - name: Switch to using Python v3.11 by default uses: actions/setup-python@v4 with: python-version: 3.11 - name: >- Mark the build as untagged '${{ github.event.repository.default_branch }}' branch build id: untagged-check if: >- github.event_name == 'push' && github.ref == format( 'refs/heads/{0}', github.event.repository.default_branch ) run: | from os import environ from pathlib import Path FILE_APPEND_MODE = 'a' with Path(environ['GITHUB_OUTPUT']).open( mode=FILE_APPEND_MODE, ) as outputs_file: print('is-untagged-devel=true', file=outputs_file) - name: Mark the build as "release request" id: request-check if: github.event_name == 'workflow_dispatch' run: | from os import environ from pathlib import Path FILE_APPEND_MODE = 'a' with Path(environ['GITHUB_OUTPUT']).open( mode=FILE_APPEND_MODE, ) as outputs_file: print('release-requested=true', file=outputs_file) - name: Check out src from Git if: >- steps.request-check.outputs.release-requested != 'true' uses: actions/checkout@v3 with: fetch-depth: 0 ref: ${{ github.event.inputs.release-committish }} - name: >- Calculate Python interpreter version hash value for use in the cache key if: >- steps.request-check.outputs.release-requested != 'true' id: calc-cache-key-py run: | from hashlib import sha512 from os import environ from pathlib import Path from sys import version FILE_APPEND_MODE = 'a' hash = sha512(version.encode()).hexdigest() with Path(environ['GITHUB_OUTPUT']).open( mode=FILE_APPEND_MODE, ) as outputs_file: print(f'py-hash-key={hash}', file=outputs_file) - name: >- Calculate dependency files' combined hash value for use in the cache key if: >- steps.request-check.outputs.release-requested != 'true' id: calc-cache-key-files run: | from os import environ from pathlib import Path FILE_APPEND_MODE = 'a' with Path(environ['GITHUB_OUTPUT']).open( mode=FILE_APPEND_MODE, ) as outputs_file: print( "files-hash-key=${{ hashFiles( 'setup.cfg', 'setup.py', 'tox.ini', 'pyproject.toml', '.pre-commit-config.yaml', 'pytest.ini' ) }}", file=outputs_file, ) - name: Get pip cache dir id: pip-cache-dir if: >- steps.request-check.outputs.release-requested != 'true' run: >- echo "dir=$(python -m pip cache dir)" >> "${GITHUB_OUTPUT}" shell: bash - name: Set up pip cache if: >- steps.request-check.outputs.release-requested != 'true' uses: actions/cache@v3 with: path: ${{ steps.pip-cache-dir.outputs.dir }} key: >- ${{ runner.os }}-pip-${{ steps.calc-cache-key-py.outputs.py-hash-key }}-${{ steps.calc-cache-key-files.outputs.files-hash-key }} restore-keys: | ${{ runner.os }}-pip-${{ steps.calc-cache-key-py.outputs.py-hash-key }}- ${{ runner.os }}-pip- ${{ runner.os }}- - name: Drop Git tags from HEAD for non-release requests if: >- steps.request-check.outputs.release-requested != 'true' run: >- git tag --points-at HEAD | xargs git tag --delete shell: bash - name: Set up versioning prerequisites if: >- steps.request-check.outputs.release-requested != 'true' run: >- python -m pip install --user setuptools-scm shell: bash - name: Set the current dist version from Git if: steps.request-check.outputs.release-requested != 'true' id: scm-version run: | from os import environ from pathlib import Path import setuptools_scm FILE_APPEND_MODE = 'a' ver = setuptools_scm.get_version( ${{ steps.untagged-check.outputs.is-untagged-devel == 'true' && 'local_scheme="no-local-version"' || '' }} ) with Path(environ['GITHUB_OUTPUT']).open( mode=FILE_APPEND_MODE, ) as outputs_file: print(f'dist-version={ver}', file=outputs_file) - name: Set the target Git tag id: git-tag run: | from os import environ from pathlib import Path FILE_APPEND_MODE = 'a' with Path(environ['GITHUB_OUTPUT']).open( mode=FILE_APPEND_MODE, ) as outputs_file: print( "tag=v${{ steps.request-check.outputs.release-requested == 'true' && github.event.inputs.release-version || steps.scm-version.outputs.dist-version }}", file=outputs_file, ) - name: Set the expected dist artifact names id: artifact-name run: | from os import environ from pathlib import Path FILE_APPEND_MODE = 'a' with Path(environ['GITHUB_OUTPUT']).open( mode=FILE_APPEND_MODE, ) as outputs_file: print( "sdist=sphinxcontrib-towncrier-${{ steps.request-check.outputs.release-requested == 'true' && github.event.inputs.release-version || steps.scm-version.outputs.dist-version }}.tar.gz", file=outputs_file, ) print( "wheel=sphinxcontrib_towncrier-${{ steps.request-check.outputs.release-requested == 'true' && github.event.inputs.release-version || steps.scm-version.outputs.dist-version }}-py3-none-any.whl", file=outputs_file, ) build: name: >- πŸ‘· dists ${{ needs.pre-setup.outputs.git-tag }} [mode: ${{ fromJSON(needs.pre-setup.outputs.is-untagged-devel) && 'nightly' || '' }}${{ fromJSON(needs.pre-setup.outputs.release-requested) && 'release' || '' }}${{ ( !fromJSON(needs.pre-setup.outputs.is-untagged-devel) && !fromJSON(needs.pre-setup.outputs.release-requested) ) && 'test' || '' }}] needs: - pre-setup runs-on: ubuntu-latest env: TOXENV: build-dists steps: - name: Switch to using Python v3.11 uses: actions/setup-python@v4 with: python-version: 3.11 - name: Grab the source from Git uses: actions/checkout@v3 with: fetch-depth: >- ${{ fromJSON(needs.pre-setup.outputs.release-requested) && 1 || 0 }} ref: ${{ github.event.inputs.release-committish }} - name: >- Calculate Python interpreter version hash value for use in the cache key id: calc-cache-key-py run: | from hashlib import sha512 from os import environ from pathlib import Path from sys import version FILE_APPEND_MODE = 'a' hash = sha512(version.encode()).hexdigest() with Path(environ['GITHUB_OUTPUT']).open( mode=FILE_APPEND_MODE, ) as outputs_file: print(f'py-hash-key={hash}', file=outputs_file) shell: python - name: Get pip cache dir id: pip-cache-dir run: >- echo "dir=$(python -m pip cache dir)" >> "${GITHUB_OUTPUT}" - name: Set up pip cache uses: actions/cache@v3 with: path: ${{ steps.pip-cache-dir.outputs.dir }} key: >- ${{ runner.os }}-pip-${{ steps.calc-cache-key-py.outputs.py-hash-key }}-${{ needs.pre-setup.outputs.cache-key-files }} restore-keys: | ${{ runner.os }}-pip-${{ steps.calc-cache-key-py.outputs.py-hash-key }}- ${{ runner.os }}-pip- - name: Install tox run: >- python -m pip install --user tox - name: Pre-populate the tox env run: >- python -m tox --parallel auto --parallel-live --skip-missing-interpreters false --notest - name: Drop Git tags from HEAD for non-tag-create events if: >- !fromJSON(needs.pre-setup.outputs.release-requested) run: >- git tag --points-at HEAD | xargs git tag --delete shell: bash - name: Setup git user as [bot] if: >- fromJSON(needs.pre-setup.outputs.release-requested) || fromJSON(needs.pre-setup.outputs.is-untagged-devel) uses: fregante/setup-git-user@v2 - name: >- Tag the release in the local Git repo as ${{ needs.pre-setup.outputs.git-tag }} for setuptools-scm to set the desired version if: >- fromJSON(needs.pre-setup.outputs.is-untagged-devel) || fromJSON(needs.pre-setup.outputs.release-requested) run: >- git tag -m '${{ needs.pre-setup.outputs.git-tag }}' '${{ needs.pre-setup.outputs.git-tag }}' -- ${{ github.event.inputs.release-committish }} - name: Build dists run: >- python -m tox --parallel auto --parallel-live --skip-missing-interpreters false --skip-pkg-install - name: Verify that the artifacts with expected names got created run: >- ls -1 'dist/${{ needs.pre-setup.outputs.sdist-artifact-name }}' 'dist/${{ needs.pre-setup.outputs.wheel-artifact-name }}' - name: Store the distribution packages uses: actions/upload-artifact@v3 with: name: python-package-distributions # NOTE: Exact expected file names are specified here # NOTE: as a safety measure β€” if anything weird ends # NOTE: up being in this dir or not all dists will be # NOTE: produced, this will fail the workflow. path: | dist/${{ needs.pre-setup.outputs.sdist-artifact-name }} dist/${{ needs.pre-setup.outputs.wheel-artifact-name }} retention-days: >- ${{ ( fromJSON(needs.pre-setup.outputs.release-requested) ) && 90 || 30 }} lint: uses: ./.github/workflows/reusable-linters.yml tests: name: >- πŸ“${{ matrix.towncrier-version }} / 🐍${{ matrix.python-version }} / πŸ’»${{ matrix.os }} needs: - build - pre-setup # transitive, for accessing settings runs-on: ${{ matrix.os }} strategy: matrix: towncrier-version: - 23.10.0rc1 - 23.6.0 - 22.12.0rc1 - 22.8.0 - 21.9.0rc1 - 21.3.0 - 19.9.0 - 19.2.0 python-version: - ~3.12.0-0 - 3.11 - >- 3.10 - 3.9 - 3.8 - 3.7 - 3.6 os: - ubuntu-22.04 - ubuntu-20.04 - macos-12 - macos-11 - windows-latest exclude: - os: ubuntu-22.04 python-version: 3.6 # EOL, only provided for older OSs - python-version: 3.6 towncrier-version: 22.8.0 # Dropped support for Python 3.6 - python-version: 3.6 towncrier-version: 22.12.0rc1 # Does not support Python 3.6 - python-version: 3.6 towncrier-version: 23.6.0 # Dropped support for Python 3.6 - python-version: 3.6 towncrier-version: 23.10.0rc1 # Does not support Python 3.6 - python-version: 3.7 towncrier-version: 23.10.0rc1 # Dropped support for Python 3.7 - python-version: ~3.12.0-0 towncrier-version: 19.2.0 # Does not support Python 3.12 - python-version: ~3.12.0-0 towncrier-version: 19.9.0 # Does not support Python 3.12 - python-version: ~3.12.0-0 towncrier-version: 21.3.0 # Does not support Python 3.12 continue-on-error: >- ${{ ( fromJSON(needs.pre-setup.outputs.is-yolo-mode) ) && true || false }} env: TOXENV: python steps: - name: Grab the source from Git uses: actions/checkout@v3 with: ref: ${{ github.event.inputs.release-committish }} - name: Download all the dists uses: actions/download-artifact@v3 with: name: python-package-distributions path: dist/ - name: Set up Python ${{ matrix.python-version }} id: python-install uses: actions/setup-python@v4 with: python-version: ${{ matrix.python-version }} - name: >- Calculate Python interpreter version hash value for use in the cache key id: calc-cache-key-py run: | from hashlib import sha512 from os import environ from pathlib import Path from sys import version FILE_APPEND_MODE = 'a' hash = sha512(version.encode()).hexdigest() with Path(environ['GITHUB_OUTPUT']).open( mode=FILE_APPEND_MODE, ) as outputs_file: print(f'py-hash-key={hash}', file=outputs_file) shell: python - name: Set up pip cache uses: actions/cache@v3 with: path: ~/.cache/pip key: >- ${{ runner.os }}-pip-${{ steps.calc-cache-key-py.outputs.py-hash-key }}-${{ hashFiles('setup.cfg') }}-${{ hashFiles('tox.ini') }}-${{ hashFiles('pyproject.toml') }}-${{ hashFiles('.pre-commit-config.yaml') }} restore-keys: | ${{ runner.os }}-pip-${{ steps.calc-cache-key-py.outputs.py-hash-key }}- ${{ runner.os }}-pip- ${{ runner.os }}- - name: Install tox # NOTE: Tox4 does not work correctly in our CI under Windows. Limiting the # NOTE: version is a workaround to be used until it's fixed. # Ref: https://github.com/tox-dev/tox/issues/2692 run: >- python -m pip install --user "tox${{ runner.os == 'Windows' && ' < 4' || '' }}" - name: Log installed dists run: | python -m pip freeze --all - name: Patch tox.ini for Python 3.6 under Windows if: >- runner.os == 'Windows' && matrix.python-version == '3.6' run: >- sed -i 's/^package_env\(\s\)\?=.*/package_env = py36-win-dummy/g' tox.ini shell: bash - name: Initialize tox envs run: >- python -m tox --parallel auto --parallel-live --skip-missing-interpreters false --installpkg 'dist/${{ needs.pre-setup.outputs.wheel-artifact-name }}' --force-dep 'towncrier ~= ${{ matrix.towncrier-version }}' --notest - name: Test with tox run: >- python -m tox --parallel auto --parallel-live --skip-missing-interpreters false --installpkg 'dist/${{ needs.pre-setup.outputs.wheel-artifact-name }}' --force-dep 'towncrier ~= ${{ matrix.towncrier-version }}' - name: Send coverage data to Codecov uses: codecov/codecov-action@v3 with: files: .test-results/pytest/cov.xml flags: >- CI-GHA, OS-${{ runner.os }}, VM-${{ matrix.os }}, Py-${{ steps.python-install.outputs.python-version }}, Towncrier-v${{ matrix.towncrier-version }} check: # This job does nothing and is only used for the branch protection if: always() needs: - lint - pre-setup # transitive, for accessing settings - tests runs-on: ubuntu-latest steps: - name: Decide whether the needed jobs succeeded or failed uses: re-actors/alls-green@release/v1 with: allowed-failures: >- ${{ fromJSON(needs.pre-setup.outputs.is-yolo-mode) && 'lint, tests' || '' }} jobs: ${{ toJSON(needs) }} publish-pypi: name: Publish πŸπŸ“¦ ${{ needs.pre-setup.outputs.git-tag }} to PyPI needs: - check - pre-setup # transitive, for accessing settings if: >- fromJSON(needs.pre-setup.outputs.release-requested) runs-on: ubuntu-latest permissions: id-token: write # IMPORTANT: mandatory for trusted publishing environment: name: pypi url: >- https://pypi.org/project/sphinxcontrib-towncrier/${{ needs.pre-setup.outputs.dist-version }} steps: - name: Download all the dists uses: actions/download-artifact@v3 with: name: python-package-distributions path: dist/ - name: >- Publish πŸπŸ“¦ ${{ needs.pre-setup.outputs.git-tag }} to PyPI uses: pypa/gh-action-pypi-publish@release/v1 publish-testpypi: name: Publish πŸπŸ“¦ ${{ needs.pre-setup.outputs.git-tag }} to TestPyPI needs: - check - pre-setup # transitive, for accessing settings if: >- fromJSON(needs.pre-setup.outputs.is-untagged-devel) || fromJSON(needs.pre-setup.outputs.release-requested) runs-on: ubuntu-latest permissions: id-token: write # IMPORTANT: mandatory for trusted publishing environment: name: testpypi url: >- https://test.pypi.org/project/sphinxcontrib-towncrier/${{ needs.pre-setup.outputs.dist-version }} steps: - name: Download all the dists uses: actions/download-artifact@v3 with: name: python-package-distributions path: dist/ - name: >- Publish πŸπŸ“¦ ${{ needs.pre-setup.outputs.git-tag }} to TestPyPI uses: pypa/gh-action-pypi-publish@release/v1 with: repository-url: https://test.pypi.org/legacy/ post-release-repo-update: name: >- Publish post-release Git tag for ${{ needs.pre-setup.outputs.git-tag }} needs: - publish-pypi - pre-setup # transitive, for accessing settings runs-on: ubuntu-latest steps: - name: >- Check if the requested tag ${{ needs.pre-setup.outputs.git-tag }} is present and is pointing at the required commit ${{ github.event.inputs.release-committish }} id: existing-remote-tag-check run: | REMOTE_TAGGED_COMMIT_SHA="$( git ls-remote --tags --refs $(git remote get-url origin) '${{ needs.pre-setup.outputs.git-tag }}' | awk '{print $1}' )" if [[ "${REMOTE_TAGGED_COMMIT_SHA}" == '${{ github.event.inputs.release-committish }}' ]] then echo "already-exists=true" >> "${GITHUB_OUTPUT}" fi - name: Fetch the src snapshot if: steps.existing-remote-tag-check.outputs.already-exists == 'true' uses: actions/checkout@v3 with: fetch-depth: 1 ref: ${{ github.event.inputs.release-committish }} - name: Setup git user as [bot] if: steps.existing-remote-tag-check.outputs.already-exists == 'true' uses: fregante/setup-git-user@v2 - name: >- Tag the release in the local Git repo as ${{ needs.pre-setup.outputs.git-tag }} if: steps.existing-remote-tag-check.outputs.already-exists == 'true' run: >- git tag -m '${{ needs.pre-setup.outputs.git-tag }}' -m 'Published at https://pypi.org/project/sphinxcontrib-towncrier/${{ needs.pre-setup.outputs.dist-version }}' -m 'This release has been produced by the following workflow run: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}' '${{ needs.pre-setup.outputs.git-tag }}' -- ${{ github.event.inputs.release-committish }} - name: >- Push ${{ needs.pre-setup.outputs.git-tag }} tag corresponding to the just published release back to GitHub if: steps.existing-remote-tag-check.outputs.already-exists == 'true' run: >- git push --atomic origin '${{ needs.pre-setup.outputs.git-tag }}' publish-github-release: name: >- Publish a GitHub Release for ${{ needs.pre-setup.outputs.git-tag }} needs: - post-release-repo-update - pre-setup # transitive, for accessing settings runs-on: ubuntu-latest permissions: contents: write discussions: write id-token: write # IMPORTANT: mandatory for Sigstore signing steps: - name: Download all the dists uses: actions/download-artifact@v3 with: name: python-package-distributions path: dist/ - name: Sign the dists with Sigstore uses: sigstore/gh-action-sigstore-python@v1.2.3 with: inputs: >- dist/${{ needs.pre-setup.outputs.sdist-artifact-name }} dist/${{ needs.pre-setup.outputs.wheel-artifact-name }} - name: >- Publish a GitHub Release for ${{ needs.pre-setup.outputs.git-tag }} with Sigstore-signed artifacts uses: ncipollo/release-action@v1.11.1 with: allowUpdates: false artifactErrorsFailBuild: false artifacts: | dist/${{ needs.pre-setup.outputs.sdist-artifact-name }} dist/${{ needs.pre-setup.outputs.sdist-artifact-name }}.crt dist/${{ needs.pre-setup.outputs.sdist-artifact-name }}.sig dist/${{ needs.pre-setup.outputs.wheel-artifact-name }} dist/${{ needs.pre-setup.outputs.wheel-artifact-name }}.crt dist/${{ needs.pre-setup.outputs.wheel-artifact-name }}.sig artifactContentType: raw # Because whl and tgz are of different types body: > # Release ${{ needs.pre-setup.outputs.git-tag }} This release is published to https://pypi.org/project/sphinxcontrib-towncrier/${{ needs.pre-setup.outputs.dist-version }}. This release has been produced by the following workflow run: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}. # bodyFile: # FIXME: Use once Towncrier is integrated. commit: ${{ github.event.inputs.release-committish }} discussionCategory: Announcements draft: false name: ${{ needs.pre-setup.outputs.git-tag }} # omitBody: false omitBodyDuringUpdate: true omitName: false omitNameDuringUpdate: true omitPrereleaseDuringUpdate: true prerelease: false removeArtifacts: false replacesArtifacts: false tag: ${{ needs.pre-setup.outputs.git-tag }} token: ${{ secrets.GITHUB_TOKEN }} ... sphinxcontrib-towncrier-0.4.0a0/.github/workflows/reusable-linters.yml000066400000000000000000000054001452305177600262510ustar00rootroot00000000000000--- name: 🚨linters on: # yamllint disable-line rule:truthy workflow_call: jobs: linters: name: >- ${{ matrix.toxenv }} @ py${{ matrix.python-version }} runs-on: ${{ matrix.os }} strategy: fail-fast: false matrix: python-version: # - ~3.12.0-0 - 3.11 - >- 3.10 - 3.9 - 3.8 os: - ubuntu-latest toxenv: - lint - build-dists env: PY_COLORS: 1 TOX_PARALLEL_NO_SPINNER: 1 TOXENV: ${{ matrix.toxenv }} steps: - uses: actions/checkout@v3 - name: Set up Python ${{ matrix.python-version }} uses: actions/setup-python@v4 with: python-version: ${{ matrix.python-version }} - name: >- Calculate Python interpreter version hash value for use in the cache key id: calc_cache_key_py run: | from hashlib import sha512 from os import environ from pathlib import Path from sys import version FILE_APPEND_MODE = 'a' hash = sha512(version.encode()).hexdigest() with Path(environ['GITHUB_OUTPUT']).open( mode=FILE_APPEND_MODE, ) as outputs_file: print(f'py_hash_key={hash}', file=outputs_file) shell: python - name: Set up pip cache uses: actions/cache@v3 with: path: ~/.cache/pip key: >- ${{ runner.os }}-pip-${{ steps.calc_cache_key_py.outputs.py_hash_key }}-${{ hashFiles('setup.cfg') }}-${{ hashFiles('tox.ini') }}-${{ hashFiles('pyproject.toml') }}-${{ hashFiles('.pre-commit-config.yaml') }} restore-keys: | ${{ runner.os }}-pip-${{ steps.calc_cache_key_py.outputs.py_hash_key }}- ${{ runner.os }}-pip- ${{ runner.os }}- - name: Set up pre-commit cache uses: actions/cache@v3 with: path: ~/.cache/pre-commit key: >- ${{ runner.os }}-pre-commit-${{ steps.calc_cache_key_py.outputs.py_hash_key }}-${{ hashFiles('setup.cfg') }}-${{ hashFiles('tox.ini') }}-${{ hashFiles('pyproject.toml') }}-${{ hashFiles('.pre-commit-config.yaml') }} - name: Install tox run: | python -m pip install --upgrade tox - name: Log installed dists run: | python -m pip freeze --all - name: Initialize tox envs run: | python -m tox --parallel auto --parallel-live --notest - name: Initialize pre-commit envs if needed run: >- test -d .tox/lint && .tox/lint/bin/python -m pre_commit install-hooks || : - name: Test with tox run: | python -m tox --parallel auto --parallel-live ... sphinxcontrib-towncrier-0.4.0a0/.gitignore000066400000000000000000000036241452305177600206470ustar00rootroot00000000000000# Byte-compiled / optimized / DLL files __pycache__/ *.py[cod] *$py.class # C extensions *.so # Distribution / packaging .Python build/ develop-eggs/ dist/ downloads/ eggs/ .eggs/ lib/ lib64/ parts/ sdist/ var/ wheels/ pip-wheel-metadata/ share/python-wheels/ *.egg-info/ .installed.cfg *.egg MANIFEST # PyInstaller # Usually these files are written by a python script from a template # before PyInstaller builds the exe, so as to inject date/other infos into it. *.manifest *.spec # Installer logs pip-log.txt pip-delete-this-directory.txt # Unit test / coverage reports htmlcov/ .tox/ .nox/ .coverage .coverage.* .cache nosetests.xml coverage.xml *.cover *.py,cover .hypothesis/ .pytest_cache/ # Translations *.mo *.pot # Django stuff: *.log local_settings.py db.sqlite3 db.sqlite3-journal # Flask stuff: instance/ .webassets-cache # Scrapy stuff: .scrapy # Sphinx documentation docs/_build/ # PyBuilder target/ # Jupyter Notebook .ipynb_checkpoints # IPython profile_default/ ipython_config.py # pyenv .python-version # pipenv # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. # However, in case of collaboration, if having platform-specific dependencies or dependencies # having no cross-platform support, pipenv may install dependencies that don't work, or not # install all needed dependencies. #Pipfile.lock # PEP 582; used by e.g. github.com/David-OConnor/pyflow __pypackages__/ # Celery stuff celerybeat-schedule celerybeat.pid # SageMath parsed files *.sage.py # Environments .env .venv env/ venv/ ENV/ env.bak/ venv.bak/ # Spyder project settings .spyderproject .spyproject # Rope project settings .ropeproject # mkdocs documentation /site # mypy .mypy_cache/ .dmypy.json dmypy.json # Pyre type checker .pyre/ # Build-time setuptools-scm generated version module /src/sphinxcontrib/towncrier/_scm_version.py # Pytest related reports /.test-results/ sphinxcontrib-towncrier-0.4.0a0/.isort.cfg000066400000000000000000000007501452305177600205530ustar00rootroot00000000000000# https://pycqa.github.io/isort/docs/configuration/config_files/ [settings] default_section = THIRDPARTY honor_noqa = true include_trailing_comma = true indent = 4 known_frameworks = towncrier, sphinx known_testing = pytest line_length = 79 lines_after_imports = 2 # https://pycqa.github.io/isort/#multi-line-output-modes multi_line_output = 5 no_lines_before = LOCALFOLDER sections = STDLIB, TESTING, FRAMEWORKS, THIRDPARTY, FIRSTPARTY, LOCALFOLDER use_parentheses = true verbose = true sphinxcontrib-towncrier-0.4.0a0/.pre-commit-config.yaml000066400000000000000000000176231452305177600231440ustar00rootroot00000000000000--- ci: autoupdate_schedule: quarterly skip: - nitpick-check # can't run on pre-commit.ci while using gh:// repos: - repo: local hooks: - id: immutable-setup-py name: Verify that setup.py stays immutable description: >- This is a sanity check that makes sure that the `setup.py` file isn't changed. # Using Python here because using # shell test does not seem to work in CIs: entry: >- sh -c 'git hash-object setup.py | python -c raise\ SystemExit\(input\(\)\ !=\ \"38cc2638672e1f6ca56e4d5ceaf16451dd702b67\"\) ' pass_filenames: false language: system files: >- ^setup\.py$ - id: immutable-tests-init-py name: Verify that tests/__init__.py stays immutable description: >- This is a sanity check that makes sure that the `tests/__init__.py` file isn't changed. # Using Python here because using # shell test does not seem to work in CIs: entry: >- sh -c 'git hash-object tests/__init__.py | python -c raise\ SystemExit\(input\(\)\ !=\ \"674d7b907efe86dafcd2b8ddc5655fc55ddf5395\"\) ' pass_filenames: false language: system files: >- ^tests/__init__\.py$ - id: enforced-flake8-version name: Verify that enforced flake8 version stays unchanged description: >- This is a sanity check and fixer that makes sure that the `flake8` version in this file remains matching the corresponding request in the `# enforce-version` comment. # Using Python here because using # shell test does not always work in CIs: entry: >- python -c 'import pathlib, re, sys; pre_commit_config = pathlib.Path(sys.argv[1]); cfg_txt = pre_commit_config.read_text(); new_cfg_txt = re.sub( r"(?P\s+)rev:\s(?:\d+\.\d+\.\d+)\s{0,2}" r"#\senforce-version:\s(?P\d+\.\d+\.\d+)" r"[ \t\f\v]*", r"\grev: \g " r"# enforce-version: \g", cfg_txt, ); cfg_txt != new_cfg_txt and pre_commit_config.write_text(new_cfg_txt) ' pass_filenames: true language: system files: >- ^\.pre-commit-config\.ya?ml$ types: - yaml - repo: https://github.com/asottile/add-trailing-comma.git rev: v3.1.0 hooks: - id: add-trailing-comma - repo: https://github.com/asottile/pyupgrade.git rev: v3.14.0 hooks: - id: pyupgrade args: - --py36-plus - repo: https://github.com/PyCQA/isort.git rev: 5.12.0 hooks: - id: isort args: - --honor-noqa - repo: https://github.com/Lucas-C/pre-commit-hooks.git rev: v1.5.4 hooks: - id: remove-tabs - repo: https://github.com/python-jsonschema/check-jsonschema.git rev: 0.27.0 hooks: - id: check-github-workflows files: ^\.github/workflows/[^/]+$ types: - yaml # yamllint disable rule:comments-indentation # - id: check-jsonschema # name: Check GitHub Workflows set timeout-minutes # args: # - --builtin-schema # - github-workflows-require-timeout # files: ^\.github/workflows/[^/]+$ # types: # - yaml # - id: check-readthedocs # yamllint enable rule:comments-indentation - repo: https://github.com/andreoliwa/nitpick.git rev: v0.34.0 hooks: - id: nitpick-check args: - -v stages: [] - repo: https://github.com/pre-commit/pygrep-hooks.git rev: v1.10.0 hooks: - id: python-check-blanket-noqa - id: python-check-mock-methods - id: python-no-eval - id: python-no-log-warn - id: rst-backticks - repo: https://github.com/pre-commit/pre-commit-hooks.git rev: v4.4.0 hooks: # Side-effects: - id: trailing-whitespace - id: check-merge-conflict - id: double-quote-string-fixer - id: end-of-file-fixer - id: requirements-txt-fixer exclude: >- ^(docs/requirements|requirements-build)\.txt$ # Non-modifying checks: - id: name-tests-test files: >- ^tests/[^_].*\.py$ - id: check-added-large-files - id: check-byte-order-marker - id: check-case-conflict # disabled due to pre-commit/pre-commit-hooks#159 # - id: check-docstring-first - id: check-json - id: check-symlinks - id: check-yaml # args: # - --unsafe - id: detect-private-key # Heavy checks: - id: check-ast - id: debug-statements - repo: https://github.com/Lucas-C/pre-commit-hooks-markup.git rev: v1.0.1 hooks: - id: rst-linter files: >- ^README\.rst$ - repo: https://github.com/PyCQA/pydocstyle.git rev: 6.3.0 hooks: - id: pydocstyle - repo: https://github.com/codespell-project/codespell.git rev: v2.2.6 hooks: - id: codespell exclude: >- ^\.github/\.json-schemas/.*\.json$ - repo: https://github.com/adrienverge/yamllint.git rev: v1.32.0 hooks: - id: yamllint files: \.(yaml|yml)$ types: [file, yaml] args: - --strict - repo: https://github.com/openstack/bashate.git rev: 2.1.1 hooks: - id: bashate args: - -i - E006 - repo: https://github.com/shellcheck-py/shellcheck-py.git rev: v0.9.0.6 hooks: - id: shellcheck - repo: https://github.com/PyCQA/flake8.git rev: 6.1.0 hooks: - id: flake8 alias: flake8-no-wps name: flake8 WPS-excluded additional_dependencies: - flake8-2020 ~= 1.7.0 - flake8-length ~= 0.3.0 - flake8-pytest-style ~= 1.6.0 language_version: python3 - repo: https://github.com/PyCQA/flake8.git # NOTE: This is kept at v4 for until WPS starts supporting flake v5. rev: 4.0.1 # enforce-version: 4.0.1 hooks: - id: flake8 alias: flake8-only-wps name: flake8 WPS-only args: - --select - WPS additional_dependencies: - wemake-python-styleguide ~= 0.16.1 language_version: python3 - repo: local hooks: - id: pylint language: system name: PyLint files: \.py$ entry: python -m pylint args: - --rcfile - .pylintrc stages: - manual - repo: https://github.com/pre-commit/mirrors-mypy.git rev: v1.5.1 hooks: - id: mypy alias: mypy-py312 name: MyPy, for Python 3.12 additional_dependencies: - lxml # requirement of `--txt-report` - pytest - Sphinx >= 3.1.2 - types-colorama - types-Pillow - types-Pygments - types-pytz - types-setuptools args: - --namespace-packages - --install-types - --non-interactive - --python-version=3.12 - --txt-report=.tox/.tmp/.mypy/python-3.12 - src/sphinxcontrib/ - tests/ pass_filenames: false - id: mypy alias: mypy-py310 name: MyPy, for Python 3.10 additional_dependencies: - lxml # requirement of `--txt-report` - pytest - Sphinx >= 3.1.2 - types-colorama - types-Pillow - types-Pygments - types-pytz - types-setuptools args: - --namespace-packages - --install-types - --non-interactive - --python-version=3.10 - --txt-report=.tox/.tmp/.mypy/python-3.10 - src/sphinxcontrib/ - tests/ pass_filenames: false - id: mypy alias: mypy-py38 name: MyPy, for Python 3.8 additional_dependencies: - lxml # requirement of `--txt-report` - pytest - Sphinx >= 3.1.2 - types-colorama - types-Pillow - types-Pygments - types-pytz - types-setuptools args: - --namespace-packages - --install-types - --non-interactive - --python-version=3.8 - --txt-report=.tox/.tmp/.mypy/python-3.8 - src/sphinxcontrib/ - tests/ pass_filenames: false - id: mypy alias: mypy-py36 name: MyPy, for Python 3.6 additional_dependencies: - importlib_metadata - lxml # requirement of `--txt-report` - pytest - Sphinx >= 3.1.2, < 6 - types-colorama - types-Pillow - types-Pygments - types-pytz - types-setuptools - types-typed-ast args: - --namespace-packages - --install-types - --non-interactive - --python-version=3.6 - --txt-report=.tox/.tmp/.mypy/python-3.6 - src/sphinxcontrib/ - tests/ pass_filenames: false ... sphinxcontrib-towncrier-0.4.0a0/.pylintrc000066400000000000000000000371761452305177600205350ustar00rootroot00000000000000[MASTER] # A comma-separated list of package or module names from where C extensions may # be loaded. Extensions are loading into the active Python interpreter and may # run arbitrary code. extension-pkg-whitelist= # Specify a score threshold to be exceeded before program exits with error. fail-under=10 # Add files or directories to the blacklist. They should be base names, not # paths. ignore=CVS # Add files or directories matching the regex patterns to the blacklist. The # regex matches against base names, not paths. ignore-patterns= # Python code to execute, usually for sys.path manipulation such as # pygtk.require(). #init-hook= # Use multiple processes to speed up Pylint. Specifying 0 will auto-detect the # number of processors available to use. jobs = 0 # Control the amount of potential inferred values when inferring a single # object. This can help the performance when dealing with large functions or # complex, nested conditions. limit-inference-results=100 # List of plugins (as comma separated values of python module names) to load, # usually to register additional checkers. load-plugins= # Pickle collected data for later comparisons. persistent=yes # When enabled, pylint would attempt to guess common misconfiguration and emit # user-friendly hints instead of false-positive error messages. suggestion-mode=yes # Allow loading of arbitrary C extensions. Extensions are imported into the # active Python interpreter and may run arbitrary code. unsafe-load-any-extension=no [MESSAGES CONTROL] # Only show warnings with the listed confidence levels. Leave empty to show # all. Valid levels: HIGH, INFERENCE, INFERENCE_FAILURE, UNDEFINED. confidence= # Disable the message, report, category or checker with the given id(s). You # can either give multiple identifiers separated by comma (,) or put this # option multiple times (only on the command line, not in the configuration # file where it should appear only once). You can also use "--disable=all" to # disable everything first and then reenable specific checks. For example, if # you want to run only the similarities checker, you can use "--disable=all # --enable=similarities". If you want to run only the classes checker, but have # no Warning level messages displayed, use "--disable=all --enable=classes # --disable=W". disable= cyclic-import # Enable the message, report, category or checker with the given id(s). You can # either give multiple identifier separated by comma (,) or put this option # multiple time (only on the command line, not in the configuration file where # it should appear only once). See also the "--disable" option for examples. enable=c-extension-no-member [REPORTS] # Python expression which should return a score less than or equal to 10. You # have access to the variables 'error', 'warning', 'refactor', and 'convention' # which contain the number of messages in each category, as well as 'statement' # which is the total number of statements analyzed. This score is used by the # global evaluation report (RP0004). evaluation=10.0 - ((float(5 * error + warning + refactor + convention) / statement) * 10) # Template used to display messages. This is a python new-style format string # used to format the message information. See doc for all details. #msg-template= # Set the output format. Available formats are text, parseable, colorized, json # and msvs (visual studio). You can also give a reporter class, e.g. # mypackage.mymodule.MyReporterClass. output-format=colorized # Tells whether to display a full report or only the messages. reports=no # Activate the evaluation score. score=yes [REFACTORING] # Maximum number of nested blocks for function / method body max-nested-blocks=5 # Complete name of functions that never returns. When checking for # inconsistent-return-statements if a never returning function is called then # it will be considered as an explicit return statement and no message will be # printed. never-returning-functions=sys.exit [MISCELLANEOUS] # List of note tags to take in consideration, separated by a comma. notes=FIXME, XXX, TODO # Regular expression of note tags to take in consideration. #notes-rgx= [SPELLING] # Limits count of emitted suggestions for spelling mistakes. max-spelling-suggestions=4 # Spelling dictionary name. Available dictionaries: none. To make it work, # install the python-enchant package. spelling-dict= # List of comma separated words that should not be checked. spelling-ignore-words= # A path to a file that contains the private dictionary; one word per line. spelling-private-dict-file= # Tells whether to store unknown words to the private dictionary (see the # --spelling-private-dict-file option) instead of raising a message. spelling-store-unknown-words=no [FORMAT] # Expected format of line ending, e.g. empty (any line ending), LF or CRLF. expected-line-ending-format= # Regexp for a line that is allowed to be longer than the limit. ignore-long-lines=^\s*(# )??$ # Number of spaces of indent required inside a hanging or continued line. indent-after-paren=4 # String used as indentation unit. This is usually " " (4 spaces) or "\t" (1 # tab). indent-string=' ' # Maximum number of characters on a single line. max-line-length=79 # Maximum number of lines in a module. max-module-lines=1000 # Allow the body of a class to be on the same line as the declaration if body # contains single statement. single-line-class-stmt=no # Allow the body of an if to be on the same line as the test if there is no # else. single-line-if-stmt=no [SIMILARITIES] # Ignore comments when computing similarities. ignore-comments=yes # Ignore docstrings when computing similarities. ignore-docstrings=yes # Ignore imports when computing similarities. ignore-imports=no # Minimum lines number of a similarity. min-similarity-lines=4 [STRING] # This flag controls whether inconsistent-quotes generates a warning when the # character used as a quote delimiter is used inconsistently within a module. check-quote-consistency=no # This flag controls whether the implicit-str-concat should generate a warning # on implicit string concatenation in sequences defined over several lines. check-str-concat-over-line-jumps=no [TYPECHECK] # List of decorators that produce context managers, such as # contextlib.contextmanager. Add to this list to register other decorators that # produce valid context managers. contextmanager-decorators=contextlib.contextmanager # List of members which are set dynamically and missed by pylint inference # system, and so shouldn't trigger E1101 when accessed. Python regular # expressions are accepted. generated-members= # Tells whether missing members accessed in mixin class should be ignored. A # mixin class is detected if its name ends with "mixin" (case insensitive). ignore-mixin-members=yes # Tells whether to warn about missing members when the owner of the attribute # is inferred to be None. ignore-none=yes # This flag controls whether pylint should warn about no-member and similar # checks whenever an opaque object is returned when inferring. The inference # can return multiple potential results while evaluating a Python object, but # some branches might not be evaluated, which results in partial inference. In # that case, it might be useful to still emit no-member and other checks for # the rest of the inferred objects. ignore-on-opaque-inference=yes # List of class names for which member attributes should not be checked (useful # for classes with dynamically set attributes). This supports the use of # qualified names. ignored-classes=optparse.Values,thread._local,_thread._local # List of module names for which member attributes should not be checked # (useful for modules/projects where namespaces are manipulated during runtime # and thus existing member attributes cannot be deduced by static analysis). It # supports qualified module names, as well as Unix pattern matching. ignored-modules= # Show a hint with possible names when a member name was not found. The aspect # of finding the hint is based on edit distance. missing-member-hint=yes # The minimum edit distance a name should have in order to be considered a # similar match for a missing member name. missing-member-hint-distance=1 # The total number of similar names that should be taken in consideration when # showing a hint for a missing member. missing-member-max-choices=1 # List of decorators that change the signature of a decorated function. signature-mutators= [LOGGING] # The type of string formatting that logging methods do. `old` means using % # formatting, `new` is for `{}` formatting. logging-format-style=old # Logging modules to check that the string format arguments are in logging # function parameter format. logging-modules=logging [BASIC] # Naming style matching correct argument names. argument-naming-style=snake_case # Regular expression matching correct argument names. Overrides argument- # naming-style. #argument-rgx= # Naming style matching correct attribute names. attr-naming-style=snake_case # Regular expression matching correct attribute names. Overrides attr-naming- # style. #attr-rgx= # Bad variable names which should always be refused, separated by a comma. bad-names=foo, bar, baz, toto, tutu, tata # Bad variable names regexes, separated by a comma. If names match any regex, # they will always be refused bad-names-rgxs= # Naming style matching correct class attribute names. class-attribute-naming-style=any # Regular expression matching correct class attribute names. Overrides class- # attribute-naming-style. #class-attribute-rgx= # Naming style matching correct class names. class-naming-style=PascalCase # Regular expression matching correct class names. Overrides class-naming- # style. #class-rgx= # Naming style matching correct constant names. const-naming-style=UPPER_CASE # Regular expression matching correct constant names. Overrides const-naming- # style. #const-rgx= # Minimum line length for functions/classes that require docstrings, shorter # ones are exempt. docstring-min-length=-1 # Naming style matching correct function names. function-naming-style=snake_case # Regular expression matching correct function names. Overrides function- # naming-style. #function-rgx= # Good variable names which should always be accepted, separated by a comma. good-names=i, j, k, exc, logger, _, # Good variable names regexes, separated by a comma. If names match any regex, # they will always be accepted good-names-rgxs= # Include a hint for the correct naming format with invalid-name. include-naming-hint = yes # Naming style matching correct inline iteration names. inlinevar-naming-style=any # Regular expression matching correct inline iteration names. Overrides # inlinevar-naming-style. #inlinevar-rgx= # Naming style matching correct method names. method-naming-style=snake_case # Regular expression matching correct method names. Overrides method-naming- # style. #method-rgx= # Naming style matching correct module names. module-naming-style=snake_case # Regular expression matching correct module names. Overrides module-naming- # style. #module-rgx= # Colon-delimited sets of names that determine each other's naming style when # the name regexes allow several styles. name-group= # Regular expression which should only match function or class names that do # not require a docstring. no-docstring-rgx=^_ # List of decorators that produce properties, such as abc.abstractproperty. Add # to this list to register other decorators that produce valid properties. # These decorators are taken in consideration only for invalid-name. property-classes=abc.abstractproperty # Naming style matching correct variable names. variable-naming-style=snake_case # Regular expression matching correct variable names. Overrides variable- # naming-style. #variable-rgx= [VARIABLES] # List of additional names supposed to be defined in builtins. Remember that # you should avoid defining new builtins when possible. additional-builtins= # Tells whether unused global variables should be treated as a violation. allow-global-unused-variables=yes # List of strings which can identify a callback function by name. A callback # name must start or end with one of those strings. callbacks=cb_, _cb # A regular expression matching the name of dummy variables (i.e. expected to # not be used). dummy-variables-rgx=_+$|(_[a-zA-Z0-9_]*[a-zA-Z0-9]+?$)|dummy|^ignored_|^unused_ # Argument names that match this expression will be ignored. Default to name # with leading underscore. ignored-argument-names=_.*|^ignored_|^unused_ # Tells whether we should check for unused import in __init__ files. init-import=no # List of qualified module names which can have objects that can redefine # builtins. redefining-builtins-modules=six.moves,past.builtins,future.builtins,builtins,io [CLASSES] # List of method names used to declare (i.e. assign) instance attributes. defining-attr-methods=__init__, __new__, setUp, __post_init__ # List of member names, which should be excluded from the protected access # warning. exclude-protected=_asdict, _fields, _replace, _source, _make # List of valid names for the first argument in a class method. valid-classmethod-first-arg=cls # List of valid names for the first argument in a metaclass class method. valid-metaclass-classmethod-first-arg=cls [IMPORTS] # List of modules that can be imported at any level, not just the top level # one. allow-any-import-level= # Allow wildcard imports from modules that define __all__. allow-wildcard-with-all=no # Analyse import fallback blocks. This can be used to support both Python 2 and # 3 compatible code, which means that the block might have code that exists # only in one or another interpreter, leading to false positives when analysed. analyse-fallback-blocks = yes # Deprecated modules which should not be used, separated by a comma. deprecated-modules = optparse, tkinter.tix, unittest, # Create a graph of external dependencies in the given file (report RP0402 must # not be disabled). ext-import-graph= # Create a graph of every (i.e. internal and external) dependencies in the # given file (report RP0402 must not be disabled). import-graph= # Create a graph of internal dependencies in the given file (report RP0402 must # not be disabled). int-import-graph= # Force import order to recognize a module as part of the standard # compatibility libraries. known-standard-library= # Force import order to recognize a module as part of a third party library. known-third-party=enchant # Couples of modules and preferred modules, separated by a comma. preferred-modules = unittest:pytest, [DESIGN] # Maximum number of arguments for function / method. max-args=5 # Maximum number of attributes for a class (see R0902). max-attributes=7 # Maximum number of boolean expressions in an if statement (see R0916). max-bool-expr=5 # Maximum number of branch for function / method body. max-branches=12 # Maximum number of locals for function / method body. max-locals=15 # Maximum number of parents for a class (see R0901). max-parents=7 # Maximum number of public methods for a class (see R0904). max-public-methods=20 # Maximum number of return / yield for function / method body. max-returns=6 # Maximum number of statements in function / method body. max-statements=50 # Minimum number of public methods for a class (see R0903). min-public-methods=2 [EXCEPTIONS] # Exceptions that will emit a warning when being caught. Defaults to # "BaseException, Exception". overgeneral-exceptions=builtins.BaseException, builtins.Exception sphinxcontrib-towncrier-0.4.0a0/.readthedocs.yml000066400000000000000000000003621452305177600217410ustar00rootroot00000000000000--- version: 2 formats: all sphinx: builder: dirhtml configuration: docs/conf.py fail_on_warning: true build: image: latest python: version: 3.8 install: - requirements: docs/requirements.txt - method: pip path: . ... sphinxcontrib-towncrier-0.4.0a0/.yamllint000066400000000000000000000001371452305177600205050ustar00rootroot00000000000000--- extends: default rules: indentation: level: error indent-sequences: false ... sphinxcontrib-towncrier-0.4.0a0/CONTRIBUTING.rst000066400000000000000000000014641452305177600213200ustar00rootroot00000000000000*************************************** Contributing to sphinxcontrib-towncrier *************************************** .. attention:: sphinxcontrib-towncrier project exists solely to allow embedding the unreleased changelog fragments that are prepared for the Towncrier tool into Sphinx-based docs sites. At the moment we don't accept any contributions, nor feature requests that are unrelated to this goal. But if you want to contribute a bug fix or send a pull-request improving our CI, testing and packaging, we will gladly review it. In order to contribute, you'll need to: 1. Fork the repository. 2. Create a branch, push your changes there. 3. Send it to us as a PR. 4. Iterate on your PR, incorporating the requested improvements and participating in the discussions. sphinxcontrib-towncrier-0.4.0a0/LICENSE000066400000000000000000000027621452305177600176660ustar00rootroot00000000000000BSD 3-Clause License Copyright (c) 2020, sphinx-contrib All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. sphinxcontrib-towncrier-0.4.0a0/README.rst000066400000000000000000000060031452305177600203400ustar00rootroot00000000000000.. image:: https://raw.githubusercontent.com/vshymanskyy/StandWithUkraine/main/banner-direct-team.svg :target: https://github.com/vshymanskyy/StandWithUkraine/blob/main/docs/README.md :alt: SWUbanner .. image:: https://img.shields.io/pypi/v/sphinxcontrib-towncrier.svg?logo=Python&logoColor=white :target: https://pypi.org/project/sphinxcontrib-towncrier :alt: sphinxcontrib-towncrier @ PyPI .. image:: https://github.com/sphinx-contrib/sphinxcontrib-towncrier/actions/workflows/ci-cd.yml/badge.svg?event=push :target: https://github.com/sphinx-contrib/sphinxcontrib-towncrier/actions/workflows/ci-cd.yml :alt: GitHub Actions CI/CD build status β€” Python package .. image:: https://codecov.io/gh/sphinx-contrib/sphinxcontrib-towncrier/branch/master/graph/badge.svg :target: https://codecov.io/gh/sphinx-contrib/sphinxcontrib-towncrier :alt: sphinxcontrib-towncrier coverage charts @ Covecov.io .. DO-NOT-REMOVE-docs-badges-END .. image:: https://img.shields.io/readthedocs/sphinxcontrib-towncrier/latest.svg?logo=Read%20The%20Docs&logoColor=white :target: https://sphinxcontrib-towncrier.rtfd.io/en/latest/?badge=latest :alt: Documentation Status @ RTD sphinxcontrib-towncrier ======================= .. DO-NOT-REMOVE-docs-intro-START An RST directive for injecting a Towncrier-generated changelog draft containing fragments for the unreleased (next) project version. How to use this? ---------------- .. code-block:: shell-session $ pip install sphinxcontrib-towncrier .. code-block:: python extensions = ['sphinxcontrib.towncrier.ext'] # Options: draft/sphinx-version/sphinx-release towncrier_draft_autoversion_mode = 'draft' towncrier_draft_include_empty = True towncrier_draft_working_directory = PROJECT_ROOT_DIR # Not yet supported: # towncrier_draft_config_path = 'pyproject.toml' # relative to cwd Make sure to point to the dir with ``pyproject.toml`` and pre-configure towncrier itself in the config. If everything above is set up correctly, you should be able to add .. code-block:: rst .. towncrier-draft-entries:: to your documents, like ``changelog.rst``. With no argument, the version title will be generated using the strategy set up in the ``towncrier_draft_autoversion_mode`` setting. If you want to be in control, override it with an argument you like: .. code-block:: rst .. towncrier-draft-entries:: |release| [UNRELEASED DRAFT] Native RST substitutions in the argument work, just make sure to declare any non-default ones via ``rst_epilog`` or at the end of the document where the ``towncrier-draft-entries`` directive is being used. Does anybody actually use this? ------------------------------- So far we know about two projects using ``sphinxcontrib-towncrier`` β€” ansible/pylibssh and pypa/pip. Also, this Sphinx extension is inspired by and somewhat based on the ideas used in pytest-dev/pytest and tox-dev/tox. We believe that these projects are full of wonderful tricks that you may want to explore regardless of whether you'll use our project. sphinxcontrib-towncrier-0.4.0a0/docs/000077500000000000000000000000001452305177600176025ustar00rootroot00000000000000sphinxcontrib-towncrier-0.4.0a0/docs/change-notes-layout.rst000066400000000000000000000350231452305177600242250ustar00rootroot00000000000000******************************* Advanced changelog layout setup ******************************* This page attempts do demonstrate one way of setting up a docs site for use with |project| and includes a few opinionated integration solutions. But of course, this layout may not fit everybody's needs. When configuring your project, try to figure out what works for you β€” you don't have to follow everything laid out here blindly. Project structure ^^^^^^^^^^^^^^^^^ The author likes the following project directory layout: :: {{ project_root }}/ β”‚ β”œβ”€ docs/ β”‚ β”œβ”€ changelog.d/ β”‚ β”‚ │─ .gitignore β”‚ β”‚ │─ .towncrier-template.rst.j2 β”‚ β”‚ │─ {{ issue_number }}.{{ changelog_fragment_type }}.rst β”‚ β”‚ │─ ... β”‚ β”‚ └─ README.rst β”‚ β”œβ”€ changelog.rst β”‚ β”œβ”€ conf.py β”‚ β”œβ”€ index.rst β”‚ β”œβ”€ requirements.in β”‚ └─ requirements.txt β”œβ”€ src/ β”‚ └─ {{ python_importable_name }}/ β”‚ └─ ... β”œβ”€ .readthedocs.yml β”œβ”€ CHANGELOG.rst β”œβ”€ pyproject.toml β”œβ”€ README.rst β”œβ”€ tox.ini └─ ... This is an ``src``-layout project with a Python package located at ``src/{{ python_importable_name }}/`` but we won't touch this topic. There are several automation, configuration, documentation and metadata files in the project root that will be described later on this page. Finally, a :doc:`Sphinx `-based site is located under the ``docs/``. The rest of this page will describe what to have in each of those files. ``docs/changelog.d/`` ^^^^^^^^^^^^^^^^^^^^^ Let's start with the ``docs/changelog.d/``. This is a folder where the end-users are supposed to add their changelog fragments for Towncrier to consume. ``docs/changelog.d/.gitignore`` ------------------------------- First, let's make sure Git only tracks files that we want there by adding a ``.gitignore`` file in this folder. First thing, it adds everything to "ignore" but then allows ``.gitignore``, ``.gitignore``, ``README.rst`` and any RST documents matching Towncrier change note fragment naming convention. .. code-block:: * !.gitignore !.towncrier-template.rst.j2 !*.*.rst !README.rst ``docs/changelog.d/.towncrier-template.rst.j2`` ----------------------------------------------- Then, there's ``.towncrier-template.rst.j2``. It's a changelog template, for Towncrier to use. It can be copied from https://github.com/twisted/towncrier/tree/master/src/towncrier/templates. This name is set in ``pyproject.toml`` in the project root. ``docs/changelog.d/{{ issue_number }}.{{ changelog_fragment_type }}.rst`` ------------------------------------------------------------------------- These are changelog fragments in RST format. They are absorbed by Towncrier during the release and before that, these files will be used in the preview generated by |project|. ``docs/changelog.d/README.rst`` ------------------------------- This ``README.rst`` file would normally contain β€” a guide for the contributors on how to write change notes. For example, setuptools has a useful write-up on :ref:`authoring changelog fragments `. It is useful to have it in this place so that it shows up on GitHub when the users navigate to the folder with the fragments via the web UI. ``docs/`` ^^^^^^^^^^^^^^^^^^^^^ ``docs/changelog.rst`` ---------------------- This is a Sphinx page that contains both the future version changelog preview via ``.. towncrier-draft-entries::`` directive and the changelog for all already released versions that is managed by Towncrier in a separate RST document ``CHANGELOG.rst`` in the project root. .. code-block:: rst ********* Changelog ********* Versions follow `Semantic Versioning`_ (``..``). Backward incompatible (breaking) changes will only be introduced in major versions with advance notice in the **Deprecations** section of releases. .. _Semantic Versioning: https://semver.org/ .. towncrier-draft-entries:: |release| [UNRELEASED DRAFT] as on |today| .. include:: ../CHANGELOG.rst ``docs/conf.py`` ---------------- The Sphinx configuration demonstrates how to keep the version information known to Sphinx in sync with the Git tag based metadata. Note the exclusion of ``docs/changelog.d/`` and the settings prefixed with ``towncrier_draft_``. .. code-block:: python """Configuration for the Sphinx documentation generator.""" from functools import partial from pathlib import Path from setuptools_scm import get_version # -- Path setup -------------------------------------------------------------- PROJECT_ROOT_DIR = Path(__file__).parents[1].resolve() get_scm_version = partial(get_version, root=PROJECT_ROOT_DIR) # -- Project information ----------------------------------------------------- github_url = 'https://github.com' github_repo_org = 'your-org' github_repo_name = 'your-project' github_repo_slug = f'{github_repo_org}/{github_repo_name}' github_repo_url = f'{github_url}/{github_repo_slug}' github_sponsors_url = f'{github_url}/sponsors' project = github_repo_name author = f'{project} Contributors' copyright = f'2021, {author}' # The short X.Y version version = '.'.join( get_scm_version( local_scheme='no-local-version', ).split('.')[:3], ) # The full version, including alpha/beta/rc tags release = get_scm_version() rst_epilog = f""" .. |project| replace:: {project} """ # -- General configuration --------------------------------------------------- extensions = [ # Built-in extensions: 'sphinx.ext.extlinks', 'sphinx.ext.intersphinx', # Third-party extensions: 'sphinxcontrib.towncrier.ext', # provides `.. towncrier-draft-entries::` ] exclude_patterns = [ '_build', 'Thumbs.db', '.DS_Store', # <- Defaults 'changelog.d/**', # Towncrier-managed change notes ] # -- Options for HTML output ------------------------------------------------- html_theme = 'furo' # -- Extension configuration ------------------------------------------------- # -- Options for intersphinx extension --------------------------------------- intersphinx_mapping = { 'python': ('https://docs.python.org/3', None), 'rtd': ('https://docs.rtfd.io/en/stable', None), 'sphinx': ('https://www.sphinx-doc.org/en/master', None), } # -- Options for extlinks extension ------------------------------------------ extlinks = { 'issue': (f'{github_repo_url}/issues/%s', '#'), 'pr': (f'{github_repo_url}/pull/%s', 'PR #'), 'commit': (f'{github_repo_url}/commit/%s', ''), 'gh': (f'{github_url}/%s', 'GitHub: '), 'user': (f'{github_sponsors_url}/%s', '@'), } # -- Options for towncrier_draft extension ----------------------------------- towncrier_draft_autoversion_mode = 'draft' # or: 'sphinx-version', 'sphinx-release' towncrier_draft_include_empty = True towncrier_draft_working_directory = PROJECT_ROOT_DIR # Not yet supported: towncrier_draft_config_path = 'pyproject.toml' # relative to cwd # -- Strict mode ------------------------------------------------------------- default_role = 'any' nitpicky = True ``docs/index.rst`` ------------------ The root document includes most of the README excluding one badge and its title. It allows to flexibly control what information goes to the PyPI and GitHub repo pages and what appears in the docs. This document must contain a ``.. toctree::`` directive that has a pointer to the ``changelog`` document in the list. .. code-block:: rst Welcome to |project|'s documentation! ===================================== .. include:: ../README.rst :end-before: DO-NOT-REMOVE-docs-badges-END .. include:: ../README.rst :start-after: DO-NOT-REMOVE-docs-intro-START .. toctree:: :maxdepth: 2 :caption: Contents: changelog ``docs/requirements.in`` ------------------------ ``requirements.in`` is a standard ``requirements.txt``-type file that only lists dependencies that are directly used by the :doc:`Sphinx static docs site generator `. It may optionally contain the minimum necessary versions of those. .. code-block:: text furo setuptools-scm Sphinx sphinxcontrib-towncrier ``docs/requirements.txt`` ------------------------- But stating just the direct dependencies without strict version restrictions is not enough for reproducible builds. Since it is important to keep the docs build predictable over time, we use `pip-tools`_ to generate a ``constraints.txt``-type pip-compatible lockfile with pinned version constraints for the whole transitive dependency tree. This file is ``requirements.txt`` and using it will ensure that the virtualenv for building the docs always has the same software with the same versions in it. .. tip:: As a bonus, having a ``.in`` + ``.txt`` pair of files is natively supported by GitHub Dependabot. .. _pip-tools: https://github.com/jazzband/pip-tools ``.readthedocs.yml`` ^^^^^^^^^^^^^^^^^^^^ To set up Read the Docs, add a ``.readthedocs.yml`` file in the project root. The following configuration makes sure that the lockfile is used to provision the build env. It also configures how Sphinx should behave like failing the build on any warnings and having nice URLs. .. code-block:: yaml --- version: 2 formats: all sphinx: builder: dirhtml configuration: docs/conf.py fail_on_warning: true build: image: latest python: version: 3.8 install: - requirements: docs/requirements.txt ... .. note:: When you have a Read the Docs YAML config in your repository, none of the :ref:`settings supported by it ` are derived from the web UI. .. tip:: Having :doc:`Read the Docs ` plugged into your project it is also possible to :doc:`enable pull-request builds `. ``CHANGELOG.rst`` ^^^^^^^^^^^^^^^^^ This file in the project root contains the compiled changelog with the notes from the released project versions. It is managed by Towncrier and should not be edited by you manually. .. code-block:: rst .. towncrier release notes start ``pyproject.toml`` ^^^^^^^^^^^^^^^^^^ ``pyproject.toml`` in the root contains the setup for Towncrier itself under the ``[tool.towncrier]`` section. It binds it all together pointing at the directory for the change notes, the target changelog document and the template to use when generating it. It also lists the categories for the change fragments. .. code-block:: toml [tool.towncrier] directory = "docs/changelog.d/" filename = "CHANGELOG.rst" issue_format = ":issue:`{issue}`" package_dir = "src" template = "docs/changelog.d/.towncrier-template.rst.j2" title_format = "v{version} ({project_date})" underlines = ["=", "^", "-", "~"] [[tool.towncrier.section]] path = "" [[tool.towncrier.type]] directory = "bugfix" name = "Bugfixes" showcontent = true [[tool.towncrier.type]] directory = "feature" name = "Features" showcontent = true [[tool.towncrier.type]] directory = "deprecation" name = "Deprecations (removal in next major release)" showcontent = true [[tool.towncrier.type]] directory = "breaking" name = "Backward incompatible changes" showcontent = true [[tool.towncrier.type]] directory = "doc" name = "Documentation" showcontent = true [[tool.towncrier.type]] directory = "misc" name = "Miscellaneous" showcontent = true ``README.rst`` ^^^^^^^^^^^^^^ The README document is an important bit of your project. It shows up on GitHub and is normally shown on PyPI. Besides that, it's possible to include its fragments into the docs front page. The example below shows how to use comment markers to include a part of the badges into a Sphinx document also embedding some prose from the README. Scroll up and see how it's being embedded into ``docs/index.rst``. .. code-block:: rst .. image:: https://img.shields.io/pypi/v/your-project.svg?logo=Python&logoColor=white :target: https://pypi.org/project/your-project :alt: your-project @ PyPI .. image:: https://github.com/your-org/your-project/actions/workflows/ci-cd.yml/badge.svg?event=push :target: https://github.com/your-org/your-project/actions/workflows/ci-cd.yml :alt: GitHub Actions CI/CD build status .. DO-NOT-REMOVE-docs-badges-END .. image:: https://img.shields.io/readthedocs/your-project/latest.svg?logo=Read%20The%20Docs&logoColor=white :target: https://your-project.rtfd.io/en/latest/?badge=latest :alt: Documentation Status @ RTD your-project ============ .. DO-NOT-REMOVE-docs-intro-START A project with Sphinx-managed documentation and description sourced from this README. ``tox.ini`` ^^^^^^^^^^^ This is an example of setting up a tox-based Sphinx invocation .. code-block:: ini [tox] envlist = python isolated_build = true minversion = 3.21.0 [testenv:docs] basepython = python3 deps = -r{toxinidir}{/}docs{/}requirements.txt description = Build The Docs commands = # Retrieve possibly missing commits: -git fetch --unshallow -git fetch --tags # Build the html docs with Sphinx: {envpython} -m sphinx \ -j auto \ -b html \ {tty:--color} \ -a \ -n \ -W --keep-going \ -d "{temp_dir}{/}.doctrees" \ {posargs:} \ . \ "{envdir}{/}docs_out" # Print out the output docs dir and a way to serve html: -{envpython} -c\ 'import pathlib;\ docs_dir = pathlib.Path(r"{envdir}") / "docs_out";\ index_file = docs_dir / "index.html";\ print("\n" + "=" * 120 +\ f"\n\nDocumentation available under:\n\n\ \tfile://\{index_file\}\n\nTo serve docs, use\n\n\ \t$ python3 -m http.server --directory \ \N\{QUOTATION MARK\}\{docs_dir\}\N\{QUOTATION MARK\} 0\n\n" +\ "=" * 120)' changedir = {toxinidir}{/}docs isolated_build = true passenv = SSH_AUTH_SOCK skip_install = true whitelist_externals = git With this setup, run ``tox -e docs`` to build the site locally. Integrate the same command in your CI. sphinxcontrib-towncrier-0.4.0a0/docs/conf.py000066400000000000000000000143401452305177600211030ustar00rootroot00000000000000# pylint: disable=invalid-name # Requires Python 3.6+ # Ref: https://www.sphinx-doc.org/en/master/usage/configuration.html """Configuration for the Sphinx documentation generator.""" import sys from functools import partial from pathlib import Path from typing import Mapping from sphinx.application import Sphinx from setuptools_scm import get_version # -- Path setup -------------------------------------------------------------- PROJECT_ROOT_DIR = Path(__file__).parents[1].resolve() PROJECT_SRC_DIR = PROJECT_ROOT_DIR / 'src' get_scm_version = partial(get_version, root=PROJECT_ROOT_DIR) # If extensions (or modules to document with autodoc) are in another directory, # add these directories to sys.path here. If the directory is relative to the # documentation root, use os.path.abspath to make it absolute, like shown here. sys.path.insert(0, str(PROJECT_SRC_DIR)) # -- Project information ----------------------------------------------------- github_url = 'https://github.com' github_repo_org = 'sphinx-contrib' github_repo_name = 'sphinxcontrib-towncrier' github_repo_slug = f'{github_repo_org}/{github_repo_name}' github_repo_url = f'{github_url}/{github_repo_slug}' github_sponsors_url = f'{github_url}/sponsors' project = github_repo_name author = 'Sviatoslav Sydorenko' copyright = f'2021, {author}' # pylint: disable=redefined-builtin # The short X.Y version version = '.'.join( get_scm_version( local_scheme='no-local-version', ).split('.')[:3], ) # The full version, including alpha/beta/rc tags release = get_scm_version() rst_epilog = f""" .. |project| replace:: {project} """ # -- General configuration --------------------------------------------------- extensions = [ # Built-in extensions: 'sphinx.ext.autodoc', 'sphinx.ext.autosectionlabel', # autocreate section targets for refs 'sphinx.ext.doctest', 'sphinx.ext.extlinks', 'sphinx.ext.intersphinx', 'sphinx.ext.todo', 'sphinx.ext.coverage', 'sphinx.ext.viewcode', # Third-party extensions: 'myst_parser', # extended markdown; https://pypi.org/project/myst-parser/ 'sphinxcontrib.apidoc', # Tree-local extensions: 'sphinxcontrib.towncrier.ext', # provides `.. towncrier-draft-entries::` ] # Add any paths that contain templates here, relative to this directory. templates_path = ['_templates'] # The language for content autogenerated by Sphinx. Refer to documentation # for a list of supported languages. # # This is also used if you do content translation via gettext catalogs. # Usually you set "language" from the command line for these cases. language = 'en' # List of patterns, relative to source directory, that match files and # directories to ignore when looking for source files. # This pattern also affects html_static_path and html_extra_path. exclude_patterns = [ '_build', 'Thumbs.db', '.DS_Store', # <- Defaults 'changelog-fragments/**', # Towncrier-managed change notes ] # -- Options for HTML output ------------------------------------------------- html_theme = 'furo' html_show_sphinx = True # -- Extension configuration ------------------------------------------------- # -- Options for intersphinx extension --------------------------------------- intersphinx_mapping = { 'python': ('https://docs.python.org/3', None), 'rtd': ('https://docs.rtfd.io/en/stable', None), 'setuptools': ('https://setuptools.rtfd.io/en/latest', None), 'sphinx': ('https://www.sphinx-doc.org/en/master', None), } # -- Options for todo extension ---------------------------------------------- # If true, `todo` and `todoList` produce output, else they produce nothing. todo_include_todos = True # -- Options for sphinxcontrib.apidoc extension ------------------------------ apidoc_excluded_paths = [] apidoc_extra_args = [ '--implicit-namespaces', '--private', # include β€œ_private” modules ] apidoc_module_dir = str(PROJECT_SRC_DIR / 'sphinxcontrib') apidoc_module_first = False apidoc_output_dir = 'pkg' apidoc_separate_modules = True apidoc_toc_file = None # -- Options for extlinks extension ------------------------------------------ extlinks = { 'issue': (f'{github_repo_url}/issues/%s', '#%s'), # noqa: WPS323 'pr': (f'{github_repo_url}/pull/%s', 'PR #%s'), # noqa: WPS323 'commit': (f'{github_repo_url}/commit/%s', '%s'), # noqa: WPS323 'gh': (f'{github_url}/%s', 'GitHub: %s'), # noqa: WPS323 'user': (f'{github_sponsors_url}/%s', '@%s'), # noqa: WPS323 } # -- Options for linkcheck builder ------------------------------------------- linkcheck_ignore = [ r'http://localhost:\d+/', # local URLs ] linkcheck_workers = 25 # Ref: # * https://github.com/djungelorm/sphinx-tabs/issues/26#issuecomment-422160463 sphinx_tabs_valid_builders = ['linkcheck'] # prevent linkcheck warning # -- Options for autosectionlabel extension ---------------------------------- # Ref: # * https://www.sphinx-doc.org/en/master/usage/extensions/autosectionlabel.html autosectionlabel_maxdepth = 2 # mitigate Towncrier nested subtitles collision # -- Options for towncrier_draft extension ----------------------------------- # mode is one of 'draft', 'sphinx-version' or 'sphinx-release' towncrier_draft_autoversion_mode = 'draft' towncrier_draft_include_empty = True towncrier_draft_working_directory = PROJECT_ROOT_DIR # Not yet supported: towncrier_draft_config_path = 'pyproject.toml' # relative to cwd # -- Strict mode ------------------------------------------------------------- # Ref: python-attrs/attrs#571 default_role = 'any' nitpicky = True _py_class_role = 'py:class' nitpick_ignore = [ # NOTE: Docutils does not have any intersphinx-compatible site (_py_class_role, 'docutils.nodes.Node'), (_py_class_role, 'docutils.nodes.document'), (_py_class_role, 'docutils.statemachine.State'), (_py_class_role, 'docutils.nodes.Node'), ] def setup(app: Sphinx) -> Mapping[str, str]: """Set up extra Sphinx extension integrations.""" # NOTE: Sphinx doesn't seem to expose its :event: role at the moment. # NOTE: This hack re-declares the event type locally. # Ref: https://github.com/sphinx-doc/sphinx/issues/8987 app.add_object_type('event', 'event') return { 'parallel_read_safe': True, 'parallel_write_safe': True, 'version': 'builtin', } sphinxcontrib-towncrier-0.4.0a0/docs/contributing.rst000066400000000000000000000000411452305177600230360ustar00rootroot00000000000000.. include:: ../CONTRIBUTING.rst sphinxcontrib-towncrier-0.4.0a0/docs/index.rst000066400000000000000000000007531452305177600214500ustar00rootroot00000000000000Welcome to |project|'s documentation! ===================================== .. include:: ../README.rst :end-before: DO-NOT-REMOVE-docs-badges-END .. include:: ../README.rst :start-after: DO-NOT-REMOVE-docs-intro-START .. toctree:: :maxdepth: 2 :caption: Go deeper: change-notes-layout contributing .. toctree:: :maxdepth: 2 :caption: Private (Dev) API: pkg/modules Indices and tables ================== * :ref:`genindex` * :ref:`modindex` * :ref:`search` sphinxcontrib-towncrier-0.4.0a0/docs/pkg/000077500000000000000000000000001452305177600203635ustar00rootroot00000000000000sphinxcontrib-towncrier-0.4.0a0/docs/pkg/.gitignore000066400000000000000000000000171452305177600223510ustar00rootroot00000000000000* !.gitignore sphinxcontrib-towncrier-0.4.0a0/docs/requirements.in000066400000000000000000000001661452305177600226600ustar00rootroot00000000000000furo >= 2021.02.28.beta28 myst-parser >= 0.13.5 setuptools_scm >= 3.5.0 Sphinx >= 3.5.1 sphinxcontrib-apidoc >= 0.3.0 sphinxcontrib-towncrier-0.4.0a0/docs/requirements.txt000066400000000000000000000311261452305177600230710ustar00rootroot00000000000000# # This file is autogenerated by pip-compile # To update, run: # # pip-compile --allow-unsafe --generate-hashes --output-file=docs/requirements.txt docs/requirements.in # alabaster==0.7.12 \ --hash=sha256:446438bdcca0e05bd45ea2de1668c1d9b032e1a9154c2c259092d77031ddd359 \ --hash=sha256:a661d72d58e6ea8a57f7a86e37d86716863ee5e92788398526d58b26a4e4dc02 # via sphinx attrs==21.2.0 \ --hash=sha256:149e90d6d8ac20db7a955ad60cf0e6881a3f20d37096140088356da6c716b0b1 \ --hash=sha256:ef6aaac3ca6cd92904cdd0d83f629a15f18053ec84e6432106f7a4d04ae4f5fb # via markdown-it-py babel==2.9.1 \ --hash=sha256:ab49e12b91d937cd11f0b67cb259a57ab4ad2b59ac7a3b41d6c06c0ac5b0def9 \ --hash=sha256:bc0c176f9f6a994582230df350aa6e05ba2ebe4b3ac317eab29d9be5d2768da0 # via sphinx beautifulsoup4==4.9.3 \ --hash=sha256:4c98143716ef1cb40bf7f39a8e3eec8f8b009509e74904ba3a7b315431577e35 \ --hash=sha256:84729e322ad1d5b4d25f805bfa05b902dd96450f43842c4e99067d5e1369eb25 \ --hash=sha256:fff47e031e34ec82bf17e00da8f592fe7de69aeea38be00523c04623c04fb666 # via furo certifi==2022.12.7 \ --hash=sha256:35824b4c3a97115964b408844d64aa14db1cc518f6562e8d7261699d1350a9e3 \ --hash=sha256:4ad3232f5e926d6718ec31cfc1fcadfde020920e278684144551c91769c7bc18 # via requests chardet==4.0.0 \ --hash=sha256:0d6f53a15db4120f2b08c94f11e7d93d2c911ee118b6b30a04ec3ee8310179fa \ --hash=sha256:f864054d66fd9118f2e67044ac8981a54775ec5b67aed0441892edb553d21da5 # via requests docutils==0.16 \ --hash=sha256:0c5b78adfbf7762415433f5515cd5c9e762339e23369dbe8000d84a4bf4ab3af \ --hash=sha256:c2de3a60e9e7d07be26b7f2b00ca0309c207e06c100f9cc2a94931fc75a478fc # via # myst-parser # sphinx furo==2021.4.11b34 \ --hash=sha256:3d88e2855949cecf5f562e8a28cab1a6d3355d82f3cf5796eddf9ec234e97519 \ --hash=sha256:576a1dc1bcbe337d7c53cbc75b886802778a5964fd2e3324433d706066e9aea8 # via -r requirements.in idna==2.10 \ --hash=sha256:b307872f855b18632ce0c21c5e45be78c0ea7ae4c15c828c20788b26921eb3f6 \ --hash=sha256:b97d804b1e9b523befed77c48dacec60e6dcb0b5391d57af6a65a312a90648c0 # via requests imagesize==1.2.0 \ --hash=sha256:6965f19a6a2039c7d48bca7dba2473069ff854c36ae6f19d2cde309d998228a1 \ --hash=sha256:b1f6b5a4eab1f73479a50fb79fcf729514a900c341d8503d62a62dbc4127a2b1 # via sphinx jinja2==3.0.1 \ --hash=sha256:1f06f2da51e7b56b8f238affdd6b4e2c61e39598a378cc49345bc1bd42a978a4 \ --hash=sha256:703f484b47a6af502e743c9122595cc812b0271f661722403114f71a79d0f5a4 # via # myst-parser # sphinx markdown-it-py==1.1.0 \ --hash=sha256:36be6bb3ad987bfdb839f5ba78ddf094552ca38ccbd784ae4f74a4e1419fc6e3 \ --hash=sha256:98080fc0bc34c4f2bcf0846a096a9429acbd9d5d8e67ed34026c03c61c464389 # via # mdit-py-plugins # myst-parser markupsafe==2.0.1 \ --hash=sha256:01a9b8ea66f1658938f65b93a85ebe8bc016e6769611be228d797c9d998dd298 \ --hash=sha256:023cb26ec21ece8dc3907c0e8320058b2e0cb3c55cf9564da612bc325bed5e64 \ --hash=sha256:0446679737af14f45767963a1a9ef7620189912317d095f2d9ffa183a4d25d2b \ --hash=sha256:0717a7390a68be14b8c793ba258e075c6f4ca819f15edfc2a3a027c823718567 \ --hash=sha256:0955295dd5eec6cb6cc2fe1698f4c6d84af2e92de33fbcac4111913cd100a6ff \ --hash=sha256:10f82115e21dc0dfec9ab5c0223652f7197feb168c940f3ef61563fc2d6beb74 \ --hash=sha256:1d609f577dc6e1aa17d746f8bd3c31aa4d258f4070d61b2aa5c4166c1539de35 \ --hash=sha256:2ef54abee730b502252bcdf31b10dacb0a416229b72c18b19e24a4509f273d26 \ --hash=sha256:3c112550557578c26af18a1ccc9e090bfe03832ae994343cfdacd287db6a6ae7 \ --hash=sha256:47ab1e7b91c098ab893b828deafa1203de86d0bc6ab587b160f78fe6c4011f75 \ --hash=sha256:49e3ceeabbfb9d66c3aef5af3a60cc43b85c33df25ce03d0031a608b0a8b2e3f \ --hash=sha256:4efca8f86c54b22348a5467704e3fec767b2db12fc39c6d963168ab1d3fc9135 \ --hash=sha256:53edb4da6925ad13c07b6d26c2a852bd81e364f95301c66e930ab2aef5b5ddd8 \ --hash=sha256:594c67807fb16238b30c44bdf74f36c02cdf22d1c8cda91ef8a0ed8dabf5620a \ --hash=sha256:611d1ad9a4288cf3e3c16014564df047fe08410e628f89805e475368bd304914 \ --hash=sha256:6557b31b5e2c9ddf0de32a691f2312a32f77cd7681d8af66c2692efdbef84c18 \ --hash=sha256:693ce3f9e70a6cf7d2fb9e6c9d8b204b6b39897a2c4a1aa65728d5ac97dcc1d8 \ --hash=sha256:6a7fae0dd14cf60ad5ff42baa2e95727c3d81ded453457771d02b7d2b3f9c0c2 \ --hash=sha256:6c4ca60fa24e85fe25b912b01e62cb969d69a23a5d5867682dd3e80b5b02581d \ --hash=sha256:7d91275b0245b1da4d4cfa07e0faedd5b0812efc15b702576d103293e252af1b \ --hash=sha256:905fec760bd2fa1388bb5b489ee8ee5f7291d692638ea5f67982d968366bef9f \ --hash=sha256:97383d78eb34da7e1fa37dd273c20ad4320929af65d156e35a5e2d89566d9dfb \ --hash=sha256:984d76483eb32f1bcb536dc27e4ad56bba4baa70be32fa87152832cdd9db0833 \ --hash=sha256:a30e67a65b53ea0a5e62fe23682cfe22712e01f453b95233b25502f7c61cb415 \ --hash=sha256:ab3ef638ace319fa26553db0624c4699e31a28bb2a835c5faca8f8acf6a5a902 \ --hash=sha256:b2f4bf27480f5e5e8ce285a8c8fd176c0b03e93dcc6646477d4630e83440c6a9 \ --hash=sha256:b7f2d075102dc8c794cbde1947378051c4e5180d52d276987b8d28a3bd58c17d \ --hash=sha256:be98f628055368795d818ebf93da628541e10b75b41c559fdf36d104c5787066 \ --hash=sha256:d7f9850398e85aba693bb640262d3611788b1f29a79f0c93c565694658f4071f \ --hash=sha256:f5653a225f31e113b152e56f154ccbe59eeb1c7487b39b9d9f9cdb58e6c79dc5 \ --hash=sha256:f826e31d18b516f653fe296d967d700fddad5901ae07c622bb3705955e1faa94 \ --hash=sha256:f8ba0e8349a38d3001fae7eadded3f6606f0da5d748ee53cc1dab1d6527b9509 \ --hash=sha256:f9081981fe268bd86831e5c75f7de206ef275defcb82bc70740ae6dc507aee51 \ --hash=sha256:fa130dd50c57d53368c9d59395cb5526eda596d3ffe36666cd81a44d56e48872 # via jinja2 mdit-py-plugins==0.2.8 \ --hash=sha256:1833bf738e038e35d89cb3a07eb0d227ed647ce7dd357579b65343740c6d249c \ --hash=sha256:5991cef645502e80a5388ec4fc20885d2313d4871e8b8e320ca2de14ac0c015f # via myst-parser myst-parser==0.14.0 \ --hash=sha256:8d7db76e2f33cd1dc1fe0c76af9f09e5cf19ce2c2e85074bc82f272c0f7c08ce \ --hash=sha256:fc262959a74cdc799d7fa9b30c320c17187485b9a1e8c39e988fc12f3adff63c # via -r requirements.in packaging==20.9 \ --hash=sha256:5b327ac1320dc863dca72f4514ecc086f31186744b84a230374cc1fd776feae5 \ --hash=sha256:67714da7f7bc052e064859c05c595155bd1ee9f69f76557e21f051443c20947a # via sphinx pbr==5.6.0 \ --hash=sha256:42df03e7797b796625b1029c0400279c7c34fd7df24a7d7818a1abb5b38710dd \ --hash=sha256:c68c661ac5cc81058ac94247278eeda6d2e6aecb3e227b0387c30d277e7ef8d4 # via sphinxcontrib-apidoc pygments==2.9.0 \ --hash=sha256:a18f47b506a429f6f4b9df81bb02beab9ca21d0a5fee38ed15aef65f0545519f \ --hash=sha256:d66e804411278594d764fc69ec36ec13d9ae9147193a1740cd34d272ca383b8e # via sphinx pyparsing==2.4.7 \ --hash=sha256:c203ec8783bf771a155b207279b9bccb8dea02d8f0c9e5f8ead507bc3246ecc1 \ --hash=sha256:ef9d7589ef3c200abe66653d3f1ab1033c3c419ae9b9bdb1240a85b024efc88b # via packaging pytz==2021.1 \ --hash=sha256:83a4a90894bf38e243cf052c8b58f381bfe9a7a483f6a9cab140bc7f702ac4da \ --hash=sha256:eb10ce3e7736052ed3623d49975ce333bcd712c7bb19a58b9e2089d4057d0798 # via babel pyyaml==5.4.1 \ --hash=sha256:08682f6b72c722394747bddaf0aa62277e02557c0fd1c42cb853016a38f8dedf \ --hash=sha256:0f5f5786c0e09baddcd8b4b45f20a7b5d61a7e7e99846e3c799b05c7c53fa696 \ --hash=sha256:129def1b7c1bf22faffd67b8f3724645203b79d8f4cc81f674654d9902cb4393 \ --hash=sha256:294db365efa064d00b8d1ef65d8ea2c3426ac366c0c4368d930bf1c5fb497f77 \ --hash=sha256:3b2b1824fe7112845700f815ff6a489360226a5609b96ec2190a45e62a9fc922 \ --hash=sha256:3bd0e463264cf257d1ffd2e40223b197271046d09dadf73a0fe82b9c1fc385a5 \ --hash=sha256:4465124ef1b18d9ace298060f4eccc64b0850899ac4ac53294547536533800c8 \ --hash=sha256:49d4cdd9065b9b6e206d0595fee27a96b5dd22618e7520c33204a4a3239d5b10 \ --hash=sha256:4e0583d24c881e14342eaf4ec5fbc97f934b999a6828693a99157fde912540cc \ --hash=sha256:5accb17103e43963b80e6f837831f38d314a0495500067cb25afab2e8d7a4018 \ --hash=sha256:607774cbba28732bfa802b54baa7484215f530991055bb562efbed5b2f20a45e \ --hash=sha256:6c78645d400265a062508ae399b60b8c167bf003db364ecb26dcab2bda048253 \ --hash=sha256:72a01f726a9c7851ca9bfad6fd09ca4e090a023c00945ea05ba1638c09dc3347 \ --hash=sha256:74c1485f7707cf707a7aef42ef6322b8f97921bd89be2ab6317fd782c2d53183 \ --hash=sha256:895f61ef02e8fed38159bb70f7e100e00f471eae2bc838cd0f4ebb21e28f8541 \ --hash=sha256:8c1be557ee92a20f184922c7b6424e8ab6691788e6d86137c5d93c1a6ec1b8fb \ --hash=sha256:bb4191dfc9306777bc594117aee052446b3fa88737cd13b7188d0e7aa8162185 \ --hash=sha256:bfb51918d4ff3d77c1c856a9699f8492c612cde32fd3bcd344af9be34999bfdc \ --hash=sha256:c20cfa2d49991c8b4147af39859b167664f2ad4561704ee74c1de03318e898db \ --hash=sha256:cb333c16912324fd5f769fff6bc5de372e9e7a202247b48870bc251ed40239aa \ --hash=sha256:d2d9808ea7b4af864f35ea216be506ecec180628aced0704e34aca0b040ffe46 \ --hash=sha256:d483ad4e639292c90170eb6f7783ad19490e7a8defb3e46f97dfe4bacae89122 \ --hash=sha256:dd5de0646207f053eb0d6c74ae45ba98c3395a571a2891858e87df7c9b9bd51b \ --hash=sha256:e1d4970ea66be07ae37a3c2e48b5ec63f7ba6804bdddfdbd3cfd954d25a82e63 \ --hash=sha256:e4fac90784481d221a8e4b1162afa7c47ed953be40d31ab4629ae917510051df \ --hash=sha256:fa5ae20527d8e831e8230cbffd9f8fe952815b2b7dae6ffec25318803a7528fc \ --hash=sha256:fd7f6999a8070df521b6384004ef42833b9bd62cfee11a09bda1079b4b704247 \ --hash=sha256:fdc842473cd33f45ff6bce46aea678a54e3d21f1b61a7750ce3c498eedfe25d6 \ --hash=sha256:fe69978f3f768926cfa37b867e3843918e012cf83f680806599ddce33c2c68b0 # via myst-parser requests==2.25.1 \ --hash=sha256:27973dd4a904a4f13b263a19c866c13b92a39ed1c964655f025f3f8d3d75b804 \ --hash=sha256:c210084e36a42ae6b9219e00e48287def368a26d03a048ddad7bfee44f75871e # via sphinx setuptools-scm==6.0.1 \ --hash=sha256:c3bd5f701c8def44a5c0bfe8d407bef3f80342217ef3492b951f3777bd2d915c \ --hash=sha256:d1925a69cb07e9b29416a275b9fadb009a23c148ace905b2fb220649a6c18e92 # via -r requirements.in snowballstemmer==2.1.0 \ --hash=sha256:b51b447bea85f9968c13b650126a888aabd4cb4463fca868ec596826325dedc2 \ --hash=sha256:e997baa4f2e9139951b6f4c631bad912dfd3c792467e2f03d7239464af90e914 # via sphinx soupsieve==2.2.1 \ --hash=sha256:052774848f448cf19c7e959adf5566904d525f33a3f8b6ba6f6f8f26ec7de0cc \ --hash=sha256:c2c1c2d44f158cdbddab7824a9af8c4f83c76b1e23e049479aa432feb6c4c23b # via beautifulsoup4 sphinx==3.5.4 \ --hash=sha256:19010b7b9fa0dc7756a6e105b2aacd3a80f798af3c25c273be64d7beeb482cb1 \ --hash=sha256:2320d4e994a191f4b4be27da514e46b3d6b420f2ff895d064f52415d342461e8 # via # -r requirements.in # furo # myst-parser # sphinxcontrib-apidoc sphinxcontrib-apidoc==0.3.0 \ --hash=sha256:6671a46b2c6c5b0dca3d8a147849d159065e50443df79614f921b42fbd15cb09 \ --hash=sha256:729bf592cf7b7dd57c4c05794f732dc026127275d785c2a5494521fdde773fb9 # via -r requirements.in sphinxcontrib-applehelp==1.0.2 \ --hash=sha256:806111e5e962be97c29ec4c1e7fe277bfd19e9652fb1a4392105b43e01af885a \ --hash=sha256:a072735ec80e7675e3f432fcae8610ecf509c5f1869d17e2eecff44389cdbc58 # via sphinx sphinxcontrib-devhelp==1.0.2 \ --hash=sha256:8165223f9a335cc1af7ffe1ed31d2871f325254c0423bc0c4c7cd1c1e4734a2e \ --hash=sha256:ff7f1afa7b9642e7060379360a67e9c41e8f3121f2ce9164266f61b9f4b338e4 # via sphinx sphinxcontrib-htmlhelp==2.0.0 \ --hash=sha256:d412243dfb797ae3ec2b59eca0e52dac12e75a241bf0e4eb861e450d06c6ed07 \ --hash=sha256:f5f8bb2d0d629f398bf47d0d69c07bc13b65f75a81ad9e2f71a63d4b7a2f6db2 # via sphinx sphinxcontrib-jsmath==1.0.1 \ --hash=sha256:2ec2eaebfb78f3f2078e73666b1415417a116cc848b72e5172e596c871103178 \ --hash=sha256:a9925e4a4587247ed2191a22df5f6970656cb8ca2bd6284309578f2153e0c4b8 # via sphinx sphinxcontrib-qthelp==1.0.3 \ --hash=sha256:4c33767ee058b70dba89a6fc5c1892c0d57a54be67ddd3e7875a18d14cba5a72 \ --hash=sha256:bd9fc24bcb748a8d51fd4ecaade681350aa63009a347a8c14e637895444dfab6 # via sphinx sphinxcontrib-serializinghtml==1.1.5 \ --hash=sha256:352a9a00ae864471d3a7ead8d7d79f5fc0b57e8b3f95e9867eb9eb28999b92fd \ --hash=sha256:aa5f6de5dfdf809ef505c4895e51ef5c9eac17d0f287933eb49ec495280b6952 # via sphinx urllib3==1.26.5 \ --hash=sha256:753a0374df26658f99d826cfe40394a686d05985786d946fbe4165b5148f5a7c \ --hash=sha256:a7acd0977125325f516bda9735fa7142b909a8d01e8b2e4c8108d0984e6e0098 # via requests # The following packages are considered to be unsafe in a requirements file: setuptools==57.0.0 \ --hash=sha256:401cbf33a7bf817d08014d51560fc003b895c4cdc1a5b521ad2969e928a07535 \ --hash=sha256:c8b9f1a457949002e358fea7d3f2a1e1b94ddc0354b2e40afc066bf95d21bf7b # via # setuptools-scm # sphinx sphinxcontrib-towncrier-0.4.0a0/mypy.ini000066400000000000000000000010321452305177600203450ustar00rootroot00000000000000[mypy] python_version = 3.6 color_output = True error_summary = True check_untyped_defs = True disallow_untyped_calls = True disallow_any_generics = True enable_error_code = ignore-without-code follow_imports = normal ignore_missing_imports = False pretty = true show_column_numbers = true show_error_codes = true strict_optional = True warn_no_return = True warn_redundant_casts = True warn_unused_ignores = True [mypy-towncrier.*] ignore_missing_imports = True [mypy-sphinxcontrib.towncrier.*] ignore_missing_imports = True sphinxcontrib-towncrier-0.4.0a0/nitpick-style.toml000066400000000000000000000020511452305177600223440ustar00rootroot00000000000000[nitpick.styles] include = [ "py://nitpick/resources/any/editorconfig", "py://nitpick/resources/any/git-legal", "py://nitpick/resources/any/pre-commit-hooks", # "py://nitpick/resources/python/flake8", "py://nitpick/resources/python/github-workflow", "gh://andreoliwa/nitpick@8a1d2bd0/src/nitpick/resources/python/hooks.toml", # NOTE: Needed for as long as Python 3.6 remains supported # "py://nitpick/resources/python/pre-commit-hooks", # FIXME: Uncomment as soon as Python 3.6 support is dropped # "py://nitpick/resources/python/isort", # Requires config to be in `setup.cfg` so not for us # "py://nitpick/resources/python/mypy", # Requires CLI args but we have that in `mypy.ini` # "py://nitpick/resources/python/pylint", # Makes several bad suggestions "py://nitpick/resources/python/radon", "py://nitpick/resources/shell/bashate", "py://nitpick/resources/shell/shellcheck", ] [".flake8".flake8] max-line-length = 79 [".isort.cfg".settings] line_length = 79 [".pylintrc".FORMAT] max-line-length = 79 sphinxcontrib-towncrier-0.4.0a0/pyproject.toml000066400000000000000000000011241452305177600215640ustar00rootroot00000000000000[build-system] requires = [ # Essentials "setuptools>=40.6.0", # Plugins "setuptools_scm[toml] >= 3.5", # version is required for "no-local-version" scheme + toml extra is needed for supporting config in this file "setuptools_scm_git_archive >= 1.1", ] build-backend = "setuptools.build_meta" # ATTENTION: the following section must be kept last in # `pyproject.toml` because the CI appends one line in # the end when publishing non-tagged versions. [tool.setuptools_scm] write_to = "src/sphinxcontrib/towncrier/_scm_version.py" # ATTENTION: DO NOT ADD ANYTHING AFTER THIS SECTION ^ sphinxcontrib-towncrier-0.4.0a0/pytest.ini000066400000000000000000000046151452305177600207110ustar00rootroot00000000000000[pytest] addopts = # `pytest-xdist`: --numprocesses=auto # NOTE: the plugin disabled because it's slower with so few tests --numprocesses=0 # Show 10 slowest invocations: --durations=10 # A bit of verbosity doesn't hurt: -v # Report all the things == -rxXs: -ra # Show values of the local vars in errors/tracebacks: --showlocals # Autocollect and invoke the doctests from all modules: # https://docs.pytest.org/en/stable/doctest.html --doctest-modules # Dump the test results in junit format: --junitxml=.test-results/pytest/results.xml # `pytest-cov`: --cov --cov=sphinxcontrib.towncrier --cov=tests/ --cov-report term-missing:skip-covered --cov-report xml:.test-results/pytest/cov.xml # Pre-load `pytest-cov` plugin early: -p pytest_cov # Fail on config parsing warnings: # --strict-config # Fail on non-existing markers: # * Deprecated since v6.2.0 but may be reintroduced later covering a # broader scope: # --strict # * Exists since v4.5.0 (advised to be used instead of `--strict`): --strict-markers doctest_optionflags = ALLOW_UNICODE ELLIPSIS # Marks tests with an empty parameterset as xfail(run=False) empty_parameter_set_mark = xfail faulthandler_timeout = 30 filterwarnings = error # FIXME: drop this once `pytest-cov` is updated. # Ref: https://github.com/pytest-dev/pytest-cov/issues/557 ignore:The --rsyncdir command line argument and rsyncdirs config variable are deprecated.:DeprecationWarning # FIXME: drop this once `towncrier < 19.9.0` is no longer supported. ignore:Deprecated call to `pkg_resources.declare_namespace.'sphinxcontrib'.`.:DeprecationWarning # FIXME: drop this once `towncrier < 19.9.0` is no longer supported. ignore:pkg_resources is deprecated as an API:DeprecationWarning # https://docs.pytest.org/en/stable/usage.html#creating-junitxml-format-files junit_duration_report = call # xunit1 contains more metadata than xunit2 so it's better for CI UIs: junit_family = xunit1 junit_logging = all junit_log_passing_tests = true junit_suite_name = towncrier_test_suite # A mapping of markers to their descriptions allowed in strict mode: markers = minversion = 6.1.0 # Optimize pytest's lookup by restricting potentially deep dir tree scan: norecursedirs = build dist docs src/sphinxcontrib_towncrier.egg-info .cache .eggs .git .github .tox *.egg testpaths = tests/ xfail_strict = true sphinxcontrib-towncrier-0.4.0a0/setup.cfg000066400000000000000000000042271452305177600205000ustar00rootroot00000000000000[bdist_wheel] # NOTE: "universal = 1" causes `bdist_wheel` to create a wheel that with the # NOTE: tag "py2.py3" which implies (and tricks pip into thinking) that this # NOTE: wheel contains Python 2 compatible code. This is not true and conflicts # NOTE: with the "Requires-Python" field in the metadata that says that we only # NOTE: support Python 3.6+. # NOTE: We need to keep it at "0" which will produce wheels tagged with "py3" # NOTE: when built under Python 3. # Ref: https://github.com/pypa/packaging.python.org/issues/726 universal = 0 [metadata] name = sphinxcontrib-towncrier url = https://github.com/sphinx-contrib/sphinxcontrib-towncrier project_urls = GitHub: repo = https://github.com/sphinx-contrib/sphinxcontrib-towncrier GitHub: issues = https://github.com/sphinx-contrib/sphinxcontrib-towncrier/issues description = An RST directive for injecting a Towncrier-generated changelog draft containing fragments for the unreleased (next) project version long_description = file: README.rst long_description_content_type = text/x-rst author = Sviatoslav Sydorenko author_email = wk+pypi/sphinxcontrib-towncrier@sydorenko.org.ua maintainer = Oleksiy Vasylyshyn maintainer_email = slsh1o-git@protonmail.com license = BSD 3-Clause License license_files = LICENSE classifiers = Development Status :: 3 - Alpha Framework :: Sphinx Framework :: Sphinx :: Extension Intended Audience :: Developers License :: OSI Approved :: BSD License Operating System :: OS Independent Programming Language :: Python :: 3.6 Programming Language :: Python :: 3.7 Programming Language :: Python :: 3.8 Programming Language :: Python :: 3.9 Programming Language :: Python :: 3.10 Programming Language :: Python :: 3.11 Programming Language :: Python :: 3.12 Topic :: Software Development :: Documentation Topic :: Documentation :: Sphinx Topic :: System :: Software Distribution Topic :: Utilities [options] include_package_data = True install_requires = importlib-metadata >= 4; python_version < '3.8' sphinx towncrier >= 19.2 package_dir = = src packages = find_namespace: python_requires = >=3.6 zip_safe = True [options.packages.find] where = src sphinxcontrib-towncrier-0.4.0a0/setup.py000077500000000000000000000011301452305177600203620ustar00rootroot00000000000000#! /usr/bin/env python3 # NOTE: THIS FILE IS IMMUTABLE AND SHOULD REMAIN UNCHANGED UNLESS THERE ARE # NOTE: SERIOUS REASONS TO EDIT IT. THIS IS ENFORCED BY THE PRE-COMMIT TOOL. """The distribution package setuptools installer for sphinxcontrib-towncrier. The presence of this file ensures the support of pip editable mode *with setuptools only*. It is also required for `tox --devenv some-env-folder` command to work because it does `pip install -e .` under the hood. """ from setuptools import setup # pylint: disable=expression-not-assigned __name__ == '__main__' and setup() # noqa: WPS428 sphinxcontrib-towncrier-0.4.0a0/src/000077500000000000000000000000001452305177600174415ustar00rootroot00000000000000sphinxcontrib-towncrier-0.4.0a0/src/sphinxcontrib/000077500000000000000000000000001452305177600223335ustar00rootroot00000000000000sphinxcontrib-towncrier-0.4.0a0/src/sphinxcontrib/towncrier/000077500000000000000000000000001452305177600243475ustar00rootroot00000000000000sphinxcontrib-towncrier-0.4.0a0/src/sphinxcontrib/towncrier/__init__.py000066400000000000000000000006041452305177600264600ustar00rootroot00000000000000"""Sphinx extension for injecting an unreleased changelog into docs. This is an importable package containing the whole project. The Sphinx extension entry point is declared in the :file:`ext` submodule. To use this extension, add the following to your :file:`conf.py`: .. code-block:: python extensions = ['sphinxcontrib.towncrier.ext'] """ from .ext import __version__, setup sphinxcontrib-towncrier-0.4.0a0/src/sphinxcontrib/towncrier/_compat.py000066400000000000000000000016301452305177600263430ustar00rootroot00000000000000"""Cross-Python compatibility helpers.""" import sys from typing import Iterable if sys.version_info >= (3, 8): from importlib.metadata import ( # noqa: WPS433 version as importlib_metadata_get_version, ) from shlex import join as shlex_join # noqa: WPS433 else: # Python 3.7 and lower: from shlex import quote as _shlex_quote # noqa: WPS433 # pylint: disable-next=line-too-long from importlib_metadata import ( # type: ignore[no-redef, unused-ignore] # noqa: LN002, WPS433, WPS440 # `unused-ignore` is only needed under Python 3.6 version as importlib_metadata_get_version, ) def shlex_join(split_command: Iterable[str]) -> str: # noqa: WPS440 """Return a shell-escaped string from *split_command*.""" return ' '.join(_shlex_quote(arg) for arg in split_command) __all__ = ('importlib_metadata_get_version', 'shlex_join') # noqa: WPS410 sphinxcontrib-towncrier-0.4.0a0/src/sphinxcontrib/towncrier/_data_transformers.py000066400000000000000000000014431452305177600306000ustar00rootroot00000000000000"""Data transformation helpers.""" def escape_project_version_rst_substitution(version: str) -> str: """Prepend an escaped whitespace before RST substitution.""" if not version.startswith('|') or version.count('|') <= 1: return version # A corner case exists when the towncrier config has something like # `v{version}` in the title format **and** the directive target # argument starts with a substitution like `|release|`. And so # when combined, they produce a v|release|` causing RST to not # substitute the `|release|` part. But adding an escaped space # solves this: that escaped space renders as an empty string and # the substitution gets processed properly so the result would # be something like `v1.0` as expected. return rf'\ {version}' sphinxcontrib-towncrier-0.4.0a0/src/sphinxcontrib/towncrier/_fragment_discovery.py000066400000000000000000000050051452305177600307520ustar00rootroot00000000000000"""Changelog fragment discovery helpers.""" from functools import lru_cache from pathlib import Path from typing import Optional, Set from sphinx.util import logging try: # pylint: disable=no-name-in-module from towncrier.build import find_fragments # noqa: WPS433 except ImportError: # pylint: disable=import-self,no-name-in-module from towncrier import ( # type: ignore[attr-defined] # noqa: WPS433,WPS440 find_fragments, ) from ._towncrier import get_towncrier_config # noqa: WPS436 logger = logging.getLogger(__name__) def _resolve_spec_config( base: Path, spec_name: Optional[str] = None, ) -> Optional[Path]: return base / spec_name if spec_name is not None else None # pylint: disable=fixme # FIXME: consider consolidating this logic upstream in towncrier def _find_config_file(base: Path) -> Path: """Find the best config file.""" candidate_names = 'towncrier.toml', 'pyproject.toml' candidates = list(map(base.joinpath, candidate_names)) extant = filter(Path.is_file, candidates) return next(extant, candidates[-1]) # pylint: disable=fixme # FIXME: refactor `lookup_towncrier_fragments` to drop noqas @lru_cache(maxsize=1, typed=True) # noqa: WPS210 def lookup_towncrier_fragments( # noqa: WPS210 working_dir: Optional[str] = None, config_path: Optional[str] = None, ) -> Set[Path]: """Emit RST-formatted Towncrier changelog fragment paths.""" project_path = Path.cwd() if working_dir is None else Path(working_dir) final_config_path = ( _resolve_spec_config(project_path, config_path) or _find_config_file(project_path) ) try: towncrier_config = get_towncrier_config( project_path, final_config_path, ) except KeyError as key_err: # NOTE: The error is missing key 'towncrier' or similar logger.warning( f'Missing key {key_err!s} in file {final_config_path!s}', ) return set() fragment_directory: Optional[str] = 'newsfragments' try: fragment_base_directory = project_path / towncrier_config['directory'] except KeyError: assert fragment_directory is not None fragment_base_directory = project_path / fragment_directory else: fragment_directory = None _fragments, fragment_filenames = find_fragments( str(fragment_base_directory), towncrier_config['sections'], fragment_directory, towncrier_config['types'], ) return set(fragment_filenames) sphinxcontrib-towncrier-0.4.0a0/src/sphinxcontrib/towncrier/_scm_version.pyi000066400000000000000000000001751452305177600275630ustar00rootroot00000000000000# This stub file is necessary because `_scm_version.py` # autogenerated on build and absent on mypy checks time version: str sphinxcontrib-towncrier-0.4.0a0/src/sphinxcontrib/towncrier/_towncrier.py000066400000000000000000000031621452305177600270760ustar00rootroot00000000000000"""Towncrier related shims.""" from contextlib import suppress as _suppress_exception from pathlib import Path from typing import Any, Dict, Union with _suppress_exception(ImportError): # NOTE: This will not raise an exception under Python >= 3.7, and is only # NOTE: needed for Towncrier >= 22.12.0rc1 which doesn't support Python 3.6 from dataclasses import asdict as _dataclass_to_dict # noqa: WPS433 try: # Towncrier >= 22.8.0rc1 # pylint: disable=import-error,no-name-in-module from towncrier._settings.load import ( # noqa: WPS433, WPS436 load_config_from_file, ) except ImportError: # pylint: disable=import-error,no-name-in-module from towncrier._settings import ( # noqa: WPS433, WPS436, WPS440 load_config_from_file, ) def get_towncrier_config( project_path: Path, final_config_path: Union[Path, None], ) -> Dict[str, Any]: # FIXME: add a better type # pylint: disable=fixme """Return the towncrier config dictionary.""" try: # Towncrier >= 19.9.0 config = load_config_from_file( str(project_path), str(final_config_path), ) except TypeError: # Towncrier < 19.9.0 if final_config_path is None or not final_config_path.exists(): # Towncrier < 19.9.0 raise FileNotFoundError( f"[Errno 2] No such file or directory: '{final_config_path}'", ) from None return load_config_from_file(str(final_config_path)) if isinstance(config, dict): # Towncrier < 22.12.0rc1 return config return _dataclass_to_dict(config) sphinxcontrib-towncrier-0.4.0a0/src/sphinxcontrib/towncrier/_version.py000066400000000000000000000005411452305177600265450ustar00rootroot00000000000000"""Version definition.""" try: # pylint: disable=unused-import from ._scm_version import version as __version__ # noqa: WPS433, WPS436 except ImportError: from ._compat import importlib_metadata_get_version # noqa: WPS433, WPS436 __version__ = importlib_metadata_get_version( # noqa: WPS440 'sphinxcontrib-towncrier', ) sphinxcontrib-towncrier-0.4.0a0/src/sphinxcontrib/towncrier/ext.py000066400000000000000000000311461452305177600255260ustar00rootroot00000000000000"""Sphinx extension for injecting an unreleased changelog into docs.""" import subprocess # noqa: S404 import sys from contextlib import suppress as suppress_exceptions from functools import lru_cache from pathlib import Path from typing import Dict, List, Optional, Set, Tuple, Union from sphinx.application import Sphinx from sphinx.config import Config as SphinxConfig from sphinx.environment import BuildEnvironment from sphinx.environment.collectors import EnvironmentCollector from sphinx.util import logging from sphinx.util.docutils import SphinxDirective from sphinx.util.nodes import nested_parse_with_titles, nodes # isort: split # Ref: https://github.com/PyCQA/pylint/issues/3817 from docutils import statemachine # pylint: disable=wrong-import-order from ._compat import shlex_join # noqa: WPS436 from ._data_transformers import ( # noqa: WPS436 escape_project_version_rst_substitution, ) from ._fragment_discovery import lookup_towncrier_fragments # noqa: WPS436 from ._version import __version__ # noqa: WPS436 PROJECT_ROOT_DIR = Path(__file__).parents[3].resolve() TOWNCRIER_DRAFT_CMD = ( sys.executable, '-m', # invoke via runpy under the same interpreter 'towncrier', 'build', '--draft', # write to stdout, don't change anything on disk ) logger = logging.getLogger(__name__) @lru_cache(typed=True) def _get_changelog_draft_entries( target_version: str, allow_empty: bool = False, working_dir: Optional[str] = None, config_path: Optional[str] = None, ) -> str: """Retrieve the unreleased changelog entries from Towncrier.""" extra_cli_args: Tuple[str, ...] = ( '--version', # A version to be used in the RST title: escape_project_version_rst_substitution(target_version), ) if config_path is not None: # This isn't actually supported by a released version of Towncrier yet: # https://github.com/twisted/towncrier/pull/157#issuecomment-666549246 # https://github.com/twisted/towncrier/issues/269 extra_cli_args += '--config', str(config_path) try: towncrier_output = subprocess.check_output( # noqa: S603 TOWNCRIER_DRAFT_CMD + extra_cli_args, cwd=str(working_dir) if working_dir else None, stderr=subprocess.PIPE, universal_newlines=True, # a "text" alias exists since Python 3.7 ).strip() except subprocess.CalledProcessError as proc_exc: cmd = shlex_join(proc_exc.cmd) stdout = proc_exc.stdout or '[No output]' stderr = proc_exc.stderr or '[No output]' raise RuntimeError( 'Command exited unexpectedly.\n\n' f'Command: {cmd}\n' f'Return code: {proc_exc.returncode}\n\n' f'Standard output:\n{stdout}\n\n' f'Standard error:\n{stderr}', ) from proc_exc if not allow_empty and 'No significant changes' in towncrier_output: raise LookupError('There are no unreleased changelog entries so far') return towncrier_output @lru_cache(maxsize=1, typed=True) def _get_draft_version_fallback( strategy: str, sphinx_config: SphinxConfig, ) -> str: """Generate a fallback version string for towncrier draft.""" known_strategies = {'draft', 'sphinx-version', 'sphinx-release'} if strategy not in known_strategies: raise ValueError( 'Expected "strategy" to be ' f'one of {known_strategies!r} but got {strategy!r}', ) if 'sphinx' in strategy: return ( sphinx_config.release if 'release' in strategy else sphinx_config.version ) return '[UNRELEASED DRAFT]' def _nodes_from_document_markup_source( state: statemachine.State, markup_source: str, ) -> List[nodes.Node]: """Turn an RST or Markdown string into a list of nodes. These nodes can be used in the document. """ node = nodes.Element() node.document = state.document nested_parse_with_titles( state=state, content=statemachine.ViewList( statemachine.string2lines(markup_source), source='[towncrier-fragments]', ), node=node, ) return node.children class TowncrierDraftEntriesDirective(SphinxDirective): """Definition of the ``towncrier-draft-entries`` directive.""" has_content = True # default: False def run(self) -> List[nodes.Node]: # noqa: WPS210 """Generate a node tree in place of the directive.""" target_version = ( self.content[:1][0] if self.content[:1] else None ) if self.content[1:]: # inner content present raise self.error( f'Error in "{self.name!s}" directive: ' 'only one argument permitted.', ) config = self.env.config autoversion_mode = config.towncrier_draft_autoversion_mode include_empty = config.towncrier_draft_include_empty towncrier_fragment_paths = lookup_towncrier_fragments( working_dir=config.towncrier_draft_working_directory, config_path=config.towncrier_draft_config_path, ) for path in towncrier_fragment_paths: # make sphinx discard doctree cache on file changes self.env.note_dependency(str(path)) try: # pylint: disable-next=line-too-long self.env.towncrier_fragment_paths |= ( # type: ignore[attr-defined] towncrier_fragment_paths ) except AttributeError: # If the attribute hasn't existed, initialize it instead of # updating self.env.towncrier_fragment_paths = ( # type: ignore[attr-defined] towncrier_fragment_paths ) try: self.env.towncrier_fragment_docs |= { # type: ignore[attr-defined] self.env.docname, } except AttributeError: # If the attribute hasn't existed, initialize it instead of # updating self.env.towncrier_fragment_docs = { # type: ignore[attr-defined] self.env.docname, } try: draft_changes = _get_changelog_draft_entries( target_version or _get_draft_version_fallback(autoversion_mode, config), allow_empty=include_empty, working_dir=config.towncrier_draft_working_directory, config_path=config.towncrier_draft_config_path, ) except RuntimeError as runtime_err: raise self.error(runtime_err) except LookupError: return [] return _nodes_from_document_markup_source( state=self.state, markup_source=draft_changes, ) class TowncrierDraftEntriesEnvironmentCollector(EnvironmentCollector): r"""Environment collector for ``TowncrierDraftEntriesDirective``. When :py:class:`~TowncrierDraftEntriesDirective` is used in a document, it depends on some dynamically generated change fragments. After the first render, the doctree nodes are put in cache and are reused from there. There's a way to make Sphinx aware of the directive dependencies by calling :py:meth:`BuildEnvironment.\ note_dependency ` but this will only work for fragments that have existed at the time of that first directive invocation. In order to track newly appearing change fragment dependencies, we need to do so at the time of Sphinx identifying what documents require rebuilding. There's :event:`env-get-outdated` that allows to extend this list of planned rebuilds and we could use it by assigning a document-to-fragments map from within the directive and reading it in the event handler later (since env contents are preserved in cache). But this approach does not take into account cleanups and parallel runs of Sphinx. In order to make it truly parallelism-compatible, we need to define how to merge our custom cache attribute collected within multiple Sphinx subprocesses into one object and that's where :py:class:`~sphinx.environment.\ collectors.EnvironmentCollector` comes into play. Refs: * https://github.com/sphinx-doc/sphinx/issues/8040#issuecomment-671587308 * https://github.com/sphinx-contrib/sphinxcontrib-towncrier/issues/1 """ def clear_doc( self, app: Sphinx, env: BuildEnvironment, docname: str, ) -> None: """Clean up env metadata related to the removed document. This is a handler for :event:`env-purge-doc`. """ with suppress_exceptions(AttributeError, KeyError): env.towncrier_fragment_docs.remove( # type: ignore[attr-defined] docname, ) def merge_other( self, app: Sphinx, env: BuildEnvironment, docnames: Set[str], other: BuildEnvironment, ) -> None: """Merge doc-to-fragments from another proc into this env. This is a handler for :event:`env-merge-info`. """ try: other_fragment_docs: Set[str] = ( other.towncrier_fragment_docs # type: ignore[attr-defined] ) except AttributeError: # If the other process env doesn't have documents using # `TowncrierDraftEntriesDirective`, there's nothing to merge return if not hasattr(env, 'towncrier_fragment_docs'): # noqa: WPS421 # If the other process env doesn't have documents using # `TowncrierDraftEntriesDirective`, initialize the structure # at least env.towncrier_fragment_docs = set() # type: ignore[attr-defined] if not hasattr(env, 'towncrier_fragment_paths'): # noqa: WPS421 env.towncrier_fragment_paths = set() # type: ignore[attr-defined] # Since Sphinx does not pull the same document into multiple # processes, we don't care about the same dict key appearing # in different envs with different sets of the deps env.towncrier_fragment_docs.update( # type: ignore[attr-defined] other_fragment_docs, ) env.towncrier_fragment_paths.update( # type: ignore[attr-defined] other.towncrier_fragment_paths, # type: ignore[attr-defined] ) def process_doc(self, app: Sphinx, doctree: nodes.document) -> None: """React to :event:`doctree-read` with no-op.""" # pylint: disable=too-many-arguments def get_outdated_docs( # noqa: WPS211 self, app: Sphinx, env: BuildEnvironment, added: Set[str], changed: Set[str], removed: Set[str], ) -> List[str]: """Mark docs with changed fragment deps for rebuild. This is a handler for :event:`env-get-outdated`. """ towncrier_fragment_paths = lookup_towncrier_fragments( working_dir=env.config.towncrier_draft_working_directory, config_path=env.config.towncrier_draft_config_path, ) fragments_changed = False with suppress_exceptions(AttributeError): fragments_changed = bool( towncrier_fragment_paths ^ env.towncrier_fragment_paths, # type: ignore[attr-defined] ) return ( list( env.towncrier_fragment_docs # type: ignore[attr-defined] - changed, ) if fragments_changed else [] ) def setup(app: Sphinx) -> Dict[str, Union[bool, str]]: """Initialize the extension.""" rebuild_trigger = 'html' # rebuild full html on settings change app.add_config_value( 'towncrier_draft_config_path', default=None, rebuild=rebuild_trigger, ) app.add_config_value( 'towncrier_draft_autoversion_mode', default='scm-draft', rebuild=rebuild_trigger, ) app.add_config_value( 'towncrier_draft_include_empty', default=True, rebuild=rebuild_trigger, ) app.add_config_value( 'towncrier_draft_working_directory', default=None, rebuild=rebuild_trigger, ) app.add_directive( 'towncrier-draft-entries', TowncrierDraftEntriesDirective, ) # Register an environment collector to merge data gathered by the # directive in parallel builds app.add_env_collector(TowncrierDraftEntriesEnvironmentCollector) return { 'parallel_read_safe': True, 'parallel_write_safe': True, 'version': __version__, } sphinxcontrib-towncrier-0.4.0a0/src/sphinxcontrib/towncrier/py.typed000066400000000000000000000004611452305177600260470ustar00rootroot00000000000000`sphinxcontrib.towncrier` is a Sphinx extension. It does not expose own public API. However, this PEP 561 marker file exists to let the type checkers know that this project has type annotations declared. In particular, this is useful for type-checking our own tests since they make corresponding imports. sphinxcontrib-towncrier-0.4.0a0/tests/000077500000000000000000000000001452305177600200145ustar00rootroot00000000000000sphinxcontrib-towncrier-0.4.0a0/tests/__init__.py000066400000000000000000000002421452305177600221230ustar00rootroot00000000000000# ATTENTION: This file only exists to make relative helper imports work. # ATTENTION: Do not put anything inside! """Test suite for `sphinxcontrib.towncrier`.""" sphinxcontrib-towncrier-0.4.0a0/tests/_compat.py000066400000000000000000000011551452305177600220120ustar00rootroot00000000000000# pylint: disable=no-name-in-module """Compatibility shims for Python and Towncrier matrix.""" try: # Towncrier >= 22.8.0rc1 # pylint: disable-next=unused-import from towncrier._settings.load import ( # noqa: WPS433 ConfigError as TowncrierConfigError, ) except ImportError: # Towncrier < 22.8.0rc1 try: # noqa: WPS505 # Towncrier >= 19.9.0 from towncrier._settings import ( # noqa: WPS433, WPS440 ConfigError as TowncrierConfigError, ) except ImportError: # Towncrier < 19.9.0 TowncrierConfigError = ValueError # noqa: WPS440 sphinxcontrib-towncrier-0.4.0a0/tests/_data_transformers_test.py000066400000000000000000000016401452305177600253030ustar00rootroot00000000000000"""Data transformation tests.""" import pytest from sphinxcontrib.towncrier._data_transformers import ( escape_project_version_rst_substitution, ) @pytest.mark.parametrize( ('test_input', 'escaped_input'), ( (r'\ |release|', r'\ |release|'), ('|release|', r'\ |release|'), ('|release', '|release'), ('v|release|', 'v|release|'), ), ids=( 'substitution already escaped', 'correct substitution at the beginning', 'unclosed substitution at the beginning', 'correct substitution in the middle', ), ) def test_escape_version(test_input: str, escaped_input: str) -> None: """Test that the version is escaped before RST substitutions. RST substitution as the first item should be escaped. Otherwise, the input is expected to remain unchanged. """ assert escape_project_version_rst_substitution(test_input) == escaped_input sphinxcontrib-towncrier-0.4.0a0/tests/_fragment_discovery_test.py000066400000000000000000000026651452305177600254670ustar00rootroot00000000000000"""Unit tests of the fragment discovery logic.""" from pathlib import Path from typing import Set import pytest from sphinxcontrib.towncrier._fragment_discovery import _find_config_file PYPROJECT_TOML_FILENAME = 'pyproject.toml' TOWNCRIER_TOML_FILENAME = 'towncrier.toml' @pytest.mark.parametrize( ('config_file_names_on_disk', 'expected_config_file_name'), ( pytest.param( set(), PYPROJECT_TOML_FILENAME, id='pyproject.toml-when-no-configs', ), pytest.param( {PYPROJECT_TOML_FILENAME}, 'pyproject.toml', id='pyproject.toml-only', ), pytest.param( {TOWNCRIER_TOML_FILENAME}, TOWNCRIER_TOML_FILENAME, id='towncrier.toml-only', ), pytest.param( {PYPROJECT_TOML_FILENAME, TOWNCRIER_TOML_FILENAME}, TOWNCRIER_TOML_FILENAME, id='towncrier.toml-over-pyproject.toml', ), ), ) def test_find_config_file( config_file_names_on_disk: Set[str], expected_config_file_name: str, tmp_path: Path, ) -> None: """Verify that the correct Towncrier config is always preferred.""" for config_file_name_on_disk in config_file_names_on_disk: tmp_path.joinpath(config_file_name_on_disk).write_text( '', encoding='utf-8', ) assert _find_config_file(tmp_path).name == expected_config_file_name sphinxcontrib-towncrier-0.4.0a0/tests/_towncrier_test.py000066400000000000000000000030571452305177600236050ustar00rootroot00000000000000"""Towncrier config reader tests.""" from pathlib import Path from typing import Union import pytest from sphinxcontrib.towncrier._towncrier import get_towncrier_config from ._compat import TowncrierConfigError def test_towncrier_config_section_missing( monkeypatch: pytest.MonkeyPatch, tmp_path: Path, ) -> None: """Test config file without Towncrier section raises an error.""" tmp_working_dir_path = tmp_path / 'working-directory' tmp_working_dir_path.mkdir() empty_config_file = Path('arbitrary-config.toml') (tmp_working_dir_path / empty_config_file).touch() monkeypatch.chdir(tmp_working_dir_path) expected_error_msg = r'^No \[tool\.towncrier\] section\.$' with pytest.raises(TowncrierConfigError, match=expected_error_msg): get_towncrier_config(tmp_path, empty_config_file) @pytest.mark.parametrize( 'config_file_name', ( None, Path('pyproject.toml'), Path('towncrier.toml'), ), ) def test_towncrier_config_file_missing( config_file_name: Union[Path, None], monkeypatch: pytest.MonkeyPatch, tmp_path: Path, ) -> None: """Test missing Towncrier config file raises an error.""" tmp_working_dir_path = tmp_path / 'working-directory' tmp_working_dir_path.mkdir() monkeypatch.chdir(tmp_working_dir_path) expected_error_msg = ( fr"^\[Errno 2\] No such file or directory: '{config_file_name}'$" ) with pytest.raises(FileNotFoundError, match=expected_error_msg): get_towncrier_config(tmp_path, config_file_name) sphinxcontrib-towncrier-0.4.0a0/tests/units_test.py000066400000000000000000000053111452305177600225670ustar00rootroot00000000000000"""Unit tests of the extension bits.""" import sys import pytest from sphinxcontrib.towncrier._compat import shlex_join from sphinxcontrib.towncrier.ext import _get_changelog_draft_entries NO_OUTPUT_MARKER = r'\[No output\]' _get_changelog_draft_entries_unwrapped = ( _get_changelog_draft_entries. __wrapped__ # So that the non-cached function version is tested ) @pytest.mark.parametrize( ('failing_cmd', 'stdout_msg', 'stderr_msg'), ( ( ( 'false', ), NO_OUTPUT_MARKER, NO_OUTPUT_MARKER, ), ( ( sys.executable, '-c', r'print("test standard output\nsecond line");' 'raise SystemExit(1)', ), r'test standard output\nsecond line\n', NO_OUTPUT_MARKER, ), ( ( sys.executable, '-c', r'raise SystemExit("test standard error\nsecond line")', ), NO_OUTPUT_MARKER, r'test standard error\nsecond line', ), ( ( sys.executable, '-c', r'print("test standard output\nsecond line out");' r'raise SystemExit("test standard error\nsecond line err")', ), r'test standard output\nsecond line out\n', r'test standard error\nsecond line err', ), ), ids=( 'no stdout, no stderr', 'stdout, no stderr', 'no stdout, stderr', 'stdout, stderr', ), ) def test_towncrier_draft_generation_failure_msg( failing_cmd, stdout_msg, stderr_msg, monkeypatch, ) -> None: """Test that a failing command produces a :class:`RuntimeError`.""" version_string = 'test version' monkeypatch.setattr( 'sphinxcontrib.towncrier.ext.TOWNCRIER_DRAFT_CMD', failing_cmd, # So that the invoked command would return a failure ) escaped_failing_cmd = ( # This is necessary because it's used in a regexp shlex_join(failing_cmd). replace('\\', r'\\'). replace('(', r'\('). replace(')', r'\)') ) expected_return_code = 1 expected_error_message = ( '^' # noqa: WPS221 'Command exited unexpectedly.\n\n' rf"Command: {escaped_failing_cmd} --version '{version_string}'\n" f'Return code: {expected_return_code}\n\n' 'Standard output:\n' f'{stdout_msg}\n\n' 'Standard error:\n' f'{stderr_msg}' '$' ) with pytest.raises(RuntimeError, match=expected_error_message): _get_changelog_draft_entries_unwrapped(version_string) sphinxcontrib-towncrier-0.4.0a0/tests/version_test.py000066400000000000000000000002641452305177600231140ustar00rootroot00000000000000"""Version tests.""" from sphinxcontrib.towncrier import __version__ def test_version(): """Test that version has at least 3 parts.""" assert __version__.count('.') >= 2 sphinxcontrib-towncrier-0.4.0a0/tox.ini000066400000000000000000000060511452305177600201670ustar00rootroot00000000000000[tox] envlist = python isolated_build = true minversion = 3.21.0 [testenv] description = Run test suite commands = {envpython} -m \ pytest \ {tty:--color=yes} \ {posargs:} deps = pytest pytest-cov pytest-xdist # Ref: https://github.com/tox-dev/tox/issues/1199 towncrier isolated_build = true package = wheel wheel_build_env = .pkg usedevelop = false [testenv:build-dists] description = Build dists and put them into the dist{/} folder basepython = python3 isolated_build = true # NOTE: `package_env = none` is needed so it's possible to use `--installpkg` # NOTE: with the main `testenv`. # Ref: https://github.com/tox-dev/tox/issues/2442 package_env = ❌ DUMMY NON-EXISTENT ENV NAME ❌ # `usedevelop = true` overrides `skip_install` instruction, it's unwanted usedevelop = false skip_install = true deps = build ~= 1.0.0 commands = {envpython} -c \ "import shutil; \ shutil.rmtree('{toxinidir}{/}dist{/}', ignore_errors=True)" {envpython} -m build \ --outdir '{toxinidir}{/}dist{/}' \ {posargs:} \ '{toxinidir}' [testenv:lint] description = Run the quality checks basepython = python3 commands = {envpython} -m \ pre_commit run \ --show-diff-on-failure \ --hook-stage manual \ {posargs:--all-files} # Print out the advice on how to install pre-commit from this env into Git: -{envpython} -c \ 'cmd = "{envpython} -m pre_commit install"; \ scr_width = len(cmd) + 10; \ sep = "=" * scr_width; \ cmd_str = " $ \{cmd\}";' \ 'print(f"\n\{sep\}\nTo install pre-commit hooks into the Git repo, run:\n\n\{cmd_str\}\n\n\{sep\}\n")' deps = {[testenv]deps} {[testenv:build-docs]deps} pre-commit >= 2.6.0 pylint ~= 2.15.0 isolated_build = true [testenv:build-docs] allowlist_externals = git basepython = python3 depends = make-changelog deps = # -r{toxinidir}{/}docs{/}requirements.txt # FIXME: re-enable the "-r" + "-c" paradigm once the pip bug is fixed. # Ref: https://github.com/pypa/pip/issues/9243 -r{toxinidir}{/}docs{/}requirements.in # -c{toxinidir}{/}docs{/}requirements.txt description = Build The Docs commands = # Retrieve possibly missing commits: -git fetch --unshallow -git fetch --tags # Build the html docs with Sphinx: {envpython} -m sphinx \ -j auto \ -b html \ {tty:--color} \ -a \ -n \ -W --keep-going \ -d "{temp_dir}{/}.doctrees" \ {posargs:} \ . \ "{envdir}{/}docs_out" # Print out the output docs dir and a way to serve html: -{envpython} -c\ 'import pathlib;\ docs_dir = pathlib.Path(r"{envdir}") / "docs_out";\ index_file = docs_dir / "index.html";\ print("\n" + "=" * 120 +\ f"\n\nDocumentation available under:\n\n\ \tfile://\{index_file\}\n\nTo serve docs, use\n\n\ \t$ python3 -m http.server --directory \ \N\{QUOTATION MARK\}\{docs_dir\}\N\{QUOTATION MARK\} 0\n\n" +\ "=" * 120)' changedir = {toxinidir}{/}docs isolated_build = true passenv = SSH_AUTH_SOCK skip_install = false # whitelist_externals is a compatibility alias for allowlist_externals @ old tox whitelist_externals = git