"""
SVN Repo Installer Log Viewer
"""
import os
import sys
try:
import xbmcgui
import xbmc
DEBUG = False
except:
DEBUG = True
import urllib
import re
from xml.sax.saxutils import unescape
def log(msg):
xbmc.log("[%s]: %s" % (__plugin__, msg), xbmc.LOGDEBUG)
class _Info:
def __init__( self, *args, **kwargs ):
self.__dict__.update( kwargs )
__plugin__ = sys.modules["__main__"].__plugin__
__date__ = '15-10-2009'
log( "Module: %s Dated: %s loaded!" % (__name__, __date__ ) )
#HOME_DIR = os.getcwd()
HOME_DIR = os.path.dirname(os.path.dirname(__file__)) # until XBMC getwd() bug fixed (affects linux)
class ChangelogParser:
# TODO: make these settings
BASE_URL = "http://code.google.com/p/%s/updates/list?start=%d"
PAGES = 3
def __init__( self, repo, category=None, revision=None, parse=True ):
log( "%s __init__!" % (self.__class__))
if ( DEBUG ):
self.log = "[B]%s: %s[/B]\n----\n" % ( category or repo, "ChangeLog" )
else:
self.log = "[B]%s: %s[/B]\n----\n" % ( category or repo, xbmc.getLocalizedString( 30017 ) )
self.repo = repo
self.category = category
self.revision = revision
self.parse = parse
def fetch_changelog( self ):
try:
if ( DEBUG ):
base_path = HOME_DIR
else:
base_path = os.path.join( xbmc.translatePath( "special://profile/" ), "plugin_data", "programs", HOME_DIR )
# make path
if ( not os.path.isdir( base_path ) ):
os.makedirs( base_path )
for page in range( self.PAGES ):
path = os.path.join( base_path, "%s%d.txt" % ( self.repo, page, ) )
# open socket
if ( os.path.isfile( path ) and self.revision is None):
log( "%s path=%s" % (self.__class__.__name__, path) )
usock = open( path, "r" )
else:
url = self.BASE_URL % ( self.repo, page * 50, )
log( "%s url=%s" % (self.__class__.__name__, url) )
usock = urllib.urlopen( url )
#read html source
htmlSource = usock.read()
# close socket
usock.close()
# save source for debugging
if ( self.parse == False or not os.path.isfile( path ) ):
file_object = open( path, "w" )
file_object.write( htmlSource )
file_object.close()
# parse source
if ( self.parse ):
self._parse_html_source( htmlSource )
except Exception, e:
print str( e )
self.log = str(e)
return ""
else:
return self.log
def _parse_html_source( self, htmlSource ):
# regex's
regex_items = re.compile( '
(.+?)', re.DOTALL )
regex_revisions = re.compile( '([^<]+)' )
regex_dates = re.compile( '([^<]+)' )
regex_details = re.compile( '(.+?)
', re.DOTALL )
if ( self.category is not None ):
regex_subst = re.compile( "\[%s\]" % self.category, re.IGNORECASE )
# scrape info
items = regex_items.findall( htmlSource )
# enumerate thru and scrape and combine all info
for item in items:
try:
# scrape info
revision = regex_revisions.findall( item )[ 0 ]
date = regex_dates.findall( item )[ 0 ]
author = regex_authors.findall( item )[ 0 ]
detail = regex_details.findall( item )[ 0 ]
# add to log
if ( self.category is not None and re.findall( "\[.*%s.*\]" % self.category, detail, re.IGNORECASE ) ):
if ( self.revision is not None and int( revision[ 1 : ] ) <= self.revision ):
self.log += "[I]%s - %s - %s[/I]\n%s\n----\n" % ( revision, date, author, unescape( re.sub( regex_subst, "", detail ).strip(), { "'": "'", """: '"' } ), )
elif ( self.revision is None ):
self.log += "[I]%s - %s - %s[/I]\n%s\n----\n" % ( revision, date, author, unescape( re.sub( regex_subst, "", detail ).strip(), { "'": "'", """: '"' } ), )
elif ( self.category is None ):
pos = ( detail.find( "]" ) )
if ( pos >= 0 ):
msg = unescape( "%s [I]%s - %s - %s[/I]\n%s\n----\n" % ( detail[ : pos + 1 ].strip(), revision, date, author, detail[ pos + 1 : ].strip() ), { "'": "'", """: '"' } )
else:
msg = unescape( "[I]%s - %s - %s[/I]\n%s\n----\n" % ( revision, date, author, detail.strip(), ), { "'": "'", """: '"' } )
self.log += msg
except:
# not a valid log message
pass
if ( not DEBUG ):
class GUI( xbmcgui.WindowXMLDialog ):
# action codes
ACTION_EXIT_SCRIPT = ( 9, 10, )
def __init__( self, *args, **kwargs ):
log( "%s __init__!" % (self.__class__) )
xbmcgui.WindowXMLDialog.__init__( self )
self._parse_argv()
def onInit( self ):
self.dialog = xbmcgui.DialogProgress()
self.dialog.create( __plugin__, xbmc.getLocalizedString( 30001 ) )
if ( self.args.repo is None ):
log = self._fetch_readme()
else:
log = self._fetch_changelog()
self.dialog.close()
self._paste_log( log )
def _parse_argv( self ):
# call _Info() with our formatted argv to create the self.args object
exec "self.args = _Info(%s)" % ( urllib.unquote_plus( sys.argv[ 2 ][ 1 : ].replace( "&", ", " ) ), )
def _fetch_changelog( self ):
if ( self.args.revision == True ):
try:
self.args.revision = int( re.findall( "\$Revision: ([0-9]+) \$", sys.modules[ "__main__" ].__svn_revision__ )[ 0 ] )
except:
self.args.revision = None
parser = ChangelogParser( self.args.repo, self.args.category, self.args.revision, self.args.parse )
return parser.fetch_changelog()
def getReadmePath(self):
home_dir = os.path.dirname(os.path.dirname(__file__))
base_path = os.path.join( home_dir, "resources", "language" )
path = os.path.join( base_path, xbmc.getLanguage(), "readme.txt" )
if not os.path.isfile(path):
path = os.path.join( base_path, "English", "readme.txt" )
if not os.path.isfile(path):
path = os.path.join( home_dir, "resources", "readme.txt" )
if not os.path.isfile(path):
path = os.path.join( home_dir, "readme.txt" )
if not os.path.isfile(path):
path = None
return path
def _fetch_readme( self ):
try:
self.args.category = "readme.txt"
usock = None
readme = None
if ( self.args.readme is None ):
# local readme - determine correct language path
path = self.getReadmePath()
if path:
# open socket
log("%s path=%s" % (self.__class__.__name__, path) )
usock = open( path, "r" )
else:
log("%s url=%s" % (self.__class__.__name__, self.args.readme) )
usock = urllib.urlopen( self.args.readme )
#read html source
if usock:
readme = usock.read()
# close socket
usock.close()
if not usock or not readme or "404 Not Found" in readme:
readme = "Readme not found."
except Exception, e:
print str(e)
readme = str(e)
return readme
def _paste_log( self, log ):
try:
title = ( self.args.category or self.args.repo )
self.getControl( 5 ).setText( log )
self.getControl( 3 ).setText( title )
except:
pass
def onClick( self, controlId ):
pass
def onFocus( self, controlId ):
pass
def onAction( self, action ):
if ( action in self.ACTION_EXIT_SCRIPT ):
self.close()
def Main():
ui = GUI( "DialogScriptInfo.xml", HOME_DIR, "Default" )
ui.doModal()
del ui
if ( __name__ == "__main__" ):
print "is logviewer __main__"
if ( not DEBUG ):
Main()
else:
parser = ChangelogParser( "xbmc-addons", "SVN Repo Installer" )
parser.fetch_changelog()
print parser.log