8000 Sphinx - PEP 0 generation by AA-Turner · Pull Request #1932 · python/peps · GitHub
[go: up one dir, main page]

Skip to content

Sphinx - PEP 0 generation 8000 #1932

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 37 commits into from
Jun 12, 2021
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
37 commits
Select commit Hold shift + click to select a range
4a52b3c
Add PEP 0 parser
AA-Turner Apr 20, 2021
d3771d4
Add PEP 0 writer
AA-Turner Apr 20, 2021
c8268fb
Add PEP 0 generator and authors override
AA-Turner Apr 20, 2021
85ae140
Add/update build and run
AA-Turner Apr 20, 2021
835adfc
Simplify `create_index_file`
AA-Turner May 7, 2021
530ca9a
Special status handling
AA-Turner Jun 9, 2021
2578fe2
Add constants for PEP related magic strings
AA-Turner Jun 9, 2021
c839d51
Prefer checking on class
AA-Turner Jun 9, 2021
a9b0559
Add PEP.hide_status, use constants
AA-Turner Jun 9, 2021
77c5492
Remove comment from 2008 (current method works fine)
AA-Turner Jun 9, 2021
f6f7b65
Clarify intent of for-else loop
AA-Turner Jun 9, 2021
d0513e2
Hook in to Sphinx (oops, missed when splitting out this PR)
AA-Turner Jun 9, 2021
b8d9eff
Rename AUTHORS.csv for clarity
AA-Turner Jun 9, 2021
4b0d042
Sort and strip spaces
AA-Turner Jun 9, 2021
a993eed
Prefer `authors_overrides` name
AA-Turner Jun 9, 2021
92fe1fb
Add pep_0_errors.py
AA-Turner Jun 9, 2021
3f695ab
Move author_sort_by to writer
AA-Turner Jun 9, 2021
327fd1b
PEP init misc
AA-Turner Jun 9, 2021
403bff3
Split out Author
AA-Turner Jun 9, 2021
0d9bf61
Drop pep_0 prefix
AA-Turner Jun 9, 2021
dedb043
Pass title length as an argument
AA-Turner Jun 9, 2021
84518a3
Add constants.py to hold global type / status values
AA-Turner Jun 9, 2021
5164571
Capitalise constants
AA-Turner Jun 9, 2021
29738c5
Capitalise constants
AA-Turner Jun 9, 2021
918a4b9
Update PEP classification algorithm
AA-Turner Jun 9, 2021
70011e0
Extract static methods to module level
AA-Turner Jun 9, 2021
e72bed1
Add emit_text, emit_pep_row
AA-Turner Jun 9, 2021
32454c8
Use constants in writer.py
AA-Turner Jun 9, 2021
e42938a
Sort imports
AA-Turner Jun 9, 2021
d4447ab
Sort constants
AA-Turner Jun 9, 2021
5ebcb9d
Fix sorting in historical and dead PEPs
AA-Turner Jun 9, 2021
a4a4f50
Extract static methods to module level
AA-Turner Jun 9, 2021
1ec8438
Extract static methods to module level (parser.py
AA-Turner Jun 9, 2021
de9ab25
Make Author a NamedTuple
AA-Turner Jun 9, 2021
4cb6e8c
Fix author duplication bug with NamedTuples
AA-Turner Jun 9, 2021
1e62868
Revert to old PEP classification algorithm
AA-Turner Jun 10, 2021
48b72c2
Define PEP equality
AA-Turner Jun 10, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Make Author a NamedTuple
  • Loading branch information
AA-Turner committed Jun 9, 2021
commit de9ab25dd24565fc0315eeb795b6c2f1e511bf53
99 changes: 41 additions & 58 deletions pep_sphinx_extensions/pep_zero_generator/author.py
Original file line number Diff line number Diff line change
@@ -1,68 +1,51 @@
from __future__ import annotations

from typing import NamedTuple
import unicodedata


class Name(NamedTuple):
class _Name(NamedTuple):
mononym: str = None
forename: str = None
surname: str = None
suffix: str = None


class Author:
"""Represent PEP authors.
class Author(NamedTuple):
"""Represent PEP authors."""
last_first: str # The author's name in Surname, Forename, Suffix order.
nick: str # Author's nickname for PEP tables. Defaults to surname.
email: str # The author's email address.

Attributes:
last_first: The author's name in Surname, Forename, Suffix order.
nick: Author's nickname for PEP tables. Defaults to surname.
email: The author's email address.
_first_last: The author's full name, unchanged

"""
__slots__ = "last_first", "nick", "email", "_first_last"

def __init__(self, author_email_tuple: tuple[str, str], authors_overrides: dict[str, dict[str, str]]):
"""Parse the name and email address of an author."""
name, email = author_email_tuple
self._first_last: str = name.strip()
self.email: str = email.lower()

self.last_first: str = ""
self.nick: str = ""

if self._first_last in authors_overrides:
name_dict = authors_overrides[self._first_last]
self.last_first = name_dict["Surname First"]
self.nick = name_dict["Name Reference"]
else:
name_parts = _parse_name(self._first_last)
if name_parts.mononym is not None:
self.last_first = self.nick = name_parts.mononym
else:
if name_parts.surname[1] == ".":
# Add an escape to avoid docutils turning `v.` into `22.`.
name_parts.surname = f"\\{name_parts.surname}"
self.last_first = f"{name_parts.surname}, {name_parts.forename}"
self.nick = name_parts.surname

if name_parts.suffix is not None:
self.last_first += f", {name_parts.suffix}"

def __hash__(self):
return hash(self.last_first)

def __eq__(self, other):
if not isinstance(other, Author):
return NotImplemented
return self.last_first == other.last_first

def __len__(self):
return len(unicodedata.normalize("NFC", self.last_first))


def _parse_name(full_name: str) -> Name:
def parse_author_email(author_email_tuple: tuple[str, str], authors_overrides: dict[str, dict[str, str]]) -> Author:
"""Parse the name and email address of an author."""
name, email = author_email_tuple
_first_last = name.strip()
email = email.lower()

if _first_last in authors_overrides:
name_dict = authors_overrides[_first_last]
last_first = name_dict["Surname First"]
nick = name_dict["Name Reference"]
return Author(last_first, nick, email)

name_parts = _parse_name(_first_last)
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 is not None:
last_first = f"{nam 10000 e_parts.surname}, {name_parts.forename}, {name_parts.suffix}"
return Author(last_first, name_parts.surname, email)

last_first = f"{name_parts.surname}, {name_parts.forename}"
return Author(last_first, name_parts.surname, email)


def _parse_name(full_name: str) -> _Name:
"""Decompose a full name into parts.

If a mononym (e.g, 'Aahz') then return the full name. If there are
Expand All @@ -78,14 +61,14 @@ def _parse_name(full_name: str) -> Name:
pre_suffix, _, raw_suffix = full_name.partition(",")
name_parts = pre_suffix.strip().split(" ")
num_parts = len(name_parts)
suffix = raw_suffix.strip() or None
suffix = raw_suffix.strip()

if num_parts == 0:
raise ValueError("Name is empty!")
elif num_parts == 1:
return Name(mononym=name_parts[0], suffix=suffix)
return _Name(mononym=name_parts[0], suffix=suffix)
elif num_parts == 2:
return Name(forename=name_parts[0].strip(), surname=name_parts[1], suffix=suffix)
return _Name(forename=name_parts[0].strip(), surname=name_parts[1], suffix=suffix)

# handles rogue uncaught suffixes
if name_parts[-1] in possible_suffixes:
Expand All @@ -95,16 +78,16 @@ def _parse_name(full_name: str) -> Name:
if name_parts[-2].islower():
forename = " ".join(name_parts[:-2]).strip()
surname = " ".join(name_parts[-2:])
return Name(forename=forename, surname=surname, suffix=suffix)
return _Name(forename=forename, surname=surname, suffix=suffix)

# handles double surnames after a middle initial (e.g. N. Vander Weele)
elif any(s.endswith(".") for s in name_parts):
split_position = [i for i, x in enumerate(name_parts) if x.endswith(".")][-1] + 1
forename = " ".join(name_parts[:split_position]).strip()
surname = " ".join(name_parts[split_position:])
return Name(forename=forename, surname=surname, suffix=suffix)
return _Name(forename=forename, surname=surname, suffix=suffix)

# default to using the last item as the surname
else:
forename = " ".join(name_parts[:-1]).strip()
return Name(forename=forename, surname=name_parts[-1], suffix=suffix)
return _Name(forename=forename, surname=name_parts[-1], suffix=suffix)
8 changes: 6 additions & 2 deletions pep_sphinx_extensions/pep_zero_generator/parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,9 @@
from pathlib import Path
import re
import textwrap
from typing import TYPE_CHECKING

from pep_sphinx_extensions.pep_zero_generator.author import Author
from pep_sphinx_extensions.pep_zero_generator.author import parse_author_email
from pep_sphinx_extensions.pep_zero_generator.constants import ACTIVE_ALLOWED
from pep_sphinx_extensions.pep_zero_generator.constants import HIDE_STATUS
from pep_sphinx_extensions.pep_zero_generator.constants import SPECIAL_STATUSES
Expand All @@ -18,6 +19,9 @@
from pep_sphinx_extensions.pep_zero_generator.constants import TYPE_VALUES
from pep_sphinx_extensions.pep_zero_generator.errors import PEPError

if TYPE_CHECKING:
from pep_sphinx_extensions.pep_zero_generator.author import Author


class PEP:
"""Representation of PEPs.
Expand Down Expand Up @@ -118,7 +122,7 @@ def _parse_authors(pep: PEP, author_header: str, authors_overrides: dict) -> lis
authors_and_emails = _parse_author(author_header)
if not authors_and_emails:
raise _raise_pep_error(pep, "no authors found", pep_num=True)
return [Author(author_tuple, authors_overrides) for author_tuple in authors_and_emails]
return [parse_author_email(author_tuple, authors_overrides) for author_tuple in authors_and_emails]


author_angled = re.compile(r"(?P<author>.+?) <(?P<email>.+?)>(,\s*)?")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,8 +56,7 @@ def create_pep_zero(_: Sphinx, env: BuildEnvironment, docnames: list[str]) -> No
pep = parser.PEP(path.joinpath(file_path).absolute(), authors_overrides)
peps.append(pep)

pep_writer = writer.PEPZeroWriter()
pep0_text = pep_writer.write_pep0(sorted(peps))
pep0_text = writer.PEPZeroWriter().write_pep0(sorted(peps))
Path(f"{pep_zero_filename}.rst").write_text(pep0_text, encoding="utf-8")

# Add to files for builder
Expand Down
2 changes: 1 addition & 1 deletion pep_sphinx_extensions/pep_zero_generator/writer.py
Original file line number Diff line number Diff line change
Expand Up @@ -195,7 +195,7 @@ def write_pep0(self, peps: list[PEP]):

# PEP owners
authors_dict = _verify_email_addresses(peps)
max_name_len = max(len(author) for author in authors_dict.keys())
max_name_len = max(len(author.last_first) for author in authors_dict.keys())
self.emit_title("Authors/Owners", "authors")
self.emit_author_table_separator(max_name_len)
self.emit_text(f"{'Name':{max_name_len}} Email Address")
Expand Down
0