Skip to content
Open
Changes from all commits
Commits
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
60 changes: 42 additions & 18 deletions pep_sphinx_extensions/pep_zero_generator/parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,24 @@
from pep_sphinx_extensions.pep_zero_generator.errors import PEPError


@dataclasses.dataclass(order=True, frozen=True)
class _Author:
_frozen_ordered = dataclasses.dataclass(order=True, frozen=True)


@_frozen_ordered
class _Participant:
"""Represent PEP participant."""
full_name: str # The participant's name.
email: str # The participant's email address.


@_frozen_ordered
class _Author(_Participant):
"""Represent PEP authors."""
full_name: str # The author's name.
email: str # The author's email address.


@_frozen_ordered
class _Sponsor(_Participant):
"""Represent PEP sponsors."""
Comment on lines +21 to +38
Copy link
Member

@johnslavik johnslavik Feb 8, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Consider not creating an alias here, obeying the locality of behavior rule (LoB) and keeping separate classes slightly more self-contained. Consider using dataclasses.field(doc=...).

Suggested change
_frozen_ordered = dataclasses.dataclass(order=True, frozen=True)
@_frozen_ordered
class _Participant:
"""Represent PEP participant."""
full_name: str # The participant's name.
email: str # The participant's email address.
@_frozen_ordered
class _Author(_Participant):
"""Represent PEP authors."""
full_name: str # The author's name.
email: str # The author's email address.
@_frozen_ordered
class _Sponsor(_Participant):
"""Represent PEP sponsors."""
@dataclasses.dataclass(order=True, frozen=True)
class _Participant:
"""Represent PEP participant."""
full_name: str = dataclasses.field(doc="The participant's name.")
email: str = dataclasses.field(doc="The participant's email address.")
@dataclasses.dataclass(order=True, frozen=True)
class _Author(_Participant):
"""Represent PEP authors."""
full_name: str = dataclasses.field(doc="The author's name.")
email: str = dataclasses.field(doc="The author's email address.")
@dataclasses.dataclass(order=True, frozen=True)
class _Sponsor(_Participant):
"""Represent PEP sponsors."""



class PEP:
Expand Down Expand Up @@ -95,6 +108,9 @@ def __init__(self, filename: Path):
if not self.authors:
raise _raise_pep_error(self, "no authors found", pep_num=True)

# Parse PEP sponsors
self.sponsor: str | None = _parse_sponsor(metadata["Sponsor"]).full_name if metadata["Sponsor"] else None

# Topic (for sub-indices)
_topic = metadata.get("Topic", "").lower().split(",")
self.topic: set[str] = {topic for topic_raw in _topic if (topic := topic_raw.strip())}
Expand Down Expand Up @@ -157,6 +173,7 @@ def full_details(self) -> dict[str, str | int | Sequence[str]]:
"number": self.number,
"title": self.title,
"authors": ", ".join(self._author_names),
"sponsor": self.sponsor,
"discussions_to": self.discussions_to,
"status": self.status,
"type": self.pep_type,
Expand All @@ -182,25 +199,32 @@ def _raise_pep_error(pep: PEP, msg: str, pep_num: bool = False) -> None:

jr_placeholder = ",Jr"


def _parse_author(data: str) -> list[_Author]:
"""Return a list of author names and emails."""

author_list = []
def _parse_participants(data: str) -> tuple[str, str]:
participants_list = []
data = (data.replace("\n", " ")
.replace(", Jr", jr_placeholder)
.rstrip().removesuffix(","))
for author_email in data.split(", "):
if ' <' in author_email:
author, email = author_email.removesuffix(">").split(" <")
for participant_email in data.split(", "):
if ' <' in participant_email:
participant, email = participant_email.removesuffix(">").split(" <")
else:
author, email = author_email, ""
participant, email = participant_email, ""

author = author.strip()
if author == "":
participant = participant.strip()
if participant == "":
raise ValueError("Name is empty!")

author = author.replace(jr_placeholder, ", Jr")
participant = participant.replace(jr_placeholder, ", Jr")
email = email.lower()
author_list.append(_Author(author, email))
return author_list
participants_list.append((participant, email))
return participants_list



def _parse_author(data: str) -> list[_Author]:
"""Return a list of author names and emails."""
return [_Author(author, email) for author, email in _parse_participants(data)]

def _parse_sponsor(data: str) -> _Sponsor:
"""Return sponsor name and email"""
return _Sponsor(*_parse_participants(data)[0])
Comment on lines +221 to +230
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Formatting nits

Suggested change
def _parse_author(data: str) -> list[_Author]:
"""Return a list of author names and emails."""
return [_Author(author, email) for author, email in _parse_participants(data)]
def _parse_sponsor(data: str) -> _Sponsor:
"""Return sponsor name and email"""
return _Sponsor(*_parse_participants(data)[0])
def _parse_author(data: str) -> list[_Author]:
"""Return a list of author names and emails."""
return [_Author(author, email) for author, email in _parse_participants(data)]
def _parse_sponsor(data: str) -> _Sponsor:
"""Return sponsor name and email"""
return _Sponsor(*_parse_participants(data)[0])

Loading