Package zeroinstall :: Package injector :: Module reader
[frames] | no frames]

Source Code for Module zeroinstall.injector.reader

  1  """ 
  2  Parses an XML interface into a Python representation. 
  3  """ 
  4   
  5  # Copyright (C) 2006, Thomas Leonard 
  6  # See the README file for details, or visit http://0install.net. 
  7   
  8  import os 
  9  import sys 
 10  import shutil 
 11  import time 
 12  from logging import debug, warn, info 
 13  from os.path import dirname 
 14   
 15  from zeroinstall.support import basedir 
 16  from zeroinstall.injector import qdom, distro 
 17  from zeroinstall.injector.namespaces import * 
 18  from zeroinstall.injector.model import * 
 19  from zeroinstall.injector import model 
 20  from zeroinstall import version, SafeException 
 21   
22 -def update_from_cache(interface):
23 """Read a cached interface and any native feeds or user overrides. 24 @param interface: the interface object to update 25 @type interface: L{model.Interface} 26 @return: True if cached version and user overrides loaded OK. 27 False if upstream not cached. Local interfaces (starting with /) are 28 always considered to be cached, although they are not actually stored in the cache. 29 @rtype: bool""" 30 interface.reset() 31 main_feed = None 32 33 if interface.uri.startswith('/'): 34 debug("Loading local interface file '%s'", interface.uri) 35 update(interface, interface.uri, local = True) 36 cached = True 37 else: 38 cached = basedir.load_first_cache(config_site, 'interfaces', escape(interface.uri)) 39 if cached: 40 debug("Loading cached information for %s from %s", interface, cached) 41 main_feed = update(interface, cached) 42 43 # Add the distribution package manager's version, if any 44 path = basedir.load_first_data(config_site, 'native_feeds', model._pretty_escape(interface.uri)) 45 if path: 46 # Resolve any symlinks 47 info("Adding native packager feed '%s'", path) 48 interface.extra_feeds.append(Feed(os.path.realpath(path), None, False)) 49 50 update_user_overrides(interface, main_feed) 51 52 # Special case: add our fall-back local copy of the injector as a feed 53 if interface.uri == injector_gui_uri: 54 local_gui = os.path.join(os.path.abspath(dirname(dirname(__file__))), '0launch-gui', 'ZeroInstall-GUI.xml') 55 interface.extra_feeds.append(Feed(local_gui, None, False)) 56 57 return bool(cached)
58
59 -def update_user_overrides(interface, main_feed = None):
60 """Update an interface with user-supplied information. 61 @param interface: the interface object to update 62 @type interface: L{model.Interface} 63 @param main_feed: feed to update with last_checked information 64 @note: feed updates shouldn't really be here. main_feed may go away in future. 65 """ 66 user = basedir.load_first_config(config_site, config_prog, 67 'user_overrides', escape(interface.uri)) 68 if not user: 69 return 70 71 root = qdom.parse(file(user)) 72 73 # This is a bit wrong; this information is about the feed, 74 # not the interface. 75 if main_feed: 76 last_checked = root.getAttribute('last-checked') 77 if last_checked: 78 main_feed.last_checked = int(last_checked) 79 80 stability_policy = root.getAttribute('stability-policy') 81 if stability_policy: 82 interface.set_stability_policy(stability_levels[str(stability_policy)]) 83 84 for item in root.childNodes: 85 if item.uri != XMLNS_IFACE: continue 86 if item.name == 'implementation': 87 id = item.getAttribute('id') 88 assert id is not None 89 if not (id.startswith('/') or id.startswith('.') or id.startswith('package:')): 90 assert '=' in id 91 impl = interface.implementations.get(id, None) 92 if not impl: 93 debug("Ignoring user-override for unknown implementation %s in %s", id, interface) 94 continue 95 96 user_stability = item.getAttribute('user-stability') 97 if user_stability: 98 impl.user_stability = stability_levels[str(user_stability)] 99 elif item.name == 'feed': 100 feed_src = item.getAttribute('src') 101 if not feed_src: 102 raise InvalidInterface('Missing "src" attribute in <feed>') 103 interface.extra_feeds.append(Feed(feed_src, item.getAttribute('arch'), True, langs = item.getAttribute('langs')))
104
105 -def check_readable(interface_uri, source):
106 """Test whether an interface file is valid. 107 @param interface_uri: the interface's URI 108 @type interface_uri: str 109 @param source: the name of the file to test 110 @type source: str 111 @return: the modification time in src (usually just the mtime of the file) 112 @rtype: int 113 @raise InvalidInterface: If the source's syntax is incorrect, 114 """ 115 tmp = Interface(interface_uri) 116 try: 117 update(tmp, source) 118 except InvalidInterface, ex: 119 info("Error loading feed:\n" 120 "Interface URI: %s\n" 121 "Local file: %s\n%s" % 122 (interface_uri, source, ex)) 123 raise InvalidInterface("Error loading feed '%s':\n\n%s" % (interface_uri, ex)) 124 return tmp.last_modified
125
126 -def update(interface, source, local = False):
127 """Read in information about an interface. 128 @param interface: the interface object to update 129 @type interface: L{model.Interface} 130 @param source: the name of the file to read 131 @type source: str 132 @param local: use file's mtime for last-modified, and uri attribute is ignored 133 @raise InvalidInterface: if the source's syntax is incorrect 134 @return: the new feed (since 0.32) 135 @see: L{update_from_cache}, which calls this""" 136 assert isinstance(interface, Interface) 137 138 try: 139 root = qdom.parse(file(source)) 140 except IOError, ex: 141 if ex.errno == 2: 142 raise InvalidInterface("Feed not found. Perhaps this is a local feed that no longer exists? You can remove it from the list of feeds in that case.", ex) 143 raise InvalidInterface("Can't read file", ex) 144 except Exception, ex: 145 raise InvalidInterface("Invalid XML", ex) 146 147 if local: 148 local_path = source 149 else: 150 local_path = None 151 feed = ZeroInstallFeed(root, local_path, distro.get_host_distribution()) 152 feed.last_modified = int(os.stat(source).st_mtime) 153 154 if not local: 155 if feed.url != interface.uri: 156 raise InvalidInterface("Incorrect URL used for feed.\n\n" 157 "%s is given in the feed, but\n" 158 "%s was requested" % 159 (feed.url, interface.uri)) 160 161 interface._main_feed = feed 162 return feed
163