@@ -34,10 +34,6 @@ class PEP:
34
34
# The required RFC 822 headers for all PEPs.
35
35
required_headers = {"PEP" , "Title" , "Author" , "Status" , "Type" , "Created" }
36
36
37
- def raise_pep_error (self , msg : str , pep_num : bool = False ) -> None :
38
- pep_number = self .number if pep_num else None
39
- raise PEPError (msg , self .filename , pep_number = pep_number )
40
-
41
37
def __init__ (self , filename : Path , authors_overrides : dict ):
42
38
"""Init object from an open PEP file object.
43
39
@@ -51,106 +47,115 @@ def __init__(self, filename: Path, authors_overrides: dict):
51
47
metadata = HeaderParser ().parsestr (pep_text )
52
48
required_header_misses = PEP .required_headers - set (metadata .keys ())
53
49
if required_header_misses :
54
- self . raise_pep_error ( f"PEP is missing required headers { required_header_misses } " )
50
+ _raise_pep_error ( self , f"PEP is missing required headers { required_header_misses } " )
55
51
56
52
try :
57
53
self .number = int (metadata ["PEP" ])
58
54
except ValueError :
59
- self . raise_pep_error ( "PEP number isn't an integer" )
55
+ _raise_pep_error ( self , "PEP number isn't an integer" )
60
56
61
57
# Check PEP number matches filename
62
58
if self .number != int (filename .stem [4 :]):
63
- self . raise_pep_error ( f"PEP number does not match file name ({ filename } )" , pep_num = True )
59
+ _raise_pep_error ( self , f"PEP number does not match file name ({ filename } )" , pep_num = True )
64
60
65
61
# Title
66
62
self .title : str = metadata ["Title" ]
67
63
68
64
# Type
69
65
self .pep_type : str = metadata ["Type" ]
70
66
if self .pep_type not in TYPE_VALUES :
71
- self . raise_pep_error ( f"{ self .pep_type } is not a valid Type value" , pep_num = True )
67
+ _raise_pep_error ( self , f"{ self .pep_type } is not a valid Type value" , pep_num = True )
72
68
73
69
# Status
74
70
status = metadata ["Status" ]
75
71
if status in SPECIAL_STATUSES :
76
72
status = SPECIAL_STATUSES [status ]
77
73
if status not in STATUS_VALUES :
78
- self . raise_pep_error ( f"{ status } is not a valid Status value" , pep_num = True )
74
+ _raise_pep_error ( self , f"{ status } is not a valid Status value" , pep_num = True )
79
75
80
76
# Special case for Active PEPs.
81
77
if status == STATUS_ACTIVE and self .pep_type not in ACTIVE_ALLOWED :
82
78
msg = "Only Process and Informational PEPs may have an Active status"
83
- self . raise_pep_error ( msg , pep_num = True )
79
+ _raise_pep_error ( self , msg , pep_num = True )
84
80
85
81
# Special case for Provisional PEPs.
86
82
if status == STATUS_PROVISIONAL and self .pep_type != TYPE_STANDARDS :
87
83
msg = "Only Standards Track PEPs may have a Provisional status"
88
- self . raise_pep_error ( msg , pep_num = True )
84
+ _raise_pep_error ( self , msg , pep_num = True )
89
85
self .status : str = status
90
86
91
87
# Parse PEP authors
92
- self .authors : list [Author ] = self . parse_authors ( metadata ["Author" ], authors_overrides )
88
+ self .authors : list [Author ] = _parse_authors ( self , metadata ["Author" ], authors_overrides )
93
89
94
90
def __repr__ (self ) -> str :
95
91
return f"<PEP { self .number :0>4} - { self .title } >"
96
92
97
93
def __lt__ (self , other : PEP ) -> bool :
98
94
return self .number < other .number
99
95
100
- def parse_authors (self , author_header : str , authors_overrides : dict ) -> list [Author ]:
101
- """Parse Author header line"""
102
- authors_and_emails = self ._parse_author (author_header )
103
- if not authors_and_emails :
104
- raise self .raise_pep_error ("no authors found" , pep_num = True )
105
- return [Author (author_tuple , authors_overrides ) for author_tuple in authors_and_emails ]
106
-
107
- angled = re .compile (r"(?P<author>.+?) <(?P<email>.+?)>(,\s*)?" )
108
- paren = re .compile (r"(?P<email>.+?) \((?P<author>.+?)\)(,\s*)?" )
109
- simple = re .compile (r"(?P<author>[^,]+)(,\s*)?" )
110
-
111
- @staticmethod
112
- def _parse_author (data : str ) -> list [tuple [str , str ]]:
113
- """Return a list of author names and emails."""
114
-
115
- author_list = []
116
- for regex in (PEP .angled , PEP .paren , PEP .simple ):
117
- for match in regex .finditer (data ):
118
- # Watch out for suffixes like 'Jr.' when they are comma-separated
119
- # from the name and thus cause issues when *all* names are only
120
- # separated by commas.
121
- match_dict = match .groupdict ()
122
- author = match_dict ["author" ]
123
- if not author .partition (" " )[1 ] and author .endswith ("." ):
124
- prev_author = author_list .pop ()
125
- author = ", " .join ([prev_author , author ])
126
- if "email" not in match_dict :
127
- email = ""
128
- else :
129
- email = match_dict ["email" ]
130
- author_list .append ((author , email ))
131
-
132
- # If authors were found then stop searching as only expect one
133
- # style of author citation.
134
- if author_list :
135
- break
136
- return author_list
137
-
138
- def title_abbr (self , title_length ) -> str :
139
- """Shorten the title to be no longer than the max title length."""
140
- if len (self .title ) <= title_length :
141
- return self .title
142
- wrapped_title , * _excess = textwrap .wrap (self .title , title_length - 4 )
143
- return f"{ wrapped_title } ..."
144
-
145
- def pep (self , * , title_length ) -> dict [str , str | int ]:
96
+ def details (self , * , title_length ) -> dict [str , str | int ]:
146
97
"""Return the line entry for the PEP."""
147
98
return {
148
99
# how the type is to be represented in the index
149
100
"type" : self .pep_type [0 ].upper (),
150
101
"number" : self .number ,
151
- "title" : self .title_abbr ( title_length ),
102
+ "title" : _title_abbr ( self .title , title_length ),
152
103
# how the status should be represented in the index
153
- "status" : self . status [ 0 ]. upper () if self .status not in HIDE_STATUS else " " ,
104
+ "status" : " " if self .status in HIDE_STATUS else self . status [ 0 ]. upper () ,
154
105
# the author list as a comma-separated with only last names
155
106
"authors" : ", " .join (x .nick for x in self .authors ),
156
107
}
108
+
109
+
110
+ def _raise_pep_error (pep : PEP , msg : str , pep_num : bool = False ) -> None :
111
+ if pep_num :
112
+ raise PEPError (msg , pep .filename , pep_number = pep .number )
113
+ raise PEPError (msg , pep .filename )
114
+
115
+
116
+ def _parse_authors (pep : PEP , author_header : str , authors_overrides : dict ) -> list [Author ]:
117
+ """Parse Author header line"""
118
+ authors_and_emails = _parse_author (author_header )
119
+ if not authors_and_emails :
120
+ raise _raise_pep_error (pep , "no authors found" , pep_num = True )
121
+ return [Author (author_tuple , authors_overrides ) for author_tuple in authors_and_emails ]
122
+
123
+
124
+ author_angled = re .compile (r"(?P<author>.+?) <(?P<email>.+?)>(,\s*)?" )
125
+ author_paren = re .compile (r"(?P<email>.+?) \((?P<author>.+?)\)(,\s*)?" )
126
+ author_simple = re .compile (r"(?P<author>[^,]+)(,\s*)?" )
127
+
128
+
129
+ def _parse_author (data : str ) -> list [tuple [str , str ]]:
130
+ """Return a list of author names and emails."""
131
+
132
+ author_list = []
133
+ for regex in (author_angled , author_paren , author_simple ):
134
+ for match in regex .finditer (data ):
135
+ # Watch out for suffixes like 'Jr.' when they are comma-separated
136
+ # from the name and thus cause issues when *all* names are only
137
+ # separated by commas.
138
+ match_dict = match .groupdict ()
139
+ author = match_dict ["author" ]
140
+ if not author .partition (" " )[1 ] and author .endswith ("." ):
141
+ prev_author = author_list .pop ()
142
+ author = ", " .join ([prev_author , author ])
143
+ if "email" not in match_dict :
144
+ email = ""
145
+ else :
146
+ email = match_dict ["email" ]
147
+ author_list .append ((author , email ))
148
+
149
+ # If authors were found then stop searching as only expect one
150
+ # style of author citation.
151
+ if author_list :
152
+ break
153
+ return author_list
154
+
155
+
156
+ def _title_abbr (title , title_length ) -> str :
157
+ """Shorten the title to be no longer than the max title length."""
158
+ if len (title ) <= title_length :
159
+ return title
160
+ wrapped_title , * _excess = textwrap .wrap (title , title_length - 4 )
161
+ return f"{ wrapped_title } ..."
0 commit comments