Added --wrapper option for debugging and tracing.
[zeroinstall.git] / zeroinstall / injector / autopolicy.py
blobcec0ab297f2dd23befe7de07c0620e9bb51b8179
1 """
2 A simple non-interactive policy.
4 This module provides a simple policy that will select, download and run a suitable set of
5 implementations. It is not interactive. This is the policy used when you run B{0launch -c}, and
6 is also the policy used to run the injector's GUI.
7 """
9 # Copyright (C) 2006, Thomas Leonard
10 # See the README file for details, or visit http://0install.net.
12 import os
13 from logging import debug, info
15 from zeroinstall.injector import model, policy, run, handler
16 from zeroinstall import NeedDownload
18 class AutoPolicy(policy.Policy):
19 __slots__ = ['allow_downloads', 'download_only', 'dry_run']
21 def __init__(self, interface_uri, download_only = False, dry_run = False, src = False):
22 policy.Policy.__init__(self, interface_uri, handler.Handler(), src = src)
23 self.dry_run = dry_run
24 self.allow_downloads = not dry_run
25 self.download_only = download_only
26 self.dry_run = dry_run
28 def need_download(self):
29 """Decide whether we need to download anything (but don't do it!)
30 @return: true if we MUST download something (interfaces or implementations)
31 @rtype: bool
32 @postcondition: if we return False, self.stale_feeds contains any feeds which SHOULD be updated
33 """
34 old = self.allow_downloads
35 self.allow_downloads = False
36 try:
37 try:
38 self.recalculate(fetch_stale_interfaces = False)
39 debug("Recalculated: ready = %s; %d stale feeds", self.ready, len(self.stale_feeds))
40 if not self.ready: return False
41 self.start_downloading_impls()
42 except NeedDownload:
43 return True
44 return False
45 finally:
46 self.allow_downloads = old
48 def begin_iface_download(self, interface, force = False):
49 if self.dry_run or not self.allow_downloads:
50 raise NeedDownload(interface.uri)
51 else:
52 policy.Policy.begin_iface_download(self, interface, force)
54 def start_downloading_impls(self):
55 for iface, impl in self.get_uncached_implementations():
56 debug("start_downloading_impls: for %s get %s", iface, impl)
57 source = self.get_best_source(impl)
58 if not source:
59 raise model.SafeException("Implementation " + impl.id + " of "
60 "interface " + iface.get_name() + " cannot be "
61 "downloaded (no download locations given in "
62 "interface!)")
63 self.begin_impl_download(impl, source)
65 def begin_archive_download(self, download_source, success_callback, force = False):
66 if self.dry_run or not self.allow_downloads:
67 raise NeedDownload(download_source.url)
68 return policy.Policy.begin_archive_download(self, download_source, success_callback, force = force)
70 def execute(self, prog_args, main = None, wrapper = None):
71 self.start_downloading_impls()
72 self.handler.wait_for_downloads()
73 if not self.download_only:
74 run.execute(self, prog_args, dry_run = self.dry_run, main = main, wrapper = wrapper)
75 else:
76 info("Downloads done (download-only mode)")
78 def recalculate_with_dl(self):
79 self.recalculate()
80 while self.handler.monitored_downloads:
81 self.handler.wait_for_downloads()
82 self.recalculate()
84 def download_and_execute(self, prog_args, refresh = False, main = None):
85 self.recalculate_with_dl()
86 if refresh:
87 self.refresh_all(False)
88 self.recalculate_with_dl()
89 if not self.ready:
90 raise model.SafeException("Can't find all required implementations:\n" +
91 '\n'.join(["- %s -> %s" % (iface, self.implementation[iface])
92 for iface in self.implementation]))
93 self.execute(prog_args, main = main)