Require a "Ticket:" field for future proposals in certain states.

New proposals in states {OPEN,ACCEPTED,CLOSED,FINISHED} must have a
"Ticket:" field which may either be a ticket number or a publicly
accessible URL.  When the ticket is just a number, it should be in
reference to Tor's canonical bug tracker.

This information greatly helps both new contributors and relay
operators who are interested in the implementation status of a working
proposal.  This patch permits the "Ticket:" field to be added to older
proposals (<= prop#288), but it does not require it.
This commit is contained in:
Isis Lovecruft 2017-11-20 18:27:47 +00:00
parent c78806e96e
commit 8be6722e8d
No known key found for this signature in database
GPG Key ID: B8938BC5E86C046F
2 changed files with 35 additions and 7 deletions

View File

@ -85,11 +85,19 @@ What should go in a proposal:
Filename, Title, Author, Created, Status.
These fields are optional but recommended:
Target, Implemented-In.
Target, Implemented-In, Ticket**.
The Target field should describe which version the proposal is hoped to be
implemented in (if it's Open or Accepted). The Implemented-In field
should describe which version the proposal was implemented in (if it's
Finished or Closed).
Finished or Closed). The Ticket field should be a ticket number referring
to Tor's canonical bug tracker (e.g. "#7144" refers to
https://bugs.torproject.org/7144) or to a publicly accessible URI where one
may subscribe to updates and/or retrieve information on implementation
status.
** Proposals with assigned numbers of prop#283 and higher are REQUIRED to
have a Ticket field if the Status is OPEN, ACCEPTED, CLOSED, or FINISHED.
The body of the proposal should start with an Overview section explaining
what the proposal's about, what it does, and about what state it's in.

View File

@ -5,11 +5,11 @@ class Error(Exception): pass
STATUSES = """DRAFT NEEDS-REVISION NEEDS-RESEARCH OPEN ACCEPTED META FINISHED
CLOSED SUPERSEDED DEAD REJECTED OBSOLETE RESERVE INFORMATIONAL""".split()
REQUIRED_FIELDS = [ "Filename", "Status", "Title" ]
CONDITIONAL_FIELDS = { "OPEN" : [ "Target" ],
"ACCEPTED" : [ "Target "],
"CLOSED" : [ "Implemented-In" ],
"FINISHED" : [ "Implemented-In" ] }
REQUIRED_FIELDS = [ "Filename", "Status", "Title"]
CONDITIONAL_FIELDS = { "OPEN" : [ "Target", "Ticket" ],
"ACCEPTED" : [ "Target", "Ticket" ],
"CLOSED" : [ "Implemented-In", "Ticket" ],
"FINISHED" : [ "Implemented-In", "Ticket" ] }
FNAME_RE = re.compile(r'^(\d\d\d)-.*[^\~]$')
DIR = "."
OUTFILE = "000-index.txt"
@ -45,9 +45,29 @@ def readProposal(fn):
finally:
f.close()
def getProposalNumber(fn):
"""Get the proposal's assigned number from its filename `fn`."""
parts = fn.split('-', 1)
assert len(parts) == 2, \
"Filename must have a proposal number and title separated by a '-'"
return int(parts[0])
def checkProposal(fn, fields):
status = fields.get("Status")
need_fields = REQUIRED_FIELDS + CONDITIONAL_FIELDS.get(status, [])
number = getProposalNumber(fn)
# Since prop#288 was the newest when we began requiring the 'Ticket:'
# field, we don't require the field for it or any older proposal.
# (Although you're encouraged to add it to your proposal, and add it for
# older proposals where you know the correct ticket, as it greatly helps
# newcomers find more information on the implementation.)
if number <= 288:
if "Ticket" in need_fields:
need_fields.remove("Ticket")
for f in need_fields:
if not fields.has_key(f):
raise Error("%s has no %s field"%(fn, f))