blob: 8927ac7d8cf997f3c4ce0c36b758a2114ff7bc8e [file] [log] [blame]
#
# Copyright (C) 2016 The Android Open Source Project
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
"""This file provides all Packs element related parsing."""
from project import collection
from project import common
from project import loader
from project import pack
class PacksFactory(object):
@staticmethod
def new(**kwargs):
"""Creates a new Packs instance from an XML file or element.
Walks an ElementTree element looking for <pack> child
nodes and instantiates Pack objects.
Args:
**kwargs: Any valid keywords for loader.PathElementLoader.load()
Returns:
new Packs() instance
Raises
LoadError: LoadError, or a subclass, will be raised if an error
occurs loading and validating content from the XML.
"""
ps = Packs()
l = loader.PathElementLoader('packs', ['namespace'])
# Get the final root node.
root = l.load(**kwargs)
root.limit_attribs(['version', 'namespace', 'path'])
ps.namespace = root.get_attrib('namespace')
ns = ps.namespace
# pylint: disable=no-member
if 'namespace' in root.old_attrib:
ns = root.old_attrib['namespace']
packs = {}
for node in root.findall('pack'):
name = node.get_attrib('name')
if name in packs:
# Note, this only catch duplication within the same
# packs tree. As packs namespaces are non-unique, collision
# can occur when aggregating packs.
raise common.LoadErrorWithOrigin(
node,
'Duplicate pack {} in namespace {}'.format(name,
ps.namespace))
p = pack.Pack(ns, name)
p.load(node)
# Even if 'namespace' is carried over in the root attributes, we
# have to alias any global requires/provides in the pack.
if ns != ps.namespace:
p.alias(ps.namespace)
packs[name] = p
ps.entries = packs
ps.origins = l.origins
return ps
class Packs(collection.Base):
"""Collection of Pack objects."""
def __init__(self):
super(Packs, self).__init__('packs')
self._namespace = ()
@property
def packs(self):
return self.entries
@property
def namespace(self):
"""Return the namespace for all child pack objects."""
return self._namespace
@namespace.setter
def namespace(self, ns):
for pack_ in self._entries.values():
pack_.alias(ns)
self._namespace = ns
def add_pack(self, new_pack):
if new_pack.name in self.entries:
# Note, this only catch duplication within the same
# packs tree. As packs namespaces are non-unique, collision
# can occur when aggregating packs.
raise common.LoadErrorWithOrigin(
new_pack.origin,
'Duplicate pack {} in namespace {}'.format(new_pack.name,
self.namespace))
self.entries[new_pack.name] = new_pack
def __repr__(self):
return '<packs namespace="{}">{}</packs>'.format(
self._namespace, ''.join([str(p) for p in self._entries.values()]))