[xiph-cvs] r6796 - in websites-ngen: . news news/2004 news/2004/04 news/2004/04/21 news/2004/05 news/2004/05/12 news/2004/05/29 xiph.org xiph.org/speex xiph.org/speex/Error xiph.org/speex/Error/404 xiph.org/vorbis
comatoast at xiph.org
comatoast at xiph.org
Tue Jun 1 10:33:40 PDT 2004
Author: comatoast
Date: 2004-06-01 13:32:59 -0400 (Tue, 01 Jun 2004)
New Revision: 6796
Added:
websites-ngen/news/2004/
websites-ngen/news/2004/04/
websites-ngen/news/2004/04/21/
websites-ngen/news/2004/04/21/speex115.markdown
websites-ngen/news/2004/05/
websites-ngen/news/2004/05/12/
websites-ngen/news/2004/05/12/icecast201Released.markdown
websites-ngen/news/2004/05/29/
websites-ngen/news/2004/05/29/postfish.markdown
websites-ngen/time.py
websites-ngen/xiph.org/speex/.htaccess
websites-ngen/xiph.org/speex/Error/
websites-ngen/xiph.org/speex/Error/404/
websites-ngen/xiph.org/speex/Error/404/index.markdown
websites-ngen/xiph.org/vorbis/.htaccess
Removed:
websites-ngen/news/on2004-04-19at0149.txt
websites-ngen/news/on2004-04-21at0000.txt
Modified:
websites-ngen/
websites-ngen/news/options.ini
websites-ngen/style.txt
websites-ngen/todo.txt
websites-ngen/wrapup.py
websites-ngen/xiph.org/
websites-ngen/xiph.org/aftermaintext.inherit
websites-ngen/xiph.org/index.markdown
Log:
* News stuff implemented. Not completely, but we seem to have real archives and permalinks.
* time.py added, because most normal humans don't know what time it is in Greenwich.
* /postfish/ stubbed out.
* style.txt updates.
* Custom ErrorDocuments for /vorbis/ and /speex/.
<p><p>Property changes on: websites-ngen
___________________________________________________________________
Name: svn:ignore
- *index.html
commit.txt
+ *index.html
commit.txt
tags
<p>Copied: websites-ngen/news/2004/04/21/speex115.markdown (from rev 6779, websites-ngen/news/on2004-04-21at0000.txt)
Added: websites-ngen/news/2004/05/12/icecast201Released.markdown
===================================================================
--- websites-ngen/news/2004/05/12/icecast201Released.markdown 2004-05-30 13:56:29 UTC (rev 6795)
+++ websites-ngen/news/2004/05/12/icecast201Released.markdown 2004-06-01 17:32:59 UTC (rev 6796)
@@ -0,0 +1,3 @@
+This patch release fixes a overflow buffer which can cause server crashes under certain circumstances. This release contains **only** the fix for this issue. We are still targeting a 2.1.0 release with new features and functionality in the near future.
+
+Download Icecast 2.0.1 from the [Download page](http://www.xiph.org/icecast/download/).
Added: websites-ngen/news/2004/05/29/postfish.markdown
===================================================================
--- websites-ngen/news/2004/05/29/postfish.markdown 2004-05-30 13:56:29 UTC (rev 6795)
+++ websites-ngen/news/2004/05/29/postfish.markdown 2004-06-01 17:32:59 UTC (rev 6796)
@@ -0,0 +1,5 @@
+Monty put together a prerelease of [Postfish][] so he could get back to work on [OggFile][].
+
+ [postfish]: http://www.xiph.org/postfish/
+ [oggfile]: http://www.xiph.org/oggfile/
+
Deleted: websites-ngen/news/on2004-04-19at0149.txt
===================================================================
--- websites-ngen/news/on2004-04-19at0149.txt 2004-05-30 13:56:29 UTC (rev 6795)
+++ websites-ngen/news/on2004-04-19at0149.txt 2004-06-01 17:32:59 UTC (rev 6796)
@@ -1,3 +0,0 @@
-This is a news post. With a [link to our new website][l].
-
- [l]: http://www.xiph.org/
Deleted: websites-ngen/news/on2004-04-21at0000.txt
===================================================================
--- websites-ngen/news/on2004-04-21at0000.txt 2004-05-30 13:56:29 UTC (rev 6795)
+++ websites-ngen/news/on2004-04-21at0000.txt 2004-06-01 17:32:59 UTC (rev 6796)
@@ -1,6 +0,0 @@
-The main change in this release is that the 1.1.5
-<abbr title='application programming interface'>API</abbr> and
-<abbr title='application binary interface'>ABI</abbr> are now compatible with Speex
-1.0.<var>x</var>.
-The versions of the functions taking a `short*` now have an â_intâ suffix, as in
-`speex_encode_int()`.
Modified: websites-ngen/news/options.ini
===================================================================
--- websites-ngen/news/options.ini 2004-05-30 13:56:29 UTC (rev 6795)
+++ websites-ngen/news/options.ini 2004-06-01 17:32:59 UTC (rev 6796)
@@ -1,30 +1,23 @@
;[Template]
;; One or more of the following in a space-separated list:
-;; general
-;; vorbis
-;; flac
-;; theora
-;; icecast
+;; general vorbis flac theora icecast postfish
+;; security (for security-critical updates)
-; required:
-; Title
-; Tag Suffix
-;
-;
+[2004-05-29:postfish]
+title = Postfish Prerelease
+sections = postfish
+summary = Monty makes a prerelease version of Postfish, a digital audio post-processing, restoration, filtering, and mixdown tool.
+created = 2004-05-29T10:43:01Z
-[on2004-04-21at0000]
-Title = Speex 1.1.5 Released
-Tag Suffix = Speex115
-Sections = speex
-Issued = 2004-05-21T04:09:33Z
-; Modified = (optional)
-Summary = The 1.1.x branch of Speex now has a 1.0.x-compatible API and ABI.
+[2004-05-12:icecast201Released]
+title = Icecast 2.0.1 Released
+sections = icecast
+summary = This update fixes a remote crash bug.
+created = 2004-05-12T01:04:00Z
-[on2004-04-19at0149]
-Title = Vorbis-Tools Released (fake post)
-Tag Suffix = VorbisToolsReleased
-Sections = vorbis flac
-Summary = A new version of vorbis-tools was released; oggenc now has a FLAC input.
-
-
+[2004-04-21:speex115]
+title = Speex 1.1.5 Released
+sections = speex
+created = 2004-04-21T04:09:33Z
+summary = The 1.1.x branch of Speex now has a 1.0.x-compatible API and ABI.
Modified: websites-ngen/style.txt
===================================================================
--- websites-ngen/style.txt 2004-05-30 13:56:29 UTC (rev 6795)
+++ websites-ngen/style.txt 2004-06-01 17:32:59 UTC (rev 6796)
@@ -30,9 +30,9 @@
* Prefer ## to -------- for second-level headings, unlike in this file and in todo.txt.
-* Directories generally not shown to users should start with a capital letter.
- Prime examples of this are /CSS/, /Error/, and /JS/. However, their subdirectories
- should start with lowercase letters, like /CSS/sidebars/.
+* Directories generally not shown to users should start with a capital letter, such as
+ /CSS/, /Error/, and /JS/. However, their subdirectories should start with lowercase letters,
+ like /CSS/sidebars/.
* Donât have multiple files or directories that differ only by case; this will cause problems
on case-insensitive file systems like NTFS and HFS+.
@@ -45,7 +45,10 @@
elsewhere in the page. To avoid getting caught by this snag, use lower case consistently
in the part with the actual URL in it (and the optional title attribute).
+* Keep as much as possible in the top-level .htaccess file. As far as I can tell, the
+ ErrorDocument directive is the only thing that needs to go in sudirectoriesâ .htaccess files.
+
Spelling, Grammar, Punctuation, and Terminology
-----------------------------------------------
@@ -78,8 +81,14 @@
For more information, see the Apache 2 information at
<http://httpd.apache.org/docs-2.0/mod/mod_alias.html#redirect>.
-* Redirect to <http://www.xiph.org/>, not <http://xiph.org/>.
+* Always refer to <http://www.xiph.org/>, not <http://xiph.org/>.
+* Avoid full URLs with the "http://www.xiph.org/" part in it as they wonât link to development
+ versions of the site when run on development machines.
+
+* Always use full URLs in news posts as the snippet of HTML could be displayed
+ anywhere from /news/ to /vorbis/news/ to some userâs news aggregator application.
+
* Do not abbreviate directory names. For example, make URLs so they look like
â/vorbis/documentation/â, not â/vorbis/doc/â, with the exception of â/faq/â.
Added: websites-ngen/time.py
===================================================================
--- websites-ngen/time.py 2004-05-30 13:56:29 UTC (rev 6795)
+++ websites-ngen/time.py 2004-06-01 17:32:59 UTC (rev 6796)
@@ -0,0 +1,6 @@
+import time
+import datetime
+
+USUAL_TIME_FORMAT = "%Y-%m-%dT%H:%M:%SZ"
+dt = datetime.datetime.utcnow()
+print "It is currently %s in W3C Date-Time-ese. Have a nice day." % dt.strftime(USUAL_TIME_FORMAT)
Modified: websites-ngen/todo.txt
===================================================================
--- websites-ngen/todo.txt 2004-05-30 13:56:29 UTC (rev 6795)
+++ websites-ngen/todo.txt 2004-06-01 17:32:59 UTC (rev 6796)
@@ -27,6 +27,7 @@
* I got one vote by j^ in #vorbis that the colors for the captioned buttons were too dark.
+
Open Questions
--------------
Modified: websites-ngen/wrapup.py
===================================================================
--- websites-ngen/wrapup.py 2004-05-30 13:56:29 UTC (rev 6795)
+++ websites-ngen/wrapup.py 2004-06-01 17:32:59 UTC (rev 6796)
@@ -24,19 +24,17 @@
import pdb
from ConfigParser import SafeConfigParser
from sets import Set
+import profile
MARKDOWN_COMMAND = "perl Markdown.pl --htmltags"
TITLE_REGEX = re.compile(r"<h1.*>(.*)</h1>")
LANGUAGE_EXTRACTOR = re.compile(r"^.*\.(.{2,5})\..*$") # anything from â.es.â to â.zh-TW.â
+USUAL_TIME_FORMAT = "%Y-%m-%dT%H:%M:%SZ" # W3C Date-Time format, so I'm told
-class MissingOptionError(Exception):
- def __init__(self, option, section):
- self.option = option
- self.section = section
+####################################################################################################
+## Markdown Stuff
+##
- def __str__(self):
- return "Must define a '%s' in section %s" % (self.option, self.section)
-
class MarkdownWrapper(object):
"""
Important attributes:
@@ -82,8 +80,8 @@
self.destFilename = destFilename
else:
self.destFilename = os.path.splitext(sourceFilename)[0] + ".html"
- self.doctype = '<!DOCTYPE HTML PUBLIC ' + \
- '"-//W3C//DTD HTML 4.01//EN" ' + \
+ self.doctype = '<!DOCTYPE HTML PUBLIC ' \
+ '"-//W3C//DTD HTML 4.01//EN" ' \
'"http://www.w3.org/TR/html4/strict.dtd">'
self.mainText = markdown(sourceFilename)
@@ -123,15 +121,6 @@
def __loadOptions(self):
- def getBaseName(path):
- """
- 'index.html' -> 'index'
- 'index.es.markdown' -> 'index.es'
- '/foo/bar/baz.es.txt' -> 'baz.es'
- """
- filename = os.path.split(path)[1]
- filenameWithoutExtension = os.path.splitext(filename)[0]
- return filenameWithoutExtension
configFilename = getParallelFile(self.sourceFilename, 'options.ini')
if not os.path.isfile(configFilename):
@@ -259,93 +248,10 @@
ret += "</html>\n"
return ret
+###################################################################################################
+## News Item stuff
+##
-def markdown(filename):
- """Returns an HTML snippet from a filename in Markdown format."""
- ret = ""
- fh = os.popen(MARKDOWN_COMMAND + ' ' + filename)
- try:
- ret = fh.read()
- finally:
- fh.close()
-
- return snipBom(ret)
-
-def snipBom(s):
- BOM = '\xef\xbb\xbf'
- ret = ''
- bomBegin = s.find(BOM)
- if bomBegin > -1:
- ret = s[:bomBegin] + s[bomBegin+3:]
- else:
- return s
- return ret
-
-
-def getParallelFile(where, what):
- """
- given f("/home/foo.txt", "bar.html"), returns "/home/bar.html".
- """
- return os.path.join(os.path.split(where)[0], what)
-
-def hasTwoDirseps(path):
- firstIndex = path.find(os.sep)
- if firstIndex == -1: return False
-
- secondIndex = path.find(os.sep, firstIndex+1)
- if secondIndex == -1: return False
-
- return True
-
-def getParentedFile(filename):
- r"""
- given a path to a file, say, /meals/breakfast/sausage/index.html, tries to return
- the first valid file of:
- /meals/breakfast/sausage/index.html
- /meals/breakfast/index.html
- /meals/index.html
- /index.html
- Or given .\meals\breakfast\eggs\index.html:
- .\meals\breakfast\eggs\index.html
- .\meals\breakfast\index.html
- .\meals\index.html
- .\index.html
- Or even given cheeses\france\brie.html:
- cheeses\france\brie.html
- cheeses\brie.html
- brie.html
-
- Returns "" if no such file is found.
- """
- while True:
- # okay, we need to abort out on two conditions:
- # 1) we found a valid path (return it)
- # 2) we've gone as far as we can, and there is no valid path (return "")
- if os.path.isfile(filename): return filename
-
- # There is no parented file if there's only one separator in the path
- if filename.find(os.sep) == -1:
- return ""
-
- # if the full string has two directory separators in it or more, then
- # there are still intermediate directories to back up through.
- # We need to chop out the thing just before the last dirsep,
- # but end just before the penultimate dirsep.
- if hasTwoDirseps(filename):
- indexOfLastDirsep = filename.rfind(os.sep)
- indexOfPenultimateDirsep = filename.rfind(os.sep, 0, indexOfLastDirsep)
- filename = filename[:indexOfPenultimateDirsep] + filename[indexOfLastDirsep:]
- if os.path.isfile(filename): return filename
- elif filename.find(os.sep) > -1:
- # If it has only one dirsep, then it's one of the following forms (modulo / vs. \)
- # * /foo.html
- # * ./foo.html
- if os.path.isfile(filename): return filename
- else: return ""
- else:
- if os.path.isfile(filename): return filename
- else: return ""
-
class NewsItem(object):
def __init__(self):
self.post = ''
@@ -356,30 +262,36 @@
self.dateIssued = None
self.dateModified = None
self.sections = Set()
+ self.url = ''
- def __cmp__(self, other):
- return cmp(self.dateCreated, other.dateCreated)
+ def __str__(self):
+ return '<NewsItem object created at %s entitled "%s">' % \
+ (strftime(USUAL_TIME_FORMAT, self.dateCreated), self.title)
+ def __repr__(self):
+ return str(self)
+ def __getTagSuffix(self):
+ return self.tag.split(':')[-1]
+ tagSuffix = property(__getTagSuffix)
+ def __cmp__(self, other): return NewsItem.compareByDateCreated(self, other)
+ def compareByDateCreated(self, other): return cmp(self.dateCreated, other.dateCreated)
+ def compareByDateIssued(self, other): return cmp(self.dateIssued, other.dateIssued)
+ def compareByDateModified(self, other): return cmp(self.dateModified, other.dateModified)
-def reverser(lhs, rhs): # primarily to sort NewsItems newest-first
- return -cmp(lhs, rhs)
-
+def reverser(lhs, rhs, comparator=cmp): # primarily to sort NewsItems newest-first
+ return -comparator(lhs, rhs)
class NewsDispenser(object):
def __init__(self, optionsFile):
- """Make a very simple list of news posts. This is not final code."""
config = SafeConfigParser({'sections': 'general'})
config.read(os.path.join("news", "options.ini"))
- FILENAME_DATE_FORMAT = "on%Y-%m-%dat%H%M"
- USUAL_TIME_FORMAT = "%Y-%m-%dT%H:%M:%SZ"
self.newsItems = []
# strftime: format as string; strptime: parse string and get a struct_time
# okay, now we want to go through the sections and associate each with their newspost.
for section in config.sections(): # section is string
ni = NewsItem()
- ni.dateCreated = time.strptime(section, FILENAME_DATE_FORMAT)
- #ni.dateModified = ni.dateIssued = ni.dateCreated #XXX
+ ni.tag = 'tag:xiph.org,' + section
for key, value in config.items(section):
if key == 'title':
ni.title = value
@@ -394,6 +306,9 @@
if key == 'sections':
ni.sections = Set(value.split())
+ if key == 'created':
+ ni.dateCreated = time.strptime(value, USUAL_TIME_FORMAT)
+
if key == 'issued':
ni.dateIssued = time.strptime(value, USUAL_TIME_FORMAT)
@@ -404,100 +319,332 @@
# now for some error checkingâ¦
if not ni.title: raise MissingOptionError('Title', section)
if not ni.summary: raise MissingOptionError('Summary', section)
+ if len(ni.sections) == 0:
+ raise MissingOptionError('Sections', section)
-
- if not ni.tag: raise MissingOptionError('Tag Suffix', section)
-
# â¦and some error coveringâ¦
+ # "date created" absolutely must be there. Everything else can be generated from that.
+ if not ni.dateCreated:
+ raise MissingOptionError('Created', section)
if not ni.dateModified:
ni.dateModified = ni.dateCreated
if not ni.dateIssued:
ni.dateIssued = ni.dateCreated
- filename = os.path.join('news', section + '.txt')
+
+ # sections look like [2004-04-21:speex115]
+ tagBits = re.compile(
+ r"^(?P<year>\d\d\d\d)-(?P<month>\d\d)-(?P<day>\d\d):(?P<tag>\w*)$")
+ m = tagBits.match(section)
+ if not m:
+ raise "the tag bits regex didn't match"
+
+ # make sure the two required dates match
+ ymdFromDateCreated = list(ni.dateCreated[:3])
+ ymdFromRegex = [int(m.group('year')), int(m.group('month')), int(m.group('day'))]
+ if ymdFromDateCreated != ymdFromRegex:
+ raise "The date in section %s does not match its Created key %s, " \
+ "when was it _really_ created? " % \
+ (section, "%s-%s-%s" % ni.dateCreated[:3])
+
+ ni.url = "http://www.xiph.org/news/%s/%s/%s/%s/" % (
+ m.group('year'),
+ m.group('month'),
+ m.group('day'),
+ m.group('tag'))
+
+ filename = os.path.join('news',
+ m.group('year'),
+ m.group('month'),
+ m.group('day'),
+ m.group('tag') + '.markdown')
s = markdown(filename)
ni.post = s
self.newsItems.append(ni)
self.newsItems.sort(reverser)
- def dump(self):
- return self.newsItems[:]
+ def items(self):
+ return self.newsItems
- def getItems(startDate, endDate):
+ def __itemsByTimespan(self, unitCode):
"""
- Return news items from
+ unitCode == 1? By year.
+ unitCode == 2? By month.
+ unitCode == 3? By day.
"""
+ allDates = [] # list of `unitCode`-tuples in (year[, month[, day]]) format
+ ret = []
+ for date in [item.dateCreated[:unitCode] for item in self.newsItems]:
+ if date not in allDates:
+ allDates.append(date)
+
+ for date in allDates:
+ itemsOfTheTimespan = [item for item in self.newsItems \
+ if item.dateCreated[:unitCode] == date]
+ ret.append(itemsOfTheTimespan)
+ return ret
+ def itemsByDay(self):
+ "Returns a list of lists of items all with the same day."
+ return self.__itemsByTimespan(3)
+
+ def itemsByMonth(self):
+ return self.__itemsByTimespan(2)
+
+ def itemsByYear(self):
+ return self.__itemsByTimespan(1)
+
+
+
+
+###################################################################################################
+## News Formatters
+##
+
class NewsFormatter(object):
- def __init__(self, newsItems): pass
+ def __init__(self, dispenser):
+ self.dispenser = dispenser
+
+ def format(self, numberOfItems=0):
+ """
+ Returns all news items as a formatted string.
+ Override this.
+ """
+ def formatByIndex(self, index): pass
def formatOne(self, newsItem): pass
- def formatAll(self): pass
class HTMLNewsFormatter(NewsFormatter):
""" This is just one HTML news formatter of possibly many, really."""
def __init__(self, newsItems, dateFormat="%A, %B %d, %Y"):
+ NewsFormatter.__init__(self, newsItems)
self.newsItems = newsItems
self.dateFormat = dateFormat
- def formatOne(self, newsItem):
- ret = "<h1>" + newsItem.title + "</h1>\n"
- ret += newsItem.post[:]
- ret += "<p>Posted %s by %s</p>" % \
- (time.strftime(self.dateFormat, newsItem.date), newsItem.author)
- ret += "\n<hr>\n\n"
+ def formatForDay(self, year, month, day):
+ "return a formatted string for the day in question."
+ loloni = self.dispenser.itemsByDay() # list of lists of NewsItems
+ ret = ''
+
+ matchingDayGroups = [x for x in loloni if x[0].dateCreated[:3] == (year, month, day)]
+ for dayGroup in matchingDayGroups:
+ ret += '<h1>News for %s</h1>\n' % strftime(self.dateFormat, dayGroup[0].dateIssued)
+ for item in dayGroup:
+ ret += self.formatOne(item, headingLevel=2)
return ret
- def formatAll(self):
+ def formatForMonth(self, year, month):
+ loloni = self.dispenser.itemsByMonth()
ret = ''
+
+ for monthGroup in [x for x in loloni if x[0].dateCreated[:2] == (year, month)]:
+ ret += strftime("<h1>News for %B %Y</h1>\n", monthGroup[0].dateIssued)
+ for item in monthGroup:
+ ret += self.formatOne(item, headingLevel=2)
+ return ret
+
+ def formatForYear(self, year):
+ loloni = self.dispenser.itemsByYear()
+ ret = ''
+ for yearGroup in [x for x in loloni if x[0].dateCreated[:1] == (year,)]:
+ ret += strftime("<h1>News for %Y</h1>\n", yearGroup[0].dateIssued)
+ for item in yearGroup:
+ ret += self.formatOne(item, headingLevel=2)
+ return ret
+
+
+ def formatOne(self, newsItem, headingLevel=1):
+ ret = "<div class='newsEntry'>\n"
+ ret += " <h%s>%s</h%s>\n" % (headingLevel, newsItem.title, headingLevel)
+ ret += newsItem.post[:]
+ ret += " <div class='postInfo'>Posted %s (<a href='%s'>permalink</a>)</div>\n" % \
+ (time.strftime(self.dateFormat, newsItem.dateIssued), newsItem.url)
+ ret += "</div>\n\n"
+
+ return ret
+
+ def format(self):
+ ret = ''
for ni in self.newsItems:
ret += self.formatOne(ni)
return ret
class AtomNewsFormatter(NewsFormatter):
-
- # Tag URIs: http://www.taguri.org/ (used for atom:id)
-
def __init__(self, newsItems):
- self.newsItems = newsItems
+ NewsFormatter.__init__(self, newsItems)
self.dateFormat = "%Y-%m-%dT%H:%M:%SZ" # lie and say it's at UTC (...Z)
- def formatOne(self, newsItem, index=0):
+ def formatOne(self, newsItem):
+ def formatDate(date):
+ return strftime(self.dateFormat, date)
+
ret = "<entry>\n"
- ret += "<title>" + newsItem.title + "</title>\n"
- if newsItem.dateCreated:
- ret += "<created>%s</created>\n" % strftime(self.dateFormat, newsItem.dateCreated)
- if newsItem.dateIssued:
- ret += "<issued>%s</issued>\n" % strftime(self.dateFormat, newsItem.dateIssued)
- if newsItem.dateModified:
- ret += "<modified>%s</modified>\n" % strftime(self.dateFormat, newsItem.dateModified)
- ret += "<id>%s</id>\n" % newsItem.tag
- ret += "<link rel='alternate' type='text/html' href='http://www.xiph.org/news/'/>\n"
- ret += "<content type='text/html' mode='escaped'><![CDATA["
- ret += newsItem.post
- ret += "]]></content>\n"
- ret += "</entry>"
+ ret += " <title>" + newsItem.title + "</title>\n"
+ ret += " <created>%s</created>\n" % formatDate(newsItem.dateCreated)
+ ret += " <issued>%s</issued>\n" % formatDate(newsItem.dateIssued)
+ ret += " <modified>%s</modified>\n" % formatDate(newsItem.dateModified)
+ ret += " <id>%s</id>\n" % newsItem.tag
+ ret += " <link rel='alternate' type='text/html' href='%s'/>\n" % newsItem.url
+ ret += " <content type='text/html' mode='escaped'><![CDATA["
+ ret += newsItem.post
+ ret += "]]></content>\n"
+ ret += "</entry>"
return ret
- def formatAll(self):
+
+ def format(self):
ret = ''
ret += "<?xml version='1.0' encoding='utf-8'?>\n" \
"<feed version='0.3' xmlns='http://purl.org/atom/ns#' xml:lang='en-US'>\n" \
"<title>Xiph.Org News</title>\n" \
"<link rel='alternate' type='text/html' href='http://www.xiph.org/news/'/>\n" \
"<modified>%s</modified>\n" % \
- strftime(self.dateFormat, self.newsItems[0].dateModified)
- ret += "<generator url='http://svn.xiph.org/websites-ngen/wrapup.py'>Wrapup</generator>\n" \
+ strftime(self.dateFormat, self.dispenser.items()[0].dateModified)
+ ret += "<generator url='http://svn.xiph.org/websites-ngen/wrapup.py'>" \
+ "Wrapup" \
+ "</generator>\n" \
"<copyright>© %s Xiph.Org Foundation</copyright>\n" % time.gmtime()[0] + \
"<author><name>Xiph.Org Foundation</name></author>\n\n"
- for index, newsItem in enumerate(self.newsItems):
- ret += self.formatOne(newsItem, index) + "\n\n"
+ for index, newsItem in enumerate(self.dispenser.items()):
+ ret += self.formatOne(newsItem) + "\n\n"
ret += "</feed>"
return ret
+###################################################################################################
+## Miscellaneous Functions and Exception Classes
+##
+
+def passPrint(x):
+ print x
+ return x
+
+class MissingOptionError(Exception):
+ def __init__(self, option, section):
+ self.option = option
+ self.section = section
+
+ def __str__(self):
+ return "Must define a '%s' in section %s" % (self.option, self.section)
+
+
+def markdown(filename):
+ """Returns an HTML snippet from a filename in Markdown format."""
+ ret = ""
+
+ if not os.path.isfile(filename):
+ raise RuntimeError("Can not markdown non-existent file " + filename)
+
+ fh = os.popen(MARKDOWN_COMMAND + ' ' + filename)
+ try:
+ ret = fh.read()
+ finally:
+ fh.close()
+
+ return snipBom(ret)
+
+
+def snipBom(s):
+ BOM = '\xef\xbb\xbf'
+ ret = ''
+ bomBegin = s.find(BOM)
+ if bomBegin > -1:
+ ret = s[:bomBegin] + s[bomBegin+3:]
+ else:
+ return s
+ return ret
+
+
+def hasTwoDirseps(path):
+ firstIndex = path.find(os.sep)
+ if firstIndex == -1: return False
+
+ secondIndex = path.find(os.sep, firstIndex+1)
+ if secondIndex == -1: return False
+
+ return True
+
+
+def getParallelFile(where, what):
+ """
+ given f("/home/foo.txt", "bar.html"), returns "/home/bar.html".
+ """
+ return os.path.join(os.path.split(where)[0], what)
+
+
+def getParentedFile(filename):
+ r"""
+ given a path to a file, say, /meals/breakfast/sausage/index.html, tries to return
+ the first valid file of:
+ /meals/breakfast/sausage/index.html
+ /meals/breakfast/index.html
+ /meals/index.html
+ /index.html
+ Or given .\meals\breakfast\eggs\index.html:
+ .\meals\breakfast\eggs\index.html
+ .\meals\breakfast\index.html
+ .\meals\index.html
+ .\index.html
+ Or even given cheeses\france\brie.html:
+ cheeses\france\brie.html
+ cheeses\brie.html
+ brie.html
+
+ Returns "" if no such file is found.
+ """
+ while True:
+ # okay, we need to abort out on two conditions:
+ # 1) we found a valid path (return it)
+ # 2) we've gone as far as we can, and there is no valid path (return "")
+ if os.path.isfile(filename): return filename
+
+ # There is no parented file if there's only one separator in the path
+ if filename.find(os.sep) == -1:
+ return ""
+
+ # if the full string has two directory separators in it or more, then
+ # there are still intermediate directories to back up through.
+ # We need to chop out the thing just before the last dirsep,
+ # but end just before the penultimate dirsep.
+ if hasTwoDirseps(filename):
+ indexOfLastDirsep = filename.rfind(os.sep)
+ indexOfPenultimateDirsep = filename.rfind(os.sep, 0, indexOfLastDirsep)
+ filename = filename[:indexOfPenultimateDirsep] + filename[indexOfLastDirsep:]
+ if os.path.isfile(filename): return filename
+ elif filename.find(os.sep) > -1:
+ # If it has only one dirsep, then it's one of the following forms (modulo / vs. \)
+ # * /foo.html
+ # * ./foo.html
+ if os.path.isfile(filename): return filename
+ else: return ""
+ else:
+ if os.path.isfile(filename): return filename
+ else: return ""
+
+
+def getBaseName(path):
+ """
+ 'index.html' -> 'index'
+ 'index.es.markdown' -> 'index.es'
+ '/foo/bar/baz.es.txt' -> 'baz.es'
+ """
+ filename = os.path.split(path)[1]
+ filenameWithoutExtension = os.path.splitext(filename)[0]
+ return filenameWithoutExtension
+
+def padto2(s):
+ if len(s) > 1:
+ return s
+ else:
+ return "0" + s
+
+
+###################################################################################################
+## Driver Functions
+##
+
def doSite():
for dirpath, dirnames, filenames in os.walk('xiph.org'):
- for filename in filter(lambda x: x.endswith(".markdown"), filenames):
+ for filename in [x for x in filenames if x.endswith('.markdown')]:
srcPath = os.path.join(dirpath, filename)
destFile = os.path.splitext(filename)[0] + ".html"
destPath = getParallelFile(srcPath, destFile)
@@ -508,13 +655,76 @@
dirnames.remove('.svn') # don't transform things in .svn directories
def doNews():
+ def doNewsInAtom(newsDispenser):
+ s = AtomNewsFormatter(newsDispenser).format()
+ fh = open(os.path.join('xiph.org', 'feeds', 'atom.xml'), 'w')
+ fh.write(s)
+ fh.close()
+ def doNewsInHTML(newsDispenser):
+ def entrywise(formatter):
+ for item in formatter.dispenser.items():
+ s = formatter.formatOne(item)
+ (year, month, day) = [padto2(str(x)) for x in item.dateCreated[:3]]
+ destPath = os.path.join('xiph.org', 'news', year, month, day, item.tagSuffix)
+ try: os.makedirs(destPath)
+ except OSError: pass # the directory was already there
+ fh = open(os.path.join(destPath, 'index.markdown'), 'w')
+ try:
+ fh.write(s)
+ finally:
+ fh.close()
+
+
+ def daily(formatter):
+ for itemGroup in formatter.dispenser.itemsByDay():
+ (year, month, day) = [padto2(str(x)) for x in itemGroup[0].dateCreated[:3]]
+ destPath = os.path.join('xiph.org', 'news', year, month, day, 'index.markdown')
+ fh = open(destPath, 'w')
+ try:
+ fh.write(formatter.formatForDay(int(year), int(month), int(day)))
+ finally:
+ fh.close()
+
+
+ def monthly(formatter):
+ for itemGroup in formatter.dispenser.itemsByMonth():
+ (year, month) = [padto2(str(x)) for x in itemGroup[0].dateCreated[:2]]
+ destPath = os.path.join('xiph.org', 'news', year, month, 'index.markdown')
+ fh = open(destPath, 'w')
+ try:
+ fh.write(formatter.formatForMonth(int(year), int(month)))
+ finally:
+ fh.close()
+
+ def yearly(formatter):
+ for itemGroup in formatter.dispenser.itemsByYear():
+ (year,) = [padto2(str(x)) for x in itemGroup[0].dateCreated[:1]]
+ destPath = os.path.join('xiph.org', 'news', year, 'index.markdown')
+ fh = open(destPath, 'w')
+ try:
+ fh.write(formatter.formatForYear(int(year)))
+ finally:
+ fh.close()
+
+ def toplevel(formatter):
+ pass
+
+ formatter = HTMLNewsFormatter(newsDispenser)
+
+ for f in [entrywise, daily, monthly, yearly, toplevel]:
+ f(formatter)
+
+
nd = NewsDispenser(os.path.join('news', 'options.ini'))
- #print HTMLNewsFormatter(nd.dump()).formatAll()
- s = AtomNewsFormatter(nd.dump()).formatAll()
- fh = open(os.path.join('xiph.org', 'feeds', 'atom.xml'), 'w')
- fh.write(s)
- fh.close()
+ doNewsInAtom(nd)
+ doNewsInHTML(nd)
+
+def main():
+ doNews()
+ doSite()
if __name__ == '__main__':
- #doNews()
- doSite()
+ if len(sys.argv) > 1 and sys.argv[1] == '--profile':
+ profile.run('main()')
+ else:
+ main()
<p>Property changes on: websites-ngen/xiph.org
___________________________________________________________________
Name: svn:ignore
- index.html
index.es.html
index.de.html
+ index.html
index.es.html
index.de.html
news
<p>Modified: websites-ngen/xiph.org/aftermaintext.inherit
===================================================================
--- websites-ngen/xiph.org/aftermaintext.inherit 2004-05-30 13:56:29 UTC (rev 6795)
+++ websites-ngen/xiph.org/aftermaintext.inherit 2004-06-01 17:32:59 UTC (rev 6796)
@@ -3,6 +3,8 @@
title='About us'>About</a> |
<a href='/press/'
title='Read our press releases'>Press</a> |
+ <a href='/news/'
+ title='Read whatâs been happening'>News</a> |
<!--
<a href='/donate/'
title='Give us money'>Donate</a> |
Modified: websites-ngen/xiph.org/index.markdown
===================================================================
--- websites-ngen/xiph.org/index.markdown 2004-05-30 13:56:29 UTC (rev 6795)
+++ websites-ngen/xiph.org/index.markdown 2004-06-01 17:32:59 UTC (rev 6796)
@@ -6,6 +6,7 @@
<!-- Communicate âHow can we help you with our codecs?â as effectively as possible -->
+<!-- quoth mother: âwhatâs a codec?â -->
Xiph.org develops multimedia codecs and related tools to ensure that the foundations of Internet
multimedia remain free and open. By using our codecs, you can save money on software- and
Added: websites-ngen/xiph.org/speex/.htaccess
===================================================================
--- websites-ngen/xiph.org/speex/.htaccess 2004-05-30 13:56:29 UTC (rev 6795)
+++ websites-ngen/xiph.org/speex/.htaccess 2004-06-01 17:32:59 UTC (rev 6796)
@@ -0,0 +1 @@
+ErrorDocument 404 /speex/Error/404/
Added: websites-ngen/xiph.org/speex/Error/404/index.markdown
===================================================================
--- websites-ngen/xiph.org/speex/Error/404/index.markdown 2004-05-30 13:56:29 UTC (rev 6795)
+++ websites-ngen/xiph.org/speex/Error/404/index.markdown 2004-06-01 17:32:59 UTC (rev 6796)
@@ -0,0 +1,4 @@
+404
+===
+
+Did you mis-type something?
Added: websites-ngen/xiph.org/vorbis/.htaccess
===================================================================
--- websites-ngen/xiph.org/vorbis/.htaccess 2004-05-30 13:56:29 UTC (rev 6795)
+++ websites-ngen/xiph.org/vorbis/.htaccess 2004-06-01 17:32:59 UTC (rev 6796)
@@ -0,0 +1,2 @@
+ErrorDocument 404 /vorbis/Error/404/
+ErrorDocument 410 /vorbis/Error/410/
--- >8 ----
List archives: http://www.xiph.org/archives/
Ogg project homepage: http://www.xiph.org/ogg/
To unsubscribe from this list, send a message to 'cvs-request at xiph.org'
containing only the word 'unsubscribe' in the body. No subject is needed.
Unsubscribe messages sent to the list will be ignored/filtered.
More information about the commits
mailing list