Skip to content

Commit

Permalink
Use pre-commit to enforce linting (#14)
Browse files Browse the repository at this point in the history
* add pre-commit to run black and ruff systematically

* solve linting issues

* execute pre-commit in the CI'

* execute CI all the time

* update readme
add pre-commit instruction
add some badges

* update actions version
Node.js 12 actions are deprecated. Please update the following actions to use Node.js 16
  • Loading branch information
12rambau authored Jan 13, 2023
1 parent 4d913b5 commit 00e934f
Show file tree
Hide file tree
Showing 8 changed files with 128 additions and 46 deletions.
35 changes: 9 additions & 26 deletions .github/workflows/basic-ci.yml
Original file line number Diff line number Diff line change
@@ -1,35 +1,18 @@
# This workflow will install Python dependencies, run tests and lint with a variety of Python versions on multiple platforms.
# For more information see: https://help.github.com/actions/language-and-framework-guides/using-python-with-github-actions

name: Python lint and test

on:
push:
branches: [ main ]
pull_request:
branches: [ main ]
- push

jobs:
format:

format:
runs-on: ubuntu-latest
strategy:
matrix:
python-version: ['3.8']

steps:
- uses: actions/checkout@v2
- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v2
with:
python-version: ${{ matrix.python-version }}
- name: Install dependencies
run: |
python -m pip install --upgrade pip
python -m pip install black
- name: Run black
run: |
python -m black --check --diff .
- uses: actions/checkout@v3
- uses: actions/setup-python@v4
with:
python-version: "3.8"
- uses: pre-commit/[email protected]

test:
runs-on: ${{ matrix.os }}
Expand All @@ -38,9 +21,9 @@ jobs:
os: [ubuntu-latest, macos-latest, windows-latest]
python-version: ['3.7', '3.8', '3.9', '3.10']
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v3
- name: Setup Python
uses: actions/setup-python@v2
uses: actions/setup-python@v4
with:
python-version: ${{ matrix.python-version }}
- name: Install dependencies
Expand Down
12 changes: 12 additions & 0 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
repos:
- repo: "https://github.com/psf/black"
rev: 22.3.0
hooks:
- id: black
stages: [commit]
- repo: https://github.com/charliermarsh/ruff-pre-commit
rev: "v0.0.217"
hooks:
- id: ruff
stages: [commit]
args: ["--force-exclude"]
14 changes: 12 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
# sphinx-favicon

[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
[![Black badge](https://img.shields.io/badge/code%20style-black-000000.svg)](https://github.com/psf/black)
[![PyPI](https://img.shields.io/pypi/v/sphinx-favicon?logo=python&logoColor=white)](https://pypi.org/project/sphinx-favicon/)
![GitHub Workflow Status](https://img.shields.io/github/actions/workflow/status/tcmetzger/sphinx-favicon/basic-ci.yml?logo=github&logoColor=white)

**A Sphinx extension to add custom favicons**

With sphinx-favicon, you can add custom favicons to your Sphinx html
Expand Down Expand Up @@ -200,5 +205,10 @@ To contribute to this extension, please open an issue or make a pull request to
the repository on GitHub.

Additional dependencies for development are listed in the file
`dev-requirements.txt` in the repository. Use ``pytest -vv`` to run tests. All
Python code should be formatted with [Black](https://github.com/psf/black).
`dev-requirements.txt` in the repository. Use ``pytest -vv`` to run tests.

Please install `pre-commit` Python package and run the following command before commiting your modifications:

```
pre-commit install
```
12 changes: 12 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,15 @@ requires = [
"wheel",
]
build-backend = "setuptools.build_meta"

[tool.ruff]
fix = true
select = ["E", "F", "W", "I", "D", "RUF"]
ignore = ["E501"] # line too long | Black take care of it
exclude = ["setup.py", "tests/roots/*"]

[tool.ruff.flake8-quotes]
docstring-quotes = "double"

[tool.ruff.pydocstyle]
convention = "google"
2 changes: 0 additions & 2 deletions setup.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
# See https://setuptools.pypa.io/en/latest/userguide/quickstart.html#development-mode

import setuptools

setuptools.setup()
56 changes: 43 additions & 13 deletions sphinx_favicon/__init__.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,12 @@
"""Sphinx extension to add custom favicons.
With sphinx-favicon, you can add custom favicons to your Sphinx html documentation quickly and easily.
You can define favicons directly in your conf.py, with different rel attributes such as "icon" or "apple-touch-icon" and any favicon size.
The sphinx-favicon extension gives you more flexibility than the standard favicon.ico supported by Sphinx. It provides a quick and easy way to add the most important favicon formats for different browsers and devices.
"""

from typing import Any, Callable, Dict, List, Optional, Union

import docutils.nodes as nodes
Expand Down Expand Up @@ -37,10 +46,10 @@ def generate_meta(favicon: Dict[str, str]) -> str:
SVG, or PNG files)
Args:
favicon (Dict[str, str]): Favicon data
favicon: Favicon data
Returns:
str: Favicon meta tag
Favicon meta tag
"""
rel = favicon.get("rel", "icon")
href = favicon["href"]
Expand All @@ -66,10 +75,17 @@ def generate_meta(favicon: Dict[str, str]) -> str:


def _static_to_href(pathto: Callable, favicon: Dict[str, str]) -> Dict[str, str]:
"""If a ``static-file`` is provided, returns a modified version of the icon
attributes replacing ``static-file`` with the correct ``href``.
"""Replace static ref to fully qualified href.
If a ``static-file`` is provided, returns a modified version of the icon attributes replacing ``static-file`` with the correct ``href``.
If both ``static-file`` and ``href`` are provided, ``href`` will be ignored.
Args:
pathto: Sphinx helper_ function to handle relative URLs
favicon: The favicon description as set in the conf.py file
Returns:
The favicon with a fully qualified href
"""
if FILE_FIELD in favicon:
attrs = favicon.copy()
Expand All @@ -84,14 +100,14 @@ def create_favicons_meta(pathto: Callable, favicons: FaviconsDef) -> Optional[st
"""Create ``<link>`` elements for favicons defined in configuration.
Args:
pathto (Callable): Sphinx helper_ function to handle relative URLs
favicons (FaviconsDef): Favicon data from configuration.
Can be a single dict or a list of dicts.
pathto: Sphinx helper_ function to handle relative URLs
favicons: Favicon data from configuration. Can be a single dict or a list of dicts.
Returns:
str: ``<link>`` elements for all favicons.
``<link>`` elements for all favicons.
.. _helper: https://www.sphinx-doc.org/en/master/templating.html#patht
See Also:
https://www.sphinx-doc.org/en/master/templating.html#path
"""
meta_favicons = ""

Expand All @@ -112,10 +128,8 @@ def create_favicons_meta(pathto: Callable, favicons: FaviconsDef) -> Optional[st
meta_favicons += generate_meta(attrs) + "\n"
else:
logger.warning(
"""
Invalid config value for favicon extension. Custom favicons will not
be included in build.
"""
"Invalid config value for favicon extension."
"Custom favicons will notbe included in build."
)
return None

Expand All @@ -129,14 +143,30 @@ def html_page_context(
context: Dict[str, Any],
doctree: nodes.document,
) -> None:
"""Update the html page context by adding the favicons.
Args:
app: The sphinx application
pagename: the name of the page as string
templatename: the name of the template as string
context: the html context dictionnary
doctree: the docutils document tree
"""
if doctree and app.config["favicons"]:
pathto: Callable = context["pathto"] # should exist in a HTML context
favicons_meta = create_favicons_meta(pathto, app.config["favicons"])
context["metatags"] += favicons_meta


def setup(app: Sphinx) -> Dict[str, Any]:
"""Add custom configuration to shinx app.
Args:
app: the Sphinx application
Returns:
the 2 parralel parameters set to ``True``
"""
app.add_config_value("favicons", None, "html")
app.connect("html-page-context", html_page_context)

Expand Down
13 changes: 10 additions & 3 deletions tests/conftest.py
Original file line number Diff line number Diff line change
@@ -1,30 +1,33 @@
import os
"""Configuration fixtures of the tests."""

import pytest
from bs4 import BeautifulSoup
from sphinx.testing.path import path

# from sphinx.application import Sphinx

pytest_plugins = "sphinx.testing.fixtures"


@pytest.fixture(scope="session")
def rootdir():
"""The root directory."""
return path(__file__).parent.abspath() / "roots"


@pytest.fixture()
def content(app):
"""The app build content."""
app.build()
yield app


def _link_tags(content, page):
"""Link tags in a page content."""
c = (content.outdir / page).read_text()
return BeautifulSoup(c, "html.parser").find_all("link")


def _favicon_tags(content, page="index.html"):
"""Favicon tags in the index.html page."""
return [
tag
for tag in _link_tags(content, page)
Expand All @@ -34,18 +37,22 @@ def _favicon_tags(content, page="index.html"):

@pytest.fixture()
def link_tags(content):
"""Link tags in index.html page."""
return _link_tags(content, "index.html")


@pytest.fixture()
def favicon_tags(content):
"""Favicon tags in index.html page."""
return _favicon_tags(content)


@pytest.fixture()
def favicon_tags_for_nested(content):
"""Favicon tags in nested/page.html page."""
return _favicon_tags(content, "nested/page.html")


def pytest_configure(config):
"""Add markers config to pytest."""
config.addinivalue_line("markers", "sphinx")
30 changes: 30 additions & 0 deletions tests/test_options.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
"""Test suit for the sphinx-favicon extention."""

from itertools import chain
from pathlib import Path

Expand All @@ -6,7 +8,11 @@

@pytest.mark.sphinx("html", testroot="list_of_three_dicts")
def test_list_of_three_dicts(favicon_tags):
"""Run tests on a list of 3 dicts.
Args:
favicon_tags: Favicon tags in index.html page.
"""
# this test should have 3 favicons
assert len(favicon_tags) == 3

Expand All @@ -29,7 +35,11 @@ def test_list_of_three_dicts(favicon_tags):

@pytest.mark.sphinx("html", testroot="list_of_three_dicts_automated_values")
def test_list_of_three_dicts_automated_values(favicon_tags):
"""Run tests on a list of 3 dicts with automated values.
Args:
favicon_tags: Favicon tags in index.html page.
"""
# this test should have 3 favicons
assert len(favicon_tags) == 3

Expand All @@ -52,7 +62,11 @@ def test_list_of_three_dicts_automated_values(favicon_tags):

@pytest.mark.sphinx("html", testroot="single_dict")
def test_single_dict(favicon_tags):
"""Run tests on a single dict.
Args:
favicon_tags: Favicon tags in index.html page.
"""
# this test should have 1 favicon
assert len(favicon_tags) == 1

Expand All @@ -68,7 +82,11 @@ def test_single_dict(favicon_tags):

@pytest.mark.sphinx("html", testroot="list_of_urls")
def test_list_of_urls(favicon_tags):
"""Run tests on a list of urls.
Args:
favicon_tags: Favicon tags in index.html page.
"""
# this test should have 3 favicons
assert len(favicon_tags) == 3

Expand All @@ -89,7 +107,13 @@ def test_list_of_urls(favicon_tags):

@pytest.mark.sphinx("html", testroot="static_files")
def test_static_files(app, favicon_tags, favicon_tags_for_nested):
"""Run tests using static files.
Args:
app: the Sphinx application
favicon_tags: Favicon tags in index.html page.
favicon_tags_for_nested: Favicon tags in nested/page.html page.
"""
# this test should have 2 favicons
assert len(favicon_tags) == 2

Expand All @@ -114,7 +138,13 @@ def test_static_files(app, favicon_tags, favicon_tags_for_nested):

@pytest.mark.sphinx("html", testroot="href_and_static")
def test_href_and_static(app, favicon_tags, favicon_tags_for_nested):
"""Run tests on a mix of static files and complete urls.
Args:
app: the Sphinx application
favicon_tags: Favicon tags in index.html page.
favicon_tags_for_nested: Favicon tags in nested/page.html page.
"""
# this test should have 3 favicons
assert len(favicon_tags) == 2

Expand Down

0 comments on commit 00e934f

Please sign in to comment.