diff --git a/tools/deferrals.py b/tools/deferrals.py
index 6674385c..f2b70a13 100755
--- a/tools/deferrals.py
+++ b/tools/deferrals.py
@@ -1,4 +1,6 @@
#!/usr/bin/env python3
+import re
+
import xml.etree.ElementTree as etree
from datetime import datetime, timedelta
@@ -17,6 +19,51 @@ def get_deferred(accepted):
yield info
+EXPERIMENTAL_STATUS = "Experimental"
+DEFERRED_STATUS = "Deferred"
+REVISION_RE = re.compile(r"\s+")
+REVISION_TEMPLATE = """
+
+ {version}
+ {now:%Y-%m-%d}
+ XEP Editor ({initials})
+ Defer due to lack of activity.
+ """
+
+
+def defer_xep(number, last_version, initials):
+ filename = "xep-{:04d}.xml".format(number)
+ with open(filename, "r") as f:
+ xep_text = f.read()
+
+ if EXPERIMENTAL_STATUS not in xep_text:
+ raise ValueError("cannot find experimental status in XEP text")
+
+ # this is so incredibly evil ...
+ xep_text = xep_text.replace(EXPERIMENTAL_STATUS, DEFERRED_STATUS, 1)
+ revision_match = REVISION_RE.search(xep_text)
+
+ version = last_version.split(".")
+ if len(version) == 1:
+ version.append("1")
+ else:
+ version[1] = str(int(version[1]) + 1)
+ del version[2:]
+
+ xep_text = (
+ xep_text[:revision_match.start()] +
+ REVISION_TEMPLATE.format(
+ now=datetime.utcnow(),
+ version=".".join(version),
+ initials=initials,
+ ) + xep_text[revision_match.start():]
+ )
+
+ with open(filename, "w") as f:
+ f.write(xep_text)
+ f.flush()
+
+
def main():
import argparse
@@ -32,10 +79,18 @@ def main():
)
parser.add_argument(
- "-m", "--modify",
+ "-v", "--verbose",
+ help="Print additional metadata for deferred XEPs",
action="store_true",
default=False,
- help="Modify the XEP files in-place."
+ )
+
+ parser.add_argument(
+ "-m", "--modify",
+ default=False,
+ metavar="INITIALS",
+ help="Modify the to-be-deferred XEPs in-place and use the given "
+ "INITIALS in the remarks."
)
args = parser.parse_args()
@@ -50,7 +105,20 @@ def main():
deferred = list(get_deferred(accepted))
for deferred_info in deferred:
- print(deferred_info["number"])
+ if args.modify:
+ defer_xep(deferred_info["number"],
+ deferred_info["last_revision"]["version"],
+ args.modify)
+
+ if args.verbose:
+ print(
+ "XEP-{info[number]:04d}: {info[title]} "
+ "(last update {info[last_revision][date]:%Y-%m-%d})".format(
+ info=deferred_info
+ )
+ )
+ else:
+ print(deferred_info["number"])
if __name__ == "__main__":
diff --git a/tools/send-updates.py b/tools/send-updates.py
index 065e93b3..09ac9c26 100755
--- a/tools/send-updates.py
+++ b/tools/send-updates.py
@@ -68,6 +68,19 @@ Changelog:
URL: {url}"""
+MAIL_DEFER_TEMPLATE = """\
+XEP-{info[number]:04d} ({info[title]}) has been Deferred because of inactivity.
+
+Abstract:
+{info[abstract]}
+
+URL: {url}
+
+If and when a new revision of this XEP is published, its status will be \
+changed back to Experimental.
+"""
+
+
SUBJECT_NONPROTO_TEMPLATE = \
"{action.value}: XEP-{info[number]:04d} ({info[title]})"
@@ -152,6 +165,10 @@ def make_nonproto_mail(action, info):
),
}
+ body_template = MAIL_NONPROTO_TEMPLATE
+ if action == Action.DEFER:
+ body_template = MAIL_DEFER_TEMPLATE
+
mail = email.message.EmailMessage()
mail["Subject"] = SUBJECT_NONPROTO_TEMPLATE.format(**kwargs)
mail["XSF-XEP-Action"] = action.value
@@ -161,7 +178,7 @@ def make_nonproto_mail(action, info):
mail["XSF-XEP-Number"] = "{:04d}".format(info["number"])
mail["XSF-XEP-Url"] = kwargs["url"]
mail.set_content(
- wraptext(MAIL_NONPROTO_TEMPLATE.format(**kwargs)),
+ wraptext(body_template.format(**kwargs)),
"plain",
"utf-8",
)
diff --git a/tools/xeplib.py b/tools/xeplib.py
index 5a250041..93065f78 100644
--- a/tools/xeplib.py
+++ b/tools/xeplib.py
@@ -35,6 +35,7 @@ class Action(enum.Enum):
OBSOLETE = "OBSOLETED"
DEFER = "DEFERRED"
UPDATE = "UPDATED"
+ DEPRECATE = "DEPRECATED"
@classmethod
def fromstatus(cls, status):
@@ -44,9 +45,9 @@ class Action(enum.Enum):
Status.ACTIVE: cls.ACTIVE,
Status.FINAL: cls.FINAL,
Status.RETRACTED: cls.RETRACT,
- Status.OBSOLETED: cls.OBSOLETE,
+ Status.OBSOLETE: cls.OBSOLETE,
Status.DEPRECATED: cls.DEPRECATE,
- Status.DEFERRED: cls.DEFERRED,
+ Status.DEFERRED: cls.DEFER,
}[status]