diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 0000000..47a31bc --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,10 @@ +version: 2 +updates: + - package-ecosystem: "github-actions" + directory: "/" + schedule: + interval: "daily" + - package-ecosystem: "pip" + directory: "/" + schedule: + interval: "daily" diff --git a/.github/workflows/create-release.yml b/.github/workflows/create-release.yml new file mode 100644 index 0000000..fa90c2b --- /dev/null +++ b/.github/workflows/create-release.yml @@ -0,0 +1,90 @@ +name: Create release + +on: + push: + tags: + - "*.*.*" + workflow_dispatch: + +permissions: + contents: read + +jobs: + publish-pypi: + runs-on: ubuntu-latest + name: PyPI Release + environment: release + permissions: + id-token: write # for PyPI trusted publishing + steps: + - uses: actions/checkout@v4 + - name: Set up Python + uses: actions/setup-python@v5 + with: + python-version: 3 + cache: pip + cache-dependency-path: pyproject.toml + + - name: Install build dependencies (pypa/build, twine) + run: | + pip install -U pip + pip install build twine + + - name: Build distribution + run: python -m build + + - name: Mint PyPI API token + id: mint-token + uses: actions/github-script@v7 + with: + # language=JavaScript + script: | + // retrieve the ambient OIDC token + const oidc_request_token = process.env.ACTIONS_ID_TOKEN_REQUEST_TOKEN; + const oidc_request_url = process.env.ACTIONS_ID_TOKEN_REQUEST_URL; + const oidc_resp = await fetch(`${oidc_request_url}&audience=pypi`, { + headers: {Authorization: `bearer ${oidc_request_token}`}, + }); + const oidc_token = (await oidc_resp.json()).value; + + // exchange the OIDC token for an API token + const mint_resp = await fetch('https://pypi.org/_/oidc/github/mint-token', { + method: 'post', + body: `{"token": "${oidc_token}"}` , + headers: {'Content-Type': 'application/json'}, + }); + const api_token = (await mint_resp.json()).token; + + // mask the newly minted API token, so that we don't accidentally leak it + core.setSecret(api_token) + core.setOutput('api-token', api_token) + + - name: Upload to PyPI + env: + TWINE_NON_INTERACTIVE: "true" + TWINE_USERNAME: "__token__" + TWINE_PASSWORD: "${{ steps.mint-token.outputs.api-token }}" + run: | + twine check dist/* + twine upload dist/* + + github-release: + runs-on: ubuntu-latest + name: GitHub release + environment: release + permissions: + contents: write # for softprops/action-gh-release to create GitHub release + steps: + - uses: actions/checkout@v4 + - name: Get release version + id: get_version + uses: actions/github-script@v7 + with: + script: core.setOutput('version', context.ref.replace("refs/tags/", "")) + + - name: Create GitHub release + uses: softprops/action-gh-release@v2 + if: startsWith(github.ref, 'refs/tags/') + with: + name: "sphinxcontrib-serializinghtml ${{ steps.get_version.outputs.version }}" + body: "Changelog: https://github.com/sphinx-doc/sphinxcontrib-serializinghtml/blob/master/CHANGES.rst" diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 2f6f9a8..e337f0f 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -1,77 +1,91 @@ name: Test -on: [push, pull_request] +on: + push: + pull_request: + workflow_dispatch: + +permissions: + contents: read + +concurrency: + group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }} + cancel-in-progress: true + +env: + FORCE_COLOR: "1" + PYTHONDEVMODE: "1" # -X dev + PYTHONWARNDEFAULTENCODING: "1" # -X warn_default_encoding jobs: tests: runs-on: ubuntu-latest strategy: matrix: - python-version: [3.6, 3.7, 3.8, 3.9, 3.10-dev] - max-parallel: 1 + python: + - "3.9" + - "3.10" + - "3.11" + - "3.12" + - "3.13-dev" + fail-fast: false steps: - - name: Print github context - env: - GITHUB_CONTEXT: ${{ toJson(github) }} - run: echo $GITHUB_CONTEXT - - - name: Checkout code - uses: actions/checkout@v2 + - uses: actions/checkout@v4 + - name: Set up Python ${{ matrix.python }} + uses: actions/setup-python@v5 + if: "!endsWith(matrix.python, '-dev')" with: - fetch-depth: 1 - - - name: pycache - uses: actions/cache@v2 - id: pycache + python-version: ${{ matrix.python }} + - name: Set up Python ${{ matrix.python }} (deadsnakes) + uses: deadsnakes/action@v3.1.0 + if: "endsWith(matrix.python, '-dev')" with: - path: ~/.cache/pip - key: ${{ runner.os }}-pip-${{ hashFiles('**/setup.py') }} - restore-keys: | - ${{ runner.os }}-pip- + python-version: ${{ matrix.python }} + - name: Install dependencies + run: | + python -m pip install --upgrade pip + python -m pip install .[standalone,test] - - name: Setup python ${{ matrix.python-version }} - uses: actions/setup-python@v2 - if: "!endsWith(matrix.python-version, '-dev')" - with: - python-version: ${{ matrix.python-version }} + - name: Test with pytest + run: python -m pytest -vv --durations 25 - - name: Setup python ${{ matrix.python-version }} (via deadsnakes) - uses: deadsnakes/action@v2.1.1 - if: "endsWith(matrix.python-version, '-dev')" - with: - python-version: ${{ matrix.python-version }} + test-latest-sphinx: + runs-on: ubuntu-latest - - name: Install tox and test related + steps: + - uses: actions/checkout@v4 + - name: Set up Python ${{ matrix.python }} + uses: actions/setup-python@v5 + with: + python-version: "3" + - name: Install dependencies run: | python -m pip install --upgrade pip - pip install tox tox-gh-actions + python -m pip install .[test] + python -m pip install "Sphinx @ git+https://github.com/sphinx-doc/sphinx" - - name: Run tox - run: | - python -V - tox -- -v --durations=25 + - name: Test with pytest + run: python -m pytest -vv --durations 25 lint: runs-on: ubuntu-latest strategy: matrix: - env: [flake8, mypy] + env: + - ruff + - mypy steps: - - name: Checkout code - uses: actions/checkout@v2 - with: - fetch-depth: 1 - + - uses: actions/checkout@v4 - name: Setup python - uses: actions/setup-python@v2 + uses: actions/setup-python@v5 with: - python-version: 3.8 + python-version: "3" - - name: Install tox and any other dependencies for test + - name: Install dependencies run: | python -m pip install --upgrade pip - pip install tox tox-gh-actions + python -m pip install --upgrade tox - name: Run tox run: tox -e ${{ matrix.env }} diff --git a/.github/workflows/transifex.yml b/.github/workflows/transifex.yml new file mode 100644 index 0000000..fbfba9a --- /dev/null +++ b/.github/workflows/transifex.yml @@ -0,0 +1,75 @@ +name: Synchronise translations + +on: + schedule: + # 22:38 GMT, every Sunday. Chosen to be a random time. + - cron: "38 22 * * SUN" + workflow_dispatch: + +permissions: + contents: read + +jobs: + push: + if: github.repository_owner == 'sphinx-doc' + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v4 + - name: Set up Python + uses: actions/setup-python@v5 + with: + python-version: 3 + - name: Install transifex client + run: | + mkdir -p /tmp/tx_cli && cd $_ + curl -o- https://raw.githubusercontent.com/transifex/cli/master/install.sh | bash + shell: bash + - name: Install dependencies + run: pip install --upgrade babel jinja2 + - name: Extract translations from source code + run: python utils/babel_runner.py extract + - name: Push translations to transifex.com + run: | + cd sphinxcontrib/serializinghtml/locales + /tmp/tx_cli/tx push --source --use-git-timestamps --workers 10 + env: + TX_TOKEN: ${{ secrets.TX_TOKEN }} + + pull: + permissions: + contents: write # for peter-evans/create-pull-request to create branch + pull-requests: write # for peter-evans/create-pull-request to create a PR + if: github.repository_owner == 'sphinx-doc' + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v4 + - name: Set up Python + uses: actions/setup-python@v5 + with: + python-version: 3 + - name: Install transifex client + run: | + mkdir -p /tmp/tx_cli && cd $_ + curl -o- https://raw.githubusercontent.com/transifex/cli/master/install.sh | bash + shell: bash + - name: Install dependencies + run: pip install --upgrade babel jinja2 + - name: Extract translations from source code + run: python utils/babel_runner.py extract + - name: Pull translations from transifex.com + run: | + cd sphinxcontrib/serializinghtml/locales + /tmp/tx_cli/tx pull --translations --all --force --use-git-timestamps --workers 10 + env: + TX_TOKEN: ${{ secrets.TX_TOKEN }} + - name: Compile message catalogs + run: python utils/babel_runner.py compile + - name: Create Pull Request + uses: peter-evans/create-pull-request@v6 + with: + commit-message: "[internationalisation] Update translations" + branch: bot/pull-translations + title: "[bot]: Update message catalogues" + labels: "internals:internationalisation" diff --git a/.gitignore b/.gitignore index 6101a7b..10cef94 100644 --- a/.gitignore +++ b/.gitignore @@ -1,13 +1,17 @@ *.pyc -*.egg -*.so -*.swp .DS_Store +idea/ +.vscode/ + .mypy_cache/ +.pytest_cache/ +.ruff_cache/ .tags .tox/ +.venv/ +venv/ + build/ dist/ -sphinxcontrib_serializinghtml.egg-info/ diff --git a/.ruff.toml b/.ruff.toml new file mode 100644 index 0000000..4b7dd2a --- /dev/null +++ b/.ruff.toml @@ -0,0 +1,53 @@ +target-version = "py39" # Pin Ruff to Python 3.9 +output-format = "full" +line-length = 95 + +[lint] +preview = true +select = [ +# "ANN", # flake8-annotations + "C4", # flake8-comprehensions + "COM", # flake8-commas + "B", # flake8-bugbear + "DTZ", # flake8-datetimez + "E", # pycodestyle + "EM", # flake8-errmsg + "EXE", # flake8-executable + "F", # pyflakes + "FA", # flake8-future-annotations + "FLY", # flynt + "FURB", # refurb + "G", # flake8-logging-format + "I", # isort + "ICN", # flake8-import-conventions + "INT", # flake8-gettext + "LOG", # flake8-logging + "PERF", # perflint + "PGH", # pygrep-hooks + "PIE", # flake8-pie + "PT", # flake8-pytest-style + "SIM", # flake8-simplify + "SLOT", # flake8-slots + "TCH", # flake8-type-checking + "UP", # pyupgrade + "W", # pycodestyle + "YTT", # flake8-2020 +] +ignore = [ + "E116", + "E241", + "E251", +] + +[lint.per-file-ignores] +"tests/*" = [ + "ANN", # tests don't need annotations +] + +[lint.isort] +forced-separate = [ + "tests", +] +required-imports = [ + "from __future__ import annotations", +] diff --git a/CHANGES b/CHANGES deleted file mode 100644 index 0a9bec6..0000000 --- a/CHANGES +++ /dev/null @@ -1,29 +0,0 @@ -Release 1.1.5 (2021-05-23) -========================== - -* Remove deprecation warnings for Sphinx-3.x - -Release 1.1.4 (2020-02-29) -========================== - -* Fix package metadata has broken - -Release 1.1.3 (2019-04-05) -========================== - -* Fix #6245: circular import error - -Release 1.1.1 (2019-02-17) -========================== - -* Fix failed to load HTML extension - -Release 1.1.0 (2019-02-17) -========================== - -* Add ``JSONHTMLBuilder`` and ``PickleHTMLBuilder`` (copied from sphinx package) - -Release 1.0.0 (2019-02-17) -========================== - -* Initial release (copied from sphinx package) diff --git a/CHANGES.rst b/CHANGES.rst new file mode 100644 index 0000000..6425c1e --- /dev/null +++ b/CHANGES.rst @@ -0,0 +1,65 @@ +Release 2.0.0 (2024-07-28) +========================== + +* Adopt Ruff +* Tighten MyPy settings +* Update GitHub actions versions + +Release 1.1.10 (2024-01-13) +=========================== + +* Remove Sphinx as a required dependency, as circular dependencies may cause + failure with package managers that expect a directed acyclic graph (DAG) + of dependencies. + +Release 1.1.9 (2023-08-20) +========================== + +* Serialise context["script_files"] and context["css_files"] as their filenames + on Sphinx 7.2.0. + +Release 1.1.8 (2023-08-14) +========================== + +* Use ``os.PathLike`` over ``pathlib.Path`` + +Release 1.1.7 (2023-08-09) +========================== + +* Fix tests for Sphinx 7.1 and below + +Release 1.1.6 (2023-08-07) +========================== + +* Drop support for Python 3.5, 3.6, 3.7, and 3.8 +* Raise minimum required Sphinx version to 5.0 + +Release 1.1.5 (2021-05-23) +========================== + +* Remove deprecation warnings for Sphinx-3.x + +Release 1.1.4 (2020-02-29) +========================== + +* Fix package metadata has broken + +Release 1.1.3 (2019-04-05) +========================== + +* Fix #6245: circular import error + +Release 1.1.1 (2019-02-17) +========================== + +* Fix failed to load HTML extension + +Release 1.1.0 (2019-02-17) +========================== + +* Add ``JSONHTMLBuilder`` and ``PickleHTMLBuilder`` (copied from sphinx package) + +Release 1.0.0 (2019-02-17) +========================== + +* Initial release (copied from sphinx package) diff --git a/LICENSE b/LICENCE.rst similarity index 100% rename from LICENSE rename to LICENCE.rst diff --git a/MANIFEST.in b/MANIFEST.in deleted file mode 100644 index d4b2097..0000000 --- a/MANIFEST.in +++ /dev/null @@ -1,8 +0,0 @@ -include README.rst -include LICENSE -include CHANGES - -include tox.ini - -recursive-include sphinxcontrib/serializinghtml/locales * -recursive-include tests * diff --git a/Makefile b/Makefile index 26f411a..438ee54 100644 --- a/Makefile +++ b/Makefile @@ -47,7 +47,7 @@ clean-mypyfiles: .PHONY: style-check style-check: - @flake8 + @ruff check .PHONY: type-check type-check: diff --git a/README.rst b/README.rst index c37d036..d9ed40a 100644 --- a/README.rst +++ b/README.rst @@ -14,23 +14,6 @@ Install from PyPI:: pip install -U sphinxcontrib-serializinghtml -Release signatures -================== - -Releases are signed with following keys: - -* `498D6B9E `_ -* `5EBA0E07 `_ - -Testing -======= - -To run the tests with the interpreter available as ``python``, use:: - - tox - -Continuous testing runs on travis: https://travis-ci.org/sphinx-doc/sphinxcontrib-serializinghtml - Contributing ============ diff --git a/babel.cfg b/babel.cfg new file mode 100644 index 0000000..fb9cc94 --- /dev/null +++ b/babel.cfg @@ -0,0 +1,8 @@ +[extract_messages] +output_file = sphinxcontrib/serializinghtml/locales/sphinxcontrib.serializinghtml.pot +keywords = _ __ + +[compile_catalog] +domain = sphinxcontrib.serializinghtml +directory = sphinxcontrib/serializinghtml/locales/ +use_fuzzy = true diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 0000000..f14054e --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,109 @@ +[build-system] +requires = ["flit_core>=3.7"] +build-backend = "flit_core.buildapi" + +# project metadata +[project] +name = "sphinxcontrib-serializinghtml" +description = """sphinxcontrib-serializinghtml is a sphinx extension which \ +outputs "serialized" HTML files (json and pickle)""" +readme = "README.rst" +urls.Changelog = "https://github.com/sphinx-doc/sphinxcontrib-serializinghtml/blob/master/CHANGES.rst" +urls.Code = "https://github.com/sphinx-doc/sphinxcontrib-serializinghtml/" +urls.Download = "https://pypi.org/project/sphinxcontrib-serializinghtml/" +urls.Homepage = "https://www.sphinx-doc.org/" +urls."Issue tracker" = "https://github.com/sphinx-doc/sphinx/issues/" +license.text = "BSD-2-Clause" +requires-python = ">=3.9" + +# Classifiers list: https://pypi.org/classifiers/ +classifiers = [ + "Development Status :: 5 - Production/Stable", + "Environment :: Console", + "Environment :: Web Environment", + "Intended Audience :: Developers", + "Intended Audience :: Education", + "License :: OSI Approved :: BSD License", + "Operating System :: OS Independent", + "Programming Language :: Python", + "Programming Language :: Python :: 3", + "Programming Language :: Python :: 3 :: Only", + "Programming Language :: Python :: 3.9", + "Programming Language :: Python :: 3.10", + "Programming Language :: Python :: 3.11", + "Programming Language :: Python :: 3.12", + "Programming Language :: Python :: 3.13", + "Framework :: Sphinx", + "Framework :: Sphinx :: Extension", + "Topic :: Documentation", + "Topic :: Documentation :: Sphinx", + "Topic :: Text Processing", + "Topic :: Utilities", +] +dependencies = [] +dynamic = ["version"] + +[project.optional-dependencies] +test = [ + "pytest", +] +lint = [ + "ruff==0.5.5", + "mypy", + "types-docutils", +] +standalone = [ + "Sphinx>=5", +] + +[[project.authors]] +name = "Georg Brandl" +email = "georg@python.org" + +[tool.flit.module] +name = "sphinxcontrib.serializinghtml" + +[tool.flit.sdist] +include = [ + "CHANGES.rst", + "LICENCE.rst", + # Tests + "tests/", + "tox.ini", +] +exclude = [ + "doc/_build", +] + +[tool.mypy] +python_version = "3.9" +packages = [ + "sphinxcontrib", + "tests", +] +exclude = [ + "tests/roots", +] +check_untyped_defs = true +disallow_any_generics = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +explicit_package_bases = true +extra_checks = true +no_implicit_reexport = true +show_column_numbers = true +show_error_context = true +strict_optional = true +warn_redundant_casts = true +warn_unused_configs = true +warn_unused_ignores = true +enable_error_code = [ + "type-arg", + "redundant-self", + "truthy-iterable", + "ignore-without-code", + "unused-awaitable", +] diff --git a/setup.cfg b/setup.cfg deleted file mode 100644 index f346323..0000000 --- a/setup.cfg +++ /dev/null @@ -1,30 +0,0 @@ -[egg_info] -tag_build = .dev -tag_date = true - -[aliases] -release = egg_info -Db '' - -[extract_messages] -output_file = sphinxcontrib/serializinghtml/locales/sphinxcontrib.serializinghtml.pot -keywords = _ __ - -[compile_catalog] -domain = sphinxcontrib.serializinghtml -directory = sphinxcontrib/serializinghtml/locales/ -use_fuzzy = true - -[bdist_wheel] -universal = 1 - -[metadata] -license_file = LICENSE - -[flake8] -max-line-length = 95 -ignore = E116,E241,E251 -exclude = .git,.tox,.venv - -[mypy] -ignore_missing_imports = True -strict_optional = False diff --git a/setup.py b/setup.py deleted file mode 100644 index 8f1b614..0000000 --- a/setup.py +++ /dev/null @@ -1,71 +0,0 @@ -# -*- coding: utf-8 -*- -import os -from setuptools import setup, find_packages - -long_desc = ''' -sphinxcontrib-serializinghtml is a sphinx extension which outputs -"serialized" HTML files (json and pickle). -''' - -extras_require = { - 'test': [ - 'pytest', - ], - 'lint': [ - 'flake8', - 'mypy', - 'docutils-stubs', - ], -} - - -def get_version(): - """Get version number of the package from version.py without importing core module.""" - package_dir = os.path.abspath(os.path.dirname(__file__)) - version_file = os.path.join(package_dir, 'sphinxcontrib/serializinghtml/version.py') - - namespace = {} - with open(version_file, 'rt') as f: - exec(f.read(), namespace) - - return namespace['__version__'] - - -setup( - name='sphinxcontrib-serializinghtml', - version=get_version(), - url='http://sphinx-doc.org/', - download_url='https://pypi.org/project/sphinxcontrib-serializinghtml/', - license='BSD', - author='Georg Brandl', - author_email='georg@python.org', - description=long_desc.strip().replace('\n', ' '), - long_description=long_desc, - zip_safe=False, - classifiers=[ - 'Development Status :: 5 - Production/Stable', - 'Environment :: Console', - 'Environment :: Web Environment', - 'Intended Audience :: Developers', - 'Intended Audience :: Education', - 'License :: OSI Approved :: BSD License', - 'Operating System :: OS Independent', - 'Programming Language :: Python', - 'Programming Language :: Python :: 3', - 'Programming Language :: Python :: 3.5', - 'Programming Language :: Python :: 3.6', - 'Programming Language :: Python :: 3.7', - 'Framework :: Sphinx', - 'Framework :: Sphinx :: Extension', - 'Topic :: Documentation', - 'Topic :: Documentation :: Sphinx', - 'Topic :: Text Processing', - 'Topic :: Utilities', - ], - platforms='any', - python_requires=">=3.5", - packages=find_packages(exclude=['tests']), - include_package_data=True, - extras_require=extras_require, - namespace_packages=['sphinxcontrib'], -) diff --git a/sphinxcontrib/__init__.py b/sphinxcontrib/__init__.py deleted file mode 100644 index c10210a..0000000 --- a/sphinxcontrib/__init__.py +++ /dev/null @@ -1,15 +0,0 @@ -""" - sphinxcontrib - ~~~~~~~~~~~~~ - - This package is a namespace package that contains all extensions - distributed in the ``sphinx-contrib`` distribution. - - :copyright: Copyright 2007-2009 by the Sphinx team, see AUTHORS. - :license: BSD, see LICENSE for details. -""" - -import pkg_resources - - -pkg_resources.declare_namespace(__name__) diff --git a/sphinxcontrib/serializinghtml/__init__.py b/sphinxcontrib/serializinghtml/__init__.py index c247656..bdbeb6f 100644 --- a/sphinxcontrib/serializinghtml/__init__.py +++ b/sphinxcontrib/serializinghtml/__init__.py @@ -1,15 +1,10 @@ -""" - sphinxcontrib.serializinghtml - ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - - :copyright: Copyright 2007-2019 by the Sphinx team, see README. - :license: BSD, see LICENSE for details. -""" +from __future__ import annotations +import os import pickle import types from os import path -from typing import Any, Dict +from typing import TYPE_CHECKING from sphinx.application import ENV_PICKLE_FILENAME, Sphinx from sphinx.builders.html import BuildInfo, StandaloneHTMLBuilder @@ -17,11 +12,19 @@ from sphinx.util.osutil import SEP, copyfile, ensuredir, os_path from sphinxcontrib.serializinghtml import jsonimpl -from sphinxcontrib.serializinghtml.version import __version__ -if False: - # For type annotation - from typing import Any, Dict, Tuple # NOQA +if TYPE_CHECKING: + from collections.abc import Sequence + from typing import Any, Protocol + + class SerialisingImplementation(Protocol): + def dump(self, obj: Any, file: Any, *args: Any, **kwargs: Any) -> None: ... + def dumps(self, obj: Any, *args: Any, **kwargs: Any) -> str | bytes: ... + def load(self, file: Any, *args: Any, **kwargs: Any) -> Any: ... + def loads(self, data: Any, *args: Any, **kwargs: Any) -> Any: ... + +__version__ = '2.0.0' +__version_info__ = (2, 0, 0) package_dir = path.abspath(path.dirname(__file__)) @@ -38,41 +41,43 @@ class SerializingHTMLBuilder(StandaloneHTMLBuilder): """ #: the serializing implementation to use. Set this to a module that #: implements a `dump`, `load`, `dumps` and `loads` functions - #: (pickle, simplejson etc.) - implementation = None # type: Any + #: (pickle, json etc.) + implementation: SerialisingImplementation implementation_dumps_unicode = False #: additional arguments for dump() - additional_dump_args = () # type: Tuple + additional_dump_args: Sequence[Any] = () #: the filename for the global context file - globalcontext_filename = None # type: str + globalcontext_filename: str = '' supported_image_types = ['image/svg+xml', 'image/png', 'image/gif', 'image/jpeg'] - def init(self): - # type: () -> None + def init(self) -> None: self.build_info = BuildInfo(self.config, self.tags) self.imagedir = '_images' - self.current_docname = None - self.theme = None # no theme necessary - self.templates = None # no template bridge necessary + self.current_docname = '' + self.theme = None # type: ignore[assignment] # no theme necessary + self.templates = None # no template bridge necessary self.init_templates() self.init_highlighter() self.init_css_files() self.init_js_files() self.use_index = self.get_builder_config('use_index', 'html') - def get_target_uri(self, docname, typ=None): - # type: (str, str) -> str + def get_target_uri(self, docname: str, typ: str | None = None) -> str: if docname == 'index': return '' if docname.endswith(SEP + 'index'): return docname[:-5] # up to sep return docname + SEP - def dump_context(self, context, filename): - # type: (Dict, str) -> None + def dump_context(self, context: dict[str, Any], filename: str | os.PathLike[str]) -> None: + context = context.copy() + if 'css_files' in context: + context['css_files'] = [css.filename for css in context['css_files']] + if 'script_files' in context: + context['script_files'] = [js.filename for js in context['script_files']] if self.implementation_dumps_unicode: with open(filename, 'w', encoding='utf-8') as ft: self.implementation.dump(context, ft, *self.additional_dump_args) @@ -80,10 +85,10 @@ def dump_context(self, context, filename): with open(filename, 'wb') as fb: self.implementation.dump(context, fb, *self.additional_dump_args) - def handle_page(self, pagename, ctx, templatename='page.html', - outfilename=None, event_arg=None): - # type: (str, Dict, str, str, Any) -> None + def handle_page(self, pagename: str, ctx: dict[str, Any], templatename: str = 'page.html', + outfilename: str | None = None, event_arg: Any = None) -> None: ctx['current_page_name'] = pagename + ctx.setdefault('pathto', lambda p: p) self.add_sidebars(pagename, ctx) if not outfilename: @@ -110,8 +115,7 @@ def handle_page(self, pagename, ctx, templatename='page.html', ensuredir(path.dirname(source_name)) copyfile(self.env.doc2path(pagename), source_name) - def handle_finish(self): - # type: () -> None + def handle_finish(self) -> None: # dump the global context outfilename = path.join(self.outdir, self.globalcontext_filename) self.dump_context(self.globalcontext, outfilename) @@ -138,7 +142,7 @@ class PickleHTMLBuilder(SerializingHTMLBuilder): implementation = pickle implementation_dumps_unicode = False - additional_dump_args = (pickle.HIGHEST_PROTOCOL,) + additional_dump_args: tuple[Any] = (pickle.HIGHEST_PROTOCOL,) indexer_format = pickle indexer_dumps_unicode = False out_suffix = '.fpickle' @@ -162,7 +166,8 @@ class JSONHTMLBuilder(SerializingHTMLBuilder): searchindex_filename = 'searchindex.json' -def setup(app: Sphinx) -> Dict[str, Any]: +def setup(app: Sphinx) -> dict[str, Any]: + app.require_sphinx('5.0') app.setup_extension('sphinx.builders.html') app.add_builder(JSONHTMLBuilder) app.add_builder(PickleHTMLBuilder) diff --git a/sphinxcontrib/serializinghtml/jsonimpl.py b/sphinxcontrib/serializinghtml/jsonimpl.py index ecb0b79..9b89875 100644 --- a/sphinxcontrib/serializinghtml/jsonimpl.py +++ b/sphinxcontrib/serializinghtml/jsonimpl.py @@ -1,47 +1,33 @@ -""" - sphinx.util.jsonimpl - ~~~~~~~~~~~~~~~~~~~~ +"""JSON serializer implementation wrapper.""" - JSON serializer implementation wrapper. - - :copyright: Copyright 2007-2019 by the Sphinx team, see AUTHORS. - :license: BSD, see LICENSE for details. -""" +from __future__ import annotations import json from collections import UserString - -if False: - # For type annotation - from typing import Any, IO # NOQA +from typing import IO, Any class SphinxJSONEncoder(json.JSONEncoder): """JSONEncoder subclass that forces translation proxies.""" - def default(self, obj): - # type: (Any) -> str + def default(self, obj: Any) -> str: if isinstance(obj, UserString): return str(obj) return super().default(obj) -def dump(obj, fp, *args, **kwds): - # type: (Any, IO, Any, Any) -> None +def dump(obj: Any, file: IO[str] | IO[bytes], *args: Any, **kwds: Any) -> None: kwds['cls'] = SphinxJSONEncoder - json.dump(obj, fp, *args, **kwds) + json.dump(obj, file, *args, **kwds) -def dumps(obj, *args, **kwds): - # type: (Any, Any, Any) -> str +def dumps(obj: Any, *args: Any, **kwds: Any) -> str: kwds['cls'] = SphinxJSONEncoder return json.dumps(obj, *args, **kwds) -def load(*args, **kwds): - # type: (Any, Any) -> Any +def load(*args: Any, **kwds: Any) -> Any: return json.load(*args, **kwds) -def loads(*args, **kwds): - # type: (Any, Any) -> Any +def loads(*args: Any, **kwds: Any) -> Any: return json.loads(*args, **kwds) diff --git a/sphinxcontrib/serializinghtml/py.typed b/sphinxcontrib/serializinghtml/py.typed new file mode 100644 index 0000000..e69de29 diff --git a/sphinxcontrib/serializinghtml/version.py b/sphinxcontrib/serializinghtml/version.py deleted file mode 100644 index dc92d0a..0000000 --- a/sphinxcontrib/serializinghtml/version.py +++ /dev/null @@ -1,10 +0,0 @@ -""" - sphinxcontrib.serializinghtml.version - ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - - :copyright: Copyright 2007-2019 by the Sphinx team, see README. - :license: BSD, see LICENSE for details. -""" - -__version__ = '1.1.5' -__version_info__ = tuple(map(int, __version__.split('.'))) diff --git a/tests/conftest.py b/tests/conftest.py index ae725dc..3934d3f 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -1,18 +1,14 @@ -""" - pytest config for sphinx extensions - ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +from __future__ import annotations - :copyright: Copyright 2007-2019 by the Sphinx team, see AUTHORS. - :license: BSD, see LICENSE for details. -""" +from pathlib import Path import pytest -from sphinx.testing.path import path - -pytest_plugins = 'sphinx.testing.fixtures' +pytest_plugins = ( + 'sphinx.testing.fixtures', +) @pytest.fixture(scope='session') -def rootdir(): - return path(__file__).parent.abspath() / 'roots' +def rootdir() -> Path: + return Path(__file__).resolve().parent / 'roots' diff --git a/tests/test_serializinghtml.py b/tests/test_serializinghtml.py index e04a201..480930b 100644 --- a/tests/test_serializinghtml.py +++ b/tests/test_serializinghtml.py @@ -1,21 +1,20 @@ -""" - test_serializinghtml - ~~~~~~~~~~~~~~~~~~~~ +"""Test for serializinghtml extension.""" - Test for serializinghtml extension. +from __future__ import annotations - :copyright: Copyright 2007-2019 by the Sphinx team, see AUTHORS. - :license: BSD, see LICENSE for details. -""" +from typing import TYPE_CHECKING import pytest +if TYPE_CHECKING: + from sphinx.application import Sphinx + @pytest.mark.sphinx('json', testroot='basic') -def test_json(app, status, warning): +def test_json(app: Sphinx) -> None: app.builder.build_all() @pytest.mark.sphinx('pickle', testroot='basic') -def test_pickle(app, status, warning): +def test_pickle(app: Sphinx) -> None: app.builder.build_all() diff --git a/tox.ini b/tox.ini index 83a34fd..3198abf 100644 --- a/tox.ini +++ b/tox.ini @@ -1,16 +1,10 @@ [tox] +minversion = 2.4.0 envlist = - py{36,37,38,39,310-dev}, - flake8, + py{39,310,311,312,313}, + ruff, mypy - -[gh-actions] -python = - 3.6: py36 - 3.7: py37 - 3.8: py38 - 3.9: py39 - 3.10: py310-dev +isolated_build = True [testenv] usedevelop = true @@ -24,14 +18,14 @@ setenv = commands= pytest --durations 25 {posargs} -[testenv:flake8] +[testenv:ruff] description = Run style checks. extras = test lint commands= - flake8 + ruff check [testenv:mypy] description = @@ -40,4 +34,4 @@ extras = test lint commands= - mypy sphinxcontrib/ + mypy pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy