Implemented network policy.
[zeroinstall.git] / policy.py
bloba741ded85a3d4362aee038d872f5aa528995910b
1 from model import *
2 import basedir
3 from namespaces import *
4 import ConfigParser
5 import reader
7 class Policy(object):
8 __slots__ = ['root', 'implementation', 'watchers',
9 'help_with_testing', 'network_use', 'updates']
11 def __init__(self):
12 self.root = None
13 self.implementation = {} # Interface -> Implementation
14 self.watchers = []
15 self.help_with_testing = False
16 self.network_use = network_minimal
17 self.updates = []
19 path = basedir.load_first_config(config_site, config_prog, 'global')
20 if path:
21 config = ConfigParser.ConfigParser()
22 config.read(path)
23 self.help_with_testing = config.getboolean('global',
24 'help_with_testing')
25 self.network_use = config.get('global', 'network_use')
26 assert self.network_use in network_levels
28 def set_root_iterface(self, root):
29 assert isinstance(root, Interface)
30 self.root = root
32 def save_config(self):
33 config = ConfigParser.ConfigParser()
34 config.add_section('global')
36 config.set('global', 'help_with_testing', self.help_with_testing)
37 config.set('global', 'network_use', self.network_use)
39 path = basedir.save_config_path(config_site, config_prog)
40 path = os.path.join(path, 'global')
41 config.write(file(path + '.new', 'w'))
42 os.rename(path + '.new', path)
44 def recalculate(self):
45 self.implementation = {}
46 self.updates = []
47 def process(iface):
48 if not iface.uptodate:
49 reader.update_from_cache(iface)
50 assert iface.uptodate
51 impl = self.get_best_implementation(iface)
52 if impl:
53 self.implementation[iface] = impl
54 for d in impl.dependencies.values():
55 process(d.get_interface())
56 process(self.root)
57 for w in self.watchers: w()
59 def get_best_implementation(self, iface):
60 if not iface.implementations:
61 return None
62 impls = iface.implementations.values()
63 best = impls[0]
64 for x in impls[1:]:
65 if self.compare(iface, x, best) < 0:
66 best = x
67 return best
69 def compare(self, interface, b, a):
70 a_stab = a.get_stability()
71 b_stab = b.get_stability()
73 # Usable ones come first
74 r = cmp(self.is_unusable(b), self.is_unusable(a))
75 if r: return r
77 # Preferred versions come first
78 r = cmp(a_stab == preferred, b_stab == preferred)
79 if r: return r
81 if self.network_use != network_full:
82 r = cmp(a.get_cached(), b.get_cached())
83 if r: return r
85 # Stability
86 policy = interface.stability_policy
87 if not policy:
88 if self.help_with_testing: policy = testing
89 else: policy = stable
91 if a_stab >= policy: a_stab = preferred
92 if b_stab >= policy: b_stab = preferred
94 r = cmp(a_stab, b_stab)
95 if r: return r
97 r = cmp(a.version, b.version)
98 if r: return r
100 if self.network_use != network_full:
101 r = cmp(a.get_cached(), b.get_cached())
102 if r: return r
104 return cmp(a.path, b.path)
106 def get_ranked_implementations(self, iface):
107 impls = iface.implementations.values()
108 impls.sort(lambda a, b: self.compare(iface, a, b))
109 return impls
111 def is_unusable(self, impl):
112 if impl.get_stability() <= buggy:
113 return True
114 if self.network_use == network_offline and not impl.get_cached():
115 return True
116 return False
118 # Singleton instance used everywhere...
119 policy = Policy()
120 policy.save_config()