2017-08-23 07:47:09 -04:00
|
|
|
#!/usr/bin/env python3
|
2017-09-11 11:40:47 -04:00
|
|
|
import re
|
|
|
|
|
2017-08-23 07:47:09 -04:00
|
|
|
import xml.etree.ElementTree as etree
|
|
|
|
|
|
|
|
from datetime import datetime, timedelta
|
|
|
|
|
|
|
|
from xeplib import load_xepinfos, Status
|
|
|
|
|
|
|
|
|
|
|
|
def get_deferred(accepted):
|
|
|
|
now = datetime.utcnow().replace(hour=0, minute=0, second=0, microsecond=0)
|
|
|
|
threshold = now.replace(year=now.year - 1)
|
|
|
|
|
|
|
|
for number, info in sorted(accepted.items()):
|
|
|
|
if info["status"] == Status.EXPERIMENTAL and "last_revision" in info:
|
|
|
|
last_update = info["last_revision"]["date"]
|
|
|
|
if last_update <= threshold:
|
|
|
|
yield info
|
|
|
|
|
|
|
|
|
2017-09-11 11:40:47 -04:00
|
|
|
EXPERIMENTAL_STATUS = "<status>Experimental</status>"
|
|
|
|
DEFERRED_STATUS = "<status>Deferred</status>"
|
|
|
|
REVISION_RE = re.compile(r"\s+<revision>")
|
|
|
|
REVISION_TEMPLATE = """
|
|
|
|
<revision>
|
|
|
|
<version>{version}</version>
|
|
|
|
<date>{now:%Y-%m-%d}</date>
|
|
|
|
<initials>XEP Editor ({initials})</initials>
|
|
|
|
<remark>Defer due to lack of activity.</remark>
|
|
|
|
</revision>"""
|
|
|
|
|
|
|
|
|
|
|
|
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:]
|
2018-01-25 02:56:23 -05:00
|
|
|
version.append("0"")
|
2017-09-11 11:40:47 -04:00
|
|
|
|
|
|
|
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()
|
|
|
|
|
|
|
|
|
2017-08-23 07:47:09 -04:00
|
|
|
def main():
|
|
|
|
import argparse
|
|
|
|
|
|
|
|
parser = argparse.ArgumentParser(
|
|
|
|
description="Show the XEPs which need to be changed to deferred."
|
|
|
|
)
|
|
|
|
|
|
|
|
parser.add_argument(
|
|
|
|
"-l", "--xeplist",
|
|
|
|
type=argparse.FileType("rb"),
|
|
|
|
default=None,
|
|
|
|
help="XEP list to use (defaults to ./build/xeplist.xml)"
|
|
|
|
)
|
|
|
|
|
|
|
|
parser.add_argument(
|
2017-09-11 11:40:47 -04:00
|
|
|
"-v", "--verbose",
|
|
|
|
help="Print additional metadata for deferred XEPs",
|
2017-08-23 07:47:09 -04:00
|
|
|
action="store_true",
|
|
|
|
default=False,
|
2017-09-11 11:40:47 -04:00
|
|
|
)
|
|
|
|
|
|
|
|
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."
|
2017-08-23 07:47:09 -04:00
|
|
|
)
|
|
|
|
|
|
|
|
args = parser.parse_args()
|
|
|
|
|
|
|
|
if args.xeplist is None:
|
|
|
|
args.xeplist = open("./build/xeplist.xml", "rb")
|
|
|
|
|
|
|
|
with args.xeplist as f:
|
|
|
|
tree = etree.parse(f)
|
|
|
|
|
|
|
|
accepted, _ = load_xepinfos(tree)
|
|
|
|
deferred = list(get_deferred(accepted))
|
|
|
|
|
|
|
|
for deferred_info in deferred:
|
2017-09-11 11:40:47 -04:00
|
|
|
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"])
|
2017-08-23 07:47:09 -04:00
|
|
|
|
|
|
|
|
|
|
|
if __name__ == "__main__":
|
|
|
|
main()
|