aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIsis Lovecruft <isis@torproject.org>2017-11-20 18:27:47 +0000
committerIsis Lovecruft <isis@torproject.org>2017-12-08 01:53:52 +0000
commit8be6722e8d901304f6795fcf97c02c0f45bca98e (patch)
tree3217331d152cb65cb93848eeea5b40527ab0e251
parentc78806e96eed6828873c6f9604f2a89d14fc123d (diff)
downloadtorspec-8be6722e8d901304f6795fcf97c02c0f45bca98e.tar.gz
torspec-8be6722e8d901304f6795fcf97c02c0f45bca98e.zip
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.
-rw-r--r--proposals/001-process.txt12
-rwxr-xr-xproposals/reindex.py30
2 files changed, 35 insertions, 7 deletions
diff --git a/proposals/001-process.txt b/proposals/001-process.txt
index ba65211..1da80da 100644
--- a/proposals/001-process.txt
+++ b/proposals/001-process.txt
@@ -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.
diff --git a/proposals/reindex.py b/proposals/reindex.py
index b442271..990016f 100755
--- a/proposals/reindex.py
+++ b/proposals/reindex.py
@@ -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))