diff --git a/.babel.cfg b/.babel.cfg new file mode 100644 index 00000000..692580d8 --- /dev/null +++ b/.babel.cfg @@ -0,0 +1 @@ +[jinja2: **.html] diff --git a/.github/workflows/pypi-package.yml b/.github/workflows/pypi-package.yml index c7acc055..744d49bd 100644 --- a/.github/workflows/pypi-package.yml +++ b/.github/workflows/pypi-package.yml @@ -11,6 +11,9 @@ on: permissions: contents: read +env: + FORCE_COLOR: 1 + jobs: # Always build & lint package. build-package: @@ -45,3 +48,5 @@ jobs: - name: Upload package to PyPI uses: pypa/gh-action-pypi-publish@release/v1 + with: + attestations: true diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 70182f02..ace177ed 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -12,7 +12,7 @@ jobs: strategy: fail-fast: false matrix: - branch: ["origin/main", "3.12", "3.11", "3.10"] + branch: ["origin/main", "3.13", "3.12", "3.11", "3.10"] steps: - uses: actions/checkout@v4 - uses: actions/setup-python@v5 @@ -48,3 +48,41 @@ jobs: with: name: doc-html-${{ matrix.branch }} path: www/ + + translations: + runs-on: ${{ matrix.os }} + strategy: + fail-fast: false + matrix: + os: ["ubuntu-latest", "windows-latest"] + # Test minimum supported and latest stable from 3.x series + python-version: ["3.9", "3"] + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-python@v5 + with: + python-version: ${{ matrix.python-version }} + allow-prereleases: true + cache: pip + - name: Install dependencies + run: | + pip install --upgrade pip + pip install -r requirements.txt + - name: Remove locale file for testing + shell: bash + run: rm -rf locales/pt_BR/ + - run: python babel_runner.py extract + - run: python babel_runner.py init -l pt_BR + - run: python babel_runner.py update + - run: python babel_runner.py update -l pt_BR + - run: python babel_runner.py compile + - run: python babel_runner.py compile -l pt_BR + - name: Print .pot file + shell: bash + run: cat locales/messages.pot + - name: Print .po file + shell: bash + run: cat locales/pt_BR/LC_MESSAGES/messages.po + - name: list files in locales dir + shell: bash + run: ls -R locales/ diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 42cd35e9..071ad406 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,12 +1,12 @@ repos: - repo: https://github.com/astral-sh/ruff-pre-commit - rev: v0.4.0 + rev: v0.6.8 hooks: - id: ruff args: [--exit-non-zero-on-fix] - repo: https://github.com/psf/black-pre-commit-mirror - rev: 24.4.0 + rev: 24.8.0 hooks: - id: black @@ -22,24 +22,24 @@ repos: - id: trailing-whitespace - repo: https://github.com/python-jsonschema/check-jsonschema - rev: 0.28.2 + rev: 0.29.2 hooks: - id: check-dependabot - id: check-github-workflows - repo: https://github.com/rhysd/actionlint - rev: v1.6.27 + rev: v1.7.2 hooks: - id: actionlint - repo: https://github.com/tox-dev/pyproject-fmt - rev: 1.8.0 + rev: 2.2.4 hooks: - id: pyproject-fmt args: [--max-supported-python=3.13] - repo: https://github.com/abravalheri/validate-pyproject - rev: v0.16 + rev: v0.20.2 hooks: - id: validate-pyproject diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 0ed7628e..2f4ac84b 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -1,6 +1,18 @@ Changelog ========= +`2024.10 `_ +------------------------------------------------------------------------------ + +- Add support for Python 3.13 (#196) + Contributed by Hugo van Kemenade +- Drop support for Python 3.8 (#197) + Contributed by Hugo van Kemenade +- Add script for handling translations (#195) + Contributed by Rafael Fontenelle +- Generate digital attestations for PyPI (PEP 740) (#198) + Contributed by Hugo van Kemenade + `2024.6 `_ ---------------------------------------------------------------------------- diff --git a/babel_runner.py b/babel_runner.py new file mode 100755 index 00000000..da4001c7 --- /dev/null +++ b/babel_runner.py @@ -0,0 +1,120 @@ +#!/usr/bin/venv python3 +"""Script for handling translations with Babel""" +from __future__ import annotations + +import argparse +import subprocess +from pathlib import Path + +try: + import tomllib +except ImportError: + try: + import tomli as tomllib + except ImportError as ie: + raise ImportError( + "tomli or tomllib is required to parse pyproject.toml" + ) from ie + +PROJECT_DIR = Path(__file__).resolve().parent + +# Global variables used by pybabel below (paths relative to PROJECT_DIR) +DOMAIN = "messages" +COPYRIGHT_HOLDER = "Python Software Foundation" +LOCALES_DIR = "locales" +POT_FILE = Path(LOCALES_DIR, f"{DOMAIN}.pot") +SOURCE_DIR = "python_docs_theme" +MAPPING_FILE = ".babel.cfg" + + +def get_project_info() -> dict: + """Retrieve project's info to populate the message catalog template""" + with open(Path(PROJECT_DIR / "pyproject.toml"), "rb") as f: + data = tomllib.load(f) + return data["project"] + + +def extract_messages() -> None: + """Extract messages from all source files into message catalog template""" + Path(PROJECT_DIR, LOCALES_DIR).mkdir(parents=True, exist_ok=True) + project_data = get_project_info() + subprocess.run( + [ + "pybabel", + "extract", + "-F", + MAPPING_FILE, + "--copyright-holder", + COPYRIGHT_HOLDER, + "--project", + project_data["name"], + "--version", + project_data["version"], + "--msgid-bugs-address", + project_data["urls"]["Issue tracker"], + "-o", + POT_FILE, + SOURCE_DIR, + ], + cwd=PROJECT_DIR, + check=True, + ) + + +def init_locale(locale: str) -> None: + """Initialize a new locale based on existing message catalog template""" + pofile = PROJECT_DIR / LOCALES_DIR / locale / "LC_MESSAGES" / f"{DOMAIN}.po" + if pofile.exists(): + print(f"There is already a message catalog for locale {locale}, skipping.") + return + cmd = ["pybabel", "init", "-i", POT_FILE, "-d", LOCALES_DIR, "-l", locale] + subprocess.run(cmd, cwd=PROJECT_DIR, check=True) + + +def update_catalogs(locale: str) -> None: + """Update translations from existing message catalogs""" + cmd = ["pybabel", "update", "-i", POT_FILE, "-d", LOCALES_DIR] + if locale: + cmd.extend(["-l", locale]) + subprocess.run(cmd, cwd=PROJECT_DIR, check=True) + + +def compile_catalogs(locale: str) -> None: + """Compile existing message catalogs""" + cmd = ["pybabel", "compile", "-d", LOCALES_DIR] + if locale: + cmd.extend(["-l", locale]) + subprocess.run(cmd, cwd=PROJECT_DIR, check=True) + + +def main() -> None: + parser = argparse.ArgumentParser(description=__doc__) + parser.add_argument( + "command", + choices=["extract", "init", "update", "compile"], + help="command to be executed", + ) + parser.add_argument( + "-l", + "--locale", + default="", + help="language code (needed for init, optional for update and compile)", + ) + + args = parser.parse_args() + locale = args.locale + + if args.command == "extract": + extract_messages() + elif args.command == "init": + if not locale: + parser.error("init requires passing the --locale option") + init_locale(locale) + elif args.command == "update": + update_catalogs(locale) + elif args.command == "compile": + compile_catalogs(locale) + + +if __name__ == "__main__": + main() diff --git a/code_of_conduct.rst b/code_of_conduct.rst deleted file mode 100644 index 4bc6630f..00000000 --- a/code_of_conduct.rst +++ /dev/null @@ -1,13 +0,0 @@ -Code of Conduct -=============== - -Please note that all interactions on -`Python Software Foundation `__-supported -infrastructure is `covered -`__ -by the `PSF Code of Conduct `__, -which includes all infrastructure used in the development of Python itself -(e.g. mailing lists, issue trackers, GitHub, etc.). - -In general this means everyone is expected to be open, considerate, and -respectful of others no matter what their position is within the project. diff --git a/pyproject.toml b/pyproject.toml index 4571a414..a39131e1 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,17 +1,17 @@ [build-system] build-backend = "flit_core.buildapi" requires = [ - "flit_core>=3.7", + "flit-core>=3.7", ] [project] name = "python-docs-theme" -version = "2024.6" +version = "2024.10" description = "The Sphinx theme for the CPython docs and related projects" readme = "README.md" license.file = "LICENSE" -authors = [{name = "PyPA", email = "distutils-sig@python.org"}] -requires-python = ">=3.8" +authors = [ { name = "PyPA", email = "distutils-sig@python.org" } ] +requires-python = ">=3.9" classifiers = [ "Development Status :: 5 - Production/Stable", "Framework :: Sphinx :: Theme", @@ -20,7 +20,6 @@ classifiers = [ "Operating System :: OS Independent", "Programming Language :: Python", "Programming Language :: Python :: 3 :: Only", - "Programming Language :: Python :: 3.8", "Programming Language :: Python :: 3.9", "Programming Language :: Python :: 3.10", "Programming Language :: Python :: 3.11", @@ -33,22 +32,18 @@ urls.Code = "https://github.com/python/python-docs-theme" urls.Download = "https://pypi.org/project/python-docs-theme/" urls.Homepage = "https://github.com/python/python-docs-theme/" urls."Issue tracker" = "https://github.com/python/python-docs-theme/issues" -[project.entry-points."sphinx.html_themes"] -python_docs_theme = 'python_docs_theme' +entry-points."sphinx.html_themes".python_docs_theme = "python_docs_theme" [tool.flit.module] name = "python_docs_theme" [tool.flit.sdist] -include = [ - "python_docs_theme/", -] +include = [ "python_docs_theme/" ] [tool.ruff] fix = true -[tool.ruff.lint] -select = [ +lint.select = [ "C4", # flake8-comprehensions "E", # pycodestyle errors "F", # pyflakes errors @@ -57,19 +52,16 @@ select = [ "LOG", # flake8-logging "PGH", # pygrep-hooks "PYI", # flake8-pyi - "RUF100", # unused noqa (yesqa) "RUF022", # unsorted-dunder-all + "RUF100", # unused noqa (yesqa) "UP", # pyupgrade "W", # pycodestyle warnings "YTT", # flake8-2020 ] -ignore = [ - "E203", # Whitespace before ':' - "E221", # Multiple spaces before operator - "E226", # Missing whitespace around arithmetic operator - "E241", # Multiple spaces after ',' +lint.ignore = [ + "E203", # Whitespace before ':' + "E221", # Multiple spaces before operator + "E226", # Missing whitespace around arithmetic operator + "E241", # Multiple spaces after ',' ] - - -[tool.ruff.lint.isort] -required-imports = ["from __future__ import annotations"] +lint.isort.required-imports = [ "from __future__ import annotations" ] diff --git a/python_docs_theme/__init__.py b/python_docs_theme/__init__.py index 7b9df306..0ee7d25d 100644 --- a/python_docs_theme/__init__.py +++ b/python_docs_theme/__init__.py @@ -2,7 +2,7 @@ import hashlib import os -from functools import lru_cache +from functools import cache from pathlib import Path from typing import Any @@ -12,7 +12,7 @@ THEME_PATH = Path(__file__).parent.resolve() -@lru_cache(maxsize=None) +@cache def _asset_hash(path: str) -> str: """Append a `?digest=` to an url based on the file content.""" full_path = THEME_PATH / path.replace("_static/", "static/") diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 00000000..18e6c17c --- /dev/null +++ b/requirements.txt @@ -0,0 +1,5 @@ +# for babel_runner.py +setuptools +Babel +Jinja2 +tomli; python_version < "3.10" 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