Add time handling in feeds.py
Lots of time format can be passed as a value (RSS/Atom time strings, timestamp, anything supported by dateutil.parser). Implemented in twitter feedify hook.master
parent
16b5e4b018
commit
12d48918d8
98
feeds.py
98
feeds.py
|
@ -1,6 +1,9 @@
|
||||||
#!/usr/bin/env python
|
#!/usr/bin/env python
|
||||||
|
|
||||||
from lxml import etree
|
from lxml import etree
|
||||||
|
from datetime import datetime
|
||||||
|
import dateutil.parser
|
||||||
|
from dateutil import tz
|
||||||
import re
|
import re
|
||||||
|
|
||||||
Element = etree.Element
|
Element = etree.Element
|
||||||
|
@ -131,6 +134,38 @@ class FeedDescriptor(object):
|
||||||
deleter = getattr(instance, 'del%s' % self.name.title())
|
deleter = getattr(instance, 'del%s' % self.name.title())
|
||||||
return deleter()
|
return deleter()
|
||||||
|
|
||||||
|
class FeedTime(FeedDescriptor):
|
||||||
|
def __get__(self, instance, owner):
|
||||||
|
getter = getattr(instance, 'get%s' % self.name.title())
|
||||||
|
raw = getter()
|
||||||
|
try:
|
||||||
|
time = parseTime(raw)
|
||||||
|
return time
|
||||||
|
except ValueError:
|
||||||
|
return None
|
||||||
|
|
||||||
|
def __set__(self, instance, value):
|
||||||
|
try:
|
||||||
|
time = parseTime(value)
|
||||||
|
raw = time.strftime(instance.timeFormat)
|
||||||
|
setter = getattr(instance, 'set%s' % self.name.title())
|
||||||
|
return setter(raw)
|
||||||
|
except ValueError:
|
||||||
|
pass
|
||||||
|
|
||||||
|
def parseTime(value):
|
||||||
|
if isinstance(value, basestring):
|
||||||
|
if re.match(r'^[0-9]+$', value):
|
||||||
|
return datetime.fromtimestamp(int(value), tz.tzutc())
|
||||||
|
else:
|
||||||
|
return dateutil.parser.parse(value, tzinfos=tz.tzutc)
|
||||||
|
elif isinstance(value, int):
|
||||||
|
return datetime.fromtimestamp(value, tz.tzutc())
|
||||||
|
elif isinstance(value, datetime):
|
||||||
|
return value
|
||||||
|
else:
|
||||||
|
return False
|
||||||
|
|
||||||
class FeedList(object):
|
class FeedList(object):
|
||||||
"""
|
"""
|
||||||
Class to map a list of xml elements against a list of matching objects,
|
Class to map a list of xml elements against a list of matching objects,
|
||||||
|
@ -334,6 +369,8 @@ class FeedParserAtom(FeedParser):
|
||||||
return self.xpath('atom:entry|atom03:entry')
|
return self.xpath('atom:entry|atom03:entry')
|
||||||
|
|
||||||
class FeedItem(FeedBase):
|
class FeedItem(FeedBase):
|
||||||
|
timeFormat = ''
|
||||||
|
|
||||||
def __init__(self, xml=None, tag='atom:feed'):
|
def __init__(self, xml=None, tag='atom:feed'):
|
||||||
if xml is None:
|
if xml is None:
|
||||||
xml = Element(tagNS(self.base[tag]))
|
xml = Element(tagNS(self.base[tag]))
|
||||||
|
@ -381,10 +418,31 @@ class FeedItem(FeedBase):
|
||||||
self.content = ""
|
self.content = ""
|
||||||
|
|
||||||
|
|
||||||
|
def getTime(self):
|
||||||
|
return None
|
||||||
|
|
||||||
|
def setTime(self, value):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def delTime(self):
|
||||||
|
self.time = None
|
||||||
|
|
||||||
|
|
||||||
|
def getUpdated(self):
|
||||||
|
return None
|
||||||
|
|
||||||
|
def setUpdated(self, value):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def delUpdated(self):
|
||||||
|
self.updated = None
|
||||||
|
|
||||||
title = FeedDescriptor('title')
|
title = FeedDescriptor('title')
|
||||||
link = FeedDescriptor('link')
|
link = FeedDescriptor('link')
|
||||||
description = desc = FeedDescriptor('desc')
|
description = desc = FeedDescriptor('desc')
|
||||||
content = FeedDescriptor('content')
|
content = FeedDescriptor('content')
|
||||||
|
time = FeedTime('time')
|
||||||
|
updated = FeedTime('updated')
|
||||||
|
|
||||||
def pushContent(self, value):
|
def pushContent(self, value):
|
||||||
if not self.desc and self.content:
|
if not self.desc and self.content:
|
||||||
|
@ -396,6 +454,7 @@ class FeedItem(FeedBase):
|
||||||
self.xml.getparent().remove(self.xml)
|
self.xml.getparent().remove(self.xml)
|
||||||
|
|
||||||
class FeedItemRSS(FeedItem):
|
class FeedItemRSS(FeedItem):
|
||||||
|
timeFormat = '%a, %d %b %Y %H:%M:%S %Z'
|
||||||
base = { 'rdf:rdf': 'rssfake:item',
|
base = { 'rdf:rdf': 'rssfake:item',
|
||||||
'channel': 'item'}
|
'channel': 'item'}
|
||||||
|
|
||||||
|
@ -447,7 +506,21 @@ class FeedItemRSS(FeedItem):
|
||||||
element = self.xgetCreate(table)
|
element = self.xgetCreate(table)
|
||||||
element.text = value
|
element.text = value
|
||||||
|
|
||||||
|
|
||||||
|
def getTime(self):
|
||||||
|
return self.xval('rssfake:pubDate|pubDate')
|
||||||
|
|
||||||
|
def setTime(self, value):
|
||||||
|
if not value:
|
||||||
|
return self.xdel('rssfake:pubDate|pubDate')
|
||||||
|
|
||||||
|
table = { 'rdf:rdf': 'rssfake:pubDate',
|
||||||
|
'channel': 'pubDate'}
|
||||||
|
element = self.xgetCreate(table)
|
||||||
|
element.text = value
|
||||||
|
|
||||||
class FeedItemAtom(FeedItem):
|
class FeedItemAtom(FeedItem):
|
||||||
|
timeFormat = '%Y-%m-%dT%H:%M:%SZ'
|
||||||
base = { 'atom:feed': 'atom:entry',
|
base = { 'atom:feed': 'atom:entry',
|
||||||
'atom03:feed': 'atom03:entry'}
|
'atom03:feed': 'atom03:entry'}
|
||||||
|
|
||||||
|
@ -513,3 +586,28 @@ class FeedItemAtom(FeedItem):
|
||||||
cleanNode(element)
|
cleanNode(element)
|
||||||
element.attrib['type'] = 'html'
|
element.attrib['type'] = 'html'
|
||||||
element.text = value
|
element.text = value
|
||||||
|
|
||||||
|
def getTime(self):
|
||||||
|
return self.xval('atom:published|atom03:published')
|
||||||
|
|
||||||
|
def setTime(self, value):
|
||||||
|
if not value:
|
||||||
|
return self.xdel('atom:published|atom03:published')
|
||||||
|
|
||||||
|
table = { 'atom:feed': 'atom:published',
|
||||||
|
'atom03:feed': 'atom03:published'}
|
||||||
|
element = self.xgetCreate(table)
|
||||||
|
element.text = value
|
||||||
|
|
||||||
|
|
||||||
|
def getUpdated(self):
|
||||||
|
return self.xval('atom:updated|atom03:updated')
|
||||||
|
|
||||||
|
def setUpdated(self, value):
|
||||||
|
if not value:
|
||||||
|
return self.xdel('atom:updated|atom03:updated')
|
||||||
|
|
||||||
|
table = { 'atom:feed': 'atom:updated',
|
||||||
|
'atom03:feed': 'atom03:updated'}
|
||||||
|
element = self.xgetCreate(table)
|
||||||
|
element.text = value
|
||||||
|
|
Loading…
Reference in New Issue