home *** CD-ROM | disk | FTP | other *** search
/ Maximum CD 2010 November / maximum-cd-2010-11.iso / DiscContents / xbmc-9.11.exe / plugins / Programs / SVN Repo Installer / installerAPI / xbmcplugin_logviewer.py < prev    next >
Encoding:
Python Source  |  2009-11-03  |  7.4 KB  |  227 lines

  1. """
  2.     SVN Repo Installer Log Viewer
  3. """
  4.  
  5. import os
  6. import sys
  7. try:
  8.     import xbmcgui
  9.     import xbmc
  10.     DEBUG = False
  11. except:
  12.     DEBUG = True
  13.     
  14. import urllib
  15. import re
  16. from xml.sax.saxutils import unescape
  17.  
  18. def log(msg):
  19.     xbmc.log("[%s]: %s" % (__plugin__, msg), xbmc.LOGDEBUG)
  20.  
  21. class _Info:
  22.     def __init__( self, *args, **kwargs ):
  23.         self.__dict__.update( kwargs )
  24.  
  25. __plugin__ = sys.modules["__main__"].__plugin__
  26. __date__ = '14-09-2009'
  27. log( "Module: %s Dated: %s loaded!" % (__name__, __date__ ) )
  28.  
  29. class ChangelogParser:
  30.     # TODO: make these settings
  31.     BASE_URL = "http://code.google.com/p/%s/updates/list?start=%d"
  32.     PAGES = 3
  33.  
  34.     def __init__( self, repo, category=None, revision=None, parse=True ):
  35.         log( "%s __init__!" % (self.__class__))
  36.         if ( DEBUG ):
  37.             self.log = "[B]%s: %s[/B]\n----\n" % ( category or repo, "ChangeLog" )
  38.         else:
  39.             self.log = "[B]%s: %s[/B]\n----\n" % ( category or repo, xbmc.getLocalizedString( 30017 ) )
  40.         self.repo = repo
  41.         self.category = category
  42.         self.revision = revision
  43.         self.parse = parse
  44.  
  45.     def fetch_changelog( self ):
  46.         try:
  47.             if ( DEBUG ):
  48.                 base_path = os.getcwd()
  49.             else:
  50.                 base_path = os.path.join( xbmc.translatePath( "special://profile/" ), "plugin_data", "programs", os.path.basename( os.getcwd() ) )
  51.             # make path
  52.             if ( not os.path.isdir( base_path ) ):
  53.                 os.makedirs( base_path )
  54.             for page in range( self.PAGES ):
  55.                 path = os.path.join( base_path, "%s%d.txt" % ( self.repo, page, ) )
  56.                 # open socket
  57.                 if ( os.path.isfile( path ) and self.revision is None):
  58.                     log( "%s path=%s" % (self.__class__.__name__, path) )
  59.                     usock = open( path, "r" )
  60.                 else:
  61.                     url = self.BASE_URL % ( self.repo, page * 50, )
  62.                     log( "%s url=%s" % (self.__class__.__name__, url) )
  63.                     usock = urllib.urlopen( url )
  64.                 #read html source
  65.                 htmlSource = usock.read()
  66.                 # close socket
  67.                 usock.close()
  68.                 # save source for debugging
  69.                 if ( self.parse == False or not os.path.isfile( path ) ):
  70.                     file_object = open( path, "w" )
  71.                     file_object.write( htmlSource )
  72.                     file_object.close()
  73.                 # parse source
  74.                 if ( self.parse ):
  75.                     self._parse_html_source( htmlSource )
  76.         except Exception, e:
  77.             print str( e )
  78.             self.log = str(e)
  79.             return ""
  80.         else:
  81.             return self.log
  82.  
  83.     def _parse_html_source( self, htmlSource ):
  84.         # regex's
  85.         regex_items = re.compile( '<li>(.+?)</li>', re.DOTALL )
  86.         regex_revisions = re.compile( '<a class="ot-revision-link" href="/p/[^/]+/source/detail\?r=[0-9]+">([^<]+)</a>' )
  87.         regex_dates = re.compile( '<span class="date below-more" title="([^"]+)"' )
  88.         regex_authors = re.compile( '<a class="ot-profile-link-2" href="/u/[^/]+/">([^<]+)</a></span>' )
  89.         regex_details = re.compile( '<div class=\"details\"><span class=\"ot-logmessage\">(.+?)</span></div>', re.DOTALL )
  90.         if ( self.category is not None ):
  91.             regex_subst = re.compile( "\[%s\]" % self.category, re.IGNORECASE )
  92.         # scrape info
  93.         items = regex_items.findall( htmlSource )
  94.         # enumerate thru and scrape and combine all info
  95.         for item in items:
  96.             try:
  97.                 # scrape info
  98.                 revision = regex_revisions.findall( item )[ 0 ]
  99.                 date = regex_dates.findall( item )[ 0 ]
  100.                 author = regex_authors.findall( item )[ 0 ]
  101.                 detail = regex_details.findall( item )[ 0 ]
  102.                 # add to log
  103.                 if ( self.category is not None and re.findall( "\[.*%s.*\]" % self.category, detail, re.IGNORECASE ) ):
  104.                     if ( self.revision is not None and int( revision[ 1 : ] ) <= self.revision ):
  105.                         self.log += "[I]%s - %s - %s[/I]\n%s\n----\n" % ( revision, date, author, unescape( re.sub( regex_subst, "", detail ).strip(), { "'": "'", """: '"' } ), )
  106.                     elif ( self.revision is None ):
  107.                         self.log += "[I]%s - %s - %s[/I]\n%s\n----\n" % ( revision, date, author, unescape( re.sub( regex_subst, "", detail ).strip(), { "'": "'", """: '"' } ), )
  108.                 elif ( self.category is None ):
  109.                     pos = ( detail.find( "]" ) )
  110.                     if ( pos >= 0 ):
  111.                         msg = unescape( "%s [I]%s - %s - %s[/I]\n%s\n----\n" % ( detail[ : pos + 1 ].strip(), revision, date, author, detail[ pos + 1 : ].strip() ), { "'": "'", """: '"' } )
  112.                     else:
  113.                         msg = unescape( "[I]%s - %s - %s[/I]\n%s\n----\n" % ( revision, date, author, detail.strip(), ), { "'": "'", """: '"' } )
  114.                     self.log += msg
  115.             except:
  116.                 # not a valid log message
  117.                 pass
  118.  
  119. if ( not DEBUG ):
  120.     class GUI( xbmcgui.WindowXMLDialog ):
  121.         # action codes
  122.         ACTION_EXIT_SCRIPT = ( 9, 10, )
  123.  
  124.         def __init__( self, *args, **kwargs ):
  125.             log( "%s __init__!" % (self.__class__) )
  126.             xbmcgui.WindowXMLDialog.__init__( self )
  127.             self._parse_argv()
  128.  
  129.         def onInit( self ):
  130.             self.dialog = xbmcgui.DialogProgress()
  131.             self.dialog.create( __plugin__, xbmc.getLocalizedString( 30001 ) )
  132.             if ( self.args.repo is None ):
  133.                 log = self._fetch_readme()
  134.             else:
  135.                 log = self._fetch_changelog()
  136.             self.dialog.close()
  137.             self._paste_log( log )
  138.  
  139.         def _parse_argv( self ):
  140.             # call _Info() with our formatted argv to create the self.args object
  141.             exec "self.args = _Info(%s)" % ( urllib.unquote_plus( sys.argv[ 2 ][ 1 : ].replace( "&", ", " ) ), )
  142.  
  143.         def _fetch_changelog( self ):
  144.             if ( self.args.revision == True ):
  145.                 try:
  146.                     self.args.revision = int( re.findall( "\$Revision: ([0-9]+) \$", sys.modules[ "__main__" ].__svn_revision__ )[ 0 ] )
  147.                 except:
  148.                     self.args.revision = None
  149.             parser = ChangelogParser( self.args.repo, self.args.category, self.args.revision, self.args.parse )
  150.             return parser.fetch_changelog()
  151.  
  152.         def getReadmePath(self):
  153.             base_path = os.path.join( os.getcwd(), "resources", "language" )
  154.             path = os.path.join( base_path, xbmc.getLanguage(), "readme.txt" )
  155.             if not os.path.isfile(path):
  156.                 path = os.path.join( base_path, "English", "readme.txt" )
  157.                 if not os.path.isfile(path):
  158.                     path = os.path.join( os.getcwd(), "resources", "readme.txt" )
  159.                     if not os.path.isfile(path):
  160.                         path = os.path.join( os.getcwd(), "readme.txt" )
  161.                         if not os.path.isfile(path):
  162.                             path = None
  163.             return path
  164.  
  165.         def _fetch_readme( self ):
  166.             try:
  167.                 self.args.category = "readme.txt"
  168.                 usock = None
  169.                 readme = None
  170.                 if ( self.args.readme is None ):
  171.                     # local readme - determine correct language path
  172.                     path = self.getReadmePath()
  173.                     if path:
  174.                         # open socket
  175.                         log("%s path=%s" % (self.__class__.__name__, path) )
  176.                         usock = open( path, "r" )
  177.                 else:
  178.                     log("%s url=%s" % (self.__class__.__name__, self.args.readme) )
  179.                     usock = urllib.urlopen( self.args.readme )
  180.  
  181.                 #read html source
  182.                 if usock:
  183.                     readme = usock.read()
  184.                     # close socket
  185.                     usock.close()
  186.  
  187.                 if not usock or not readme or "404 Not Found" in readme:
  188.                     readme = "Readme not found."
  189.  
  190.             except Exception, e:
  191.                 print str(e)
  192.                 readme = str(e)
  193.             return readme
  194.  
  195.         def _paste_log( self, log ):
  196.             try:
  197.                 title = ( self.args.category or self.args.repo )
  198.                 self.getControl( 5 ).setText( log )
  199.                 self.getControl( 3 ).setText( title )
  200.             except:
  201.                 pass
  202.  
  203.         def onClick( self, controlId ):
  204.             pass
  205.  
  206.         def onFocus( self, controlId ):
  207.             pass
  208.  
  209.         def onAction( self, action ):
  210.             if ( action in self.ACTION_EXIT_SCRIPT ):
  211.                 self.close()
  212.  
  213. def Main():
  214.     ui = GUI( "DialogScriptInfo.xml", os.getcwd(), "Default" )
  215.     ui.doModal()
  216.     del ui
  217.  
  218. if ( __name__ == "__main__" ):
  219.     print "is logviewer __main__"
  220.     if ( not DEBUG ):
  221.         Main()
  222.     else:
  223.         parser = ChangelogParser( "xbmc-addons", "SVN Repo Installer" )
  224.         parser.fetch_changelog()
  225.         print parser.log
  226.  
  227.