2 Load and save a set of chosen implementations.
6 # Copyright (C) 2007, Thomas Leonard
7 # See the README file for details, or visit http://0install.net.
11 from zeroinstall
.injector
.policy
import Policy
12 from zeroinstall
.injector
.model
import EnvironmentBinding
, InterfaceDependency
, process_binding
, process_depends
, binding_names
13 from zeroinstall
.injector
.namespaces
import XMLNS_IFACE
14 from zeroinstall
.injector
.qdom
import Element
16 class Selection(object):
17 """A single selected implementation in a L{Selections} set.
18 @ivar dependencies: list of dependencies
19 @type dependencies: [L{model.Dependency}]
20 @ivar version: the implementation's version number
22 __slots__
= ['interface', 'bindings', 'id', 'version', 'feed', 'dependencies', 'main']
24 def __init__(self
, interface
, id, version
, feed
, main
, dependencies
, bindings
= None):
29 if bindings
is None: bindings
= []
30 self
.interface
= interface
32 self
.version
= version
35 self
.dependencies
= dependencies
36 self
.bindings
= bindings
41 class Selections(object):
43 A selected set of components which will make up a complete program.
44 @ivar interface: the interface of the program
46 @ivar selections: the selected implementations
47 @type selections: {str: L{Selection}}
49 __slots__
= ['interface', 'selections']
51 def __init__(self
, source
):
53 if isinstance(source
, Policy
):
54 self
._init
_from
_policy
(source
)
55 elif isinstance(source
, Element
):
56 self
._init
_from
_qdom
(source
)
58 raise Exception("Source not a Policy or qdom.Element!")
60 def _init_from_policy(self
, policy
):
61 """Set the selections from a policy.
62 @param policy: the policy giving the selected implementations."""
63 self
.interface
= policy
.root
65 for needed_iface
in policy
.implementation
:
66 impl
= policy
.implementation
[needed_iface
]
69 self
.selections
[needed_iface
.uri
] = Selection(needed_iface
.uri
, impl
.id,
70 impl
.get_version(), impl
.feed
.url
,
75 def _init_from_qdom(self
, root
):
76 """Parse and load a selections document.
77 @param root: a saved set of selections."""
78 self
.interface
= root
.getAttribute('interface')
81 for selection
in root
.childNodes
:
82 if selection
.uri
!= XMLNS_IFACE
:
84 if selection
.name
!= 'selection':
89 for dep_elem
in selection
.childNodes
:
90 if dep_elem
.uri
!= XMLNS_IFACE
:
92 if dep_elem
.name
in binding_names
:
93 bindings
.append(process_binding(dep_elem
))
94 elif dep_elem
.name
== 'requires':
95 dep
= process_depends(dep_elem
)
98 iface_uri
= selection
.getAttribute('interface')
99 s
= Selection(iface_uri
,
100 selection
.getAttribute('id'),
101 selection
.getAttribute('version'),
102 selection
.getAttribute('from-feed') or iface_uri
,
103 selection
.getAttribute('main'),
106 self
.selections
[iface_uri
] = s
109 """Create a DOM document for the selected implementations.
110 The document gives the URI of the root, plus each selected implementation.
111 For each selected implementation, we record the ID, the version, the URI and
112 (if different) the feed URL. We also record all the bindings needed.
113 @return: a new DOM Document"""
114 from xml
.dom
import minidom
, XMLNS_NAMESPACE
116 assert self
.interface
118 impl
= minidom
.getDOMImplementation()
120 doc
= impl
.createDocument(XMLNS_IFACE
, "selections", None)
122 root
= doc
.documentElement
123 root
.setAttributeNS(XMLNS_NAMESPACE
, 'xmlns', XMLNS_IFACE
)
125 root
.setAttributeNS(None, 'interface', self
.interface
)
127 def ensure_prefix(prefixes
, ns
):
128 prefix
= prefixes
.get(ns
, None)
131 prefix
= 'ns%d' % len(prefixes
)
132 prefixes
[ns
] = prefix
137 for iface
, selection
in sorted(self
.selections
.items()):
138 selection_elem
= doc
.createElementNS(XMLNS_IFACE
, 'selection')
139 selection_elem
.setAttributeNS(None, 'interface', selection
.interface
)
140 root
.appendChild(selection_elem
)
142 selection_elem
.setAttributeNS(None, 'id', selection
.id)
143 selection_elem
.setAttributeNS(None, 'version', selection
.version
)
145 selection_elem
.setAttributeNS(None, 'main', selection
.main
)
146 if selection
.interface
!= selection
.feed
:
147 selection_elem
.setAttributeNS(None, 'from-feed', selection
.feed
)
149 for b
in selection
.bindings
:
150 selection_elem
.appendChild(b
._toxml
(doc
))
152 for dep
in selection
.dependencies
:
153 dep_elem
= doc
.createElementNS(XMLNS_IFACE
, 'requires')
154 dep_elem
.setAttributeNS(None, 'interface', dep
.interface
)
155 selection_elem
.appendChild(dep_elem
)
157 for m
in dep
.metadata
:
158 parts
= m
.split(' ', 1)
162 dep_elem
.setAttributeNS(None, localName
, dep
.metadata
[m
])
164 ns
, localName
= parts
165 dep_elem
.setAttributeNS(ns
, ensure_prefix(prefixes
, ns
) + ':' + localName
, dep
.metadata
[m
])
167 for b
in dep
.bindings
:
168 dep_elem
.appendChild(b
._toxml
(doc
))
170 for ns
, prefix
in prefixes
.items():
171 root
.setAttributeNS(XMLNS_NAMESPACE
, 'xmlns:' + prefix
, ns
)
176 return "Selections for " + self
.interface