Update of /cvsroot/freevo/freevo/src/tv
In directory sc8-pr-cvs1:/tmp/cvs-serv23763
Modified Files:
epg_xmltv.py xmltv.py
Log Message:
Synced with latest xmltv.py; also, use Python 2.3 strptime if it's available
since it's better than the version we include, and also beter than 2.2.
Please try this new xmltv parser; it worked nicely on my end.
Index: epg_xmltv.py
===================================================================
RCS file: /cvsroot/freevo/freevo/src/tv/epg_xmltv.py,v
retrieving revision 1.21
retrieving revision 1.22
diff -C2 -d -r1.21 -r1.22
*** epg_xmltv.py 6 Jul 2003 14:10:41 -0000 1.21
--- epg_xmltv.py 11 Aug 2003 13:11:32 -0000 1.22
***************
*** 10,13 ****
--- 10,19 ----
# -----------------------------------------------------------------------
# $Log$
+ # Revision 1.22 2003/08/11 13:11:32 outlyer
+ # Synced with latest xmltv.py; also, use Python 2.3 strptime if it's available
+ # since it's better than the version we include, and also beter than 2.2.
+ #
+ # Please try this new xmltv parser; it worked nicely on my end.
+ #
# Revision 1.21 2003/07/06 14:10:41 outlyer
# Reclaim stdout from config.
***************
*** 116,120 ****
# Use the alternate strptime module which seems to handle time zones
! import strptime
# The XMLTV handler from openpvr.sourceforge.net
--- 122,132 ----
# Use the alternate strptime module which seems to handle time zones
! #
! # XXX Remove when we are ready to require Python 2.3
! if float(sys.version[0:3]) < 2.3:
! import strptime
! else:
! print "Using Python 2.3 strptime"
! import _strptime as strptime
# The XMLTV handler from openpvr.sourceforge.net
***************
*** 381,385 ****
# this bug is left in for someone else to solve.
! secs = time.mktime(strptime.strptime(str, xmltv.date_format_tz))
return secs
--- 393,397 ----
# this bug is left in for someone else to solve.
! secs = time.mktime(strptime.strptime(str, xmltv.date_format))
return secs
Index: xmltv.py
===================================================================
RCS file: /cvsroot/freevo/freevo/src/tv/xmltv.py,v
retrieving revision 1.4
retrieving revision 1.5
diff -C2 -d -r1.4 -r1.5
*** xmltv.py 10 Aug 2003 20:18:44 -0000 1.4
--- xmltv.py 11 Aug 2003 13:11:32 -0000 1.5
***************
*** 4,20 ****
# Copyright (C) 2001 James Oakley
#
! # This program is free software; you can redistribute it and/or modify
! # it under the terms of the GNU General Public License as published by
! # the Free Software Foundation; either version 2 of the License, or
! # (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
! # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
! # GNU General Public License for more details.
#
! # You should have received a copy of the GNU General Public License
! # along with this program; if not, write to the Free Software
! # Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
#
--- 4,20 ----
# Copyright (C) 2001 James Oakley
#
! # This library is free software; you can redistribute it and/or
! # modify it under the terms of the GNU Lesser General Public
! # License as published by the Free Software Foundation; either
! # version 2.1 of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
! # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
! # Lesser General Public License for more details.
#
! # You should have received a copy of the GNU Lesser General Public
! # License along with this program; if not, write to the Free Software
! # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
***************
*** 32,41 ****
from xml.utils import qp_xml
! import string
! # The date formats used in XMLTV
! date_format_tz = '%Y%m%d%H%M%S %Z'
! date_format_notz = '%Y%m%d%H%M'
# The locale for dictionary keys. Leaving them in Unicode screws up the
--- 32,53 ----
from xml.utils import qp_xml
! from xml.sax import saxutils
! import string, types, re
+ # The Python-XMLTV version
+ VERSION = "0.5.15"
! # The date format used in XMLTV
! date_format = '%Y%m%d%H%M%S %Z'
! # Note: Upstream xmltv.py uses %z so remember to change that when syncing
! date_format_notz = '%Y%m%d%H%M%S'
!
! # These characters are illegal in XML
! XML_BADCHARS = re.compile(u'[^\x09\x0A\x0D\x20-\uD7FF\uE000-\uFFFD\u10000-\u10FFFF]')
!
!
! #
! # Options. They may be overridden after this module is imported
! #
# The locale for dictionary keys. Leaving them in Unicode screws up the
***************
*** 43,46 ****
--- 55,60 ----
locale = 'Latin-1'
+
+
# The extraction process could be simpler, building a tree recursively
# without caring about the element names, but it's done this way to allow
***************
*** 82,98 ****
def length(self, node):
! units = _getxmlattr(node, u'units')
try:
! seconds = int(node.textof())
! except:
! return None
! if units == 'seconds':
! return seconds
! elif units == 'minutes':
! return seconds * 60
! elif units == 'hours':
! return seconds * 3600
! else:
! return None
def icon(self, node):
--- 96,107 ----
def length(self, node):
! data = {}
! data['units'] = _getxmlattr(node, u'units')
try:
! length = int(node.textof())
! except ValueError:
! pass
! data['length'] = length
! return data
def icon(self, node):
***************
*** 122,126 ****
def audio(self, node):
! return _extractNodes(node, self)
def previously_shown(self, node):
--- 131,138 ----
def audio(self, node):
! result = {}
! for child in node.children:
! result[child.name.encode(locale)] = self._call(child)
! return result
def previously_shown(self, node):
***************
*** 146,154 ****
for child in node.children:
if child.name == u'language':
! data['language'] = child.textof()
return data
def rating(self, node):
data = {}
if node.attrs.has_key(('', u'system')):
data['system'] = node.attrs[('', u'system')]
--- 158,167 ----
for child in node.children:
if child.name == u'language':
! data['language'] = _readwithlang(child)
return data
def rating(self, node):
data = {}
+ data['icon'] = []
if node.attrs.has_key(('', u'system')):
data['system'] = node.attrs[('', u'system')]
***************
*** 156,166 ****
--- 169,188 ----
if child.name == u'value':
data['value'] = child.textof()
+ elif child.name == u'icon':
+ data['icon'].append(self.icon(child))
+ if len(data['icon']) == 0:
+ del data['icon']
return data
def star_rating(self, node):
data = {}
+ data['icon'] = []
for child in node.children:
if child.name == u'value':
data['value'] = child.textof()
+ elif child.name == u'icon':
+ data['icon'].append(self.icon(child))
+ if len(data['icon']) == 0:
+ del data['icon']
return data
***************
*** 227,237 ****
"""
def display_name(self, node):
! return node.textof()
def icon(self, node):
data = {}
! data['desc'] = node.textof()
! if node.attrs.has_key(('', u'src')):
! data['src'] = _getxmlattr(node, u'src')
return data
--- 249,259 ----
"""
def display_name(self, node):
! return _readwithlang(node)
def icon(self, node):
data = {}
! for attr in (u'src', u'width', u'height'):
! if node.attrs.has_key(('', attr)):
! data[attr.encode(locale)] = _getxmlattr(node, attr)
return data
***************
*** 251,256 ****
!
# Some convenience functions, treat them as private
def _extractNodes(node, handler):
--- 273,279 ----
! #
# Some convenience functions, treat them as private
+ #
def _extractNodes(node, handler):
***************
*** 280,284 ****
def _readwithlang(node):
"""
! Returns a tuple containing the text of a node and the text of the 'lang'
attribute
"""
--- 303,307 ----
def _readwithlang(node):
"""
! Returns a tuple containing the text of a 'node' and the text of the 'lang'
attribute
"""
***************
*** 296,314 ****
def _node_to_programme(node):
"""
! Create a programme dictionary from a qp_xml node
"""
handler = _ProgrammeHandler()
programme = _extractNodes(node, handler)
! for attr in (u'start', u'stop', u'channel'):
! try:
! programme[attr.encode(locale)] = node.attrs[(u'', attr)]
! except KeyError: # No stop time, skip
! continue
return programme
def _node_to_channel(node):
"""
! Create a channel dictionary from a qp_xml node
"""
handler = _ChannelHandler()
--- 319,341 ----
def _node_to_programme(node):
"""
! Create a programme dictionary from a qp_xml 'node'
"""
handler = _ProgrammeHandler()
programme = _extractNodes(node, handler)
! for attr in (u'start', u'channel'):
! programme[attr.encode(locale)] = node.attrs[(u'', attr)]
! if (u'', u'stop') in node.attrs:
! programme[u'stop'.encode(locale)] = node.attrs[(u'', u'stop')]
! else:
! # Sigh. Make show zero-length. This will allow the show to appear in
! # searches, but it won't be seen in a grid, if the grid is drawn to
! # scale
! programme[u'stop'.encode(locale)] = node.attrs[(u'', u'start')]
return programme
def _node_to_channel(node):
"""
! Create a channel dictionary from a qp_xml 'node'
"""
handler = _ChannelHandler()
***************
*** 357,382 ****
- def write_programmes(fp, programmes):
- """
- Write several programmes as a complete XMLTV file to the file object fp
-
- **this is not implemented yet**
-
- Parameter: fp - file object to write to
- programmes - list of programme hashrefs
- """
- pass
-
- def write_programme(fp, programme):
- """
- Write details for a single programme as XML.
-
- **This is not implemented yet**
-
- Parameters:
- reference to hash of programme details (a 'programme')
- """
- pass
-
def read_channels(fp):
"""
--- 384,387 ----
***************
*** 395,418 ****
return channels
- def write_channels(fp, channels):
- """
- Write channels data as channels.dtd XML to file 'channels.xml'.
- **This is not implemented yet**
! Parameter: channels data hashref
"""
! pass
if __name__ == '__main__':
# Tests
from pprint import pprint
import sys
! if len(sys.argv) == 1:
! print "No file specified"
! sys.exit(1)
! # This tends to generate a lot of output
! pprint(read_programmes(open(sys.argv[1])))
! pprint(read_data(open(sys.argv[1])))
! pprint(read_channels(open(sys.argv[1])))
--- 400,860 ----
return channels
! class Writer:
"""
! A class for generating XMLTV data
!
! **All strings passed to this class must be Unicode, except for dictionary
! keys**
! """
! def __init__(self, fp, encoding="iso-8859-1", date=None,
! source_info_url=None, source_info_name=None,
! generator_info_url=None, generator_info_name=None):
! """
! Arguments:
!
! 'fp' -- A File object to write XMLTV data to
!
! 'encoding' -- The text encoding that will be used.
! *Defaults to 'iso-8859-1'*
!
! 'date' -- The date this data was generated. *Optional*
!
! 'source_info_url' -- A URL for information about the source of the
! data. *Optional*
!
! 'source_info_name' -- A human readable description of
! 'source_info_url'. *Optional*
!
! 'generator_info_url' -- A URL for information about the program
! that is generating the XMLTV document.
! *Optional*
!
! 'generator_info_name' -- A human readable description of
! 'generator_info_url'. *Optional*
!
! """
! self.fp = fp
! self.encoding = encoding
! self.date = date
! self.source_info_url = source_info_url
! self.source_info_name = source_info_name
! self.generator_info_url = generator_info_url
! self.generator_info_name = generator_info_name
!
! s = """<?xml version="1.0" encoding="%s"?>
! <!DOCTYPE tv SYSTEM "xmltv.dtd">
! """ % self.encoding
!
! # tv start tag
! s += "<tv"
! for attr in ('date', 'source_info_url', 'source_info_name',
! 'generator_info_url', 'generator_info_name'):
! if attr:
! s += ' %s="%s"' % (attr, self.__dict__[attr])
! s += ">\n"
! self.fp.write(s)
!
!
! def _validateStructure(self, d):
! """
! Raises 'TypeError' if any strings are not Unicode
!
! Argumets:
!
! 's' -- A dictionary
! """
! if type(d) == types.StringType:
! raise TypeError ('All strings, except keys, must be in Unicode. Bad
string: %s' % d)
! elif type(d) == types.DictType:
! for key in d.keys():
! self._validateStructure(d[key])
! elif type(d) == types.TupleType or type(d) == types.ListType:
! for i in d:
! self._validateStructure(i)
!
!
! def _formatCDATA(self, cdata):
! """
! Returns fixed and encoded CDATA
!
! Arguments:
!
! 'cdata' -- CDATA you wish to encode
! """
! # Let's do what 4Suite does, and replace bad characters with '?'
! cdata = XML_BADCHARS.sub(u'?', cdata)
! return saxutils.escape(cdata).encode(self.encoding)
!
!
! def _formatTag(self, tagname, attrs=None, pcdata=None, indent=4):
! """
! Return a simple tag
!
! Arguments:
!
! 'tagname' -- Name of tag
!
! 'attrs' -- dictionary of attributes
!
! 'pcdata' -- Content
!
! 'indent' -- Number of spaces to indent
! """
! s = indent*' '
! s += '<%s' % tagname
! if attrs:
! for key in attrs.keys():
! s += ' %s="%s"' % (key, self._formatCDATA(attrs[key]))
! if pcdata:
! s += '>%s</%s>\n' % (self._formatCDATA(pcdata), tagname)
! else:
! s += '/>\n'
! return s
!
!
! def end(self):
! """
! Write the end of an XMLTV document
! """
! self.fp.write("</tv>\n")
!
!
! def write_programme(self, programme):
! """
! Write a single XMLTV 'programme'
!
! Arguments:
!
! 'programme' -- A dict representing XMLTV data
! """
! self._validateStructure(programme)
! s = ' <programme'
!
! # programme attributes
! for attr in ('start', 'channel'):
! if programme.has_key(attr):
! s += ' %s="%s"' % (attr, self._formatCDATA(programme[attr]))
! else:
! raise ValueError("'programme' must contain '%s' attribute" % attr)
!
! for attr in ('stop', 'pdc-start', 'vps-start', 'showview', 'videoplus',
'clumpidx'):
! if programme.has_key(attr):
! s += ' %s="%s"' % (attr, self._formatCDATA(programme[attr]))
!
! s += '>\n'
!
! # Required children
! err = 0
! if programme.has_key('title'):
! if len(programme['title']) > 0:
! for title in programme['title']:
! if title[1] != u'':
! attrs = {'lang': title[1]}
! else:
! attrs=None
! s += self._formatTag('title', attrs, title[0])
! else:
! err = 1
! else:
! err = 1
!
! if err:
! raise ValueError("'programme' must contain at least one 'title' element")
!
! # Zero or more children with PCDATA and 'lang' attribute
! for element in ('sub-title', 'desc', 'category', 'country'):
! if programme.has_key(element):
! for item in programme[element]:
! if item[1] != u'':
! attrs = {'lang': item[1]}
! else:
! attrs=None
! s += self._formatTag(element, attrs, item[0])
!
! # Zero or one children with PCDATA and 'lang' attribute
! for element in ('language', 'orig-language', 'premiere', 'last-chance'):
! if programme.has_key(element):
! if len(programme[element]) != 1:
! raise ValueError("Only one '%s' element allowed" % element)
! if programme[element][0][1] != u'':
! attrs = {'lang': programme[element][0][1]}
! else:
! attrs=None
! s += self._formatTag(element, attrs, programme[element][0][0])
!
! # Credits
! if programme.has_key('credits'):
! s += ' <credits>\n'
! for credit in ('director', 'actor', 'writer', 'adapter',
! 'producer', 'presenter', 'commentator', 'guest'):
! if programme['credits'][0].has_key(credit):
! for name in programme['credits'][0][credit]:
! s += self._formatTag(credit, pcdata=name, indent=6)
! s += ' </credits>\n'
!
! # Date
! if programme.has_key('date'):
! if len(programme['date']) != 1:
! raise ValueError("Only one 'date' element allowed")
! s += self._formatTag('date', pcdata=programme['date'][0])
!
! # Length
! if programme.has_key('length'):
! if len(programme['length']) != 1:
! raise ValueError("Only one 'length' element allowed")
! s += self._formatTag('length', {'units':
programme['length'][0]['units']},
str(programme['length'][0]['length']).decode(self.encoding))
!
! # Icon
! if programme.has_key('icon'):
! for icon in programme['icon']:
! if icon.has_key('src'):
! s += self._formatTag('icon', icon)
! else:
! raise ValueError("'icon' element requires 'src' attribute")
!
! # URL
! if programme.has_key('url'):
! for url in programme['url']:
! s += self._formatTag('url', pcdata=url)
!
! # Episode-num
! if programme.has_key('episode-num'):
! if len(programme['episode-num']) != 1:
! raise ValueError("Only one 'episode-num' element allowed")
! s += self._formatTag('episode-num', {'system':
programme['episode-num'][0][1]},
! programme['episode-num'][0][0])
!
! # Video and audio details
! for element in ('video', 'audio'):
! if programme.has_key(element):
! s += ' <%s>\n' % element
! for key in programme[element][0]:
! s += self._formatTag(key,
pcdata=str(programme[element][0][key]).decode(self.encoding), indent=6)
! s += ' </%s>\n' % element
!
! # Previously shown
! if programme.has_key('previously-shown'):
! s += self._formatTag('previously-shown',
programme['previously-shown'][0])
!
! # New
! if programme.has_key('new'):
! s += self._formatTag('new')
!
! # Subtitles
! if programme.has_key('subtitles'):
! s += ' <subtitles'
! if programme['subtitles'][0].has_key('type'):
! s += ' type="%s"' %
self._formatCDATA(programme['subtitles'][0]['type'])
! s += '>\n'
! if programme['subtitles'][0].has_key('language'):
! if programme['subtitles'][0]['language'][1] != u'':
! attrs = {'lang': programme['subtitles'][0]['language'][1]}
! else:
! attrs = None
! s += self._formatTag('language', None,
programme['subtitles'][0]['language'][0], indent=6)
! s += ' </subtitles>\n'
!
! # Rating and star rating
! for element in ('rating', 'star-rating'):
! if programme.has_key(element):
! s += ' <%s' % element
! if element == 'rating':
! if programme[element][0].has_key('system'):
! s += ' system="%s"' %
self._formatCDATA(programme[element][0]['system'])
! s += '>\n'
! if programme[element][0].has_key('value'):
! s += self._formatTag('value',
pcdata=programme[element][0]['value'], indent=6)
! if programme[element][0].has_key('icon'):
! for icon in programme[element][0]['icon']:
! s += self._formatTag('icon', icon, indent=6)
! s += ' </%s>\n' % element
!
! # End tag
! s += ' </programme>\n'
!
! self.fp.write(s)
!
!
! def write_channel(self, channel):
! """
! Write a single XMLTV 'channel'
!
! Arguments:
!
! 'channel' -- A dict representing XMLTV data
! """
! self._validateStructure(channel)
! s = ' <channel id="%s">\n' % channel['id']
!
! # Write display-name(s)
! err = 0
! if channel.has_key('display-name'):
! if len(channel['display-name']) > 0:
! for name in channel['display-name']:
! if name[1] != u'':
! attrs = {'lang': name[1]}
! else:
! attrs = None
! s += self._formatTag('display-name', attrs, name[0])
! else:
! err = 1
! else:
! err = 1
!
! if err:
! raise ValueError("'channel' must contain at least one 'display-name'
element")
!
! # Icon
! if channel.has_key('icon'):
! for icon in channel['icon']:
! if icon.has_key('src'):
! s += self._formatTag('icon', icon)
! else:
! raise ValueError("'icon' element requires 'src' attribute")
!
! # URL
! if channel.has_key('url'):
! for url in channel['url']:
! s += self._formatTag('url', pcdata=url)
!
! s += ' </channel>\n'
!
! self.fp.write(s)
!
if __name__ == '__main__':
# Tests
from pprint import pprint
+ from StringIO import StringIO
import sys
! # An example file
! xmldata = StringIO("""<?xml version="1.0" encoding="iso-8859-1"?>
! <!DOCTYPE tv SYSTEM "xmltv.dtd">
! <tv date="20030811003608 -0300"
source-info-url="http://www.funktronics.ca/python-xmltv"
source-info-name="Funktronics" generator-info-name="python-xmltv"
generator-info-url="http://www.funktronics.ca/python-xmltv">
! <channel id="C10eltv.zap2it.com">
! <display-name>Channel 10 ELTV</display-name>
! <url>http://www.eastlink.ca/</url>
! </channel>
! <channel id="C11cbht.zap2it.com">
! <display-name lang="en">Channel 11 CBHT</display-name>
! <icon src="http://tvlistings2.zap2it.com/tms_network_logos/cbc.gif"/>
! </channel>
! <programme start="20030702000000 ADT" channel="C23robtv.zap2it.com"
stop="20030702003000 ADT">
! <title>This Week in Business</title>
! <category>Biz</category>
! <category>Fin</category>
! <date>2003</date>
! <audio>
! <stereo>stereo</stereo>
! </audio>
! </programme>
! <programme start="20030702000000 ADT" channel="C36wuhf.zap2it.com"
stop="20030702003000 ADT">
! <title>Seinfeld</title>
! <sub-title>The Engagement</sub-title>
! <desc>In an effort to grow up, George proposes marriage to former girlfriend
Susan.</desc>
! <category>Comedy</category>
! <country>USA</country>
! <language>English</language>
! <orig-language>English</orig-language>
! <premiere lang="en">Not really. Just testing</premiere>
! <last-chance>Hah!</last-chance>
! <credits>
! <actor>Jerry Seinfeld</actor>
! <producer>Larry David</producer>
! </credits>
! <date>1995</date>
! <length units="minutes">22</length>
! <episode-num system="xmltv_ns">7 . 1 . 1/1</episode-num>
! <video>
! <colour>1</colour>
! <present>1</present>
! <aspect>4:3</aspect>
! </video>
! <audio>
! <stereo>stereo</stereo>
! </audio>
! <previously-shown start="19950921103000 ADT" channel="C12whdh.zap2it.com"/>
! <new/>
! <subtitles type="teletext">
! <language>English</language>
! </subtitles>
! <rating system="VCHIP">
! <value>PG</value>
! <icon src="http://some.ratings/PGicon.png" width="64" height="64"/>
! </rating>
! <star-rating>
! <value>4/5</value>
! <icon src="http://some.star/icon.png" width="32" height="32"/>
! </star-rating>
! </programme>
! </tv>
! """)
! pprint(read_data(xmldata))
! xmldata.seek(0)
! pprint(read_channels(xmldata))
! xmldata.seek(0)
! pprint(read_programmes(xmldata))
!
! # Test the writer
! programmes = [{'audio': [{'stereo': u'stereo'}],
! 'category': [(u'Biz', u''), (u'Fin', u'')],
! 'channel': u'C23robtv.zap2it.com',
! 'date': [u'2003'],
! 'start': u'20030702000000 ADT',
! 'stop': u'20030702003000 ADT',
! 'title': [(u'This Week in Business', u'')]},
! {'audio': [{'stereo': u'stereo'}],
! 'category': [(u'Comedy', u'')],
! 'channel': u'C36wuhf.zap2it.com',
! 'country': [(u'USA', u'')],
! 'credits': [{'producer': [u'Larry David'], 'actor': [u'Jerry
Seinfeld']}],
! 'date': [u'1995'],
! 'desc': [(u'In an effort to grow up, George proposes marriage to
former girlfriend Susan.',
! u'')],
! 'episode-num': [(u'7 . 1 . 1/1', u'xmltv_ns')],
! 'language': [(u'English', u'')],
! 'last-chance': [(u'Hah!', u'')],
! 'length': [{'units': u'minutes', 'length': 22}],
! 'new': [1],
! 'orig-language': [(u'English', u'')],
! 'premiere': [(u'Not really. Just testing', u'en')],
! 'previously-shown': [{'channel': u'C12whdh.zap2it.com',
! 'start': u'19950921103000 ADT'}],
! 'rating': [{'icon': [{'height': u'64',
! 'src': u'http://some.ratings/PGicon.png',
! 'width': u'64'}],
! 'system': u'VCHIP',
! 'value': u'PG'}],
! 'star-rating': [{'icon': [{'height': u'32',
! 'src': u'http://some.star/icon.png',
! 'width': u'32'}],
! 'value': u'4/5'}],
! 'start': u'20030702000000 ADT',
! 'stop': u'20030702003000 ADT',
! 'sub-title': [(u'The Engagement', u'')],
! 'subtitles': [{'type': u'teletext', 'language': (u'English',
u'')}],
! 'title': [(u'Seinfeld', u'')],
! 'video': [{'colour': 1, 'aspect': u'4:3', 'present': 1}]}]
!
! channels = [{'display-name': [(u'Channel 10 ELTV', u'')],
! 'id': u'C10eltv.zap2it.com',
! 'url': [u'http://www.eastlink.ca/']},
! {'display-name': [(u'Channel 11 CBHT', u'en')],
! 'icon': [{'src':
u'http://tvlistings2.zap2it.com/tms_network_logos/cbc.gif'}],
! 'id': u'C11cbht.zap2it.com'}]
!
!
! w = Writer(sys.stdout, encoding="iso-8859-1",
! date="20030811003608 -0300",
! source_info_url="http://www.funktronics.ca/python-xmltv",
! source_info_name="Funktronics",
! generator_info_name="python-xmltv",
! generator_info_url="http://www.funktronics.ca/python-xmltv")
! for c in channels:
! w.write_channel(c)
! for p in programmes:
! w.write_programme(p)
! w.end()
-------------------------------------------------------
This SF.Net email sponsored by: Free pre-built ASP.NET sites including
Data Reports, E-commerce, Portals, and Forums are available now.
Download today and enter to win an XBOX or Visual Studio .NET.
http://aspnet.click-url.com/go/psa00100003ave/direct;at.aspnet_072303_01/01
_______________________________________________
Freevo-cvslog mailing list
[EMAIL PROTECTED]
https://lists.sourceforge.net/lists/listinfo/freevo-cvslog