| # |
| # 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()])) |