1 """
2 Parses an XML interface into a Python representation.
3 """
4
5
6
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
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
44 path = basedir.load_first_data(config_site, 'native_feeds', model._pretty_escape(interface.uri))
45 if path:
46
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
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
104
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