Add tests for `pep_sphinx_extensions` (#2545)

Co-authored-by: Adam Turner <9087854+AA-Turner@users.noreply.github.com>
Co-authored-by: CAM Gerlach <CAM.Gerlach@Gerlach.CAM>
This commit is contained in:
Hugo van Kemenade 2022-04-26 22:07:20 +03:00 committed by GitHub
parent 73d438cadb
commit 0b0dd6ddd5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
21 changed files with 545 additions and 8 deletions

View File

@ -22,7 +22,6 @@ jobs:
- name: 👷‍ Install dependencies
run: |
python -m pip install --upgrade pip
python -m pip install --upgrade -r requirements.txt
- name: 🔧 Render PEPs
run: make pages -j$(nproc)

51
.github/workflows/test.yml vendored Normal file
View File

@ -0,0 +1,51 @@
name: Test Sphinx Extensions
on:
push:
paths:
- ".github/workflows/test.yml"
- "pep_sphinx_extensions/**"
- "tox.ini"
pull_request:
paths:
- ".github/workflows/test.yml"
- "pep_sphinx_extensions/**"
- "tox.ini"
workflow_dispatch:
env:
FORCE_COLOR: 1
jobs:
test:
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
python-version: ["3.9", "3.10"]
os: [windows-latest, macos-latest, ubuntu-latest]
steps:
- uses: actions/checkout@v3
- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v3
with:
python-version: ${{ matrix.python-version }}
cache: pip
- name: Install dependencies
run: |
python -m pip install -U pip
python -m pip install -U wheel
python -m pip install -U tox
- name: Run tests with tox
run: |
tox -e py -- -v --cov-report term
- name: Upload coverage
uses: codecov/codecov-action@v3
with:
flags: ${{ matrix.os }}
name: ${{ matrix.os }} Python ${{ matrix.python-version }}

2
.gitignore vendored
View File

@ -7,6 +7,8 @@ __pycache__
*.pyo
*~
*env
.coverage
.tox
.vscode
*.swp
/build

View File

@ -42,6 +42,30 @@ repos:
- id: check-yaml
name: "Check YAML"
- repo: https://github.com/psf/black
rev: 22.3.0
hooks:
- id: black
name: "Format with Black"
args:
- '--target-version=py39'
- '--target-version=py310'
files: 'pep_sphinx_extensions/tests/.*'
- repo: https://github.com/PyCQA/isort
rev: 5.10.1
hooks:
- id: isort
name: "Sort imports with isort"
args: ['--profile=black', '--atomic']
files: 'pep_sphinx_extensions/tests/.*'
- repo: https://github.com/tox-dev/tox-ini-fmt
rev: 0.5.2
hooks:
- id: tox-ini-fmt
name: "Format tox.ini"
# RST checks
- repo: https://github.com/pre-commit/pygrep-hooks
rev: v1.9.0

View File

@ -41,6 +41,9 @@ lint: venv
$(VENVDIR)/bin/python3 -m pre_commit --version > /dev/null || $(VENVDIR)/bin/python3 -m pip install pre-commit
$(VENVDIR)/bin/python3 -m pre_commit run --all-files
test: venv
$(VENVDIR)/bin/python3 -bb -X dev -W error -m pytest
spellcheck: venv
$(VENVDIR)/bin/python3 -m pre_commit --version > /dev/null || $(VENVDIR)/bin/python3 -m pip install pre-commit
$(VENVDIR)/bin/python3 -m pre_commit run --all-files --hook-stage manual codespell

View File

@ -204,8 +204,8 @@ def _process_pretty_url(url: str) -> tuple[str, str]:
item_name, item_type = LINK_PRETTIFIERS[parts[2]](parts)
except KeyError as error:
raise ValueError(
"{url} not a link to a recognized domain to prettify") from error
item_name = item_name.title().replace("Sig", "SIG")
f"{url} not a link to a recognized domain to prettify") from error
item_name = item_name.title().replace("Sig", "SIG").replace("Pep", "PEP")
return item_name, item_type

View File

@ -33,10 +33,6 @@ def parse_author_email(author_email_tuple: tuple[str, str], authors_overrides: d
if name_parts.mononym is not None:
return Author(name_parts.mononym, name_parts.mononym, email)
if name_parts.surname[1] == ".":
# Add an escape to avoid docutils turning `v.` into `22.`.
name_parts.surname = f"\\{name_parts.surname}"
if name_parts.suffix:
last_first = f"{name_parts.surname}, {name_parts.forename}, {name_parts.suffix}"
return Author(last_first, name_parts.surname, email)
@ -63,7 +59,7 @@ def _parse_name(full_name: str) -> _Name:
num_parts = len(name_parts)
suffix = raw_suffix.strip()
if num_parts == 0:
if name_parts == [""]:
raise ValueError("Name is empty!")
elif num_parts == 1:
return _Name(mononym=name_parts[0], suffix=suffix)

View File

View File

@ -0,0 +1,34 @@
from pathlib import Path
from pep_sphinx_extensions.pep_processor.transforms import pep_footer
def test_add_source_link():
out = pep_footer._add_source_link(Path("pep-0008.txt"))
assert "https://github.com/python/peps/blob/main/pep-0008.txt" in str(out)
def test_add_commit_history_info():
out = pep_footer._add_commit_history_info(Path("pep-0008.txt"))
assert str(out).startswith(
"<paragraph>Last modified: "
'<reference refuri="https://github.com/python/peps/commits/main/pep-0008.txt">'
)
# A variable timestamp comes next, don't test that
assert str(out).endswith("</reference></paragraph>")
def test_add_commit_history_info_invalid():
out = pep_footer._add_commit_history_info(Path("pep-not-found.txt"))
assert str(out) == "<paragraph/>"
def test_get_last_modified_timestamps():
out = pep_footer._get_last_modified_timestamps()
assert len(out) >= 585
# Should be a Unix timestamp and at least this
assert out["pep-0008.txt"] >= 1643124055

View File

@ -0,0 +1,114 @@
import pytest
from pep_sphinx_extensions.pep_processor.transforms import pep_headers
@pytest.mark.parametrize(
"test_input, expected",
[
("my-mailing-list@example.com", "my-mailing-list@example.com"),
("python-tulip@googlegroups.com", "https://groups.google.com/g/python-tulip"),
("db-sig@python.org", "https://mail.python.org/mailman/listinfo/db-sig"),
("import-sig@python.org", "https://mail.python.org/pipermail/import-sig/"),
(
"python-announce@python.org",
"https://mail.python.org/archives/list/python-announce@python.org/",
),
],
)
def test_generate_list_url(test_input, expected):
out = pep_headers._generate_list_url(test_input)
assert out == expected
@pytest.mark.parametrize(
"test_input, expected",
[
(
"https://mail.python.org/pipermail/python-3000/2006-November/004190.html",
("Python-3000", "message"),
),
(
"https://mail.python.org/archives/list/python-dev@python.org/thread/HW2NFOEMCVCTAFLBLC3V7MLM6ZNMKP42/",
("Python-Dev", "thread"),
),
(
"https://mail.python.org/mailman3/lists/capi-sig.python.org/",
("Capi-SIG", "list"),
),
(
"https://mail.python.org/mailman/listinfo/web-sig",
("Web-SIG", "list"),
),
(
"https://discuss.python.org/t/pep-643-metadata-for-package-source-distributions/5577",
("Discourse", "thread"),
),
(
"https://discuss.python.org/c/peps/",
("PEPs Discourse", "category"),
),
],
)
def test_process_pretty_url(test_input, expected):
out = pep_headers._process_pretty_url(test_input)
assert out == expected
@pytest.mark.parametrize(
"test_input, expected",
[
(
"https://example.com/",
"https://example.com/ not a link to a recognized domain to prettify",
),
(
"https://mail.python.org",
"https://mail.python.org not a link to a list, message or thread",
),
(
"https://discuss.python.org/",
"https://discuss.python.org not a link to a Discourse thread or category",
),
],
)
def test_process_pretty_url_invalid(test_input, expected):
with pytest.raises(ValueError, match=expected):
pep_headers._process_pretty_url(test_input)
@pytest.mark.parametrize(
"test_input, expected",
[
(
"https://mail.python.org/pipermail/python-3000/2006-November/004190.html",
"Python-3000 message",
),
(
"https://mail.python.org/archives/list/python-dev@python.org/thread/HW2NFOEMCVCTAFLBLC3V7MLM6ZNMKP42/",
"Python-Dev thread",
),
(
"https://mail.python.org/mailman3/lists/capi-sig.python.org/",
"Capi-SIG list",
),
(
"https://mail.python.org/mailman/listinfo/web-sig",
"Web-SIG list",
),
(
"https://discuss.python.org/t/pep-643-metadata-for-package-source-distributions/5577",
"Discourse thread",
),
(
"https://discuss.python.org/c/peps/",
"PEPs Discourse category",
),
],
)
def test_make_link_pretty(test_input, expected):
out = pep_headers._make_link_pretty(test_input)
assert out == expected

View File

@ -0,0 +1,25 @@
import pytest
from docutils import nodes
from pep_sphinx_extensions.pep_processor.transforms import pep_zero
@pytest.mark.parametrize(
"test_input, expected",
[
(
nodes.reference(
"", text="user@example.com", refuri="mailto:user@example.com"
),
'<raw format="html" xml:space="preserve">user&#32;&#97;t&#32;example.com</raw>',
),
(
nodes.reference("", text="Introduction", refid="introduction"),
'<reference refid="introduction">Introduction</reference>',
),
],
)
def test_generate_list_url(test_input, expected):
out = pep_zero._mask_email(test_input)
assert str(out) == expected

View File

@ -0,0 +1,69 @@
import pytest
from pep_sphinx_extensions.pep_zero_generator import author
from pep_sphinx_extensions.tests.utils import AUTHORS_OVERRIDES
@pytest.mark.parametrize(
"test_input, expected",
[
(
("First Last", "first@example.com"),
author.Author(
last_first="Last, First", nick="Last", email="first@example.com"
),
),
(
("Guido van Rossum", "guido@example.com"),
author.Author(
last_first="van Rossum, Guido (GvR)",
nick="GvR",
email="guido@example.com",
),
),
(
("Hugo van Kemenade", "hugo@example.com"),
author.Author(
last_first="van Kemenade, Hugo",
nick="van Kemenade",
email="hugo@example.com",
),
),
(
("Eric N. Vander Weele", "eric@example.com"),
author.Author(
last_first="Vander Weele, Eric N.",
nick="Vander Weele",
email="eric@example.com",
),
),
(
("Mariatta", "mariatta@example.com"),
author.Author(
last_first="Mariatta", nick="Mariatta", email="mariatta@example.com"
),
),
(
("First Last Jr.", "first@example.com"),
author.Author(
last_first="Last, First, Jr.", nick="Last", email="first@example.com"
),
),
pytest.param(
("First Last", "first at example.com"),
author.Author(
last_first="Last, First", nick="Last", email="first@example.com"
),
marks=pytest.mark.xfail,
),
],
)
def test_parse_author_email(test_input, expected):
out = author.parse_author_email(test_input, AUTHORS_OVERRIDES)
assert out == expected
def test_parse_author_email_empty_name():
with pytest.raises(ValueError, match="Name is empty!"):
author.parse_author_email(("", "user@example.com"), AUTHORS_OVERRIDES)

View File

@ -0,0 +1,88 @@
from pathlib import Path
import pytest
from pep_sphinx_extensions.pep_zero_generator import parser
from pep_sphinx_extensions.pep_zero_generator.author import Author
from pep_sphinx_extensions.pep_zero_generator.errors import PEPError
from pep_sphinx_extensions.tests.utils import AUTHORS_OVERRIDES
def test_pep_repr():
pep8 = parser.PEP(Path("pep-0008.txt"), AUTHORS_OVERRIDES)
assert repr(pep8) == "<PEP 0008 - Style Guide for Python Code>"
def test_pep_less_than():
pep8 = parser.PEP(Path("pep-0008.txt"), AUTHORS_OVERRIDES)
pep3333 = parser.PEP(Path("pep-3333.txt"), AUTHORS_OVERRIDES)
assert pep8 < pep3333
def test_pep_equal():
pep_a = parser.PEP(Path("pep-0008.txt"), AUTHORS_OVERRIDES)
pep_b = parser.PEP(Path("pep-0008.txt"), AUTHORS_OVERRIDES)
assert pep_a == pep_b
@pytest.mark.parametrize(
"test_input, expected",
[
(80, "Style Guide for Python Code"),
(10, "Style ..."),
],
)
def test_pep_details(test_input, expected):
pep8 = parser.PEP(Path("pep-0008.txt"), AUTHORS_OVERRIDES)
assert pep8.details(title_length=test_input) == {
"authors": "GvR, Warsaw, Coghlan",
"number": 8,
"status": " ",
"title": expected,
"type": "P",
}
@pytest.mark.parametrize(
"test_input, expected",
[
(
"First Last <user@example.com>",
[Author(last_first="Last, First", nick="Last", email="user@example.com")],
),
(
"First Last",
[Author(last_first="Last, First", nick="Last", email="")],
),
(
"user@example.com (First Last)",
[Author(last_first="Last, First", nick="Last", email="user@example.com")],
),
pytest.param(
"First Last <user at example.com>",
[Author(last_first="Last, First", nick="Last", email="user@example.com")],
marks=pytest.mark.xfail,
),
],
)
def test_parse_authors(test_input, expected):
# Arrange
pep = parser.PEP(Path("pep-0160.txt"), AUTHORS_OVERRIDES)
# Act
out = parser._parse_authors(pep, test_input, AUTHORS_OVERRIDES)
# Assert
assert out == expected
def test_parse_authors_invalid():
pep = parser.PEP(Path("pep-0008.txt"), AUTHORS_OVERRIDES)
with pytest.raises(PEPError, match="no authors found"):
parser._parse_authors(pep, "", AUTHORS_OVERRIDES)

View File

@ -0,0 +1,12 @@
from pathlib import Path
from pep_sphinx_extensions.pep_zero_generator import parser, pep_index_generator
from pep_sphinx_extensions.tests.utils import AUTHORS_OVERRIDES
def test_create_pep_json():
peps = [parser.PEP(Path("pep-0008.txt"), AUTHORS_OVERRIDES)]
out = pep_index_generator.create_pep_json(peps)
assert '"url": "https://peps.python.org/pep-0008/"' in out

View File

@ -0,0 +1,76 @@
from pathlib import Path
import pytest
from pep_sphinx_extensions.pep_zero_generator import parser, writer
from pep_sphinx_extensions.tests.utils import AUTHORS_OVERRIDES
def test_pep_zero_writer_emit_text_newline():
pep0_writer = writer.PEPZeroWriter()
pep0_writer.emit_text("my text 1")
pep0_writer.emit_newline()
pep0_writer.emit_text("my text 2")
assert pep0_writer.output == ["my text 1", "", "my text 2"]
def test_pep_zero_writer_emit_title():
pep0_writer = writer.PEPZeroWriter()
pep0_writer.emit_title("My Title")
pep0_writer.emit_subtitle("My Subtitle")
assert pep0_writer.output == [
"My Title",
"========",
"",
"My Subtitle",
"-----------",
"",
]
@pytest.mark.parametrize(
"test_input, expected",
[
(
"pep-9000.rst",
{
"Fussyreverend, Francis": "one@example.com",
"Soulfulcommodore, Javier": "two@example.com",
},
),
(
"pep-9001.rst",
{"Fussyreverend, Francis": "", "Soulfulcommodore, Javier": ""},
),
],
)
def test_verify_email_addresses(test_input, expected):
# Arrange
peps = [
parser.PEP(
Path(f"pep_sphinx_extensions/tests/peps/{test_input}"), AUTHORS_OVERRIDES
)
]
# Act
out = writer._verify_email_addresses(peps)
# Assert
assert out == expected
def test_sort_authors():
# Arrange
authors_dict = {
"Zebra, Zoë": "zoe@example.com",
"lowercase, laurence": "laurence@example.com",
"Aardvark, Alfred": "alfred@example.com",
}
# Act
out = writer._sort_authors(authors_dict)
# Assert
assert out == ["Aardvark, Alfred", "lowercase, laurence", "Zebra, Zoë"]

View File

@ -0,0 +1,7 @@
PEP: 9000
Title: Test with authors with email addresses
Author: Francis Fussyreverend <one@example.com>,
Javier Soulfulcommodore <two@example.com>
Created: 20-Apr-2022
Status: Draft
Type: Process

View File

@ -0,0 +1,7 @@
PEP: 9001
Title: Test with authors with no email addresses
Author: Francis Fussyreverend,
Javier Soulfulcommodore
Created: 20-Apr-2022
Status: Draft
Type: Process

View File

@ -0,0 +1,6 @@
AUTHORS_OVERRIDES = {
"Guido van Rossum": {
"Surname First": "van Rossum, Guido (GvR)",
"Name Reference": "GvR",
},
}

8
pytest.ini Normal file
View File

@ -0,0 +1,8 @@
[pytest]
addopts = -r a --strict-config --strict-markers --import-mode=importlib --cov pep_sphinx_extensions --cov-report html --cov-report xml
empty_parameter_set_mark = fail_at_collect
filterwarnings =
error
minversion = 6.0
testpaths = pep_sphinx_extensions
xfail_strict = True

View File

@ -5,3 +5,7 @@ docutils >= 0.17.1
# For RSS
feedgen >= 0.9.0 # For RSS feed
# For tests
pytest
pytest-cov

12
tox.ini Normal file
View File

@ -0,0 +1,12 @@
[tox]
envlist =
py{311, 310, 39}
skipsdist = true
[testenv]
passenv =
FORCE_COLOR
deps =
-rrequirements.txt
commands =
python -bb -X dev -W error -m pytest {posargs}