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.
9 # Copyright (C) 2006, Thomas Leonard
10 # See the README file for details, or visit http://0install.net.
13 from logging
import debug
, info
15 from zeroinstall
.injector
import model
, policy
, run
16 from zeroinstall
.injector
.handler
import Handler
17 from zeroinstall
import NeedDownload
19 class AutoPolicy(policy
.Policy
):
20 __slots__
= ['allow_downloads', 'download_only', 'dry_run']
22 def __init__(self
, interface_uri
, download_only
= False, dry_run
= False, src
= False, handler
= None):
23 """@param handler: (new in 0.30) handler to use, or None to create a L{Handler}"""
24 policy
.Policy
.__init
__(self
, interface_uri
, handler
or Handler(), src
= src
)
25 self
.dry_run
= dry_run
26 self
.allow_downloads
= not dry_run
27 self
.download_only
= download_only
28 self
.dry_run
= dry_run
30 def need_download(self
):
31 """Decide whether we need to download anything (but don't do it!)
32 @return: true if we MUST download something (interfaces or implementations)
34 @postcondition: if we return False, self.stale_feeds contains any feeds which SHOULD be updated
36 old
= self
.allow_downloads
37 self
.allow_downloads
= False
40 self
.recalculate(fetch_stale_interfaces
= False)
41 debug("Recalculated: ready = %s; %d stale feeds", self
.ready
, len(self
.stale_feeds
))
42 if not self
.ready
: return False
43 self
.start_downloading_impls()
48 self
.allow_downloads
= old
50 def begin_iface_download(self
, interface
, force
= False):
51 if self
.dry_run
or not self
.allow_downloads
:
52 raise NeedDownload(interface
.uri
)
54 policy
.Policy
.begin_iface_download(self
, interface
, force
)
56 def start_downloading_impls(self
):
57 for iface
, impl
in self
.get_uncached_implementations():
58 debug("start_downloading_impls: for %s get %s", iface
, impl
)
59 source
= self
.get_best_source(impl
)
61 raise model
.SafeException("Implementation " + impl
.id + " of "
62 "interface " + iface
.get_name() + " cannot be "
63 "downloaded (no download locations given in "
65 self
.begin_impl_download(impl
, source
)
67 def begin_archive_download(self
, download_source
, success_callback
, force
= False):
68 if self
.dry_run
or not self
.allow_downloads
:
69 raise NeedDownload(download_source
.url
)
70 return policy
.Policy
.begin_archive_download(self
, download_source
, success_callback
, force
= force
)
72 def execute(self
, prog_args
, main
= None, wrapper
= None):
73 self
.start_downloading_impls()
74 self
.handler
.wait_for_downloads()
75 if not self
.download_only
:
76 run
.execute(self
, prog_args
, dry_run
= self
.dry_run
, main
= main
, wrapper
= wrapper
)
78 info("Downloads done (download-only mode)")
80 def recalculate_with_dl(self
):
82 while self
.handler
.monitored_downloads
:
83 errors
= self
.handler
.wait_for_downloads()
85 raise model
.SafeException("Errors during download: " + '\n'.join(errors
))
88 def download_and_execute(self
, prog_args
, refresh
= False, main
= None):
89 self
.recalculate_with_dl()
91 self
.refresh_all(False)
92 self
.recalculate_with_dl()
94 raise model
.SafeException("Can't find all required implementations:\n" +
95 '\n'.join(["- %s -> %s" % (iface
, self
.implementation
[iface
])
96 for iface
in self
.implementation
]))
97 self
.execute(prog_args
, main
= main
)