commit python-sphinx-issues for openSUSE:Factory
Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package python-sphinx-issues for openSUSE:Factory checked in at 2024-07-03 20:29:43 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/python-sphinx-issues (Old) and /work/SRC/openSUSE:Factory/.python-sphinx-issues.new.18349 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Package is "python-sphinx-issues" Wed Jul 3 20:29:43 2024 rev:9 rq:1184074 version:4.1.0 Changes: -------- --- /work/SRC/openSUSE:Factory/python-sphinx-issues/python-sphinx-issues.changes 2023-04-22 21:59:18.656804106 +0200 +++ /work/SRC/openSUSE:Factory/.python-sphinx-issues.new.18349/python-sphinx-issues.changes 2024-07-03 20:30:14.092921450 +0200 @@ -1,0 +2,11 @@ +Sun Jun 30 07:39:29 UTC 2024 - Dirk Müller <dmueller@suse.com> + +- update to 4.1.0: + * Add `:pypi:` role for linking to PyPI projects + * Default to linking GH Sponsors for the :user: role + * Support Python 3.8-3.12. Older versions are no longer supported. + * Backwards-incompatible*: Remove ``__version__``, + ``__author__``, and ``__license__`` attributes. + Use ``importlib.metadata`` to read this metadata instead. + +------------------------------------------------------------------- Old: ---- 3.0.1.tar.gz New: ---- 4.1.0.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ python-sphinx-issues.spec ++++++ --- /var/tmp/diff_new_pack.8GlHyU/_old 2024-07-03 20:30:14.560938580 +0200 +++ /var/tmp/diff_new_pack.8GlHyU/_new 2024-07-03 20:30:14.564938726 +0200 @@ -1,7 +1,7 @@ # # spec file for package python-sphinx-issues # -# Copyright (c) 2023 SUSE LLC +# Copyright (c) 2024 SUSE LLC # # All modifications and additions to the file contributed by third parties # remain the property of their copyright owners, unless otherwise agreed @@ -16,19 +16,19 @@ # -%{?!python_module:%define python_module() python-%{**} python3-%{**}} -%bcond_without python2 %{?sle15_python_module_pythons} Name: python-sphinx-issues -Version: 3.0.1 +Version: 4.1.0 Release: 0 Summary: A Sphinx extension for linking to a project's issue tracker License: MIT URL: https://github.com/sloria/sphinx-issues Source: https://github.com/sloria/sphinx-issues/archive/%{version}.tar.gz BuildRequires: %{python_module Sphinx} +BuildRequires: %{python_module flit-core} +BuildRequires: %{python_module pip} BuildRequires: %{python_module pytest} -BuildRequires: %{python_module setuptools} +BuildRequires: %{python_module wheel} BuildRequires: fdupes BuildRequires: python-rpm-macros Requires: python-Sphinx @@ -47,10 +47,10 @@ %setup -q -n sphinx-issues-%{version} %build -%python_build +%pyproject_wheel %install -%python_install +%pyproject_install %python_expand %fdupes %{buildroot}%{$python_sitelib} %check @@ -59,5 +59,6 @@ %files %{python_files} %doc README.rst %license LICENSE -%{python_sitelib}/* +%{python_sitelib}/sphinx_issues +%{python_sitelib}/sphinx_issues-%{version}.dist-info ++++++ 3.0.1.tar.gz -> 4.1.0.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/sphinx-issues-3.0.1/.github/dependabot.yml new/sphinx-issues-4.1.0/.github/dependabot.yml --- old/sphinx-issues-3.0.1/.github/dependabot.yml 1970-01-01 01:00:00.000000000 +0100 +++ new/sphinx-issues-4.1.0/.github/dependabot.yml 2024-04-15 05:03:23.000000000 +0200 @@ -0,0 +1,11 @@ +version: 2 +updates: +- package-ecosystem: pip + directory: "/" + schedule: + interval: daily + open-pull-requests-limit: 10 +- package-ecosystem: "github-actions" + directory: "/" + schedule: + interval: "monthly" diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/sphinx-issues-3.0.1/.github/workflows/build-release.yml new/sphinx-issues-4.1.0/.github/workflows/build-release.yml --- old/sphinx-issues-3.0.1/.github/workflows/build-release.yml 1970-01-01 01:00:00.000000000 +0100 +++ new/sphinx-issues-4.1.0/.github/workflows/build-release.yml 2024-04-15 05:03:23.000000000 +0200 @@ -0,0 +1,77 @@ +name: build +on: + push: + branches: ["main"] + tags: ["*"] + pull_request: + +jobs: + tests: + name: ${{ matrix.name }} + runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + include: + - { name: "3.8", python: "3.8", tox: py38 } + - { name: "3.12", python: "3.12", tox: py312 } + steps: + - uses: actions/checkout@v4.0.0 + - uses: actions/setup-python@v5 + with: + python-version: ${{ matrix.python }} + allow-prereleases: true + - run: python -m pip install --upgrade pip + - run: python -m pip install tox + - run: python -m tox -e ${{ matrix.tox }} + build: + name: Build package + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-python@v5 + with: + python-version: "3.11" + - name: Install pypa/build + run: python -m pip install build + - name: Build a binary wheel and a source tarball + run: python -m build + - name: Install twine + run: python -m pip install twine + - name: Check build + run: python -m twine check --strict dist/* + - name: Store the distribution packages + uses: actions/upload-artifact@v4 + with: + name: python-package-distributions + path: dist/ + # this duplicates pre-commit.ci, so only run it on tags + # it guarantees that linting is passing prior to a release + lint-pre-release: + if: startsWith(github.ref, 'refs/tags') + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4.0.0 + - uses: actions/setup-python@v5 + with: + python-version: "3.11" + - run: python -m pip install tox + - run: python -m tox -e lint + publish-to-pypi: + name: PyPI release + if: startsWith(github.ref, 'refs/tags/') + needs: [build, tests, lint-pre-release] + runs-on: ubuntu-latest + environment: + name: pypi + url: https://pypi.org/p/sphinx-issues + permissions: + id-token: write + steps: + - name: Download all the dists + uses: actions/download-artifact@v4 + with: + name: python-package-distributions + path: dist/ + - name: Publish distribution to PyPI + uses: pypa/gh-action-pypi-publish@release/v1 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/sphinx-issues-3.0.1/.github/workflows/lint.yml new/sphinx-issues-4.1.0/.github/workflows/lint.yml --- old/sphinx-issues-3.0.1/.github/workflows/lint.yml 2022-01-11 17:41:14.000000000 +0100 +++ new/sphinx-issues-4.1.0/.github/workflows/lint.yml 1970-01-01 01:00:00.000000000 +0100 @@ -1,12 +0,0 @@ -name: Lint - -on: [push, pull_request, workflow_dispatch] - -jobs: - lint: - runs-on: ubuntu-latest - - steps: - - uses: actions/checkout@v2 - - uses: actions/setup-python@v2 - - uses: pre-commit/action@v2.0.3 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/sphinx-issues-3.0.1/.github/workflows/test.yml new/sphinx-issues-4.1.0/.github/workflows/test.yml --- old/sphinx-issues-3.0.1/.github/workflows/test.yml 2022-01-11 17:41:14.000000000 +0100 +++ new/sphinx-issues-4.1.0/.github/workflows/test.yml 1970-01-01 01:00:00.000000000 +0100 @@ -1,34 +0,0 @@ -name: Test - -on: [push, pull_request, workflow_dispatch] - -env: - FORCE_COLOR: 1 - -jobs: - test: - runs-on: ubuntu-latest - strategy: - fail-fast: false - matrix: - python-version: ["3.6", "3.10"] - - steps: - - uses: actions/checkout@v2 - - - name: Set up Python ${{ matrix.python-version }} - uses: actions/setup-python@v2 - with: - python-version: ${{ matrix.python-version }} - cache: pip - cache-dependency-path: "setup.py" - - - name: Install dependencies - run: | - python -m pip install -U pip - python -m pip install -U wheel - python -m pip install -U tox - - - name: Tox tests - run: | - tox -e py diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/sphinx-issues-3.0.1/.gitignore new/sphinx-issues-4.1.0/.gitignore --- old/sphinx-issues-3.0.1/.gitignore 2022-01-11 17:41:14.000000000 +0100 +++ new/sphinx-issues-4.1.0/.gitignore 2024-04-15 05:03:23.000000000 +0200 @@ -41,3 +41,9 @@ # Sphinx docs/_build README.html + +# mypy +.mypy_cache/ + +# ruff +.ruff_cache diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/sphinx-issues-3.0.1/.pre-commit-config.yaml new/sphinx-issues-4.1.0/.pre-commit-config.yaml --- old/sphinx-issues-3.0.1/.pre-commit-config.yaml 2022-01-11 17:41:14.000000000 +0100 +++ new/sphinx-issues-4.1.0/.pre-commit-config.yaml 2024-04-15 05:03:23.000000000 +0200 @@ -1,20 +1,16 @@ repos: -- repo: https://github.com/asottile/pyupgrade - rev: v2.11.0 +- repo: https://github.com/astral-sh/ruff-pre-commit + rev: v0.3.5 hooks: - - id: pyupgrade - args: [--py36-plus] -- repo: https://github.com/python/black - rev: 20.8b1 + - id: ruff + - id: ruff-format +- repo: https://github.com/python-jsonschema/check-jsonschema + rev: 0.28.1 hooks: - - id: black -- repo: https://gitlab.com/pycqa/flake8 - rev: 3.9.0 - hooks: - - id: flake8 - additional_dependencies: [flake8-bugbear==21.4.3] + - id: check-github-workflows + - id: check-readthedocs - repo: https://github.com/asottile/blacken-docs - rev: v1.10.0 + rev: 1.16.0 hooks: - id: blacken-docs - additional_dependencies: [black==20.8b1] + additional_dependencies: [black==23.12.1] diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/sphinx-issues-3.0.1/CONTRIBUTING.md new/sphinx-issues-4.1.0/CONTRIBUTING.md --- old/sphinx-issues-3.0.1/CONTRIBUTING.md 2022-01-11 17:41:14.000000000 +0100 +++ new/sphinx-issues-4.1.0/CONTRIBUTING.md 2024-04-15 05:03:23.000000000 +0200 @@ -2,32 +2,24 @@ ## Setting up for development -* Create and activate a new virtual environment -* `pip install -e '.[dev]'` -* (Optional but recommended) If you're using a Python 3.6 virtual - environment, install the pre-commit hooks, which will - format and lint your git staged files: - +- Create and activate a new virtual environment +- `pip install -e '.[dev]'` +- (Optional but recommended) Install the pre-commit hooks, which will + format and lint your git staged files: ``` # The pre-commit CLI was installed above pre-commit install ``` -* To run tests: +- To run tests: ``` pytest ``` -* To run syntax checks: +- To run syntax checks: ``` tox -e lint ``` - -* (Optional) To run tests on Python 2.7, 3.5, 3.6, and 3.7 virtual environments (must have each interpreter installed): - -``` -tox -``` diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/sphinx-issues-3.0.1/LICENSE new/sphinx-issues-4.1.0/LICENSE --- old/sphinx-issues-3.0.1/LICENSE 2022-01-11 17:41:14.000000000 +0100 +++ new/sphinx-issues-4.1.0/LICENSE 2024-04-15 05:03:23.000000000 +0200 @@ -1,4 +1,4 @@ -Copyright 2022 Steven Loria +Copyright Steven Loria and contributors Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/sphinx-issues-3.0.1/MANIFEST.in new/sphinx-issues-4.1.0/MANIFEST.in --- old/sphinx-issues-3.0.1/MANIFEST.in 2022-01-11 17:41:14.000000000 +0100 +++ new/sphinx-issues-4.1.0/MANIFEST.in 1970-01-01 01:00:00.000000000 +0100 @@ -1 +0,0 @@ -include *.rst LICENSE diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/sphinx-issues-3.0.1/README.rst new/sphinx-issues-4.1.0/README.rst --- old/sphinx-issues-3.0.1/README.rst 2022-01-11 17:41:14.000000000 +0100 +++ new/sphinx-issues-4.1.0/README.rst 2024-04-15 05:03:23.000000000 +0200 @@ -3,16 +3,12 @@ ============= .. image:: https://badgen.net/pypi/v/sphinx-issues - :alt: pypi badge - :target: https://pypi.org/project/sphinx-issues/ + :target: https://pypi.org/project/sphinx-issues/ + :alt: PyPI badge -.. image:: https://github.com/OpenASL/HowSignBot/workflows/.github/workflows/test.yml/b... - :alt: github actions status - :target: .github/workflows/test.yml - -.. image:: https://badgen.net/badge/code%20style/black/000 - :target: https://github.com/ambv/black - :alt: Code style: Black +.. image:: https://github.com/sloria/sphinx-issues/actions/workflows/build-release.yml/... + :target: https://github.com/sloria/sphinx-issues/actions/workflows/build-release.yml + :alt: Build status A Sphinx extension for linking to your project's issue tracker. Includes roles for linking to issues, pull requests, user profiles, with built-in support for GitHub (though this works with other services). @@ -139,6 +135,12 @@ :cwe:`CWE-787` - The software writes data past the end, or... +Use the ``:pypi:`` role to link to PyPI on https://pypi.org. + +.. code-block:: rst + + :pypi:`sphinx-issues` - A Sphinx extension for linking to your project's issue tracker. + Credits ******* @@ -153,6 +155,21 @@ Changelog ********* +4.1.0 (2024-04-14) +------------------ + +- Add `:pypi:` role for linking to PyPI projects (`#144 <https://github.com/sloria/sphinx-issues/issues/144>`_). + Thanks @shenxianpeng for the suggestion and PR. + +4.0.0 (2024-01-19) +------------------ + +- Default to linking GH Sponsors for the :user: role (`#129 <https://github.com/sloria/sphinx-issues/issues/129>`_). + Thanks @webknjaz for the suggestion. +- Support Python 3.8-3.12. Older versions are no longer supported. +- *Backwards-incompatible*: Remove ``__version__``, ``__author__``, and ``__license__`` attributes. + Use ``importlib.metadata`` to read this metadata instead. + 3.0.1 (2022-01-11) ------------------ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/sphinx-issues-3.0.1/RELEASING.md new/sphinx-issues-4.1.0/RELEASING.md --- old/sphinx-issues-3.0.1/RELEASING.md 1970-01-01 01:00:00.000000000 +0100 +++ new/sphinx-issues-4.1.0/RELEASING.md 2024-04-15 05:03:23.000000000 +0200 @@ -0,0 +1,8 @@ +# Releasing + +1. Bump version in `pyproject.toml` and update the changelog + with today's date. +2. Commit: `git commit -m "Bump version and update changelog"` +3. Tag the commit: `git tag x.y.z` +4. Push: `git push --tags origin main`. CI will take care of the + PyPI release. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/sphinx-issues-3.0.1/pyproject.toml new/sphinx-issues-4.1.0/pyproject.toml --- old/sphinx-issues-3.0.1/pyproject.toml 1970-01-01 01:00:00.000000000 +0100 +++ new/sphinx-issues-4.1.0/pyproject.toml 2024-04-15 05:03:23.000000000 +0200 @@ -0,0 +1,55 @@ +[project] +name = "sphinx-issues" +version = "4.1.0" +description = "A Sphinx extension for linking to your project's issue tracker" +readme = "README.rst" +license = { file = "LICENSE" } +authors = [{ name = "Steven Loria", email = "sloria1@gmail.com" }] +classifiers = [ + "Framework :: Sphinx :: Extension", + "Intended Audience :: Developers", + "License :: OSI Approved :: MIT License", + "Programming Language :: Python :: 3", + "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", +] +keywords = ["sphinx", "issues", "github"] +requires-python = ">=3.8" +dependencies = ["sphinx"] + +[project.urls] +Issues = "https://github.com/sloria/sphinx-issues/issues" +Source = "https://github.com/sloria/sphinx-issues" + +[project.optional-dependencies] +tests = ["pytest"] +dev = ["sphinx-issues[tests]", "tox", "pre-commit~=3.6"] + +[build-system] +requires = ["flit_core<4"] +build-backend = "flit_core.buildapi" + +[tool.flit.sdist] +include = ["tests/", "CONTRIBUTING.md", "NOTICE", "tox.ini"] +exclude = ["docs/_build/"] + +[tool.ruff] +src = ["src"] +fix = true +show-fixes = true +show-source = true + +[tool.ruff.lint] +ignore = ["E203", "E266", "E501", "E731"] +select = [ + "B", # flake8-bugbear + "E", # pycodestyle error + "F", # pyflakes + "I", # isort + "UP", # pyupgrade + "W", # pycodestyle warning +] diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/sphinx-issues-3.0.1/setup.cfg new/sphinx-issues-4.1.0/setup.cfg --- old/sphinx-issues-3.0.1/setup.cfg 2022-01-11 17:41:14.000000000 +0100 +++ new/sphinx-issues-4.1.0/setup.cfg 1970-01-01 01:00:00.000000000 +0100 @@ -1,9 +0,0 @@ -[metadata] -# This includes the license file in the wheel. -license_files = LICENSE - -[flake8] -ignore = E203, E266, E501, W503 -max-line-length = 90 -max-complexity = 18 -select = B,C,E,F,W,T4,B9 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/sphinx-issues-3.0.1/setup.py new/sphinx-issues-4.1.0/setup.py --- old/sphinx-issues-3.0.1/setup.py 2022-01-11 17:41:14.000000000 +0100 +++ new/sphinx-issues-4.1.0/setup.py 1970-01-01 01:00:00.000000000 +0100 @@ -1,65 +0,0 @@ -import re -from setuptools import setup - -INSTALL_REQUIRES = ["sphinx"] -EXTRAS_REQUIRE = { - "tests": ["pytest>=6.2.0"], - "lint": [ - "flake8==3.9.2", - "flake8-bugbear==20.11.1", - "pre-commit~=2.7", - ], -} -EXTRAS_REQUIRE["dev"] = EXTRAS_REQUIRE["tests"] + EXTRAS_REQUIRE["lint"] + ["tox"] - - -def find_version(fname): - """Attempts to find the version number in the file names fname. - Raises RuntimeError if not found. - """ - version = "" - with open(fname) as fp: - reg = re.compile(r'__version__ = [\'"]([^\'"]*)[\'"]') - for line in fp: - m = reg.match(line) - if m: - version = m.group(1) - break - if not version: - raise RuntimeError("Cannot find version information") - return version - - -def read(fname): - with open(fname) as fp: - content = fp.read() - return content - - -setup( - name="sphinx-issues", - version=find_version("sphinx_issues.py"), - description="A Sphinx extension for linking to your project's issue tracker", - long_description=read("README.rst"), - install_requires=INSTALL_REQUIRES, - extras_require=EXTRAS_REQUIRE, - author="Steven Loria", - author_email="sloria1@gmail.com", - url="https://github.com/sloria/sphinx-issues", - license="MIT", - keywords="sphinx issues github", - python_requires=">=3.6", - classifiers=[ - "Intended Audience :: Developers", - "License :: OSI Approved :: MIT License", - "Programming Language :: Python :: 3", - "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", - "Topic :: Software Development :: Documentation", - ], - py_modules=["sphinx_issues"], - project_urls={"Issues": "https://github.com/sloria/sphinx-issues/issues"}, -) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/sphinx-issues-3.0.1/sphinx_issues.py new/sphinx-issues-4.1.0/sphinx_issues.py --- old/sphinx-issues-3.0.1/sphinx_issues.py 2022-01-11 17:41:14.000000000 +0100 +++ new/sphinx-issues-4.1.0/sphinx_issues.py 1970-01-01 01:00:00.000000000 +0100 @@ -1,390 +0,0 @@ -"""A Sphinx extension for linking to your project's issue tracker.""" -import re -from typing import Callable, Optional, Tuple - -from docutils import nodes, utils -from sphinx.config import Config -from sphinx.util.nodes import split_explicit_title - -__version__ = "3.0.1" -__author__ = "Steven Loria" -__license__ = "MIT" - - -def cve_role(name, rawtext, text, lineno, inliner, options=None, content=None): - """Sphinx role for linking to a CVE on https://cve.mitre.org. - - Examples: :: - - :cve:`CVE-2018-17175` - - """ - options = options or {} - content = content or [] - has_explicit_title, title, target = split_explicit_title(text) - - target = utils.unescape(target).strip() - title = utils.unescape(title).strip() - ref = f"https://cve.mitre.org/cgi-bin/cvename.cgi?name={target}" - text = title if has_explicit_title else target - link = nodes.reference(text=text, refuri=ref, **options) - return [link], [] - - -GITHUB_USER_RE = re.compile("^https://github.com/([^/]+)/([^/]+)/.*") - - -def _get_default_group_and_project( - config: Config, uri_config_option: str -) -> Optional[Tuple[str, str]]: - """ - Get the default group/project or None if not set - """ - old_config = getattr(config, "issues_github_path", None) - new_config = getattr(config, "issues_default_group_project", None) - - if old_config and new_config: - raise ValueError( - "Both 'issues_github_path' and 'issues_default_group_project' are set, even" - " though they define the same setting. " - "Please only define one of these." - ) - group_and_project = new_config or old_config - - if group_and_project: - assert isinstance(group_and_project, str) - try: - group, project = group_and_project.split("/", maxsplit=1) - return group, project - except ValueError as e: - raise ValueError( - "`issues_github_path` or `issues_default_group_project` needs to " - "define a value in the form of `<group or user>/<project>` " - f"but `{config}` was given." - ) from e - - # If group and project was not set, we need to look for it within the github url - # for backward compatibility - if not group_and_project: - uri = getattr(config, uri_config_option) - if uri: - match = GITHUB_USER_RE.match(uri) - if match: - return match.groups()[0], match.groups()[1] - - return None - - -def _get_placeholder(uri_config_option: str) -> str: - """ - Get the placeholder from the uri_config_option - """ - try: - # i.e. issues_pr_uri -> pr - return uri_config_option[:-4].split("_", maxsplit=1)[1] - except IndexError: - # issues_uri -> issue - return uri_config_option[:-5] - - -def _get_uri_template( - config: Config, - uri_config_option: str, -) -> str: - """ - Get a URL format template that can be filled with user information based - on the given configuration - - The result always contains the following placeholder - - n (the issue number, user, pull request, etc...) - - The result can contain the following other placeholders - - group (same as user in github) - - project - - Examples for possible results: - - - "https://github.com/{group}/{project}/issues/{n}" - - - "https://gitlab.company.com/{group}/{project}/{n}" - - - "https://fancy.issuetrack.com?group={group}&project={project}&issue={n}" - - Raises: - - ValueError if the given uri contains an invalid placeholder - """ - format_string = str(getattr(config, uri_config_option)) - placeholder = _get_placeholder(uri_config_option) - - result = format_string.replace(f"{{{placeholder}}}", "{n}") - - try: - result.format(project="", group="", n="") - except (NameError, KeyError) as e: - raise ValueError( - f"The `{uri_config_option}` option contains invalid placeholders. " - f"Only {{group}}, {{projects}} and {{{placeholder}}} are allowed." - f'Invalid format string: "{format_string}".' - ) from e - return result - - -def _get_uri( - uri_config_option: str, - config: Config, - number: str, - group_and_project: Optional[Tuple[str, str]] = None, -) -> str: - """ - Get a URI based on the given configuration and do some sanity checking - """ - format_string = _get_uri_template(config, uri_config_option) - - url_vars = {"n": number} - - config_group_and_project = _get_default_group_and_project(config, uri_config_option) - if group_and_project: - # Group and Project defined by call - if config_group_and_project: - to_replace = "/".join(config_group_and_project) - if to_replace in format_string: - # Backward compatibility, replace default group/project - # with {group}/{project} - format_string = format_string.replace(to_replace, "{group}/{project}") - (url_vars["group"], url_vars["project"]) = group_and_project - elif config_group_and_project: - # If not defined by call use the default if given - (url_vars["group"], url_vars["project"]) = config_group_and_project - - try: - return format_string.format(**url_vars) - except (NameError, KeyError) as e: - # The format string was checked before, that it contains no additional not - # supported placeholders. So this occur - raise ValueError( - f"The `{uri_config_option}` format `{format_string}` requires a " - f"group/project to be defined in `issues_default_group_project`." - ) from e - - -def cwe_role(name, rawtext, text, lineno, inliner, options=None, content=None): - """Sphinx role for linking to a CWE on https://cwe.mitre.org. - - Examples: :: - - :cwe:`CWE-787` - - """ - options = options or {} - content = content or [] - has_explicit_title, title, target = split_explicit_title(text) - - target = utils.unescape(target).strip() - title = utils.unescape(title).strip() - number = target[4:] - ref = f"https://cwe.mitre.org/data/definitions/{number}.html" - text = title if has_explicit_title else target - link = nodes.reference(text=text, refuri=ref, **options) - return [link], [] - - -class IssueRole: - # Symbols used to separate and issue/pull request/merge request etc - # i.e - # - group/project#2323 for issues - # - group/project!1234 for merge requests (in gitlab) - # - group/project@adbc1234 for commits - ELEMENT_SEPARATORS = "#@!" - - EXTERNAL_REPO_REGEX = re.compile(rf"^(\w+)/(.+)([{ELEMENT_SEPARATORS}])([\w]+)$") - - def __init__( - self, - config_prefix: str, - pre_format_text: Callable[[Config, str], str] = None, - ): - self.uri_config = f"{config_prefix}_uri" - self.separator_config = f"{config_prefix}_prefix" - self.pre_format_text = pre_format_text or self.default_pre_format_text - - @staticmethod - def default_pre_format_text(config: Config, text: str) -> str: - return text - - def format_text(self, config: Config, issue_no: str) -> str: - """ - Add supported separator in front of the issue or raise an error if invalid - separator is given - """ - separator = getattr(config, self.separator_config) - if separator not in self.ELEMENT_SEPARATORS: - raise ValueError( - f"Option {self.separator_config} has to be one of " - f"{', '.join(self.ELEMENT_SEPARATORS)}." - ) - text = self.pre_format_text(config, issue_no.lstrip(self.ELEMENT_SEPARATORS)) - return f"{separator}{text}" - - def make_node(self, name: str, issue_no: str, config: Config, options=None): - if issue_no in ("-", "0"): - return None - - options = options or {} - - has_explicit_title, title, target = split_explicit_title(issue_no) - - if has_explicit_title: - issue_no = str(target) - - repo_match = self.EXTERNAL_REPO_REGEX.match(issue_no) - - if repo_match: - # External repo - group, project, original_separator, issue_no = repo_match.groups() - text = f"{group}/{project}{self.format_text(config, issue_no)}" - ref = _get_uri( - self.uri_config, - config, - issue_no, - (group, project), - ) - else: - text = self.format_text(config, issue_no) - ref = _get_uri(self.uri_config, config, issue_no) - if has_explicit_title: - return nodes.reference(text=title, refuri=ref, **options) - else: - return nodes.reference(text=text, refuri=ref, **options) - - def __call__( - self, name, rawtext, text, lineno, inliner, options=None, content=None - ): - options = options or {} - content = content or [] - issue_nos = [each.strip() for each in utils.unescape(text).split(",")] - config = inliner.document.settings.env.app.config - ret = [] - for i, issue_no in enumerate(issue_nos): - node = self.make_node(name, issue_no, config, options=options) - ret.append(node) - if i != len(issue_nos) - 1: - sep = nodes.raw(text=", ", format="html") - ret.append(sep) - return ret, [] - - -"""Sphinx role for linking to an issue. Must have -`issues_uri` or `issues_default_group_project` configured in ``conf.py``. -Examples: :: - :issue:`123` - :issue:`42,45` - :issue:`sloria/konch#123` -""" -issue_role = IssueRole( - config_prefix="issues", -) - -"""Sphinx role for linking to a pull request. Must have -`issues_pr_uri` or `issues_default_group_project` configured in ``conf.py``. -Examples: :: - :pr:`123` - :pr:`42,45` - :pr:`sloria/konch#43` -""" -pr_role = IssueRole( - config_prefix="issues_pr", -) - - -def format_commit_text(config, sha): - return sha[:7] - - -"""Sphinx role for linking to a commit. Must have -`issues_commit_uri` or `issues_default_group_project` configured in ``conf.py``. -Examples: :: - :commit:`123abc456def` - :commit:`sloria/konch@123abc456def` -""" -commit_role = IssueRole( - config_prefix="issues_commit", - pre_format_text=format_commit_text, -) - -"""Sphinx role for linking to a user profile. Defaults to linking to -GitHub profiles, but the profile URIS can be configured via the -``issues_user_uri`` config value. - -Examples: :: - - :user:`sloria` - -Anchor text also works: :: - - :user:`Steven Loria <sloria>` -""" -user_role = IssueRole(config_prefix="issues_user") - - -def setup(app): - # Format template for issues URI - # e.g. 'https://github.com/sloria/marshmallow/issues/{issue} - app.add_config_value( - "issues_uri", - default="https://github.com/{group}/{project}/issues/{issue}", - rebuild="html", - types=[str], - ) - app.add_config_value("issues_prefix", default="#", rebuild="html", types=[str]) - # Format template for PR URI - # e.g. 'https://github.com/sloria/marshmallow/pull/{issue} - app.add_config_value( - "issues_pr_uri", - default="https://github.com/{group}/{project}/pull/{pr}", - rebuild="html", - types=[str], - ) - app.add_config_value("issues_pr_prefix", default="#", rebuild="html", types=[str]) - # Format template for commit URI - # e.g. 'https://github.com/sloria/marshmallow/commits/{commit} - app.add_config_value( - "issues_commit_uri", - default="https://github.com/{group}/{project}/commit/{commit}", - rebuild="html", - types=[str], - ) - app.add_config_value( - "issues_commit_prefix", default="@", rebuild="html", types=[str] - ) - # There is no seperator config as a format_text function is given - - # Default User (Group)/Project eg. 'sloria/marshmallow' - # Called github as the package was working with github only before - app.add_config_value( - "issues_github_path", default=None, rebuild="html", types=[str] - ) - # Same as above but with new naming to reflect the new functionality - # Only on of both can be set - app.add_config_value( - "issues_default_group_project", default=None, rebuild="html", types=[str] - ) - # Format template for user profile URI - # e.g. 'https://github.com/{user}' - app.add_config_value( - "issues_user_uri", - default="https://github.com/{user}", - rebuild="html", - types=[str], - ) - app.add_config_value("issues_user_prefix", default="@", rebuild="html", types=[str]) - app.add_role("issue", issue_role) - app.add_role("pr", pr_role) - app.add_role("user", user_role) - app.add_role("commit", commit_role) - app.add_role("cve", cve_role) - app.add_role("cwe", cwe_role) - return { - "version": __version__, - "parallel_read_safe": True, - "parallel_write_safe": True, - } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/sphinx-issues-3.0.1/src/sphinx_issues/__init__.py new/sphinx-issues-4.1.0/src/sphinx_issues/__init__.py --- old/sphinx-issues-3.0.1/src/sphinx_issues/__init__.py 1970-01-01 01:00:00.000000000 +0100 +++ new/sphinx-issues-4.1.0/src/sphinx_issues/__init__.py 2024-04-15 05:03:23.000000000 +0200 @@ -0,0 +1,412 @@ +"""A Sphinx extension for linking to your project's issue tracker.""" + +import importlib.metadata +import re +from typing import Callable, Optional, Tuple + +from docutils import nodes, utils +from sphinx.config import Config +from sphinx.util.nodes import split_explicit_title + + +def cve_role(name, rawtext, text, lineno, inliner, options=None, content=None): + """Sphinx role for linking to a CVE on https://cve.mitre.org. + + Examples: :: + + :cve:`CVE-2018-17175` + + """ + options = options or {} + content = content or [] + has_explicit_title, title, target = split_explicit_title(text) + + target = utils.unescape(target).strip() + title = utils.unescape(title).strip() + ref = f"https://cve.mitre.org/cgi-bin/cvename.cgi?name={target}" + text = title if has_explicit_title else target + link = nodes.reference(text=text, refuri=ref, **options) + return [link], [] + + +GITHUB_USER_RE = re.compile("^https://github.com/([^/]+)/([^/]+)/.*") + + +def _get_default_group_and_project( + config: Config, uri_config_option: str +) -> Optional[Tuple[str, str]]: + """ + Get the default group/project or None if not set + """ + old_config = getattr(config, "issues_github_path", None) + new_config = getattr(config, "issues_default_group_project", None) + + if old_config and new_config: + raise ValueError( + "Both 'issues_github_path' and 'issues_default_group_project' are set, even" + " though they define the same setting. " + "Please only define one of these." + ) + group_and_project = new_config or old_config + + if group_and_project: + assert isinstance(group_and_project, str) + try: + group, project = group_and_project.split("/", maxsplit=1) + return group, project + except ValueError as e: + raise ValueError( + "`issues_github_path` or `issues_default_group_project` needs to " + "define a value in the form of `<group or user>/<project>` " + f"but `{config}` was given." + ) from e + + # If group and project was not set, we need to look for it within the github url + # for backward compatibility + if not group_and_project: + uri = getattr(config, uri_config_option) + if uri: + match = GITHUB_USER_RE.match(uri) + if match: + return match.groups()[0], match.groups()[1] + + return None + + +def _get_placeholder(uri_config_option: str) -> str: + """ + Get the placeholder from the uri_config_option + """ + try: + # i.e. issues_pr_uri -> pr + return uri_config_option[:-4].split("_", maxsplit=1)[1] + except IndexError: + # issues_uri -> issue + return uri_config_option[:-5] + + +def _get_uri_template( + config: Config, + uri_config_option: str, +) -> str: + """ + Get a URL format template that can be filled with user information based + on the given configuration + + The result always contains the following placeholder + - n (the issue number, user, pull request, etc...) + + The result can contain the following other placeholders + - group (same as user in github) + - project + + Examples for possible results: + + - "https://github.com/{group}/{project}/issues/{n}" + + - "https://gitlab.company.com/{group}/{project}/{n}" + + - "https://fancy.issuetrack.com?group={group}&project={project}&issue={n}" + + Raises: + - ValueError if the given uri contains an invalid placeholder + """ + format_string = str(getattr(config, uri_config_option)) + placeholder = _get_placeholder(uri_config_option) + + result = format_string.replace(f"{{{placeholder}}}", "{n}") + + try: + result.format(project="", group="", n="") + except (NameError, KeyError) as e: + raise ValueError( + f"The `{uri_config_option}` option contains invalid placeholders. " + f"Only {{group}}, {{projects}} and {{{placeholder}}} are allowed." + f'Invalid format string: "{format_string}".' + ) from e + return result + + +def _get_uri( + uri_config_option: str, + config: Config, + number: str, + group_and_project: Optional[Tuple[str, str]] = None, +) -> str: + """ + Get a URI based on the given configuration and do some sanity checking + """ + format_string = _get_uri_template(config, uri_config_option) + + url_vars = {"n": number} + + config_group_and_project = _get_default_group_and_project(config, uri_config_option) + if group_and_project: + # Group and Project defined by call + if config_group_and_project: + to_replace = "/".join(config_group_and_project) + if to_replace in format_string: + # Backward compatibility, replace default group/project + # with {group}/{project} + format_string = format_string.replace(to_replace, "{group}/{project}") + (url_vars["group"], url_vars["project"]) = group_and_project + elif config_group_and_project: + # If not defined by call use the default if given + (url_vars["group"], url_vars["project"]) = config_group_and_project + + try: + return format_string.format(**url_vars) + except (NameError, KeyError) as e: + # The format string was checked before, that it contains no additional not + # supported placeholders. So this occur + raise ValueError( + f"The `{uri_config_option}` format `{format_string}` requires a " + f"group/project to be defined in `issues_default_group_project`." + ) from e + + +def cwe_role(name, rawtext, text, lineno, inliner, options=None, content=None): + """Sphinx role for linking to a CWE on https://cwe.mitre.org. + + Examples: :: + + :cwe:`CWE-787` + + """ + options = options or {} + content = content or [] + has_explicit_title, title, target = split_explicit_title(text) + + target = utils.unescape(target).strip() + title = utils.unescape(title).strip() + number = target[4:] + ref = f"https://cwe.mitre.org/data/definitions/{number}.html" + text = title if has_explicit_title else target + link = nodes.reference(text=text, refuri=ref, **options) + return [link], [] + + +def pypi_role(name, rawtext, text, lineno, inliner, options=None, content=None): + """Sphinx role for linking to a PyPI on https://pypi.org/. + + Examples: :: + + :pypi:`sphinx-issues` + + """ + options = options or {} + content = content or [] + has_explicit_title, title, target = split_explicit_title(text) + + target = utils.unescape(target).strip() + title = utils.unescape(title).strip() + ref = f"https://pypi.org/project/{target}" + text = title if has_explicit_title else target + link = nodes.reference(text=text, refuri=ref, **options) + return [link], [] + + +class IssueRole: + # Symbols used to separate and issue/pull request/merge request etc + # i.e + # - group/project#2323 for issues + # - group/project!1234 for merge requests (in gitlab) + # - group/project@adbc1234 for commits + ELEMENT_SEPARATORS = "#@!" + + EXTERNAL_REPO_REGEX = re.compile(rf"^(\w+)/(.+)([{ELEMENT_SEPARATORS}])([\w]+)$") + + def __init__( + self, + config_prefix: str, + pre_format_text: Callable[[Config, str], str] = None, + ): + self.uri_config = f"{config_prefix}_uri" + self.separator_config = f"{config_prefix}_prefix" + self.pre_format_text = pre_format_text or self.default_pre_format_text + + @staticmethod + def default_pre_format_text(config: Config, text: str) -> str: + return text + + def format_text(self, config: Config, issue_no: str) -> str: + """ + Add supported separator in front of the issue or raise an error if invalid + separator is given + """ + separator = getattr(config, self.separator_config) + if separator not in self.ELEMENT_SEPARATORS: + raise ValueError( + f"Option {self.separator_config} has to be one of " + f"{', '.join(self.ELEMENT_SEPARATORS)}." + ) + text = self.pre_format_text(config, issue_no.lstrip(self.ELEMENT_SEPARATORS)) + return f"{separator}{text}" + + def make_node(self, name: str, issue_no: str, config: Config, options=None): + if issue_no in ("-", "0"): + return None + + options = options or {} + + has_explicit_title, title, target = split_explicit_title(issue_no) + + if has_explicit_title: + issue_no = str(target) + + repo_match = self.EXTERNAL_REPO_REGEX.match(issue_no) + + if repo_match: + # External repo + group, project, original_separator, issue_no = repo_match.groups() + text = f"{group}/{project}{self.format_text(config, issue_no)}" + ref = _get_uri( + self.uri_config, + config, + issue_no, + (group, project), + ) + else: + text = self.format_text(config, issue_no) + ref = _get_uri(self.uri_config, config, issue_no) + if has_explicit_title: + return nodes.reference(text=title, refuri=ref, **options) + else: + return nodes.reference(text=text, refuri=ref, **options) + + def __call__( + self, name, rawtext, text, lineno, inliner, options=None, content=None + ): + options = options or {} + content = content or [] + issue_nos = [each.strip() for each in utils.unescape(text).split(",")] + config = inliner.document.settings.env.app.config + ret = [] + for i, issue_no in enumerate(issue_nos): + node = self.make_node(name, issue_no, config, options=options) + ret.append(node) + if i != len(issue_nos) - 1: + sep = nodes.raw(text=", ", format="html") + ret.append(sep) + return ret, [] + + +"""Sphinx role for linking to an issue. Must have +`issues_uri` or `issues_default_group_project` configured in ``conf.py``. +Examples: :: + :issue:`123` + :issue:`42,45` + :issue:`sloria/konch#123` +""" +issue_role = IssueRole( + config_prefix="issues", +) + +"""Sphinx role for linking to a pull request. Must have +`issues_pr_uri` or `issues_default_group_project` configured in ``conf.py``. +Examples: :: + :pr:`123` + :pr:`42,45` + :pr:`sloria/konch#43` +""" +pr_role = IssueRole( + config_prefix="issues_pr", +) + + +def format_commit_text(config, sha): + return sha[:7] + + +"""Sphinx role for linking to a commit. Must have +`issues_commit_uri` or `issues_default_group_project` configured in ``conf.py``. +Examples: :: + :commit:`123abc456def` + :commit:`sloria/konch@123abc456def` +""" +commit_role = IssueRole( + config_prefix="issues_commit", + pre_format_text=format_commit_text, +) + +"""Sphinx role for linking to a user profile. Defaults to linking to +GitHub profiles, but the profile URIS can be configured via the +``issues_user_uri`` config value. + +Examples: :: + + :user:`sloria` + +Anchor text also works: :: + + :user:`Steven Loria <sloria>` +""" +user_role = IssueRole(config_prefix="issues_user") + + +def setup(app): + # Format template for issues URI + # e.g. 'https://github.com/sloria/marshmallow/issues/{issue} + app.add_config_value( + "issues_uri", + default="https://github.com/{group}/{project}/issues/{issue}", + rebuild="html", + types=[str], + ) + app.add_config_value("issues_prefix", default="#", rebuild="html", types=[str]) + # Format template for PR URI + # e.g. 'https://github.com/sloria/marshmallow/pull/{issue} + app.add_config_value( + "issues_pr_uri", + default="https://github.com/{group}/{project}/pull/{pr}", + rebuild="html", + types=[str], + ) + app.add_config_value("issues_pr_prefix", default="#", rebuild="html", types=[str]) + # Format template for commit URI + # e.g. 'https://github.com/sloria/marshmallow/commits/{commit} + app.add_config_value( + "issues_commit_uri", + default="https://github.com/{group}/{project}/commit/{commit}", + rebuild="html", + types=[str], + ) + app.add_config_value( + "issues_commit_prefix", default="@", rebuild="html", types=[str] + ) + # There is no seperator config as a format_text function is given + + # Default User (Group)/Project eg. 'sloria/marshmallow' + # Called github as the package was working with github only before + app.add_config_value( + "issues_github_path", default=None, rebuild="html", types=[str] + ) + # Same as above but with new naming to reflect the new functionality + # Only on of both can be set + app.add_config_value( + "issues_default_group_project", default=None, rebuild="html", types=[str] + ) + # Format template for user profile URI + # e.g. 'https://github.com/{user}' + app.add_config_value( + "issues_user_uri", + # Default to sponsors URL. + # GitHub will automatically redirect to profile + # if Sponsors isn't set up. + default="https://github.com/sponsors/{user}", + rebuild="html", + types=[str], + ) + app.add_config_value("issues_user_prefix", default="@", rebuild="html", types=[str]) + app.add_role("issue", issue_role) + app.add_role("pr", pr_role) + app.add_role("user", user_role) + app.add_role("commit", commit_role) + app.add_role("cve", cve_role) + app.add_role("cwe", cwe_role) + app.add_role("pypi", pypi_role) + return { + "version": importlib.metadata.version("sphinx-issues"), + "parallel_read_safe": True, + "parallel_write_safe": True, + } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/sphinx-issues-3.0.1/tests/test_sphinx_issues.py new/sphinx-issues-4.1.0/tests/test_sphinx_issues.py --- old/sphinx-issues-3.0.1/tests/test_sphinx_issues.py 2022-01-11 17:41:14.000000000 +0100 +++ new/sphinx-issues-4.1.0/tests/test_sphinx_issues.py 2024-04-15 05:03:23.000000000 +0200 @@ -7,10 +7,17 @@ import pytest import sphinx.application -from sphinx_issues import commit_role, cve_role, cwe_role, issue_role, pr_role -from sphinx_issues import setup as issues_setup -from sphinx_issues import user_role +from sphinx_issues import ( + commit_role, + cve_role, + cwe_role, + issue_role, + pr_role, + pypi_role, + user_role, +) +from sphinx_issues import setup as issues_setup BASE_DIR = Path(__file__).parent.absolute() @@ -28,7 +35,7 @@ ] ) def app(request): - src, doctree, confdir, outdir = [mkdtemp() for _ in range(4)] + src, doctree, confdir, outdir = (mkdtemp() for _ in range(4)) sphinx.application.Sphinx._log = lambda self, message, wfile, nonl=False: None app = sphinx.application.Sphinx( srcdir=src, confdir=None, outdir=outdir, doctreedir=doctree, buildername="html" @@ -80,13 +87,13 @@ "#42", "https://github.com/marshmallow-code/marshmallow/pull/42", ), - (user_role, "user", "sloria", "@sloria", "https://github.com/sloria"), + (user_role, "user", "sloria", "@sloria", "https://github.com/sponsors/sloria"), ( user_role, "user", "Steven Loria <sloria>", "Steven Loria", - "https://github.com/sloria", + "https://github.com/sponsors/sloria", ), ( cve_role, @@ -103,6 +110,13 @@ "https://cwe.mitre.org/data/definitions/787.html", ), ( + pypi_role, + "pypi", + "sphinx-issues", + "sphinx-issues", + "https://pypi.org/project/sphinx-issues", + ), + ( commit_role, "commit", "123abc456def", @@ -178,7 +192,7 @@ @pytest.fixture def app_custom_uri(): - src, doctree, confdir, outdir = [mkdtemp() for _ in range(4)] + src, doctree, confdir, outdir = (mkdtemp() for _ in range(4)) sphinx.application.Sphinx._log = lambda self, message, wfile, nonl=False: None app = sphinx.application.Sphinx( srcdir=src, confdir=None, outdir=outdir, doctreedir=doctree, buildername="html" diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/sphinx-issues-3.0.1/tox.ini new/sphinx-issues-4.1.0/tox.ini --- old/sphinx-issues-3.0.1/tox.ini 2022-01-11 17:41:14.000000000 +0100 +++ new/sphinx-issues-4.1.0/tox.ini 2024-04-15 05:03:23.000000000 +0200 @@ -1,12 +1,12 @@ [tox] -envlist = lint,py36,py37,py38,py39,py310 +envlist = lint,py{38,39,310,311,312} [testenv] extras = tests commands = pytest {posargs} [testenv:lint] -deps = pre-commit~=2.7 +deps = pre-commit~=3.6 skip_install = true commands = pre-commit run --all-files
participants (1)
-
Source-Sync