diff --git a/.github/workflows/create-release.yml b/.github/workflows/create-release.yml new file mode 100644 index 0000000..67dcf25 --- /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@v1 + if: startsWith(github.ref, 'refs/tags/') + with: + name: "Alabaster ${{ steps.get_version.outputs.version }}" + body: "Changelog: https://alabaster.readthedocs.io/en/latest/changelog.html" diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml new file mode 100644 index 0000000..11e36a7 --- /dev/null +++ b/.github/workflows/docs.yml @@ -0,0 +1,40 @@ +name: Render docs + +on: + push: + pull_request: + workflow_dispatch: + +permissions: + contents: read + +concurrency: + group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }} + cancel-in-progress: true + +jobs: + build: + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v4 + - name: Set up Python + uses: actions/setup-python@v5 + with: + python-version: 3 + cache: pip + cache-dependency-path: docs/requirements.txt + + - name: Install dependencies + run: | + python -m pip install --upgrade pip + python -m pip install -r docs/requirements.txt + + - name: Render the documentation + run: > + sphinx-build + -M html ./docs ./build + --jobs=auto + -T + -W + --keep-going diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml new file mode 100644 index 0000000..e4f4a0d --- /dev/null +++ b/.github/workflows/lint.yml @@ -0,0 +1,34 @@ +name: Lint source code + +on: + push: + pull_request: + workflow_dispatch: + +permissions: + contents: read + +concurrency: + group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }} + cancel-in-progress: true + +jobs: + ruff: + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v4 + - name: Set up Python + uses: actions/setup-python@v5 + with: + python-version: 3 + + - name: Install dependencies + run: | + python -m pip install --upgrade pip + python -m pip install "ruff==0.5.2" + + - name: Lint with Ruff + run: | + ruff check . --output-format github + ruff format . --check diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml new file mode 100644 index 0000000..3bf0bd4 --- /dev/null +++ b/.github/workflows/test.yml @@ -0,0 +1,103 @@ +name: Tests + +on: + push: + pull_request: + workflow_dispatch: + +permissions: + contents: read + +concurrency: + group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }} + cancel-in-progress: true + +jobs: + vary-sphinx: + runs-on: ubuntu-latest + name: Sphinx ${{ matrix.sphinx-version }} + strategy: + fail-fast: false + matrix: + sphinx-version: + - "6.2" + - "7.4" + steps: + - uses: actions/checkout@v4 + - name: Set up Python + uses: actions/setup-python@v4 + with: + python-version: 3 + + - name: Install Sphinx + run: | + python -m pip install -U pip + python -m pip install "sphinx~=${{ matrix.sphinx-version }}.0" + python -m pip install . + + - name: Run Sphinx + run: > + sphinx-build + -M html ./docs ./build + -j=auto + -T + -W + --keep-going + + vary-python: + runs-on: ubuntu-latest + name: Python ${{ matrix.python-version }} + strategy: + fail-fast: false + matrix: + python-version: + - "3.10" + - "3.11" + - "3.12" + steps: + - uses: actions/checkout@v4 + - name: Set up Python ${{ matrix.python-version }} + uses: actions/setup-python@v4 + with: + python-version: ${{ matrix.python-version }} + + - name: Install Sphinx + run: | + python -m pip install -U pip + python -m pip install -U sphinx + python -m pip install . + + - name: Run Sphinx + run: > + sphinx-build + -M html ./docs ./build + --jobs=auto + -T + -W + --keep-going + + oldest-supported: + runs-on: ubuntu-latest + name: Oldest supported + + steps: + - uses: actions/checkout@v4 + - name: Set up Python + uses: actions/setup-python@v4 + with: + python-version: 3 + + - name: Install Sphinx + run: | + python -m pip install -U pip + python -m pip install "sphinx~=6.2.0" + python -m pip install . + + - name: Run Sphinx + run: > + sphinx-build + -M html ./docs ./build + -j=auto + -T + -W + --keep-going diff --git a/.readthedocs.yml b/.readthedocs.yml new file mode 100644 index 0000000..604f672 --- /dev/null +++ b/.readthedocs.yml @@ -0,0 +1,12 @@ +version: 2 + +build: + os: ubuntu-22.04 + tools: + python: "3" + +python: + install: + - requirements: docs/requirements.txt + - method: pip + path: . diff --git a/.ruff.toml b/.ruff.toml new file mode 100644 index 0000000..429bbc2 --- /dev/null +++ b/.ruff.toml @@ -0,0 +1,21 @@ +target-version = "py310" # Pin Ruff to Python 3.10 +output-format = "full" + +[lint] +preview = true +select = [ + "B", # flake8-bugbear + "E", # pycodestyle + "F", # pyflakes + "I", # isort + "W", # pycodestyle +] +ignore = [ +# "E124", +# "E125", +# "E128", + "E261", +# "E301", +# "E302", +# "E303", +] diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index 529cf10..0000000 --- a/.travis.yml +++ /dev/null @@ -1,35 +0,0 @@ -language: python -cache: pip -python: - - "2.7" - - "3.4" - - "3.5" - - "3.6" - - "pypy" - - "pypy3" -env: - - SPHINX=">=1.3,<1.4" - - SPHINX=">=1.4,<1.5" - - SPHINX=">=1.5,<1.6" - - SPHINX=">=1.6,<1.7" - - SPHINX=">=1.7,<1.8" -install: - # For some reason Travis' build envs have wildly different pip/setuptools - # versions between minor Python versions, and this can cause many hilarious - # corner packaging cases. So... - - pip install -U pip - # Setuptools 34+ seems to get less stable - - pip install 'setuptools>33,<34' - # Install dev requirements - - pip install -r dev-requirements.txt - # Limit Sphinx version re: test matrix - - pip install "sphinx$SPHINX" - # Sanity/debug-friendliness: list what got installed - - pip list --format=columns - # Dev tooling sanity test: can invoke list tasks? - - inv --list -script: - - inv travis.blacken - - flake8 - # Does our own dogfooding website build ok? :D - - inv docs diff --git a/LICENSE b/LICENSE.rst similarity index 100% rename from LICENSE rename to LICENSE.rst diff --git a/MANIFEST.in b/MANIFEST.in deleted file mode 100644 index d16888e..0000000 --- a/MANIFEST.in +++ /dev/null @@ -1,4 +0,0 @@ -include LICENSE -include README.md -recursive-include alabaster *.* -recursive-exclude alabaster .*.swp diff --git a/README.rst b/README.rst index 08093fb..4dd5e72 100644 --- a/README.rst +++ b/README.rst @@ -1,19 +1,33 @@ +.. image:: https://img.shields.io/pypi/v/alabaster.svg + :target: https://pypi.org/project/alabaster/ + :alt: Package on PyPI + +.. image:: https://github.com/sphinx-doc/alabaster/actions/workflows/test.yml/badge.svg + :target: https://github.com/sphinx-doc/alabaster/actions/workflows/test.yml + :alt: CI Status + +.. image:: https://readthedocs.org/projects/alabaster/badge/ + :target: https://alabaster.readthedocs.io/ + :alt: Documentation Status + +.. image:: https://img.shields.io/badge/License-BSD%203--Clause-blue.svg + :target: https://opensource.org/license/BSD-3-Clause + :alt: BSD 3 Clause + + What is Alabaster? ================== Alabaster is a visually (c)lean, responsive, configurable theme for the `Sphinx -`_ documentation system. It is Python 2+3 compatible. +`_ documentation system. +It requires Python 3.10 or newer and Sphinx 6.2 or newer. It began as a third-party theme, and is still maintained separately, but as of Sphinx 1.3, Alabaster is an install-time dependency of Sphinx and is selected as the default theme. Live examples of this theme can be seen on `this project's own website -`_, `paramiko.org `_, -`fabfile.org `_ and `pyinvoke.org `_. - -For more documentation, please see http://alabaster.readthedocs.io. +`_, `paramiko.org `_, +`fabfile.org `_ and `pyinvoke.org `_. -.. note:: - You can install the development version via ``pip install -e - git+https://github.com/bitprophet/alabaster/#egg=alabaster``. +For more documentation, please see https://alabaster.readthedocs.io/. diff --git a/alabaster/__init__.py b/alabaster/__init__.py index c88b2b5..b42431c 100644 --- a/alabaster/__init__.py +++ b/alabaster/__init__.py @@ -1,6 +1,7 @@ import os -from alabaster import _version as version +__version_info__ = (0, 7, 16) +__version__ = "0.7.16" def get_path(): @@ -12,13 +13,27 @@ def get_path(): def update_context(app, pagename, templatename, context, doctree): - context["alabaster_version"] = version.__version__ + context["alabaster_version"] = __version__ + context["alabaster_version_info"] = __version_info__ + + # Convert 'show_powered_by' in the theme options to + # the preferred option, html_show_sphinx. + html_theme_options = app.config.html_theme_options + if "show_powered_by" in html_theme_options: + show_powered_by = html_theme_options["show_powered_by"] + if isinstance(show_powered_by, str): + context["show_sphinx"] = show_powered_by.lower() == "true" + else: + context["show_sphinx"] = bool(show_powered_by) # to allow int values def setup(app): - # add_html_theme is new in Sphinx 1.6+ - if hasattr(app, "add_html_theme"): - theme_path = os.path.abspath(os.path.dirname(__file__)) - app.add_html_theme("alabaster", theme_path) + app.require_sphinx("6.2") + theme_path = os.path.abspath(os.path.dirname(__file__)) + app.add_html_theme("alabaster", theme_path) app.connect("html-page-context", update_context) - return {"version": version.__version__, "parallel_read_safe": True} + return { + "version": __version__, + "parallel_read_safe": True, + "parallel_write_safe": True, + } diff --git a/alabaster/_version.py b/alabaster/_version.py deleted file mode 100644 index ed3c608..0000000 --- a/alabaster/_version.py +++ /dev/null @@ -1,2 +0,0 @@ -__version_info__ = (0, 7, 12) -__version__ = ".".join(map(str, __version_info__)) diff --git a/alabaster/about.html b/alabaster/about.html index dbb4262..2bf686f 100644 --- a/alabaster/about.html +++ b/alabaster/about.html @@ -1,9 +1,11 @@ {% if theme_logo %}

{{ project }}

+ {% elif theme_logo_name|lower != 'false' %} +

{{ theme_logo_name }}

{% endif %}

diff --git a/alabaster/layout.html b/alabaster/layout.html index 0885d03..d71dcec 100644 --- a/alabaster/layout.html +++ b/alabaster/layout.html @@ -2,14 +2,15 @@ {%- block extrahead %} {{ super() }} - + {% if theme_touch_icon %} - + {% endif %} - {% if theme_canonical_url %} - + + {# Deprecated in favor of html_baseurl (pageurl). This is already set in the basic theme #} + {% if theme_canonical_url and not pageurl %} + {% endif %} - {% endblock %} {# top+bottom related navs; we also have our own in sidebar #} @@ -86,27 +87,31 @@ {%- block footer %} {% if theme_github_banner|lower != 'false' %} - Fork me on GitHub + {%- if theme_github_banner|lower == 'true' %} + Fork me on GitHub + {%- else %} + Fork me on GitHub + {%- endif %} {% endif %} {% if theme_analytics_id %} -