Skip to content

Commit 1fbe18e

Browse files
committed
add the supporting library for generating PEP 0
1 parent 9dcc92f commit 1fbe18e

File tree

4 files changed

+511
-0
lines changed

4 files changed

+511
-0
lines changed

pep0/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
# Empty

pep0/constants.py

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
# -*- coding: utf-8 -*-
2+
title_length = 55
3+
column_format = (u' %(type)1s%(status)1s %(number)4s %(title)-' +
4+
unicode(title_length) + u's %(authors)-s')
5+
6+
header = u"""PEP: 0
7+
Title: Index of Python Enhancement Proposals (PEPs)
8+
Version: $Revision$
9+
Last-Modified: $Date$
10+
Author: David Goodger <[email protected]>,
11+
Barry A. Warsaw <[email protected]>
12+
Status: Active
13+
Type: Informational
14+
Created: 13-Jul-2000
15+
"""
16+
17+
intro = u"""
18+
The PEP contains the index of all Python Enhancement Proposals,
19+
known as PEPs. PEP numbers are assigned by the PEP Editor, and
20+
once assigned are never changed. The SVN history[1] of the PEP
21+
texts represent their historical record.
22+
23+
The BDFL maintains his own Pronouncements page[2] at
24+
http://www.python.org/doc/essays/pepparade.html which contains his
25+
musings on the various outstanding PEPs.
26+
"""
27+
28+
references = u"""
29+
[1] View PEP history online
30+
http://svn.python.org/projects/peps/trunk/
31+
"""
32+
33+
footer = u"""
34+
Local Variables:
35+
mode: indented-text
36+
indent-tabs-mode: nil
37+
sentence-end-double-space: t
38+
fill-column: 70
39+
coding: utf-8
40+
End:"""

pep0/output.py

Lines changed: 183 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,183 @@
1+
"""Code to handle the output of PEP 0."""
2+
import sys
3+
import unicodedata
4+
5+
from operator import attrgetter
6+
7+
from . import constants
8+
from .pep import PEP, PEPError
9+
10+
11+
indent = u' '
12+
13+
def write_column_headers(output):
14+
"""Output the column headers for the PEP indices."""
15+
column_headers = {'status': u'', 'type': u'', 'number': u'num',
16+
'title': u'title', 'authors': u'owner'}
17+
print>>output, constants.column_format % column_headers
18+
underline_headers = {}
19+
for key, value in column_headers.items():
20+
underline_headers[key] = unicode(len(value) * '-')
21+
print>>output, constants.column_format % underline_headers
22+
23+
24+
def sort_peps(peps):
25+
"""Sort PEPs into meta, informational, accepted, open, finished,
26+
and essentially dead."""
27+
meta = []
28+
info = []
29+
accepted = []
30+
open_ = []
31+
finished = []
32+
dead = []
33+
for pep in peps:
34+
# Order of 'if' statement important. Key Status values take precedence
35+
# over Type value, and vice-versa.
36+
if pep.type_ == 'Process':
37+
meta.append(pep)
38+
elif pep.status == 'Draft':
39+
open_.append(pep)
40+
elif pep.status in ('Rejected', 'Withdrawn', 'Deferred',
41+
'Incomplete', 'Replaced'):
42+
dead.append(pep)
43+
elif pep.type_ == 'Informational':
44+
info.append(pep)
45+
elif pep.status in ('Accepted', 'Active'):
46+
accepted.append(pep)
47+
elif pep.status == 'Final':
48+
finished.append(pep)
49+
else:
50+
raise PEPError("unsorted (%s/%s)" %
51+
(pep.type_, pep.status),
52+
pep.filename, pep.number)
53+
return meta, info, accepted, open_, finished, dead
54+
55+
56+
def verify_email_addresses(peps):
57+
authors_dict = {}
58+
for pep in peps:
59+
for author in pep.authors:
60+
# If this is the first time we have come across an author, add him.
61+
if author not in authors_dict:
62+
authors_dict[author] = [author.email]
63+
else:
64+
found_emails = authors_dict[author]
65+
# If no email exists for the author, use the new value.
66+
if not found_emails[0]:
67+
authors_dict[author] = [author.email]
68+
# If the new email is an empty string, move on.
69+
elif not author.email:
70+
continue
71+
# If the email has not been seen, add it to the list.
72+
elif author.email not in found_emails:
73+
authors_dict[author].append(author.email)
74+
75+
valid_authors_dict = {}
76+
too_many_emails = []
77+
for author, emails in authors_dict.items():
78+
if len(emails) > 1:
79+
too_many_emails.append((author.first_last, emails))
80+
else:
81+
valid_authors_dict[author] = emails[0]
82+
if too_many_emails:
83+
err_output = []
84+
for author, emails in too_many_emails:
85+
err_output.append(" %s: %r" % (author, emails))
86+
raise ValueError("some authors have more than one email address "
87+
"listed:\n" + '\n'.join(err_output))
88+
89+
return valid_authors_dict
90+
91+
92+
def sort_authors(authors_dict):
93+
authors_list = authors_dict.keys()
94+
authors_list.sort(key=attrgetter('sort_by'))
95+
return authors_list
96+
97+
def normalized_last_first(name):
98+
return len(unicodedata.normalize('NFC', name.last_first))
99+
100+
101+
def write_pep0(peps, output=sys.stdout):
102+
print>>output, constants.header
103+
print>>output
104+
print>>output, u"Introduction"
105+
print>>output, constants.intro
106+
print>>output
107+
print>>output, u"Index by Category"
108+
print>>output
109+
write_column_headers(output)
110+
meta, info, accepted, open_, finished, dead = sort_peps(peps)
111+
print>>output
112+
print>>output, u" Meta-PEPs (PEPs about PEPs or Processs)"
113+
print>>output
114+
for pep in meta:
115+
print>>output, unicode(pep)
116+
print>>output
117+
print>>output, u" Other Informational PEPs"
118+
print>>output
119+
for pep in info:
120+
print>>output, unicode(pep)
121+
print>>output
122+
print>>output, u" Accepted PEPs (accepted; may not be implemented yet)"
123+
print>>output
124+
for pep in accepted:
125+
print>>output, unicode(pep)
126+
print>>output
127+
print>>output, u" Open PEPs (under consideration)"
128+
print>>output
129+
for pep in open_:
130+
print>>output, unicode(pep)
131+
print>>output
132+
print>>output, u" Finished PEPs (done, implemented in code repository)"
133+
print>>output
134+
for pep in finished:
135+
print>>output, unicode(pep)
136+
print>>output
137+
print>>output, u" Deferred, Abandoned, Withdrawn, and Rejected PEPs"
138+
print>>output
139+
for pep in dead:
140+
print>>output, unicode(pep)
141+
print>>output
142+
print>>output
143+
print>>output, u" Numerical Index"
144+
print>>output
145+
write_column_headers(output)
146+
prev_pep = 0
147+
for pep in peps:
148+
if pep.number - prev_pep > 1:
149+
print>>output
150+
print>>output, unicode(pep)
151+
prev_pep = pep.number
152+
print>>output
153+
print>>output
154+
print>>output, u"Key"
155+
print>>output
156+
for type_ in PEP.type_values:
157+
print>>output, u" %s - %s PEP" % (type_[0], type_)
158+
print>>output
159+
for status in PEP.status_values:
160+
print>>output, u" %s - %s proposal" % (status[0], status)
161+
162+
print>>output
163+
print>>output
164+
print>>output, u"Owners"
165+
print>>output
166+
authors_dict = verify_email_addresses(peps)
167+
max_name = max(authors_dict.keys(), key=normalized_last_first)
168+
max_name_len = len(max_name.last_first)
169+
print>>output, u" %s %s" % ('name'.ljust(max_name_len), 'email address')
170+
print>>output, u" %s %s" % ((len('name')*'-').ljust(max_name_len),
171+
len('email address')*'-')
172+
sorted_authors = sort_authors(authors_dict)
173+
for author in sorted_authors:
174+
# Use the email from authors_dict instead of the one from 'author' as
175+
# the author instance may have an empty email.
176+
print>>output, (u" %s %s" %
177+
(author.last_first.ljust(max_name_len), authors_dict[author]))
178+
print>>output
179+
print>>output
180+
print>>output, u"References"
181+
print>>output
182+
print>>output, constants.references
183+
print>>output, constants.footer

0 commit comments

Comments
 (0)