home *** CD-ROM | disk | FTP | other *** search
/ PC World 2002 May / PCWorld_2002-05_cd.bin / Software / TemaCD / activepython / ActivePython-2.1.1.msi / Python21_PPM_ppmconfig.py < prev    next >
Encoding:
Python Source  |  2001-07-26  |  14.9 KB  |  426 lines

  1. # Copyright 2001 (C) ActiveState Tool Corp., All Rights Reserved.
  2. #
  3. import os,sys,string,whrandom
  4. import xml.dom.minidom
  5.  
  6. from types import *
  7. # imports the trace object, the formatter object
  8. # and bunch of exceptions
  9. from ppmerrors import *
  10.  
  11. whrandom.seed()
  12.  
  13. def get_softpack_node(NodeList):
  14.     for node in NodeList:
  15.         if node.nodeType == node.ELEMENT_NODE and node.tagName == "INSTPPD":
  16.             subnode = node
  17.     for node in subnode.childNodes:
  18.         if node.nodeType == node.ELEMENT_NODE and node.tagName == "SOFTPKG":
  19.             return node
  20.     raise NodeNotFound
  21.  
  22. def get_package_name(softpkgnode):
  23.     try:
  24.         return str(softpkgnode.getAttribute('NAME'))
  25.     except KeyError, e:
  26.         ppmerrors.Error("Can not find the name of the package!: %s" % e)
  27.     return ''
  28.  
  29. def get_package_version(softpkgnode):
  30.     try:
  31.         return string.replace(softpkgnode.getAttribute('VERSION'),',','.')
  32.     except KeyError, e:
  33.         ppmerrors.Error("Can not find the version of the package: %s " % e)
  34.     return ''
  35.  
  36. def get_node_attr(node,attrname):
  37.     try:
  38.         return str(node.getAttribute(string.upper(attrname)))
  39.     except KeyError, e:
  40.         #caused a lot of useless messages. So, it is disabled for now
  41.         #errorreporter.Warn( "Can not find the specified attribute: %s " % e)
  42.         pass
  43.     return None
  44.  
  45. def get_package_cdata(softpkgnode, nodename):
  46.     for node in softpkgnode.childNodes:
  47.         if node.nodeType == node.ELEMENT_NODE and node.tagName == string.upper(nodename):
  48.             return get_text(node.childNodes)
  49.     return ""
  50.  
  51. def get_package_codebase(softpkgnode):
  52.     myhash = {}
  53.     for node in softpkgnode.childNodes:
  54.         if node.nodeType == node.ELEMENT_NODE and node.tagName == 'CODEBASE':
  55.             myhash['href'] = get_node_attr(node,'href')
  56.             myhash['filename'] = get_node_attr(node,'filename')
  57.             return myhash
  58.     return myhash    
  59.  
  60. def get_package_dependency(element):
  61.     myhash = {}
  62.     for node in element.childNodes:
  63.         if node.nodeType == node.ELEMENT_NODE and node.tagName == 'DEPENDENCY':
  64.             key = get_node_attr(node,'name')
  65.             value = get_node_attr(node,'version')
  66.             if key and value:
  67.                 myhash[key] = value
  68.     return myhash
  69.     
  70. def get_text(NodeList):
  71.     """get all the text nodes values in an element and
  72.        return the concatonated text values"""
  73.     rc = ""
  74.     for node in NodeList:
  75.         if node.nodeType == node.TEXT_NODE:
  76.             rc += node.data
  77.     return str(rc)
  78.  
  79. def get_array(NodeList): 
  80.     rc = []
  81.     for node in NodeList:
  82.         if node.nodeType == node.TEXT_NODE:
  83.             if string.find(node.data , ';'):        
  84.                 rc += string.split(node.data , ';')
  85.     return rc
  86.  
  87. def parse_location(location):
  88.     import urlparse
  89.     parsed_loco = urlparse.urlparse(location)
  90.     namespace = str(parsed_loco[4])
  91.     location = urlparse.urlunparse(parsed_loco[0:3]+('','',''))
  92.     return (location , namespace)
  93.  
  94. def get_ppmconfig_filename():
  95.     try:
  96.       fname = os.environ['PYPPM_DAT']
  97.       if os.path.isfile(fname) and not os.path.isdir(fname):
  98.         return fname
  99.       else:
  100.         raise KeyError
  101.     except KeyError:
  102.       pass 
  103.       fname = os.path.join(sys.exec_prefix,'lib','pyppm.xml')
  104.     if os.path.isfile(fname):
  105.         return fname
  106.       fname = os.path.join(os.curdir,'pyppm.xml')
  107.     if os.path.isfile(fname):
  108.         return fname
  109.     raise BadConfigFile("No config file. Try 'genconfig' command.")
  110.  
  111. def get_bool_values(AttrValue):
  112.     try:
  113.         return int(str(AttrValue))
  114.     except ValueError:
  115.         return 0
  116.     
  117. def get_str_values(AttrValue):
  118.         return str(AttrValue)
  119.  
  120. class Repository:
  121.     def __init__(self,name,namespace,uri,username,passwd):
  122.         self.name = name
  123.         self.namespace = namespace
  124.         self.uri = uri
  125.         self.username = username
  126.         self.passwd = passwd
  127.     def __repr__(self):
  128.         return self.uri
  129.     __str__ = __repr__
  130.  
  131. class BasicImplementation:
  132.     def __init__(self,ImpElement):
  133.         """This class encapsulates the information of the implementation section(of a PPD) of 
  134.            the packages which are already installed."""
  135.         self._node = ImpElement
  136.         self.dependencies = get_package_dependency(self._node) 
  137.         # this is a hash with 'href' or 'filename'
  138.         self.codebase = get_package_codebase(self._node)
  139.         # if the following is specified, Distutils setup.py is not going to 
  140.         # be used and instead it uses the followings
  141.         self.installer = get_package_cdata(self._node , 'install')
  142.         if self.installer == '':
  143.             try: self.installer = get_node_attr(self._node.getElementsByTagName("INSTALL")[0] , 'EXEC')
  144.             except IndexError: self.installer = ''
  145.         
  146. class Implementation(BasicImplementation):
  147.     
  148.     def __init__(self,node):
  149.         """This class encapsulates the information of the implementation section(of a PPD) of
  150.            a python package"""
  151.         BasicImplementation.__init__(self,node)
  152.         self._node = node
  153.         try:
  154.             self.python_version = get_package_version(self._node.getElementsByTagName("PYTHONCORE")[0])
  155.         except Exception, e:
  156.                         self.python_version = None
  157.             errorreporter.LowError("'PYTHONCORE' tag can not be found: %s" % e)
  158.         self.oss = map((lambda x: get_node_attr(x,'value')) ,
  159.                    self._node.getElementsByTagName("OS"))
  160.         # this is out dated tag attribute but it is still supported
  161.         if None in self.oss:
  162.             self.oss = map((lambda x: get_node_attr(x,'name')) ,
  163.                        self._node.getElementsByTagName("OS"))
  164.         if len(self.oss)==1:
  165.             try:
  166.                 self.osversion = get_node_attr(self._node.getElementsByTagName("OSVERSION")[0],'version')
  167.             except IndexError:
  168.                 self.osversion = 0
  169.         self.processors =  map((lambda x: get_node_attr(x,'value')) ,
  170.                        self._node.getElementsByTagName("PROCESSOR"))
  171.         self.architectures = map((lambda x: get_node_attr(x,'value')) ,
  172.                      self._node.getElementsByTagName("ARCHITECTURE"))
  173.  
  174.     def __repr__(self):
  175.         return 'Implementaion Object -> codebase: '+str(self.codebase)
  176.     __str__ = __repr__
  177.  
  178. class Package:
  179.  
  180.     def __init__(self,softpack):
  181.         """Package definition as conformed with PPD.DTD.
  182.            This function takes a softpack dom element."""
  183.         self._node = softpack
  184.         self.ppd = self._node.toxml()  
  185.         self.name = get_package_name(self._node)
  186.         self.version = get_package_version (self._node)
  187.         self.title = get_package_cdata(self._node , 'title')
  188.         self.abstract = get_package_cdata(self._node , 'abstract')
  189.         self.implementations = map((lambda x: Implementation(x)) , self._node.getElementsByTagName("IMPLEMENTATION"))
  190.  
  191.     def __repr__(self):
  192.         return errorreporter.formatter.formatPackage(self)
  193.     __str__ = __repr__
  194.  
  195.  
  196. class InstalledPackage(Package):
  197.  
  198.     def __init__(self,instpack):
  199.         """Installed packages as conformed with PPM Configuration DTD.
  200.            This function takes an installed package (with <PACKAGE> tag)
  201.            dom element in."""
  202.         Package.__init__(self,get_softpack_node(instpack.childNodes))
  203.         self._node = instpack
  204.         self.primname = get_node_attr(self._node , 'name')
  205.         self.author = get_text(self._node.getElementsByTagName('AUTHOR')[0].childNodes)
  206.         self.location = get_text(self._node.getElementsByTagName('LOCATION')[0].childNodes)
  207.         self.instpacklist =  get_text(self._node.getElementsByTagName('INSTPACKLIST')[0].childNodes)
  208.         self.instroot = get_text(self._node.getElementsByTagName('INSTROOT')[0].childNodes)
  209.         self.instdate = get_text(self._node.getElementsByTagName('INSTDATE')[0].childNodes)
  210.         
  211. class PPMConfig:
  212.  
  213.     def __init__(self, config_file_name=None):
  214.         if config_file_name:
  215.             self.config_file_name = config_file_name
  216.         else:
  217.             self.config_file_name = get_ppmconfig_filename()
  218.            #configuration file is another XML file
  219.            #so, we parse it like another PPD file.
  220.         try:
  221.             self.config_file = open(self.config_file_name , 'r+')
  222.         except Exception, e:
  223.             raise BadConfigFile('-- Config file not found, or you do not have write permission.')
  224.         self._locations =[]
  225.         self.required_packages = []
  226.         self._have_run = {}
  227.         self.options = {}
  228.         self.dom = xml.dom.minidom.parse(self.config_file)
  229.         try:
  230.             self.ppmconfignode = self.dom.getElementsByTagName('PPMCONFIG')[0]
  231.         except IndexError:
  232.             raise BadConfgFile('No PPMCONFIG tag')
  233.         self.get_version()
  234.         try:
  235.             self.get_options()
  236.         except IndexError:
  237.             raise BadConfigFile(' No OPTIONS tag.')
  238.         # tracer object is imported from the 'ppmerrors.py' module
  239.                 # XXX 
  240.                 # XXXX 
  241.  
  242.                 # XXX 
  243.                 # XXX 
  244.                 # XXX 
  245.                 # XXX 
  246.                 tracefile = self.options['tracefile']
  247.         errorreporter.tracer.SetLogName(tracefile)
  248.                 errorreporter.tracer.tl = int(self.options['trace'])
  249.                 if using_gui():
  250.                     errorreporter.tracer.displayer = Win32ErrorDisplay()
  251.                     errorreporter.tracer.verbose = 0
  252.                     sys.stderr=sys.stdout=open(tracefile,"a")
  253.                 else:
  254.                     errorreporter.tracer.displayer = StderrErrorDisplay()
  255.  
  256.             try:
  257.             errorreporter.tracer.verbose = int(self.options['verbose'])
  258.             except (AttributeError, ValueError):
  259.                         errorreporter.tracer.verbose = 1
  260.  
  261.     def refresh(self):
  262.         """writes the dom to the configfile"""
  263.         self.config_file.close()
  264.         self.config_file = open(self.config_file_name, 'w')
  265.         self.config_file.write(self.dom.toxml())
  266.         self.config_file.flush()
  267.         
  268.     def get_version(self):
  269.         try:
  270.             self._have_run['version']
  271.             return self.version
  272.         except KeyError:
  273.             self.version = get_text(self.dom.getElementsByTagName("PPMVER")[0].childNodes)
  274.             self.version = string.replace(self.version,',','.')
  275.             if len(self.version)>=5: self.version = self.version[0:5]
  276.             self._have_run['version']=1
  277.             return self.version
  278.             
  279.        def get_repository_info(self):
  280.         try:
  281.             self._have_run['repository_info']
  282.             return self._locations
  283.                 except KeyError:
  284.             for node in self.dom.getElementsByTagName("REPOSITORY"):
  285.                 name = node.getAttribute('NAME')
  286.                 loco = node.getAttribute('LOCATION')
  287.                 uri , namespace = parse_location(loco) 
  288.                 try:
  289.                     username = node.getAttribute('USERNAME')
  290.                 except AttributeError:
  291.                     username = ''
  292.                 try:
  293.                     password = node.getAttribute('PASSWORD')
  294.                 except AttributeError:
  295.                     password = ''
  296.                 repository = Repository(name,namespace,uri,username,password)
  297.                 self._locations.append(repository)
  298.             self._have_run['repository_info'] = 1
  299.             return self._locations
  300.     
  301.     def get_required_packages(self):
  302.         try:
  303.             self._have_run['reqpackages']
  304.             return self.required_packages
  305.         except KeyError:    
  306.             self.required_packages = get_array(self.dom.getElementsByTagName("PPMPRECIOUS")[0].childNodes)
  307.             self._have_run['reqpackages']=1
  308.             return self.required_packages
  309.     
  310.     def get_platform_info(self):
  311.         try:
  312.             self._have_run['platform_info']
  313.             return [self.cpu , self.os_value , self.os_version , self.lang]
  314.         except KeyError:    
  315.             PlatNode = self.dom.getElementsByTagName("PLATFORM")[0]
  316.                         self.cpu = get_str_values(PlatNode.getAttribute('CPU') )
  317.                         self.os_value = get_str_values(PlatNode.getAttribute('OSVALUE'))
  318.                         self.os_version = get_bool_values(PlatNode.getAttribute('OSVERSION'))
  319.                         self.lang = get_str_values(PlatNode.getAttribute('LANGUAGE'))
  320.             self._have_run['platform_info'] = 1
  321.             return [self.cpu , self.os_value , self.os_version , self.lang]
  322.  
  323.     def get_options(self):
  324.         try:
  325.             self._have_run['options']
  326.             return self.options
  327.         except KeyError:
  328.             OptionNode = self.dom.getElementsByTagName("OPTIONS")[0]
  329.             self.options['clean'] = get_bool_values(OptionNode.getAttribute('CLEAN'))
  330.             self.options['ignorecase'] = get_bool_values(OptionNode.getAttribute('IGNORECASE'))
  331.             self.options['confirm'] = get_bool_values(OptionNode.getAttribute('CONFIRM'))
  332.             self.options['forceinstall'] = get_bool_values(OptionNode.getAttribute('FORCEINSTALL'))
  333.             self.options['verbose'] = get_bool_values(OptionNode.getAttribute('VERBOSE'))
  334.  
  335.             self.options['downloadstatus'] = get_bool_values(OptionNode.getAttribute('DOWNLOADSTATUS'))
  336.             self.options['trace'] =  get_bool_values(OptionNode.getAttribute('TRACE'))
  337.  
  338.                         self.builddir = get_str_values(OptionNode.getAttribute('BUILDDIR'))
  339.  
  340.                         if not self.builddir:
  341.                 self.builddir = os.path.join(sys.exec_prefix,'Downloads') 
  342.             self.options['root'] = get_str_values(OptionNode.getAttribute('ROOT')) 
  343.                         self.options['tracefile'] = str(OptionNode.getAttribute('TRACEFILE'))
  344.             if not self.options['tracefile']:
  345.                                 default = os.path.join(sys.exec_prefix,'PPM.LOG')
  346.                 self.options['tracefile'] = default
  347.             self._have_run['options'] = 1
  348.             return self.options
  349.                  
  350.     def get_installed_packages(self):
  351.         InstPackages = self.ppmconfignode.getElementsByTagName("PACKAGE")
  352.         self.InstPackages = map((lambda x: InstalledPackage(x)) , InstPackages)
  353.         return self.InstPackages
  354.  
  355.     #def add_repository(self,location,username="", passwd=""):
  356.     #    uri, nm = parse_location(location)
  357.     #    rep = 'new'+str(whrandom.randint(1,100))
  358.     #    repository = Repository(rep,nm,uri,username,passwd)
  359.     #    self._locations.append(repository)
  360.  
  361.     def add_package(self,package,location):
  362.         from PyPMHelps import InstPackXML
  363.         import time
  364.         if isinstance(location,Repository):
  365.             URL = location.uri+'?'+location.namespace
  366.         elif type(location) is StringType:
  367.             # check to see if this is a path or a filename
  368.             if location[-1]!='/':
  369.                 URL = location[:string.rfind(location,'/')]
  370.             else:
  371.                 URL = location
  372.         Date = time.strftime('%a %b %d %H:%M',time.localtime(time.time()))
  373.         InstPackXML = InstPackXML % (str(package.name) , str(URL) , Date) 
  374.         doc = xml.dom.minidom.parseString(InstPackXML)
  375.         InstPackNode = doc.getElementsByTagName('PACKAGE')[0]
  376.         InstPPDNode = InstPackNode.getElementsByTagName('INSTPPD')[0]
  377.         InstPPDNode.appendChild(package._node)
  378.         self.ppmconfignode.appendChild(InstPackNode)
  379.         self.refresh()
  380.  
  381.     # becarefull when calling this method. The attribute InstPackages should
  382.     # already be initialized prior to calling this method, unless it won't
  383.     # remove anything from the database
  384.     def remove_package(self,package):
  385.         def ispackage(package,InstPackages):
  386.             for pac in InstPackages:
  387.                 if package.name == pac.name:
  388.                     return 1, pac
  389.             return 0, None
  390.         
  391.         r , inst_p = ispackage(package,self.InstPackages)
  392.         if r:
  393.             self.ppmconfignode.removeChild(inst_p._node)
  394.             self.refresh()
  395.             inst_p._node.unlink()
  396.  
  397.     #save the options to the configuration file
  398.     def save_options(self):
  399.         import PyPMHelps
  400.         Str = string.replace(PyPMHelps.OptString,'\n','')
  401.         L = self.options.keys()
  402.         L.sort()
  403.         A = []
  404.         for l in L: A.append(self.options[l])
  405.         Str  =  Str % ((self.builddir,)+tuple(A))
  406.         doc = xml.dom.minidom.parseString(Str)
  407.         NewOptNode = doc.getElementsByTagName('OPTIONS')[0]
  408.         self.ppmconfignode = self.dom.getElementsByTagName('PPMCONFIG')[0]
  409.         OldOptNode = self.ppmconfignode.getElementsByTagName('OPTIONS')[0]
  410.         self.ppmconfignode.removeChild(OldOptNode)
  411.         self.ppmconfignode.appendChild(NewOptNode)
  412.         OldOptNode.unlink()
  413.         self.refresh()
  414.  
  415. def using_gui():
  416.     try: 
  417.         import win32api, pywintypes
  418.     except ImportError:
  419.         return 0 # not Windows
  420.  
  421.     try:
  422.         win32api.GetConsoleTitle()
  423.         return 0
  424.     except pywintypes.error:
  425.         return 1
  426.