From 79f7f769cec11ac088f41b8df7437d8e28bbe332 Mon Sep 17 00:00:00 2001 From: Dirk Thomas Date: Sat, 22 Sep 2012 22:09:32 -0700 Subject: [PATCH] renamed all REPs from .txt to .rst, removed obsolete stuff, moved REP attachments to subfolders, updated doc to reference new github repo --- .gitignore | 3 + Makefile | 34 +- PyRSS2Gen.py | 443 ------------------ docutils.conf | 2 +- docutils_transforms_reps.py | 14 +- docutils_writers_rep/__init__.py | 2 +- docutils_writers_rep/template.txt | 2 +- genrepindex.py | 4 +- propcheck.py | 75 --- rep-0001.txt => rep-0001.rst | 18 +- rep-0001-1.png => rep-0001/rep-0001-1.png | Bin rep-0002.txt => rep-0002.rst | 0 rep-0003.txt => rep-0003.rst | 0 rep-0008.txt => rep-0008.rst | 0 rep-0009.txt => rep-0009.rst | 0 rep-0010.txt => rep-0010.rst | 0 rep-0012.txt => rep-0012.rst | 2 +- rep-0100.txt => rep-0100.rst | 0 rep-0101.txt => rep-0101.rst | 0 rep-0102.txt => rep-0102.rst | 0 rep-0103.txt => rep-0103.rst | 0 rep-0104.txt => rep-0104.rst | 0 rep-0105.txt => rep-0105.rst | 0 rep-0106.txt => rep-0106.rst | 0 rep-0107.txt => rep-0107.rst | 0 rep-0108.txt => rep-0108.rst | 0 rep-0109.txt => rep-0109.rst | 0 rep-0110.txt => rep-0110.rst | 0 rep-0111.txt => rep-0111.rst | 0 rep-0112.txt => rep-0112.rst | 0 rep-0113.txt => rep-0113.rst | 0 rep-0114.txt => rep-0114.rst | 0 rep-0115.txt => rep-0115.rst | 0 rep-0116.txt => rep-0116.rst | 0 rep-0117.txt => rep-0117.rst | 0 rep-0118.txt => rep-0118.rst | 0 rep-0119.txt => rep-0119.rst | 0 rep-0120.txt => rep-0120.rst | 0 rep-0120-1.jpg => rep-0120/rep-0120-1.jpg | Bin rep-0120-2.jpg => rep-0120/rep-0120-2.jpg | Bin rep-0121.txt => rep-0121.rst | 0 rep-0122.txt => rep-0122.rst | 0 rep-0123.txt => rep-0123.rst | 0 rep-0124.txt => rep-0124.rst | 0 rep-0125.txt => rep-0125.rst | 0 rep-0126.txt => rep-0126.rst | 0 rep-0127.txt => rep-0127.rst | 0 rep-html-template | 2 +- rep0/constants.py | 4 +- rep2html.py | 40 +- rep2pyramid.py | 533 ---------------------- rep2rss.py | 69 --- 52 files changed, 60 insertions(+), 1187 deletions(-) create mode 100644 .gitignore delete mode 100644 PyRSS2Gen.py delete mode 100644 propcheck.py rename rep-0001.txt => rep-0001.rst (97%) rename rep-0001-1.png => rep-0001/rep-0001-1.png (100%) rename rep-0002.txt => rep-0002.rst (100%) rename rep-0003.txt => rep-0003.rst (100%) rename rep-0008.txt => rep-0008.rst (100%) rename rep-0009.txt => rep-0009.rst (100%) rename rep-0010.txt => rep-0010.rst (100%) rename rep-0012.txt => rep-0012.rst (99%) rename rep-0100.txt => rep-0100.rst (100%) rename rep-0101.txt => rep-0101.rst (100%) rename rep-0102.txt => rep-0102.rst (100%) rename rep-0103.txt => rep-0103.rst (100%) rename rep-0104.txt => rep-0104.rst (100%) rename rep-0105.txt => rep-0105.rst (100%) rename rep-0106.txt => rep-0106.rst (100%) rename rep-0107.txt => rep-0107.rst (100%) rename rep-0108.txt => rep-0108.rst (100%) rename rep-0109.txt => rep-0109.rst (100%) rename rep-0110.txt => rep-0110.rst (100%) rename rep-0111.txt => rep-0111.rst (100%) rename rep-0112.txt => rep-0112.rst (100%) rename rep-0113.txt => rep-0113.rst (100%) rename rep-0114.txt => rep-0114.rst (100%) rename rep-0115.txt => rep-0115.rst (100%) rename rep-0116.txt => rep-0116.rst (100%) rename rep-0117.txt => rep-0117.rst (100%) rename rep-0118.txt => rep-0118.rst (100%) rename rep-0119.txt => rep-0119.rst (100%) rename rep-0120.txt => rep-0120.rst (100%) rename rep-0120-1.jpg => rep-0120/rep-0120-1.jpg (100%) rename rep-0120-2.jpg => rep-0120/rep-0120-2.jpg (100%) rename rep-0121.txt => rep-0121.rst (100%) rename rep-0122.txt => rep-0122.rst (100%) rename rep-0123.txt => rep-0123.rst (100%) rename rep-0124.txt => rep-0124.rst (100%) rename rep-0125.txt => rep-0125.rst (100%) rename rep-0126.txt => rep-0126.rst (100%) rename rep-0127.txt => rep-0127.rst (100%) delete mode 100755 rep2pyramid.py delete mode 100755 rep2rss.py diff --git a/.gitignore b/.gitignore new file mode 100644 index 000000000..36834cb50 --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +rep-0000.rst +*.html +*.pyc diff --git a/Makefile b/Makefile index 07c032ac8..dcc77f4e4 100644 --- a/Makefile +++ b/Makefile @@ -1,40 +1,30 @@ -# Rules to only make the required HTML versions, not all of them, -# without the user having to keep track of which. -# -# Not really important, but convenient. +# targets to generate an index, HTML files and upload them to the server REP2HTML=rep2html.py PYTHON=python -.SUFFIXES: .txt .html +.SUFFIXES: .rst .html -.txt.html: +.rst.html: @$(PYTHON) $(REP2HTML) $< -REPS=$(filter-out rep-0000.txt,$(wildcard rep-????.txt)) +REPS=$(filter-out rep-0000.rst,$(wildcard rep-????.rst)) -TARGETS=$(REPS:.txt=.html) rep-0000.html +SUBDIRS=$(wildcard rep-????) -all: rep-0000.txt $(TARGETS) +TARGETS=$(REPS:.rst=.html) rep-0000.html -$(TARGETS) rep-0000.html1: rep2html.py +all: rep-0000.rst $(TARGETS) -rep-0000.txt: $(REPS) - $(PYTHON) genrepindex.py . +$(TARGETS): rep2html.py -install: - echo "Installing is not necessary anymore. It will be done in post-commit." +rep-0000.rst: $(REPS) + $(PYTHON) genrepindex.py . clean: -rm *.html - -rm rep-0000.txt - -update: - svn update - -propcheck: - $(PYTHON) propcheck.py + -rm rep-0000.rst upload: all - rsync *.txt *.html *.jpg *.png root@wgs32.willowgarage.com:/var/www/www.ros.org/html/reps + rsync -r *.html rep.css style.css rep-0000.rst $(SUBDIRS) root@wgs32.willowgarage.com:/var/www/www.ros.org/html/reps/new diff --git a/PyRSS2Gen.py b/PyRSS2Gen.py deleted file mode 100644 index 5a1975e7f..000000000 --- a/PyRSS2Gen.py +++ /dev/null @@ -1,443 +0,0 @@ -"""PyRSS2Gen - A Python library for generating RSS 2.0 feeds.""" - -__name__ = "PyRSS2Gen" -__version__ = (1, 0, 0) -__author__ = "Andrew Dalke " - -_generator_name = __name__ + "-" + ".".join(map(str, __version__)) - -import datetime - -# Could make this the base class; will need to add 'publish' -class WriteXmlMixin: - def write_xml(self, outfile, encoding = "utf-8"): - from xml.sax import saxutils - handler = saxutils.XMLGenerator(outfile, encoding) - handler.startDocument() - self.publish(handler) - handler.endDocument() - - def to_xml(self, encoding = "utf-8"): - try: - import cStringIO as StringIO - except ImportError: - import StringIO - f = StringIO.StringIO() - self.write_xml(f, encoding) - return f.getvalue() - - -def _element(handler, name, obj, d = {}): - if isinstance(obj, basestring) or obj is None: - # special-case handling to make the API easier - # to use for the common case. - handler.startElement(name, d) - if obj is not None: - handler.characters(obj) - handler.endElement(name) - else: - # It better know how to emit the correct XML. - obj.publish(handler) - -def _opt_element(handler, name, obj): - if obj is None: - return - _element(handler, name, obj) - - -def _format_date(dt): - """convert a datetime into an RFC 822 formatted date - - Input date must be in GMT. - """ - # Looks like: - # Sat, 07 Sep 2002 00:00:01 GMT - # Can't use strftime because that's locale dependent - # - # Isn't there a standard way to do this for Python? The - # rfc822 and email.Utils modules assume a timestamp. The - # following is based on the rfc822 module. - return "%s, %02d %s %04d %02d:%02d:%02d GMT" % ( - ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"][dt.weekday()], - dt.day, - ["Jan", "Feb", "Mar", "Apr", "May", "Jun", - "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"][dt.month-1], - dt.year, dt.hour, dt.minute, dt.second) - - -## -# A couple simple wrapper objects for the fields which -# take a simple value other than a string. -class IntElement: - """implements the 'publish' API for integers - - Takes the tag name and the integer value to publish. - - (Could be used for anything which uses str() to be published - to text for XML.) - """ - element_attrs = {} - def __init__(self, name, val): - self.name = name - self.val = val - def publish(self, handler): - handler.startElement(self.name, self.element_attrs) - handler.characters(str(self.val)) - handler.endElement(self.name) - -class DateElement: - """implements the 'publish' API for a datetime.datetime - - Takes the tag name and the datetime to publish. - - Converts the datetime to RFC 2822 timestamp (4-digit year). - """ - def __init__(self, name, dt): - self.name = name - self.dt = dt - def publish(self, handler): - _element(handler, self.name, _format_date(self.dt)) -#### - -class Category: - """Publish a category element""" - def __init__(self, category, domain = None): - self.category = category - self.domain = domain - def publish(self, handler): - d = {} - if self.domain is not None: - d["domain"] = self.domain - _element(handler, "category", self.category, d) - -class Cloud: - """Publish a cloud""" - def __init__(self, domain, port, path, - registerProcedure, protocol): - self.domain = domain - self.port = port - self.path = path - self.registerProcedure = registerProcedure - self.protocol = protocol - def publish(self, handler): - _element(handler, "cloud", None, { - "domain": self.domain, - "port": str(self.port), - "path": self.path, - "registerProcedure": self.registerProcedure, - "protocol": self.protocol}) - -class Image: - """Publish a channel Image""" - element_attrs = {} - def __init__(self, url, title, link, - width = None, height = None, description = None): - self.url = url - self.title = title - self.link = link - self.width = width - self.height = height - self.description = description - - def publish(self, handler): - handler.startElement("image", self.element_attrs) - - _element(handler, "url", self.url) - _element(handler, "title", self.title) - _element(handler, "link", self.link) - - width = self.width - if isinstance(width, int): - width = IntElement("width", width) - _opt_element(handler, "width", width) - - height = self.height - if isinstance(height, int): - height = IntElement("height", height) - _opt_element(handler, "height", height) - - _opt_element(handler, "description", self.description) - - handler.endElement("image") - -class Guid: - """Publish a guid - - Defaults to being a permalink, which is the assumption if it's - omitted. Hence strings are always permalinks. - """ - def __init__(self, guid, isPermaLink = 1): - self.guid = guid - self.isPermaLink = isPermaLink - def publish(self, handler): - d = {} - if self.isPermaLink: - d["isPermaLink"] = "true" - else: - d["isPermaLink"] = "false" - _element(handler, "guid", self.guid, d) - -class TextInput: - """Publish a textInput - - Apparently this is rarely used. - """ - element_attrs = {} - def __init__(self, title, description, name, link): - self.title = title - self.description = description - self.name = name - self.link = link - - def publish(self, handler): - handler.startElement("textInput", self.element_attrs) - _element(handler, "title", self.title) - _element(handler, "description", self.description) - _element(handler, "name", self.name) - _element(handler, "link", self.link) - handler.endElement("textInput") - - -class Enclosure: - """Publish an enclosure""" - def __init__(self, url, length, type): - self.url = url - self.length = length - self.type = type - def publish(self, handler): - _element(handler, "enclosure", None, - {"url": self.url, - "length": str(self.length), - "type": self.type, - }) - -class Source: - """Publish the item's original source, used by aggregators""" - def __init__(self, name, url): - self.name = name - self.url = url - def publish(self, handler): - _element(handler, "source", self.name, {"url": self.url}) - -class SkipHours: - """Publish the skipHours - - This takes a list of hours, as integers. - """ - element_attrs = {} - def __init__(self, hours): - self.hours = hours - def publish(self, handler): - if self.hours: - handler.startElement("skipHours", self.element_attrs) - for hour in self.hours: - _element(handler, "hour", str(hour)) - handler.endElement("skipHours") - -class SkipDays: - """Publish the skipDays - - This takes a list of days as strings. - """ - element_attrs = {} - def __init__(self, days): - self.days = days - def publish(self, handler): - if self.days: - handler.startElement("skipDays", self.element_attrs) - for day in self.days: - _element(handler, "day", day) - handler.endElement("skipDays") - -class RSS2(WriteXmlMixin): - """The main RSS class. - - Stores the channel attributes, with the "category" elements under - ".categories" and the RSS items under ".items". - """ - - rss_attrs = {"version": "2.0"} - element_attrs = {} - def __init__(self, - title, - link, - description, - - language = None, - copyright = None, - managingEditor = None, - webMaster = None, - pubDate = None, # a datetime, *in* *GMT* - lastBuildDate = None, # a datetime - - categories = None, # list of strings or Category - generator = _generator_name, - docs = "http://blogs.law.harvard.edu/tech/rss", - cloud = None, # a Cloud - ttl = None, # integer number of minutes - - image = None, # an Image - rating = None, # a string; I don't know how it's used - textInput = None, # a TextInput - skipHours = None, # a SkipHours with a list of integers - skipDays = None, # a SkipDays with a list of strings - - items = None, # list of RSSItems - ): - self.title = title - self.link = link - self.description = description - self.language = language - self.copyright = copyright - self.managingEditor = managingEditor - - self.webMaster = webMaster - self.pubDate = pubDate - self.lastBuildDate = lastBuildDate - - if categories is None: - categories = [] - self.categories = categories - self.generator = generator - self.docs = docs - self.cloud = cloud - self.ttl = ttl - self.image = image - self.rating = rating - self.textInput = textInput - self.skipHours = skipHours - self.skipDays = skipDays - - if items is None: - items = [] - self.items = items - - def publish(self, handler): - handler.startElement("rss", self.rss_attrs) - handler.startElement("channel", self.element_attrs) - _element(handler, "title", self.title) - _element(handler, "link", self.link) - _element(handler, "description", self.description) - - self.publish_extensions(handler) - - _opt_element(handler, "language", self.language) - _opt_element(handler, "copyright", self.copyright) - _opt_element(handler, "managingEditor", self.managingEditor) - _opt_element(handler, "webMaster", self.webMaster) - - pubDate = self.pubDate - if isinstance(pubDate, datetime.datetime): - pubDate = DateElement("pubDate", pubDate) - _opt_element(handler, "pubDate", pubDate) - - lastBuildDate = self.lastBuildDate - if isinstance(lastBuildDate, datetime.datetime): - lastBuildDate = DateElement("lastBuildDate", lastBuildDate) - _opt_element(handler, "lastBuildDate", lastBuildDate) - - for category in self.categories: - if isinstance(category, basestring): - category = Category(category) - category.publish(handler) - - _opt_element(handler, "generator", self.generator) - _opt_element(handler, "docs", self.docs) - - if self.cloud is not None: - self.cloud.publish(handler) - - ttl = self.ttl - if isinstance(self.ttl, int): - ttl = IntElement("ttl", ttl) - _opt_element(handler, "tt", ttl) - - if self.image is not None: - self.image.publish(handler) - - _opt_element(handler, "rating", self.rating) - if self.textInput is not None: - self.textInput.publish(handler) - if self.skipHours is not None: - self.skipHours.publish(handler) - if self.skipDays is not None: - self.skipDays.publish(handler) - - for item in self.items: - item.publish(handler) - - handler.endElement("channel") - handler.endElement("rss") - - def publish_extensions(self, handler): - # Derived classes can hook into this to insert - # output after the three required fields. - pass - - - -class RSSItem(WriteXmlMixin): - """Publish an RSS Item""" - element_attrs = {} - def __init__(self, - title = None, # string - link = None, # url as string - description = None, # string - author = None, # email address as string - categories = None, # list of string or Category - comments = None, # url as string - enclosure = None, # an Enclosure - guid = None, # a unique string - pubDate = None, # a datetime - source = None, # a Source - ): - - if title is None and description is None: - raise TypeError( - "must define at least one of 'title' or 'description'") - self.title = title - self.link = link - self.description = description - self.author = author - if categories is None: - categories = [] - self.categories = categories - self.comments = comments - self.enclosure = enclosure - self.guid = guid - self.pubDate = pubDate - self.source = source - # It sure does get tedious typing these names three times... - - def publish(self, handler): - handler.startElement("item", self.element_attrs) - _opt_element(handler, "title", self.title) - _opt_element(handler, "link", self.link) - self.publish_extensions(handler) - _opt_element(handler, "description", self.description) - _opt_element(handler, "author", self.author) - - for category in self.categories: - if isinstance(category, basestring): - category = Category(category) - category.publish(handler) - - _opt_element(handler, "comments", self.comments) - if self.enclosure is not None: - self.enclosure.publish(handler) - _opt_element(handler, "guid", self.guid) - - pubDate = self.pubDate - if isinstance(pubDate, datetime.datetime): - pubDate = DateElement("pubDate", pubDate) - _opt_element(handler, "pubDate", pubDate) - - if self.source is not None: - self.source.publish(handler) - - handler.endElement("item") - - def publish_extensions(self, handler): - # Derived classes can hook into this to insert - # output after the title and link elements - pass diff --git a/docutils.conf b/docutils.conf index 3ea41932a..9770262a4 100644 --- a/docutils.conf +++ b/docutils.conf @@ -15,7 +15,7 @@ template: rep-html-template embed-stylesheet: 0 # path to PEPs, for template: -rep-home: /reps/ +rep-home: https://github.com/ros-infrastructure/rep/blob/master/ # base URL for PEP references (no host so mirrors work): pep-base-url: /reps/ diff --git a/docutils_transforms_reps.py b/docutils_transforms_reps.py index 6c3b348f2..fbd198cac 100644 --- a/docutils_transforms_reps.py +++ b/docutils_transforms_reps.py @@ -32,7 +32,7 @@ class Headers(Transform): default_priority = 360 rep_url = 'rep-%04d' - rep_svn_url = 'http://code.ros.org/svn/rep/trunk/rep-%04d.txt' + rep_git_url = 'https://github.com/ros-infrastructure/rep/blob/master/rep-%04d.rst' rcs_keyword_substitutions = ( (re.compile(r'\$' r'RCSfile: (.+),v \$$', re.IGNORECASE), r'\1'), (re.compile(r'\$[a-zA-Z]+: (.+) \$$'), r'\1'),) @@ -54,10 +54,10 @@ def apply(self): value = field[1].astext() try: rep = int(value) - cvs_url = self.rep_svn_url % rep + repo_url = self.rep_git_url % rep except ValueError: rep = value - cvs_url = None + repo_url = None msg = self.document.reporter.warning( '"REP" header must contain an integer; "%s" is an ' 'invalid value.' % rep, base_node=field) @@ -96,9 +96,9 @@ def apply(self): date = time.strftime( '%d-%b-%Y', time.localtime(os.stat(self.document['source'])[8])) - if cvs_url: + if repo_url: body += nodes.paragraph( - '', '', nodes.reference('', date, refuri=cvs_url)) + '', '', nodes.reference('', date, refuri=repo_url)) else: # empty continue @@ -124,9 +124,9 @@ def apply(self): para[:] = newbody[:-1] # drop trailing space elif name == 'last-modified': utils.clean_rcs_keywords(para, self.rcs_keyword_substitutions) - if cvs_url: + if repo_url: date = para.astext() - para[:] = [nodes.reference('', date, refuri=cvs_url)] + para[:] = [nodes.reference('', date, refuri=repo_url)] elif name == 'content-type': rep_type = para.astext() uri = self.document.settings.rep_base_url + self.rep_url % 12 diff --git a/docutils_writers_rep/__init__.py b/docutils_writers_rep/__init__.py index 878a95c2b..a60d88e31 100644 --- a/docutils_writers_rep/__init__.py +++ b/docutils_writers_rep/__init__.py @@ -26,7 +26,7 @@ class Writer(html4css1.Writer): os.path.join(os.getcwd(), 'dummy'), os.path.join(os.path.dirname(__file__), default_stylesheet)) - default_template = 'template.txt' + default_template = 'template.rst' default_template_path = utils.relative_path( os.path.join(os.getcwd(), 'dummy'), diff --git a/docutils_writers_rep/template.txt b/docutils_writers_rep/template.txt index 123fd0cdd..d75731d2c 100644 --- a/docutils_writers_rep/template.txt +++ b/docutils_writers_rep/template.txt @@ -20,7 +20,7 @@ to templates. DO NOT USE THIS HTML FILE AS YOUR TEMPLATE! [ROS Home] [REP Index] -[REP Source] +[REP Source]
%(body)s diff --git a/genrepindex.py b/genrepindex.py index 116865fae..13a265c7b 100644 --- a/genrepindex.py +++ b/genrepindex.py @@ -38,7 +38,7 @@ def main(argv): abs_file_path = os.path.join(path, file_path) if not os.path.isfile(abs_file_path): continue - if file_path.startswith("rep-") and file_path.endswith(".txt") and not file_path == 'rep-0000.txt': + if file_path.startswith("rep-") and file_path.endswith(".rst") and not file_path == 'rep-0000.rst': with codecs.open(abs_file_path, 'r', encoding='UTF-8') as rep_file: try: rep = REP(rep_file) @@ -58,7 +58,7 @@ def main(argv): else: raise ValueError("argument must be a directory or file path") - with codecs.open('rep-0000.txt', 'w', encoding='UTF-8') as rep0_file: + with codecs.open('rep-0000.rst', 'w', encoding='UTF-8') as rep0_file: write_rep0(reps, rep0_file) if __name__ == "__main__": diff --git a/propcheck.py b/propcheck.py deleted file mode 100644 index 23c2a87df..000000000 --- a/propcheck.py +++ /dev/null @@ -1,75 +0,0 @@ -#!/usr/bin/env python -"""Perform an integrity check upon all REPs to make sure the needed svn -properties are set.""" - -import glob -import pdb -import subprocess -from xml.etree import ElementTree - -PROPS = {'svn:eol-style': "native", 'svn:keywords': "Author Date Id Revision"} - - -def get_props(): - """Return the properties set on rep-*.txt files as an ElementTree instance. - - Files with no properties set will not be contained in the returned data. - - """ - cmd = 'svn proplist --xml rep-*.txt' - proc = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE) - xml_results = proc.communicate()[0] - if proc.returncode: - raise subprocess.CalledProcessError("%s returned %d" % - (cmd, proc.returncode)) - return ElementTree.fromstring(xml_results) - - -def missing_props(props): - """Figure out what properties are missing on what REPs, returning a sequence - of (path, [missing_props]) pairs. - - For the set properties (as calculated by get_props()), see which REPs are - lacking any properties. For the REPs that are not even listed in the set - properties, assume they are missing all needed properties. - - """ - problems = [] - missing_files = set(glob.glob('rep-*.txt')) - missing_files.remove('rep-0000.txt') - for target in props: - assert target.tag == 'target' - needs = PROPS.keys() - path = target.attrib['path'] - missing_files.remove(path) - for property in target.getchildren(): - assert property.tag == 'property' - try: - needs.remove(property.attrib['name']) - except ValueError: - pass - if needs: - problems.append([path, needs]) - for path in missing_files: - problems.append([path, PROPS.keys()]) - return problems - - -def fix_props(missing_props): - """Fix the missing properties.""" - for path, missing in missing_props: - print "For %s, setting %s" % (path, missing) - for problem in missing: - cmd = 'svn propset %s "%s" %s' % (problem, PROPS[problem], path) - subprocess.check_call(cmd, shell=True) - - -def main(): - props = get_props() - need_fixing = missing_props(props) - fix_props(need_fixing) - - - -if __name__ == '__main__': - main() diff --git a/rep-0001.txt b/rep-0001.rst similarity index 97% rename from rep-0001.txt rename to rep-0001.rst index 7950798dc..a72031ad8 100644 --- a/rep-0001.txt +++ b/rep-0001.rst @@ -123,7 +123,7 @@ for Now, TBD) can be consulted during the approval phase, and is the final arbiter of the draft's REP-ability. As updates are necessary, the REP author can check in new versions if -they have SVN commit permissions, or can email new REP versions to +they have GIT commit permissions, or can email new REP versions to the REP editor for committing. Standards Track REPs consist of two parts, a design document and a @@ -178,7 +178,7 @@ an API can replace version 1. The possible paths of the status of REPs are as follows: -.. image:: rep-0001-1.png +.. image:: rep-0001/rep-0001-1.png Some Informational and Process REPs may also have a status of "Active" if they are never meant to be completed. E.g. REP 1 (this REP). @@ -359,7 +359,7 @@ When in doubt about where to send your changes, please check first with the REP author and/or REP editor. REP authors who are also ROS committers can update the -REPs themselves by using "svn commit" to commit their changes. +REPs themselves by using "git commit/push" to commit their changes. Transferring REP Ownership @@ -412,17 +412,17 @@ Once the REP is ready for the repository, the REP editor will: * List the REP in REP 0 (in two places: the categorized list, and the numeric list). -* Add the REP to SVN. +* Add the REP to GIT. The command to check out a read-only copy of the repository is:: - svn checkout https://code.ros.org/svn/rep/trunk rep + git clone https://github.com/ros-infrastructure/rep.git * Send email back to the REP author with next steps (post to ros-users). Updates to existing REPs also come in to ros-users@code.ros.org. Many -REP authors are not SVN committers yet, so we do the commits for them. +REP authors are not GIT committers yet, so we do the commits for them. Many REPs are written and maintained by developers with write access to the ROS codebase. The REP editors monitor the rep-commits list for @@ -443,10 +443,10 @@ Resources: References and Footnotes ======================== -.. [1] This historical record is available by the normal SVN commands +.. [1] This historical record is available by the normal GIT commands for retrieving older revisions. For those without direct access to - the SVN tree, you can browse the current and past REP revisions here: - https://code.ros.org/gf/project/rep/scmsvn/?action=browse&path=/trunk/ + the GIT tree, you can browse the current and past REP revisions here: + https://github.com/ros-infrastructure/rep/commits/master .. [2] REP 12, Sample reStructuredText REP Template (http://ros.org/reps/rep-0012.html) diff --git a/rep-0001-1.png b/rep-0001/rep-0001-1.png similarity index 100% rename from rep-0001-1.png rename to rep-0001/rep-0001-1.png diff --git a/rep-0002.txt b/rep-0002.rst similarity index 100% rename from rep-0002.txt rename to rep-0002.rst diff --git a/rep-0003.txt b/rep-0003.rst similarity index 100% rename from rep-0003.txt rename to rep-0003.rst diff --git a/rep-0008.txt b/rep-0008.rst similarity index 100% rename from rep-0008.txt rename to rep-0008.rst diff --git a/rep-0009.txt b/rep-0009.rst similarity index 100% rename from rep-0009.txt rename to rep-0009.rst diff --git a/rep-0010.txt b/rep-0010.rst similarity index 100% rename from rep-0010.txt rename to rep-0010.rst diff --git a/rep-0012.txt b/rep-0012.rst similarity index 99% rename from rep-0012.txt rename to rep-0012.rst index 68a4272db..22a66e15f 100644 --- a/rep-0012.txt +++ b/rep-0012.rst @@ -61,7 +61,7 @@ client libraries or standard libraries. When in doubt, read REP 1 for details. Once you've decided which type of REP yours is going to be, follow the directions below. -- Make a copy of this file (``.txt`` file, **not** HTML!) and perform +- Make a copy of this file (``.rst`` file, **not** HTML!) and perform the following edits. - Replace the "REP: 9" header with "REP: XXX" since you don't yet have diff --git a/rep-0100.txt b/rep-0100.rst similarity index 100% rename from rep-0100.txt rename to rep-0100.rst diff --git a/rep-0101.txt b/rep-0101.rst similarity index 100% rename from rep-0101.txt rename to rep-0101.rst diff --git a/rep-0102.txt b/rep-0102.rst similarity index 100% rename from rep-0102.txt rename to rep-0102.rst diff --git a/rep-0103.txt b/rep-0103.rst similarity index 100% rename from rep-0103.txt rename to rep-0103.rst diff --git a/rep-0104.txt b/rep-0104.rst similarity index 100% rename from rep-0104.txt rename to rep-0104.rst diff --git a/rep-0105.txt b/rep-0105.rst similarity index 100% rename from rep-0105.txt rename to rep-0105.rst diff --git a/rep-0106.txt b/rep-0106.rst similarity index 100% rename from rep-0106.txt rename to rep-0106.rst diff --git a/rep-0107.txt b/rep-0107.rst similarity index 100% rename from rep-0107.txt rename to rep-0107.rst diff --git a/rep-0108.txt b/rep-0108.rst similarity index 100% rename from rep-0108.txt rename to rep-0108.rst diff --git a/rep-0109.txt b/rep-0109.rst similarity index 100% rename from rep-0109.txt rename to rep-0109.rst diff --git a/rep-0110.txt b/rep-0110.rst similarity index 100% rename from rep-0110.txt rename to rep-0110.rst diff --git a/rep-0111.txt b/rep-0111.rst similarity index 100% rename from rep-0111.txt rename to rep-0111.rst diff --git a/rep-0112.txt b/rep-0112.rst similarity index 100% rename from rep-0112.txt rename to rep-0112.rst diff --git a/rep-0113.txt b/rep-0113.rst similarity index 100% rename from rep-0113.txt rename to rep-0113.rst diff --git a/rep-0114.txt b/rep-0114.rst similarity index 100% rename from rep-0114.txt rename to rep-0114.rst diff --git a/rep-0115.txt b/rep-0115.rst similarity index 100% rename from rep-0115.txt rename to rep-0115.rst diff --git a/rep-0116.txt b/rep-0116.rst similarity index 100% rename from rep-0116.txt rename to rep-0116.rst diff --git a/rep-0117.txt b/rep-0117.rst similarity index 100% rename from rep-0117.txt rename to rep-0117.rst diff --git a/rep-0118.txt b/rep-0118.rst similarity index 100% rename from rep-0118.txt rename to rep-0118.rst diff --git a/rep-0119.txt b/rep-0119.rst similarity index 100% rename from rep-0119.txt rename to rep-0119.rst diff --git a/rep-0120.txt b/rep-0120.rst similarity index 100% rename from rep-0120.txt rename to rep-0120.rst diff --git a/rep-0120-1.jpg b/rep-0120/rep-0120-1.jpg similarity index 100% rename from rep-0120-1.jpg rename to rep-0120/rep-0120-1.jpg diff --git a/rep-0120-2.jpg b/rep-0120/rep-0120-2.jpg similarity index 100% rename from rep-0120-2.jpg rename to rep-0120/rep-0120-2.jpg diff --git a/rep-0121.txt b/rep-0121.rst similarity index 100% rename from rep-0121.txt rename to rep-0121.rst diff --git a/rep-0122.txt b/rep-0122.rst similarity index 100% rename from rep-0122.txt rename to rep-0122.rst diff --git a/rep-0123.txt b/rep-0123.rst similarity index 100% rename from rep-0123.txt rename to rep-0123.rst diff --git a/rep-0124.txt b/rep-0124.rst similarity index 100% rename from rep-0124.txt rename to rep-0124.rst diff --git a/rep-0125.txt b/rep-0125.rst similarity index 100% rename from rep-0125.txt rename to rep-0125.rst diff --git a/rep-0126.txt b/rep-0126.rst similarity index 100% rename from rep-0126.txt rename to rep-0126.rst diff --git a/rep-0127.txt b/rep-0127.rst similarity index 100% rename from rep-0127.txt rename to rep-0127.rst diff --git a/rep-html-template b/rep-html-template index 93fb17698..0a52ddfea 100644 --- a/rep-html-template +++ b/rep-html-template @@ -124,7 +124,7 @@ theForm.input.value=theForm.input.value

[REP Index] -[REP Source] +[REP Source]

diff --git a/rep0/constants.py b/rep0/constants.py index 6d1fce32e..739c8735b 100644 --- a/rep0/constants.py +++ b/rep0/constants.py @@ -21,14 +21,14 @@ intro = u""" The REP contains the index of all ROS Enhancement Proposals, known as REPs. REP numbers are assigned by the REP Editor, and - once assigned are never changed. The SVN history[1] of the REP + once assigned are never changed. The GIT history[1] of the REP texts represent their historical record. """ references = u""" [1] View REP history online - http://code.ros.org/svn/rep/trunk/ + https://github.com/ros-infrastructure/rep """ footer = u""" diff --git a/rep2html.py b/rep2html.py index 68c09335f..744d6d53b 100755 --- a/rep2html.py +++ b/rep2html.py @@ -17,7 +17,7 @@ -i, --install After generating the HTML, install it and the plaintext source file - (.txt) on python.org. In that case the user's name is used in the scp + (.rst) on python.org. In that case the user's name is used in the scp and ssh commands, unless "-u username" is given (in which case, it is used instead). Without -i, -u is ignored. @@ -31,7 +31,7 @@ -h, --help Print this help message and exit. -The optional arguments ``reps`` are either rep numbers or .txt files. +The optional arguments ``reps`` are either rep numbers or .rst files. """ import sys @@ -49,7 +49,7 @@ PROGRAM = sys.argv[0] RFCURL = 'http://www.faqs.org/rfcs/rfc%d.html' REPURL = 'rep-%04d.html' -REPSVNURL = ('http://code.ros.org/svn/rep/trunk/rep-%04d.txt') +REPGITURL = ('https://github.com/ros-infrastructure/rep/blob/master/rep-%04d.rst') REPDIRRUL = 'http://www.ros.org/reps/' HOST = "wgs32.willowgarage.com" # host for update @@ -67,7 +67,7 @@ DTD = ('') -fixpat = re.compile("((https?|ftp):[-_a-zA-Z0-9/.+~:?#$=&,]+)|(rep-\d+(.txt)?)|" +fixpat = re.compile("((https?|ftp):[-_a-zA-Z0-9/.+~:?#$=&,]+)|(rep-\d+(.rst)?)|" "(RFC[- ]?(?P\d+))|" "(REP\s+(?P\d+))|" ".") @@ -211,11 +211,11 @@ def fixfile(inpath, input_lines, outfile): 'ROS\n' '\n' '[ROS Home]') - if basename <> 'rep-0000.txt': + if basename <> 'rep-0000.rst': print >> outfile, '[REP Index]' if rep: try: - print >> outfile, ('[REP Source' + print >> outfile, ('[REP Source' ']' % int(rep)) except ValueError, error: print >> sys.stderr, ('ValueError (invalid REP number): %s' @@ -258,7 +258,7 @@ def fixfile(inpath, input_lines, outfile): date = v or time.strftime('%d-%b-%Y', time.localtime(os.stat(inpath)[8])) try: - url = REPSVNURL % int(rep) + url = REPGITURL % int(rep) v = '%s ' % (url, cgi.escape(date)) except ValueError, error: v = date @@ -289,7 +289,7 @@ def fixfile(inpath, input_lines, outfile): continue else: # REP 0 has some special treatment - if basename == 'rep-0000.txt': + if basename == 'rep-0000.rst': parts = line.split() if len(parts) > 1 and re.match(r'\s*\d{1,4}', parts[1]): # This is a REP summary line, which we need to hyperlink @@ -377,11 +377,11 @@ def get_input_lines(inpath): return lines def find_rep(rep_str): - """Find the .txt file indicated by a cmd line argument""" + """Find the .rst file indicated by a cmd line argument""" if os.path.exists(rep_str): return rep_str num = int(rep_str) - return "rep-%04d.txt" % num + return "rep-%04d.rst" % num def make_html(inpath, verbose=0): input_lines = get_input_lines(inpath) @@ -410,7 +410,7 @@ def make_html(inpath, verbose=0): os.chmod(outfile.name, 0664) return outpath -def push_rep(htmlfiles, txtfiles, username, verbose, local=0): +def push_rep(htmlfiles, rstfiles, username, verbose, local=0): quiet = "" if local: if verbose: @@ -427,7 +427,7 @@ def push_rep(htmlfiles, txtfiles, username, verbose, local=0): copy_cmd = "scp" chmod_cmd = "ssh %s%s chmod" % (username, HOST) files = htmlfiles[:] - files.extend(txtfiles) + files.extend(rstfiles) files.append("style.css") files.append("rep.css") filelist = SPACE.join(files) @@ -478,7 +478,7 @@ def rep_type_error(inpath, rep_type): def browse_file(rep): import webbrowser file = find_rep(rep) - if file.endswith(".txt"): + if file.endswith(".rst"): file = file[:-3] + "html" file = os.path.abspath(file) url = "file:" + file @@ -487,7 +487,7 @@ def browse_file(rep): def browse_remote(rep): import webbrowser file = find_rep(rep) - if file.endswith(".txt"): + if file.endswith(".rst"): file = file[:-3] + "html" url = REPDIRRUL + file webbrowser.open(url) @@ -528,11 +528,11 @@ def main(argv=None): browse = 1 if args: - reptxt = [] + reprst = [] html = [] for rep in args: file = find_rep(rep) - reptxt.append(file) + reprst.append(file) newfile = make_html(file, verbose=verbose) if newfile: html.append(newfile) @@ -540,12 +540,12 @@ def main(argv=None): browse_file(rep) else: # do them all - reptxt = [] + reprst = [] html = [] - files = glob.glob("rep-*.txt") + files = glob.glob("rep-*.rst") files.sort() for file in files: - reptxt.append(file) + reprst.append(file) newfile = make_html(file, verbose=verbose) if newfile: html.append(newfile) @@ -553,7 +553,7 @@ def main(argv=None): browse_file("0") if update: - push_rep(html, reptxt, username, verbose, local=local) + push_rep(html, reprst, username, verbose, local=local) if browse: if args: for rep in args: diff --git a/rep2pyramid.py b/rep2pyramid.py deleted file mode 100755 index c10f13e4c..000000000 --- a/rep2pyramid.py +++ /dev/null @@ -1,533 +0,0 @@ -#!/usr/bin/env python -""" -Convert REPs to (X)HTML fragments for Pyramid - courtesy of /F - -Usage: %(PROGRAM)s [options] [ ...] - -Options: - --d , --destdir - Specify the base destination directory for Pyramid files. - Default: %(SERVER_DEST_DIR_BASE)s - --f, --force - Force the rebuilding of output files, regardless of modification times. - --k, --keep-going - Continue building past errors if possible. - --q, --quiet - Turn off verbose messages. - --h, --help - Print this help message and exit. - -The optional arguments ``reps`` are either rep numbers or .txt files. -""" - -import sys -import os -import codecs -import re -import cgi -import glob -import getopt -import errno -import random -import time -import shutil - -REQUIRES = {'python': '2.2', - 'docutils': '0.5'} -PROGRAM = sys.argv[0] -SERVER_DEST_DIR_BASE = ( - '/var/www/www.ros.org/html/reps') -RFCURL = 'http://www.faqs.org/rfcs/rfc%d.html' -REPSVNURL = 'http://code.ros.org/svn/rep/trunk/rep-%04d.txt' -REPDIRURL = '/reps/' -REPURL = REPDIRURL + 'rep-%04d' -REPANCHOR = '%i' - -LOCALVARS = "Local Variables:" - -COMMENT = """""" - -# The generated HTML doesn't validate -- you cannot use
and

inside -#
 tags.  But if I change that, the result doesn't look very nice...
-
-fixpat = re.compile("((https?|ftp):[-_a-zA-Z0-9/.+~:?#$=&,]+)|(rep-\d+(.txt)?)|"
-                    "(RFC[- ]?(?P\d+))|"
-                    "(REP\s+(?P\d+))|"
-                    ".")
-
-CONTENT_HTML = """\
-
-
' - print >> outfile, '

%s

' % line.strip() - need_pre = 1 - elif not line.strip() and need_pre: - continue - else: - # REP 0 has some special treatment - if basename == 'rep-0000.txt': - parts = line.split() - if len(parts) > 1 and re.match(r'\s*\d{1,4}', parts[1]): - # This is a REP summary line, which we need to hyperlink - url = REPURL % int(parts[1]) - if need_pre: - print >> outfile, '
'
-                        need_pre = 0
-                    print >> outfile, re.sub(
-                        parts[1],
-                        '%s' % (int(parts[1]),
-                            parts[1]), line, 1),
-                    continue
-                elif parts and '@' in parts[-1]:
-                    # This is a rep email address line, so filter it.
-                    url = fixemail(parts[-1], rep)
-                    if need_pre:
-                        print >> outfile, '
'
-                        need_pre = 0
-                    print >> outfile, re.sub(
-                        parts[-1], url, line, 1),
-                    continue
-            line = fixpat.sub(lambda x, c=inpath: fixanchor(c, x), line)
-            if need_pre:
-                print >> outfile, '
'
-                need_pre = 0
-            outfile.write(line)
-    if not need_pre:
-        print >> outfile, '
' - return title - -docutils_settings = None -"""Runtime settings object used by Docutils. Can be set by the client -application when this module is imported.""" - -def fix_rst_rep(inpath, input_lines, outfile): - from docutils import core - parts = core.publish_parts( - source=''.join(input_lines), - source_path=inpath, - destination_path=outfile.name, - reader_name='rep', - parser_name='restructuredtext', - writer_name='rep_html', - settings=docutils_settings, - # Allow Docutils traceback if there's an exception: - settings_overrides={'traceback': 1}) - outfile.write(parts['whole']) - title = 'REP %s -- %s' % (parts['repnum'], parts['title'][0]) - return title - -def get_rep_type(input_lines): - """ - Return the Content-Type of the input. "text/plain" is the default. - Return ``None`` if the input is not a REP. - """ - rep_type = None - for line in input_lines: - line = line.rstrip().lower() - if not line: - # End of the RFC 2822 header (first blank line). - break - elif line.startswith('content-type: '): - rep_type = line.split()[1] or 'text/plain' - break - elif line.startswith('rep: '): - # Default REP type, used if no explicit content-type specified: - rep_type = 'text/plain' - return rep_type - -def get_input_lines(inpath): - try: - infile = codecs.open(inpath, 'r', 'utf-8') - except IOError, e: - if e.errno <> errno.ENOENT: raise - print >> sys.stderr, 'Error: Skipping missing REP file:', e.filename - sys.stderr.flush() - return None, None - lines = infile.read().splitlines(1) # handles x-platform line endings - infile.close() - return lines - -def find_rep(rep_str): - """Find the .txt file indicated by a cmd line argument""" - if os.path.exists(rep_str): - return rep_str - num = int(rep_str) - return "rep-%04d.txt" % num - -def make_html(inpath): - input_lines = get_input_lines(inpath) - rep_type = get_rep_type(input_lines) - if rep_type is None: - print >> sys.stderr, 'Error: Input file %s is not a REP.' % inpath - sys.stdout.flush() - return None - elif not REP_TYPE_DISPATCH.has_key(rep_type): - print >> sys.stderr, ('Error: Unknown REP type for input file %s: %s' - % (inpath, rep_type)) - sys.stdout.flush() - return None - elif REP_TYPE_DISPATCH[rep_type] == None: - rep_type_error(inpath, rep_type) - return None - destDir, needSvn, repnum = set_up_pyramid(inpath) - outpath = os.path.join(destDir, 'body.html') - if ( not settings.force_rebuild - and (os.path.exists(outpath) - and os.stat(inpath).st_mtime <= os.stat(outpath).st_mtime)): - if settings.verbose: - print "Skipping %s (outfile up to date)"%(inpath) - return - if settings.verbose: - print inpath, "(%s)" % rep_type, "->", outpath - sys.stdout.flush() - outfile = codecs.open(outpath, "w", "utf-8") - title = REP_TYPE_DISPATCH[rep_type](inpath, input_lines, outfile) - outfile.close() - os.chmod(outfile.name, 0664) - write_pyramid_index(destDir, title) - # for REP 0, copy body to parent directory as well - if repnum == '0000': - shutil.copyfile(outpath, os.path.join(destDir, '..', 'body.html')) - copy_aux_files(inpath, destDir) - return outpath - -def set_up_pyramid(inpath): - m = re.search(r'rep-(\d+)\.', inpath) - if not m: - print >>sys.stderr, "Can't find REP number in file name." - sys.exit(1) - repnum = m.group(1) - destDir = os.path.join(settings.dest_dir_base, 'rep-%s' % repnum) - - needSvn = 0 - if not os.path.exists(destDir): - needSvn = 1 - os.makedirs(destDir) - - # write content.html - foofilename = os.path.join(destDir, 'content.html') - fp = codecs.open(foofilename, 'w', 'utf-8') - fp.write(CONTENT_HTML) - fp.close() - os.chmod(foofilename, 0664) - - # write content.yml - foofilename = os.path.join(destDir, 'content.yml') - fp = codecs.open(foofilename, 'w', 'utf-8') - fp.write(CONTENT_YML) - os.chmod(foofilename, 0664) - return destDir, needSvn, repnum - -def write_pyramid_index(destDir, title): - filename = os.path.join(destDir, 'index.yml') - fp = codecs.open(filename, 'w', 'utf-8') - title = title.replace('\\', '\\\\') # Escape existing backslashes - fp.write(INDEX_YML % title.replace('"', '\\"')) - fp.close() - os.chmod(filename, 0664) - -def copy_aux_files(rep_path, dest_dir): - """ - Copy auxiliary files whose names match 'rep-XXXX-*.*'. - """ - dirname, repname = os.path.split(rep_path) - base, ext = os.path.splitext(repname) - files = glob.glob(os.path.join(dirname, base) + '-*.*') - for path in files: - filename = os.path.basename(path) - dest_path = os.path.join(dest_dir, filename) - print '%s -> %s' % (path, dest_path) - shutil.copy(path, dest_path) - - -REP_TYPE_DISPATCH = {'text/plain': fixfile, - 'text/x-rst': fix_rst_rep} -REP_TYPE_MESSAGES = {} - -def check_requirements(): - # Check Python: - try: - from email.Utils import parseaddr - except ImportError: - REP_TYPE_DISPATCH['text/plain'] = None - REP_TYPE_MESSAGES['text/plain'] = ( - 'Python %s or better required for "%%(rep_type)s" REP ' - 'processing; %s present (%%(inpath)s).' - % (REQUIRES['python'], sys.version.split()[0])) - # Check Docutils: - try: - import docutils - except ImportError: - REP_TYPE_DISPATCH['text/x-rst'] = None - REP_TYPE_MESSAGES['text/x-rst'] = ( - 'Docutils not present for "%(rep_type)s" REP file %(inpath)s. ' - 'See README.txt for installation.') - else: - installed = [int(part) for part in docutils.__version__.split('.')] - required = [int(part) for part in REQUIRES['docutils'].split('.')] - if installed < required: - REP_TYPE_DISPATCH['text/x-rst'] = None - REP_TYPE_MESSAGES['text/x-rst'] = ( - 'Docutils must be reinstalled for "%%(rep_type)s" REP ' - 'processing (%%(inpath)s). Version %s or better required; ' - '%s present. See README.txt for installation.' - % (REQUIRES['docutils'], docutils.__version__)) - -def rep_type_error(inpath, rep_type): - print >> sys.stderr, 'Error: ' + REP_TYPE_MESSAGES[rep_type] % locals() - sys.stdout.flush() - -def build_reps(args=None): - if args: - filenames = rep_filename_generator(args) - else: - # do them all - filenames = glob.glob("rep-*.txt") - filenames.sort() - for filename in filenames: - try: - make_html(filename) - except (KeyboardInterrupt, SystemExit): - raise - except: - print "While building REPs: %s" % filename - if settings.keep_going: - ee, ev, et = sys.exc_info() - traceback.print_exception(ee, ev, et, file=sys.stdout) - print "--keep-going/-k specified, continuing" - continue - else: - raise - -def rep_filename_generator(args): - for rep in args: - filename = find_rep(rep) - yield filename - -def main(argv=None): - check_requirements() - - if argv is None: - argv = sys.argv[1:] - - try: - opts, args = getopt.getopt( - argv, 'hd:fkq', - ['help', 'destdir=', 'force', 'keep-going', 'quiet']) - except getopt.error, msg: - usage(1, msg) - - for opt, arg in opts: - if opt in ('-h', '--help'): - usage(0) - elif opt in ('-d', '--destdir'): - settings.dest_dir_base = arg - elif opt in ('-f', '--force'): - settings.force_rebuild = True - elif opt in ('-k', '--keep-going'): - settings.force_rebuild = True - elif opt in ('-q', '--quiet'): - settings.verbose = False - - build_reps(args) - - -if __name__ == "__main__": - main() diff --git a/rep2rss.py b/rep2rss.py deleted file mode 100755 index 3db86709b..000000000 --- a/rep2rss.py +++ /dev/null @@ -1,69 +0,0 @@ -#!/usr/bin/env python - -import os, glob, time, datetime, stat, re, sys -import codecs -import PyRSS2Gen as rssgen - -RSS_PATH = os.path.join(sys.argv[1], 'reps.rss') - -def firstline_startingwith(full_path, text): - for line in codecs.open(full_path, encoding="utf-8"): - if line.startswith(text): - return line[len(text):].strip() - return None - -# get list of reps with creation time (from "Created:" string in rep .txt) -reps = glob.glob('rep-*.txt') -def rep_creation_dt(full_path): - created_str = firstline_startingwith(full_path, 'Created:') - # bleh, I was hoping to avoid re but some Reps editorialize - # on the Created line - m = re.search(r'''(\d+-\w+-\d{4})''', created_str) - if not m: - # some older ones have an empty line, that's okay, if it's old - # we ipso facto don't care about it. - # "return None" would make the most sense but datetime objects - # refuse to compare with that. :-| - return datetime.datetime(*time.localtime(0)[:6]) - created_str = m.group(1) - try: - t = time.strptime(created_str, '%d-%b-%Y') - except ValueError: - t = time.strptime(created_str, '%d-%B-%Y') - return datetime.datetime(*t[:6]) -reps_with_dt = [(rep_creation_dt(full_path), full_path) for full_path in reps] -# sort reps by date, newest first -reps_with_dt.sort(reverse=True) - -# generate rss items for 10 most recent reps -items = [] -for dt, full_path in reps_with_dt[:10]: - try: - n = int(full_path.split('-')[-1].split('.')[0]) - except ValueError: - pass - title = firstline_startingwith(full_path, 'Title:') - author = firstline_startingwith(full_path, 'Author:') - url = 'http://ros.org/reps/rep-%0.4d' % n - item = rssgen.RSSItem( - title = 'REP %d: %s' % (n, title), - link = url, - description = 'Author: %s' % author, - guid = rssgen.Guid(url), - pubDate = dt) - items.append(item) - -# the rss envelope -desc = """ -Newest ROS Enhancement Proposals (REPs) - Information on new -language features, and some meta-information like release -procedure and schedules -""".strip() -rss = rssgen.RSS2( - title = 'Newest ROS Reps', - link = 'http://ros.org/reps', - description = desc, - lastBuildDate = datetime.datetime.now(), - items = items) - -file(RSS_PATH, 'w').write(rss.to_xml())