177b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin#!/usr/bin/python 277b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin 377b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin# 477b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin# Copyright (C) 2012 The Android Open Source Project 577b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin# 677b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin# Licensed under the Apache License, Version 2.0 (the "License"); 777b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin# you may not use this file except in compliance with the License. 877b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin# You may obtain a copy of the License at 977b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin# 1077b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin# http://www.apache.org/licenses/LICENSE-2.0 1177b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin# 1277b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin# Unless required by applicable law or agreed to in writing, software 1377b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin# distributed under the License is distributed on an "AS IS" BASIS, 1477b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1577b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin# See the License for the specific language governing permissions and 1677b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin# limitations under the License. 1777b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin# 1877b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin 1977b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin""" 2077b63ca0447545a4dac3ac062f218d878ce01ba0Igor MurashkinA set of classes (models) each closely representing an XML node in the 2177b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkinmetadata_properties.xml file. 2277b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin 2377b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin Node: Base class for most nodes. 2477b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin Entry: A node corresponding to <entry> elements. 2577b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin Clone: A node corresponding to <clone> elements. 26aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin MergedEntry: A node corresponding to either <entry> or <clone> elements. 2777b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin Kind: A node corresponding to <dynamic>, <static>, <controls> elements. 2877b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin InnerNamespace: A node corresponding to a <namespace> nested under a <kind>. 2977b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin OuterNamespace: A node corresponding to a <namespace> with <kind> children. 3077b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin Section: A node corresponding to a <section> element. 3177b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin Enum: A class corresponding an <enum> element within an <entry> 32aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin EnumValue: A class corresponding to a <value> element within an Enum 3377b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin Metadata: Root node that also provides tree construction functionality. 3477b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin Tag: A node corresponding to a top level <tag> element. 35b8dc88148bca2e5a267c2ff39aff94b98b00ad6dIgor Murashkin Typedef: A node corresponding to a <typedef> element under <types>. 3677b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin""" 3777b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin 3877b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkinimport sys 395804a48bb15d245fb06f72cf6d64369f151fcc28Igor Murashkinimport itertools 40586c861e6dab3fdf48fc8440c719ad0b59d49d72Igor Murashkinfrom collections import OrderedDict 4177b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin 4277b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkinclass Node(object): 4377b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin """ 4477b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin Base class for most nodes that are part of the Metadata graph. 4577b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin 4677b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin Attributes (Read-Only): 4777b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin parent: An edge to a parent Node. 4877b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin name: A string describing the name, usually but not always the 'name' 4977b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin attribute of the corresponding XML node. 5077b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin """ 5177b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin 5277b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin def __init__(self): 5377b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin self._parent = None 5477b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin self._name = None 5577b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin 5677b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin @property 5777b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin def parent(self): 5877b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin return self._parent 5977b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin 6077b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin @property 6177b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin def name(self): 6277b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin return self._name 6377b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin 6477b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin def find_all(self, pred): 6577b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin """ 6677b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin Find all descendants that match the predicate. 6777b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin 6877b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin Args: 6977b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin pred: a predicate function that acts as a filter for a Node 7077b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin 7177b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin Yields: 7277b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin A sequence of all descendants for which pred(node) is true, 7377b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin in a pre-order visit order. 7477b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin """ 7577b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin if pred(self): 7677b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin yield self 7777b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin 7877b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin if self._get_children() is None: 7977b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin return 8077b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin 8177b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin for i in self._get_children(): 8277b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin for j in i.find_all(pred): 8377b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin yield j 8477b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin 8577b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin def find_first(self, pred): 8677b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin """ 8777b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin Find the first descendant that matches the predicate. 8877b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin 8977b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin Args: 9077b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin pred: a predicate function that acts as a filter for a Node 9177b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin 9277b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin Returns: 9377b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin The first Node from find_all(pred), or None if there were no results. 9477b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin """ 9577b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin for i in self.find_all(pred): 9677b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin return i 9777b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin 9877b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin return None 9977b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin 10077b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin def find_parent_first(self, pred): 10177b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin """ 10277b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin Find the first ancestor that matches the predicate. 10377b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin 10477b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin Args: 10577b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin pred: A predicate function that acts as a filter for a Node 10677b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin 10777b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin Returns: 10877b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin The first ancestor closest to the node for which pred(node) is true. 10977b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin """ 11077b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin for i in self.find_parents(pred): 11177b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin return i 11277b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin 11377b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin return None 11477b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin 11577b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin def find_parents(self, pred): 11677b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin """ 11777b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin Find all ancestors that match the predicate. 11877b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin 11977b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin Args: 12077b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin pred: A predicate function that acts as a filter for a Node 12177b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin 12277b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin Yields: 12377b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin A sequence of all ancestors (closest to furthest) from the node, 12477b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin where pred(node) is true. 12577b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin """ 12677b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin parent = self.parent 12777b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin 12877b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin while parent is not None: 12977b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin if pred(parent): 13077b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin yield parent 13177b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin parent = parent.parent 13277b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin 13377b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin def sort_children(self): 13477b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin """ 13577b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin Sorts the immediate children in-place. 13677b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin """ 13777b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin self._sort_by_name(self._children) 13877b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin 13977b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin def _sort_by_name(self, what): 14077b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin what.sort(key=lambda x: x.name) 14177b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin 14277b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin def _get_name(self): 14377b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin return lambda x: x.name 14477b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin 14577b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin # Iterate over all children nodes. None when node doesn't support children. 14677b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin def _get_children(self): 14777b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin return (i for i in self._children) 14877b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin 14977b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin def _children_name_map_matching(self, match=lambda x: True): 15077b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin d = {} 151aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin for i in self._get_children(): 15277b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin if match(i): 15377b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin d[i.name] = i 15477b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin return d 15577b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin 15677b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin @staticmethod 15777b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin def _dictionary_by_name(values): 158586c861e6dab3fdf48fc8440c719ad0b59d49d72Igor Murashkin d = OrderedDict() 15977b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin for i in values: 16077b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin d[i.name] = i 16177b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin 16277b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin return d 16377b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin 16477b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin def validate_tree(self): 16577b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin """ 16677b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin Sanity check the tree recursively, ensuring for a node n, all children's 16777b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin parents are also n. 16877b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin 16977b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin Returns: 17077b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin True if validation succeeds, False otherwise. 17177b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin """ 17277b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin succ = True 17377b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin children = self._get_children() 17477b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin if children is None: 17577b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin return True 17677b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin 17777b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin for child in self._get_children(): 17877b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin if child.parent != self: 17977b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin print >> sys.stderr, ("ERROR: Node '%s' doesn't match the parent" + \ 18077b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin "(expected: %s, actual %s)") \ 18177b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin %(child, self, child.parent) 18277b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin succ = False 18377b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin 18477b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin succ = child.validate_tree() and succ 18577b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin 18677b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin return succ 18777b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin 18877b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin def __str__(self): 18977b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin return "<%s name='%s'>" %(self.__class__, self.name) 19077b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin 19177b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkinclass Metadata(Node): 19277b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin """ 19377b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin A node corresponding to a <metadata> entry. 19477b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin 19577b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin Attributes (Read-Only): 19677b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin parent: An edge to the parent Node. This is always None for Metadata. 19777b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin outer_namespaces: A sequence of immediate OuterNamespace children. 19877b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin tags: A sequence of all Tag instances available in the graph. 199b8dc88148bca2e5a267c2ff39aff94b98b00ad6dIgor Murashkin types: An iterable of all Typedef instances available in the graph. 20077b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin """ 20177b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin 20277b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin def __init__(self): 20377b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin """ 20477b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin Initialize with no children. Use insert_* functions and then 20577b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin construct_graph() to build up the Metadata from some source. 20677b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin """ 20777b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin 20877b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin# Private 20977b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin self._entries = [] 21077b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin # kind => { name => entry } 21177b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin self._entry_map = { 'static': {}, 'dynamic': {}, 'controls': {} } 212586c861e6dab3fdf48fc8440c719ad0b59d49d72Igor Murashkin self._entries_ordered = [] # list of ordered Entry/Clone instances 21377b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin self._clones = [] 21477b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin 21577b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin# Public (Read Only) 21677b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin self._parent = None 21777b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin self._outer_namespaces = None 21877b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin self._tags = [] 219b8dc88148bca2e5a267c2ff39aff94b98b00ad6dIgor Murashkin self._types = [] 22077b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin 22177b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin @property 22277b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin def outer_namespaces(self): 22377b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin if self._outer_namespaces is None: 22477b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin return None 22577b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin else: 22677b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin return (i for i in self._outer_namespaces) 22777b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin 22877b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin @property 22977b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin def tags(self): 23077b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin return (i for i in self._tags) 23177b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin 232b8dc88148bca2e5a267c2ff39aff94b98b00ad6dIgor Murashkin @property 233b8dc88148bca2e5a267c2ff39aff94b98b00ad6dIgor Murashkin def types(self): 234b8dc88148bca2e5a267c2ff39aff94b98b00ad6dIgor Murashkin return (i for i in self._types) 235b8dc88148bca2e5a267c2ff39aff94b98b00ad6dIgor Murashkin 23677b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin def _get_properties(self): 23777b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin 23877b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin for i in self._entries: 23977b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin yield i 24077b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin 24177b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin for i in self._clones: 24277b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin yield i 24377b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin 24477b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin def insert_tag(self, tag, description=""): 24577b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin """ 24677b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin Insert a tag into the metadata. 24777b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin 24877b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin Args: 24977b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin tag: A string identifier for a tag. 25077b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin description: A string description for a tag. 25177b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin 25277b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin Example: 25377b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin metadata.insert_tag("BC", "Backwards Compatibility for old API") 25477b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin 25577b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin Remarks: 25677b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin Subsequent calls to insert_tag with the same tag are safe (they will 25777b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin be ignored). 25877b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin """ 25977b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin tag_ids = [tg.name for tg in self.tags if tg.name == tag] 26077b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin if not tag_ids: 2616ad61d460aabf8db9b52e946bb38b8f20717b2a8Igor Murashkin self._tags.append(Tag(tag, self, description)) 26277b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin 263b8dc88148bca2e5a267c2ff39aff94b98b00ad6dIgor Murashkin def insert_type(self, type_name, type_selector="typedef", **kwargs): 264b8dc88148bca2e5a267c2ff39aff94b98b00ad6dIgor Murashkin """ 265b8dc88148bca2e5a267c2ff39aff94b98b00ad6dIgor Murashkin Insert a type into the metadata. 266b8dc88148bca2e5a267c2ff39aff94b98b00ad6dIgor Murashkin 267b8dc88148bca2e5a267c2ff39aff94b98b00ad6dIgor Murashkin Args: 268b8dc88148bca2e5a267c2ff39aff94b98b00ad6dIgor Murashkin type_name: A type's name 269b8dc88148bca2e5a267c2ff39aff94b98b00ad6dIgor Murashkin type_selector: The selector for the type, e.g. 'typedef' 270b8dc88148bca2e5a267c2ff39aff94b98b00ad6dIgor Murashkin 271b8dc88148bca2e5a267c2ff39aff94b98b00ad6dIgor Murashkin Args (if type_selector == 'typedef'): 272b8dc88148bca2e5a267c2ff39aff94b98b00ad6dIgor Murashkin languages: A map of 'language name' -> 'fully qualified class path' 273b8dc88148bca2e5a267c2ff39aff94b98b00ad6dIgor Murashkin 274b8dc88148bca2e5a267c2ff39aff94b98b00ad6dIgor Murashkin Example: 275b8dc88148bca2e5a267c2ff39aff94b98b00ad6dIgor Murashkin metadata.insert_type('rectangle', 'typedef', 276b8dc88148bca2e5a267c2ff39aff94b98b00ad6dIgor Murashkin { 'java': 'android.graphics.Rect' }) 277b8dc88148bca2e5a267c2ff39aff94b98b00ad6dIgor Murashkin 278b8dc88148bca2e5a267c2ff39aff94b98b00ad6dIgor Murashkin Remarks: 279b8dc88148bca2e5a267c2ff39aff94b98b00ad6dIgor Murashkin Subsequent calls to insert_type with the same type name are safe (they 280b8dc88148bca2e5a267c2ff39aff94b98b00ad6dIgor Murashkin will be ignored) 281b8dc88148bca2e5a267c2ff39aff94b98b00ad6dIgor Murashkin """ 282b8dc88148bca2e5a267c2ff39aff94b98b00ad6dIgor Murashkin 283b8dc88148bca2e5a267c2ff39aff94b98b00ad6dIgor Murashkin if type_selector != 'typedef': 284b8dc88148bca2e5a267c2ff39aff94b98b00ad6dIgor Murashkin raise ValueError("Unsupported type_selector given " + type_selector) 285b8dc88148bca2e5a267c2ff39aff94b98b00ad6dIgor Murashkin 286b8dc88148bca2e5a267c2ff39aff94b98b00ad6dIgor Murashkin type_names = [tp.name for tp in self.types if tp.name == tp] 287b8dc88148bca2e5a267c2ff39aff94b98b00ad6dIgor Murashkin if not type_names: 288b8dc88148bca2e5a267c2ff39aff94b98b00ad6dIgor Murashkin self._types.append(Typedef(type_name, self, kwargs.get('languages'))) 289b8dc88148bca2e5a267c2ff39aff94b98b00ad6dIgor Murashkin 29077b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin def insert_entry(self, entry): 29177b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin """ 29277b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin Insert an entry into the metadata. 29377b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin 29477b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin Args: 29577b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin entry: A key-value dictionary describing an entry. Refer to 29677b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin Entry#__init__ for the keys required/optional. 29777b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin 29877b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin Remarks: 29977b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin Subsequent calls to insert_entry with the same entry+kind name are safe 30077b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin (they will be ignored). 30177b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin """ 30277b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin e = Entry(**entry) 30377b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin self._entries.append(e) 30477b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin self._entry_map[e.kind][e.name] = e 305586c861e6dab3fdf48fc8440c719ad0b59d49d72Igor Murashkin self._entries_ordered.append(e) 30677b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin 30777b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin def insert_clone(self, clone): 30877b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin """ 30977b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin Insert a clone into the metadata. 31077b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin 31177b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin Args: 31277b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin clone: A key-value dictionary describing a clone. Refer to 31377b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin Clone#__init__ for the keys required/optional. 31477b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin 31577b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin Remarks: 31677b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin Subsequent calls to insert_clone with the same clone+kind name are safe 31777b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin (they will be ignored). Also the target entry need not be inserted 31877b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin ahead of the clone entry. 31977b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin """ 32077b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin # figure out corresponding entry later. allow clone insert, entry insert 32177b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin entry = None 32277b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin c = Clone(entry, **clone) 32377b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin self._entry_map[c.kind][c.name] = c 32477b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin self._clones.append(c) 325586c861e6dab3fdf48fc8440c719ad0b59d49d72Igor Murashkin self._entries_ordered.append(c) 32677b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin 32777b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin def prune_clones(self): 32877b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin """ 32977b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin Remove all clones that don't point to an existing entry. 33077b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin 33177b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin Remarks: 33277b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin This should be called after all insert_entry/insert_clone calls have 33377b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin finished. 33477b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin """ 33577b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin remove_list = [] 33677b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin for p in self._clones: 33777b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin if p.entry is None: 33877b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin remove_list.append(p) 33977b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin 34077b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin for p in remove_list: 34177b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin 34277b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin # remove from parent's entries list 34377b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin if p.parent is not None: 34477b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin p.parent._entries.remove(p) 34577b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin # remove from parents' _leafs list 346aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin for ancestor in p.find_parents(lambda x: not isinstance(x, Metadata)): 34777b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin ancestor._leafs.remove(p) 34877b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin 34977b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin # remove from global list 35077b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin self._clones.remove(p) 35177b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin self._entry_map[p.kind].pop(p.name) 352586c861e6dab3fdf48fc8440c719ad0b59d49d72Igor Murashkin self._entries_ordered.remove(p) 35377b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin 35477b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin 35577b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin # After all entries/clones are inserted, 35677b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin # invoke this to generate the parent/child node graph all these objects 35777b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin def construct_graph(self): 35877b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin """ 35977b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin Generate the graph recursively, after which all Entry nodes will be 36077b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin accessible recursively by crawling through the outer_namespaces sequence. 36177b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin 36277b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin Remarks: 36377b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin This is safe to be called multiple times at any time. It should be done at 36477b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin least once or there will be no graph. 36577b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin """ 36677b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin self.validate_tree() 36777b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin self._construct_tags() 36877b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin self.validate_tree() 369b8dc88148bca2e5a267c2ff39aff94b98b00ad6dIgor Murashkin self._construct_types() 370b8dc88148bca2e5a267c2ff39aff94b98b00ad6dIgor Murashkin self.validate_tree() 37177b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin self._construct_clones() 37277b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin self.validate_tree() 37377b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin self._construct_outer_namespaces() 37477b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin self.validate_tree() 37577b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin 37677b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin def _construct_tags(self): 37777b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin tag_dict = self._dictionary_by_name(self.tags) 37877b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin for p in self._get_properties(): 37977b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin p._tags = [] 38077b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin for tag_id in p._tag_ids: 38177b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin tag = tag_dict.get(tag_id) 38277b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin 38377b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin if tag not in p._tags: 38477b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin p._tags.append(tag) 38577b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin 386617da1675f9ea7b6ea33d9e6f47e0a07379f14b1Igor Murashkin if p not in tag.entries: 387617da1675f9ea7b6ea33d9e6f47e0a07379f14b1Igor Murashkin tag._entries.append(p) 388617da1675f9ea7b6ea33d9e6f47e0a07379f14b1Igor Murashkin 389b8dc88148bca2e5a267c2ff39aff94b98b00ad6dIgor Murashkin def _construct_types(self): 390b8dc88148bca2e5a267c2ff39aff94b98b00ad6dIgor Murashkin type_dict = self._dictionary_by_name(self.types) 391b8dc88148bca2e5a267c2ff39aff94b98b00ad6dIgor Murashkin for p in self._get_properties(): 392b8dc88148bca2e5a267c2ff39aff94b98b00ad6dIgor Murashkin if p._type_name: 393b8dc88148bca2e5a267c2ff39aff94b98b00ad6dIgor Murashkin type_node = type_dict.get(p._type_name) 394b8dc88148bca2e5a267c2ff39aff94b98b00ad6dIgor Murashkin p._typedef = type_node 395b8dc88148bca2e5a267c2ff39aff94b98b00ad6dIgor Murashkin 396b8dc88148bca2e5a267c2ff39aff94b98b00ad6dIgor Murashkin if p not in type_node.entries: 397b8dc88148bca2e5a267c2ff39aff94b98b00ad6dIgor Murashkin type_node._entries.append(p) 398b8dc88148bca2e5a267c2ff39aff94b98b00ad6dIgor Murashkin 39977b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin def _construct_clones(self): 40077b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin for p in self._clones: 40177b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin target_kind = p.target_kind 40277b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin target_entry = self._entry_map[target_kind].get(p.name) 40377b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin p._entry = target_entry 40477b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin 40577b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin # should not throw if we pass validation 40677b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin # but can happen when importing obsolete CSV entries 40777b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin if target_entry is None: 40877b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin print >> sys.stderr, ("WARNING: Clone entry '%s' target kind '%s'" + \ 40977b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin " has no corresponding entry") \ 41077b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin %(p.name, p.target_kind) 41177b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin 41277b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin def _construct_outer_namespaces(self): 41377b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin 41477b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin if self._outer_namespaces is None: #the first time this runs 41577b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin self._outer_namespaces = [] 41677b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin 41777b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin root = self._dictionary_by_name(self._outer_namespaces) 41877b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin for ons_name, ons in root.iteritems(): 41977b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin ons._leafs = [] 42077b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin 421586c861e6dab3fdf48fc8440c719ad0b59d49d72Igor Murashkin for p in self._entries_ordered: 42277b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin ons_name = p.get_outer_namespace() 42377b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin ons = root.get(ons_name, OuterNamespace(ons_name, self)) 42477b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin root[ons_name] = ons 42577b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin 42677b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin if p not in ons._leafs: 42777b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin ons._leafs.append(p) 42877b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin 42977b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin for ons_name, ons in root.iteritems(): 43077b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin 43177b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin ons.validate_tree() 43277b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin 43377b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin self._construct_sections(ons) 43477b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin 43577b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin if ons not in self._outer_namespaces: 43677b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin self._outer_namespaces.append(ons) 43777b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin 43877b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin ons.validate_tree() 43977b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin 44077b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin def _construct_sections(self, outer_namespace): 44177b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin 44277b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin sections_dict = self._dictionary_by_name(outer_namespace.sections) 44377b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin for sec_name, sec in sections_dict.iteritems(): 44477b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin sec._leafs = [] 44577b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin sec.validate_tree() 44677b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin 44777b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin for p in outer_namespace._leafs: 44877b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin does_exist = sections_dict.get(p.get_section()) 44977b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin 45077b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin sec = sections_dict.get(p.get_section(), \ 45177b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin Section(p.get_section(), outer_namespace)) 45277b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin sections_dict[p.get_section()] = sec 45377b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin 45477b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin sec.validate_tree() 45577b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin 45677b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin if p not in sec._leafs: 45777b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin sec._leafs.append(p) 45877b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin 45977b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin for sec_name, sec in sections_dict.iteritems(): 46077b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin 46177b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin if not sec.validate_tree(): 46277b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin print >> sys.stderr, ("ERROR: Failed to validate tree in " + \ 46377b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin "construct_sections (start), with section = '%s'")\ 46477b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin %(sec) 46577b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin 46677b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin self._construct_kinds(sec) 46777b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin 46877b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin if sec not in outer_namespace.sections: 46977b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin outer_namespace._sections.append(sec) 47077b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin 47177b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin if not sec.validate_tree(): 47277b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin print >> sys.stderr, ("ERROR: Failed to validate tree in " + \ 47377b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin "construct_sections (end), with section = '%s'") \ 47477b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin %(sec) 47577b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin 47677b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin # 'controls', 'static' 'dynamic'. etc 47777b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin def _construct_kinds(self, section): 4785804a48bb15d245fb06f72cf6d64369f151fcc28Igor Murashkin for kind in section.kinds: 47977b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin kind._leafs = [] 48077b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin section.validate_tree() 48177b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin 4825804a48bb15d245fb06f72cf6d64369f151fcc28Igor Murashkin group_entry_by_kind = itertools.groupby(section._leafs, lambda x: x.kind) 4835804a48bb15d245fb06f72cf6d64369f151fcc28Igor Murashkin leaf_it = ((k, g) for k, g in group_entry_by_kind) 48477b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin 4855804a48bb15d245fb06f72cf6d64369f151fcc28Igor Murashkin # allow multiple kinds with the same name. merge if adjacent 4865804a48bb15d245fb06f72cf6d64369f151fcc28Igor Murashkin # e.g. dynamic,dynamic,static,static,dynamic -> dynamic,static,dynamic 4875804a48bb15d245fb06f72cf6d64369f151fcc28Igor Murashkin # this helps maintain ABI compatibility when adding an entry in a new kind 4885804a48bb15d245fb06f72cf6d64369f151fcc28Igor Murashkin for idx, (kind_name, entry_it) in enumerate(leaf_it): 4895804a48bb15d245fb06f72cf6d64369f151fcc28Igor Murashkin if idx >= len(section._kinds): 4905804a48bb15d245fb06f72cf6d64369f151fcc28Igor Murashkin kind = Kind(kind_name, section) 4915804a48bb15d245fb06f72cf6d64369f151fcc28Igor Murashkin section._kinds.append(kind) 4925804a48bb15d245fb06f72cf6d64369f151fcc28Igor Murashkin section.validate_tree() 49377b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin 4945804a48bb15d245fb06f72cf6d64369f151fcc28Igor Murashkin kind = section._kinds[idx] 49577b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin 4965804a48bb15d245fb06f72cf6d64369f151fcc28Igor Murashkin for p in entry_it: 4975804a48bb15d245fb06f72cf6d64369f151fcc28Igor Murashkin if p not in kind._leafs: 4985804a48bb15d245fb06f72cf6d64369f151fcc28Igor Murashkin kind._leafs.append(p) 49977b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin 5005804a48bb15d245fb06f72cf6d64369f151fcc28Igor Murashkin for kind in section._kinds: 50177b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin kind.validate_tree() 50277b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin self._construct_inner_namespaces(kind) 50377b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin kind.validate_tree() 50477b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin self._construct_entries(kind) 50577b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin kind.validate_tree() 50677b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin 50777b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin if not section.validate_tree(): 50877b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin print >> sys.stderr, ("ERROR: Failed to validate tree in " + \ 50977b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin "construct_kinds, with kind = '%s'") %(kind) 51077b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin 51177b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin if not kind.validate_tree(): 51277b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin print >> sys.stderr, ("ERROR: Failed to validate tree in " + \ 51377b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin "construct_kinds, with kind = '%s'") %(kind) 51477b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin 51577b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin def _construct_inner_namespaces(self, parent, depth=0): 51677b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin #parent is InnerNamespace or Kind 51777b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin ins_dict = self._dictionary_by_name(parent.namespaces) 51877b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin for name, ins in ins_dict.iteritems(): 51977b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin ins._leafs = [] 52077b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin 52177b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin for p in parent._leafs: 52277b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin ins_list = p.get_inner_namespace_list() 52377b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin 52477b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin if len(ins_list) > depth: 52577b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin ins_str = ins_list[depth] 52677b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin ins = ins_dict.get(ins_str, InnerNamespace(ins_str, parent)) 52777b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin ins_dict[ins_str] = ins 52877b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin 52977b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin if p not in ins._leafs: 53077b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin ins._leafs.append(p) 53177b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin 53277b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin for name, ins in ins_dict.iteritems(): 53377b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin ins.validate_tree() 53477b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin # construct children INS 53577b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin self._construct_inner_namespaces(ins, depth + 1) 53677b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin ins.validate_tree() 53777b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin # construct children entries 53877b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin self._construct_entries(ins, depth + 1) 53977b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin 54077b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin if ins not in parent.namespaces: 54177b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin parent._namespaces.append(ins) 54277b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin 54377b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin if not ins.validate_tree(): 54477b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin print >> sys.stderr, ("ERROR: Failed to validate tree in " + \ 54577b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin "construct_inner_namespaces, with ins = '%s'") \ 54677b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin %(ins) 54777b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin 54877b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin # doesnt construct the entries, so much as links them 54977b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin def _construct_entries(self, parent, depth=0): 55077b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin #parent is InnerNamespace or Kind 55177b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin entry_dict = self._dictionary_by_name(parent.entries) 55277b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin for p in parent._leafs: 55377b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin ins_list = p.get_inner_namespace_list() 55477b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin 55577b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin if len(ins_list) == depth: 55677b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin entry = entry_dict.get(p.name, p) 55777b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin entry_dict[p.name] = entry 55877b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin 55977b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin for name, entry in entry_dict.iteritems(): 56077b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin 56177b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin old_parent = entry.parent 56277b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin entry._parent = parent 56377b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin 56477b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin if entry not in parent.entries: 56577b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin parent._entries.append(entry) 56677b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin 56777b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin if old_parent is not None and old_parent != parent: 56877b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin print >> sys.stderr, ("ERROR: Parent changed from '%s' to '%s' for " + \ 56977b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin "entry '%s'") \ 57077b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin %(old_parent.name, parent.name, entry.name) 57177b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin 57277b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin def _get_children(self): 57377b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin if self.outer_namespaces is not None: 57477b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin for i in self.outer_namespaces: 57577b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin yield i 57677b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin 57777b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin if self.tags is not None: 57877b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin for i in self.tags: 57977b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin yield i 58077b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin 58177b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkinclass Tag(Node): 58277b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin """ 58377b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin A tag Node corresponding to a top-level <tag> element. 58477b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin 58577b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin Attributes (Read-Only): 58677b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin name: alias for id 58777b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin id: The name of the tag, e.g. for <tag id="BC"/> id = 'BC' 58877b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin description: The description of the tag, the contents of the <tag> element. 58977b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin parent: An edge to the parent, which is always the Metadata root node. 59077b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin entries: A sequence of edges to entries/clones that are using this Tag. 59177b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin """ 59277b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin def __init__(self, name, parent, description=""): 59377b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin self._name = name # 'id' attribute in XML 59477b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin self._id = name 59577b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin self._description = description 59677b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin self._parent = parent 59777b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin 59877b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin # all entries that have this tag, including clones 599617da1675f9ea7b6ea33d9e6f47e0a07379f14b1Igor Murashkin self._entries = [] # filled in by Metadata#construct_tags 60077b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin 60177b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin @property 60277b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin def id(self): 60377b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin return self._id 60477b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin 60577b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin @property 60677b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin def description(self): 60777b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin return self._description 60877b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin 60977b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin @property 61077b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin def entries(self): 61177b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin return (i for i in self._entries) 61277b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin 61377b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin def _get_children(self): 61477b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin return None 61577b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin 616b8dc88148bca2e5a267c2ff39aff94b98b00ad6dIgor Murashkinclass Typedef(Node): 617b8dc88148bca2e5a267c2ff39aff94b98b00ad6dIgor Murashkin """ 618b8dc88148bca2e5a267c2ff39aff94b98b00ad6dIgor Murashkin A typedef Node corresponding to a <typedef> element under a top-level <types>. 619b8dc88148bca2e5a267c2ff39aff94b98b00ad6dIgor Murashkin 620b8dc88148bca2e5a267c2ff39aff94b98b00ad6dIgor Murashkin Attributes (Read-Only): 621b8dc88148bca2e5a267c2ff39aff94b98b00ad6dIgor Murashkin name: The name of this typedef as a string. 622b8dc88148bca2e5a267c2ff39aff94b98b00ad6dIgor Murashkin languages: A dictionary of 'language name' -> 'fully qualified class'. 623b8dc88148bca2e5a267c2ff39aff94b98b00ad6dIgor Murashkin parent: An edge to the parent, which is always the Metadata root node. 624b8dc88148bca2e5a267c2ff39aff94b98b00ad6dIgor Murashkin entries: An iterable over all entries which reference this typedef. 625b8dc88148bca2e5a267c2ff39aff94b98b00ad6dIgor Murashkin """ 626b8dc88148bca2e5a267c2ff39aff94b98b00ad6dIgor Murashkin def __init__(self, name, parent, languages=None): 627b8dc88148bca2e5a267c2ff39aff94b98b00ad6dIgor Murashkin self._name = name 628b8dc88148bca2e5a267c2ff39aff94b98b00ad6dIgor Murashkin self._parent = parent 629b8dc88148bca2e5a267c2ff39aff94b98b00ad6dIgor Murashkin 630b8dc88148bca2e5a267c2ff39aff94b98b00ad6dIgor Murashkin # all entries that have this typedef 631b8dc88148bca2e5a267c2ff39aff94b98b00ad6dIgor Murashkin self._entries = [] # filled in by Metadata#construct_types 632b8dc88148bca2e5a267c2ff39aff94b98b00ad6dIgor Murashkin 633b8dc88148bca2e5a267c2ff39aff94b98b00ad6dIgor Murashkin self._languages = languages or {} 634b8dc88148bca2e5a267c2ff39aff94b98b00ad6dIgor Murashkin 635b8dc88148bca2e5a267c2ff39aff94b98b00ad6dIgor Murashkin @property 636b8dc88148bca2e5a267c2ff39aff94b98b00ad6dIgor Murashkin def languages(self): 637b8dc88148bca2e5a267c2ff39aff94b98b00ad6dIgor Murashkin return self._languages 638b8dc88148bca2e5a267c2ff39aff94b98b00ad6dIgor Murashkin 639b8dc88148bca2e5a267c2ff39aff94b98b00ad6dIgor Murashkin @property 640b8dc88148bca2e5a267c2ff39aff94b98b00ad6dIgor Murashkin def entries(self): 641b8dc88148bca2e5a267c2ff39aff94b98b00ad6dIgor Murashkin return (i for i in self._entries) 642b8dc88148bca2e5a267c2ff39aff94b98b00ad6dIgor Murashkin 643b8dc88148bca2e5a267c2ff39aff94b98b00ad6dIgor Murashkin def _get_children(self): 644b8dc88148bca2e5a267c2ff39aff94b98b00ad6dIgor Murashkin return None 645b8dc88148bca2e5a267c2ff39aff94b98b00ad6dIgor Murashkin 64677b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkinclass OuterNamespace(Node): 64777b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin """ 64877b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin A node corresponding to a <namespace> element under <metadata> 64977b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin 65077b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin Attributes (Read-Only): 65177b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin name: The name attribute of the <namespace name="foo"> element. 65277b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin parent: An edge to the parent, which is always the Metadata root node. 65377b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin sections: A sequence of Section children. 65477b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin """ 65577b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin def __init__(self, name, parent, sections=[]): 65677b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin self._name = name 65777b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin self._parent = parent # MetadataSet 65877b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin self._sections = sections[:] 65977b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin self._leafs = [] 66077b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin 66177b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin self._children = self._sections 66277b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin 66377b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin @property 66477b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin def sections(self): 66577b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin return (i for i in self._sections) 66677b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin 66777b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkinclass Section(Node): 66877b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin """ 66977b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin A node corresponding to a <section> element under <namespace> 67077b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin 67177b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin Attributes (Read-Only): 67277b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin name: The name attribute of the <section name="foo"> element. 67377b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin parent: An edge to the parent, which is always an OuterNamespace instance. 67477b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin description: A string description of the section, or None. 67577b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin kinds: A sequence of Kind children. 6765804a48bb15d245fb06f72cf6d64369f151fcc28Igor Murashkin merged_kinds: A sequence of virtual Kind children, 6775804a48bb15d245fb06f72cf6d64369f151fcc28Igor Murashkin with each Kind's children merged by the kind.name 67877b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin """ 67977b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin def __init__(self, name, parent, description=None, kinds=[]): 68077b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin self._name = name 68177b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin self._parent = parent 68277b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin self._description = description 68377b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin self._kinds = kinds[:] 68477b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin 68577b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin self._leafs = [] 68677b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin 68777b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin 68877b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin @property 68977b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin def description(self): 69077b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin return self._description 69177b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin 69277b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin @property 69377b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin def kinds(self): 69477b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin return (i for i in self._kinds) 69577b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin 69677b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin def sort_children(self): 69777b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin self.validate_tree() 69877b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin # order is always controls,static,dynamic 69977b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin find_child = lambda x: [i for i in self._get_children() if i.name == x] 70077b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin new_lst = find_child('controls') \ 70177b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin + find_child('static') \ 70277b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin + find_child('dynamic') 70377b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin self._kinds = new_lst 70477b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin self.validate_tree() 70577b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin 70677b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin def _get_children(self): 70777b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin return (i for i in self.kinds) 70877b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin 7095804a48bb15d245fb06f72cf6d64369f151fcc28Igor Murashkin @property 7105804a48bb15d245fb06f72cf6d64369f151fcc28Igor Murashkin def merged_kinds(self): 7115804a48bb15d245fb06f72cf6d64369f151fcc28Igor Murashkin 7125804a48bb15d245fb06f72cf6d64369f151fcc28Igor Murashkin def aggregate_by_name(acc, el): 7135804a48bb15d245fb06f72cf6d64369f151fcc28Igor Murashkin existing = [i for i in acc if i.name == el.name] 7145804a48bb15d245fb06f72cf6d64369f151fcc28Igor Murashkin if existing: 7155804a48bb15d245fb06f72cf6d64369f151fcc28Igor Murashkin k = existing[0] 7165804a48bb15d245fb06f72cf6d64369f151fcc28Igor Murashkin else: 7175804a48bb15d245fb06f72cf6d64369f151fcc28Igor Murashkin k = Kind(el.name, el.parent) 7185804a48bb15d245fb06f72cf6d64369f151fcc28Igor Murashkin acc.append(k) 7195804a48bb15d245fb06f72cf6d64369f151fcc28Igor Murashkin 7205804a48bb15d245fb06f72cf6d64369f151fcc28Igor Murashkin k._namespaces.extend(el._namespaces) 7215804a48bb15d245fb06f72cf6d64369f151fcc28Igor Murashkin k._entries.extend(el._entries) 7225804a48bb15d245fb06f72cf6d64369f151fcc28Igor Murashkin 7235804a48bb15d245fb06f72cf6d64369f151fcc28Igor Murashkin return acc 7245804a48bb15d245fb06f72cf6d64369f151fcc28Igor Murashkin 7255804a48bb15d245fb06f72cf6d64369f151fcc28Igor Murashkin new_kinds_lst = reduce(aggregate_by_name, self.kinds, []) 7265804a48bb15d245fb06f72cf6d64369f151fcc28Igor Murashkin 7275804a48bb15d245fb06f72cf6d64369f151fcc28Igor Murashkin for k in new_kinds_lst: 7285804a48bb15d245fb06f72cf6d64369f151fcc28Igor Murashkin yield k 7295804a48bb15d245fb06f72cf6d64369f151fcc28Igor Murashkin 730aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin def combine_kinds_into_single_node(self): 731aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin r""" 732aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin Combines the section's Kinds into a single node. 733aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin 734aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin Combines all the children (kinds) of this section into a single 735aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin virtual Kind node. 736aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin 737aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin Returns: 738aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin A new Kind node that collapses all Kind siblings into one, combining 739aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin all their children together. 740aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin 741aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin For example, given self.kinds == [ x, y ] 742aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin 743aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin x y z 744aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin / | | \ --> / | | \ 745aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin a b c d a b c d 746aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin 747aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin a new instance z is returned in this example. 748aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin 749aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin Remarks: 750aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin The children of the kinds are the same references as before, that is 751aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin their parents will point to the old parents and not to the new parent. 752aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin """ 753aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin combined = Kind(name="combined", parent=self) 754aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin 755aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin for k in self._get_children(): 756aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin combined._namespaces.extend(k.namespaces) 757aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin combined._entries.extend(k.entries) 758aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin 759aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin return combined 760aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin 76177b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkinclass Kind(Node): 76277b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin """ 76377b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin A node corresponding to one of: <static>,<dynamic>,<controls> under a 76477b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin <section> element. 76577b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin 76677b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin Attributes (Read-Only): 76777b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin name: A string which is one of 'static', 'dynamic, or 'controls'. 76877b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin parent: An edge to the parent, which is always a Section instance. 76977b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin namespaces: A sequence of InnerNamespace children. 77077b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin entries: A sequence of Entry/Clone children. 771617da1675f9ea7b6ea33d9e6f47e0a07379f14b1Igor Murashkin merged_entries: A sequence of MergedEntry virtual nodes from entries 77277b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin """ 77377b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin def __init__(self, name, parent): 77477b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin self._name = name 77577b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin self._parent = parent 77677b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin self._namespaces = [] 77777b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin self._entries = [] 77877b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin 77977b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin self._leafs = [] 78077b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin 78177b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin @property 78277b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin def namespaces(self): 78377b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin return self._namespaces 78477b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin 78577b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin @property 78677b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin def entries(self): 78777b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin return self._entries 78877b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin 789617da1675f9ea7b6ea33d9e6f47e0a07379f14b1Igor Murashkin @property 790617da1675f9ea7b6ea33d9e6f47e0a07379f14b1Igor Murashkin def merged_entries(self): 791617da1675f9ea7b6ea33d9e6f47e0a07379f14b1Igor Murashkin for i in self.entries: 792617da1675f9ea7b6ea33d9e6f47e0a07379f14b1Igor Murashkin yield i.merge() 793617da1675f9ea7b6ea33d9e6f47e0a07379f14b1Igor Murashkin 79477b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin def sort_children(self): 79577b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin self._namespaces.sort(key=self._get_name()) 79677b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin self._entries.sort(key=self._get_name()) 79777b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin 79877b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin def _get_children(self): 79977b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin for i in self.namespaces: 80077b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin yield i 80177b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin for i in self.entries: 80277b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin yield i 80377b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin 804aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin def combine_children_by_name(self): 805aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin r""" 806aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin Combine multiple children with the same name into a single node. 807aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin 808aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin Returns: 809aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin A new Kind where all of the children with the same name were combined. 810aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin 811aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin For example: 812aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin 813aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin Given a Kind k: 814aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin 815aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin k 816aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin / | \ 817aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin a b c 818aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin | | | 819aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin d e f 820aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin 821aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin a.name == "foo" 822aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin b.name == "foo" 823aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin c.name == "bar" 824aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin 825aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin The returned Kind will look like this: 826aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin 827aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin k' 828aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin / \ 829aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin a' c' 830aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin / | | 831aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin d e f 832aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin 833aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin Remarks: 834aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin This operation is not recursive. To combine the grandchildren and other 835aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin ancestors, call this method on the ancestor nodes. 836aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin """ 837aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin return Kind._combine_children_by_name(self, new_type=type(self)) 838aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin 839aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin # new_type is either Kind or InnerNamespace 840aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin @staticmethod 841aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin def _combine_children_by_name(self, new_type): 842aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin new_ins_dict = OrderedDict() 843aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin new_ent_dict = OrderedDict() 844aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin 845aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin for ins in self.namespaces: 846aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin new_ins = new_ins_dict.setdefault(ins.name, 847aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin InnerNamespace(ins.name, parent=self)) 848aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin new_ins._namespaces.extend(ins.namespaces) 849aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin new_ins._entries.extend(ins.entries) 850aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin 851aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin for ent in self.entries: 852aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin new_ent = new_ent_dict.setdefault(ent.name, 853aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin ent.merge()) 854aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin 855aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin kind = new_type(self.name, self.parent) 856aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin kind._namespaces = new_ins_dict.values() 857aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin kind._entries = new_ent_dict.values() 858aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin 859aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin return kind 860aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin 86177b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkinclass InnerNamespace(Node): 86277b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin """ 86377b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin A node corresponding to a <namespace> which is an ancestor of a Kind. 86477b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin These namespaces may have other namespaces recursively, or entries as leafs. 86577b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin 86677b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin Attributes (Read-Only): 86777b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin name: Name attribute from the element, e.g. <namespace name="foo"> -> 'foo' 86877b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin parent: An edge to the parent, which is an InnerNamespace or a Kind. 86977b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin namespaces: A sequence of InnerNamespace children. 87077b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin entries: A sequence of Entry/Clone children. 871617da1675f9ea7b6ea33d9e6f47e0a07379f14b1Igor Murashkin merged_entries: A sequence of MergedEntry virtual nodes from entries 87277b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin """ 87377b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin def __init__(self, name, parent): 87477b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin self._name = name 87577b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin self._parent = parent 87677b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin self._namespaces = [] 87777b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin self._entries = [] 87877b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin self._leafs = [] 87977b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin 88077b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin @property 88177b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin def namespaces(self): 88277b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin return self._namespaces 88377b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin 88477b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin @property 88577b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin def entries(self): 88677b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin return self._entries 88777b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin 888617da1675f9ea7b6ea33d9e6f47e0a07379f14b1Igor Murashkin @property 889617da1675f9ea7b6ea33d9e6f47e0a07379f14b1Igor Murashkin def merged_entries(self): 890617da1675f9ea7b6ea33d9e6f47e0a07379f14b1Igor Murashkin for i in self.entries: 891617da1675f9ea7b6ea33d9e6f47e0a07379f14b1Igor Murashkin yield i.merge() 892617da1675f9ea7b6ea33d9e6f47e0a07379f14b1Igor Murashkin 89377b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin def sort_children(self): 89477b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin self._namespaces.sort(key=self._get_name()) 89577b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin self._entries.sort(key=self._get_name()) 89677b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin 89777b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin def _get_children(self): 89877b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin for i in self.namespaces: 89977b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin yield i 90077b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin for i in self.entries: 90177b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin yield i 90277b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin 903aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin def combine_children_by_name(self): 904aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin r""" 905aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin Combine multiple children with the same name into a single node. 906aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin 907aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin Returns: 908aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin A new InnerNamespace where all of the children with the same name were 909aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin combined. 910aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin 911aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin For example: 912aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin 913aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin Given an InnerNamespace i: 914aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin 915aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin i 916aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin / | \ 917aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin a b c 918aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin | | | 919aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin d e f 920aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin 921aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin a.name == "foo" 922aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin b.name == "foo" 923aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin c.name == "bar" 924aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin 925aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin The returned InnerNamespace will look like this: 926aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin 927aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin i' 928aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin / \ 929aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin a' c' 930aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin / | | 931aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin d e f 932aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin 933aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin Remarks: 934aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin This operation is not recursive. To combine the grandchildren and other 935aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin ancestors, call this method on the ancestor nodes. 936aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin """ 937aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin return Kind._combine_children_by_name(self, new_type=type(self)) 938aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin 939375cfd3889aa72160273af802370c8f47f5c64d1Igor Murashkinclass EnumValue(Node): 94077b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin """ 94177b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin A class corresponding to a <value> element within an <enum> within an <entry>. 94277b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin 94377b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin Attributes (Read-Only): 94477b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin name: A string, e.g. 'ON' or 'OFF' 94577b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin id: An optional numeric string, e.g. '0' or '0xFF' 94677b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin optional: A boolean 94777b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin notes: A string describing the notes, or None. 948375cfd3889aa72160273af802370c8f47f5c64d1Igor Murashkin parent: An edge to the parent, always an Enum instance. 94977b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin """ 950375cfd3889aa72160273af802370c8f47f5c64d1Igor Murashkin def __init__(self, name, parent, id=None, optional=False, notes=None): 95177b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin self._name = name # str, e.g. 'ON' or 'OFF' 95277b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin self._id = id # int, e.g. '0' 95377b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin self._optional = optional # bool 95477b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin self._notes = notes # None or str 955375cfd3889aa72160273af802370c8f47f5c64d1Igor Murashkin self._parent = parent 95677b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin 95777b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin @property 95877b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin def id(self): 95977b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin return self._id 96077b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin 96177b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin @property 96277b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin def optional(self): 96377b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin return self._optional 96477b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin 96577b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin @property 96677b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin def notes(self): 96777b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin return self._notes 96877b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin 969375cfd3889aa72160273af802370c8f47f5c64d1Igor Murashkin def _get_children(self): 970375cfd3889aa72160273af802370c8f47f5c64d1Igor Murashkin return None 971375cfd3889aa72160273af802370c8f47f5c64d1Igor Murashkin 972375cfd3889aa72160273af802370c8f47f5c64d1Igor Murashkinclass Enum(Node): 97377b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin """ 97477b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin A class corresponding to an <enum> element within an <entry>. 97577b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin 97677b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin Attributes (Read-Only): 97777b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin parent: An edge to the parent, always an Entry instance. 97877b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin values: A sequence of EnumValue children. 979aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin has_values_with_id: A boolean representing if any of the children have a 980aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin non-empty id property. 98177b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin """ 98277b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin def __init__(self, parent, values, ids={}, optionals=[], notes={}): 98377b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin self._values = \ 984375cfd3889aa72160273af802370c8f47f5c64d1Igor Murashkin [ EnumValue(val, self, ids.get(val), val in optionals, notes.get(val)) \ 98577b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin for val in values ] 98677b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin 98777b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin self._parent = parent 988375cfd3889aa72160273af802370c8f47f5c64d1Igor Murashkin self._name = None 98977b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin 99077b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin @property 99177b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin def values(self): 99277b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin return (i for i in self._values) 99377b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin 994aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin @property 995aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin def has_values_with_id(self): 996aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin return bool(any(i for i in self.values if i.id)) 997aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin 998375cfd3889aa72160273af802370c8f47f5c64d1Igor Murashkin def _get_children(self): 999375cfd3889aa72160273af802370c8f47f5c64d1Igor Murashkin return (i for i in self._values) 1000375cfd3889aa72160273af802370c8f47f5c64d1Igor Murashkin 100177b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkinclass Entry(Node): 100277b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin """ 100377b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin A node corresponding to an <entry> element. 100477b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin 100577b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin Attributes (Read-Only): 100677b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin parent: An edge to the parent node, which is an InnerNamespace or Kind. 100777b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin name: The fully qualified name string, e.g. 'android.shading.mode' 100877b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin name_short: The name attribute from <entry name="mode">, e.g. mode 100977b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin type: The type attribute from <entry type="bar"> 101077b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin kind: A string ('static', 'dynamic', 'controls') corresponding to the 101177b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin ancestor Kind#name 101277b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin container: The container attribute from <entry container="array">, or None. 101377b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin container_sizes: A sequence of size strings or None if container is None. 1014b556bc47068d816cb319a5d0e2f6841b007b38f2Igor Murashkin enum: An Enum instance if the enum attribute is true, None otherwise. 1015f384f0a06cf156c51c4ca584a4323e132c15f64fEino-Ville Talvala visibility: The visibility of this entry ('system', 'hidden', 'public') 1016f384f0a06cf156c51c4ca584a4323e132c15f64fEino-Ville Talvala across the system. System entries are only visible in native code 1017f384f0a06cf156c51c4ca584a4323e132c15f64fEino-Ville Talvala headers. Hidden entries are marked @hide in managed code, while 1018f384f0a06cf156c51c4ca584a4323e132c15f64fEino-Ville Talvala public entries are visible in the Android SDK. 1019f384f0a06cf156c51c4ca584a4323e132c15f64fEino-Ville Talvala applied_visibility: As visibility, but always valid, defaulting to 'system' 1020f384f0a06cf156c51c4ca584a4323e132c15f64fEino-Ville Talvala if no visibility is given for an entry. 1021ef40ad6249555a0a45c57907f4b9509b59e3e9f5Alex Ray optional: a bool representing the optional attribute, which denotes the entry 1022ef40ad6249555a0a45c57907f4b9509b59e3e9f5Alex Ray is required for hardware level full devices, but optional for other 1023ef40ad6249555a0a45c57907f4b9509b59e3e9f5Alex Ray hardware levels. None if not present. 1024ef40ad6249555a0a45c57907f4b9509b59e3e9f5Alex Ray applied_optional: As optional but always valid, defaulting to False if no 1025ef40ad6249555a0a45c57907f4b9509b59e3e9f5Alex Ray optional attribute is present. 102677b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin tuple_values: A sequence of strings describing the tuple values, 102777b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin None if container is not 'tuple'. 102877b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin description: A string description, or None. 102977b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin range: A string range, or None. 103077b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin units: A string units, or None. 103177b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin tags: A sequence of Tag nodes associated with this Entry. 103277b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin type_notes: A string describing notes for the type, or None. 1033b8dc88148bca2e5a267c2ff39aff94b98b00ad6dIgor Murashkin typedef: A Typedef associated with this Entry, or None. 103477b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin 103577b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin Remarks: 103677b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin Subclass Clone can be used interchangeable with an Entry, 103777b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin for when we don't care about the underlying type. 103877b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin 103977b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin parent and tags edges are invalid until after Metadata#construct_graph 104077b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin has been invoked. 104177b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin """ 104277b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin def __init__(self, **kwargs): 104377b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin """ 104477b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin Instantiate a new Entry node. 104577b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin 104677b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin Args: 104777b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin name: A string with the fully qualified name, e.g. 'android.shading.mode' 104877b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin type: A string describing the type, e.g. 'int32' 104977b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin kind: A string describing the kind, e.g. 'static' 105077b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin 105177b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin Args (if container): 105277b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin container: A string describing the container, e.g. 'array' or 'tuple' 105377b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin container_sizes: A list of string sizes if a container, or None otherwise 105477b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin 105577b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin Args (if container is 'tuple'): 105677b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin tuple_values: A list of tuple values, e.g. ['width', 'height'] 105777b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin 1058b556bc47068d816cb319a5d0e2f6841b007b38f2Igor Murashkin Args (if the 'enum' attribute is true): 1059b556bc47068d816cb319a5d0e2f6841b007b38f2Igor Murashkin enum: A boolean, True if this is an enum, False otherwise 106077b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin enum_values: A list of value strings, e.g. ['ON', 'OFF'] 106177b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin enum_optionals: A list of optional enum values, e.g. ['OFF'] 106277b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin enum_notes: A dictionary of value->notes strings. 106377b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin enum_ids: A dictionary of value->id strings. 106477b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin 106577b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin Args (optional): 106677b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin description: A string with a description of the entry. 106777b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin range: A string with the range of the values of the entry, e.g. '>= 0' 106877b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin units: A string with the units of the values, e.g. 'inches' 106977b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin notes: A string with the notes for the entry 107077b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin tag_ids: A list of tag ID strings, e.g. ['BC', 'V1'] 107177b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin type_notes: A string with the notes for the type 1072f384f0a06cf156c51c4ca584a4323e132c15f64fEino-Ville Talvala visibility: A string describing the visibility, eg 'system', 'hidden', 1073f384f0a06cf156c51c4ca584a4323e132c15f64fEino-Ville Talvala 'public' 1074ef40ad6249555a0a45c57907f4b9509b59e3e9f5Alex Ray optional: A bool to mark whether optional for non-full hardware devices 1075b8dc88148bca2e5a267c2ff39aff94b98b00ad6dIgor Murashkin typedef: A string corresponding to a typedef's name attribute. 107677b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin """ 107777b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin 107877b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin if kwargs.get('type') is None: 107977b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin print >> sys.stderr, "ERROR: Missing type for entry '%s' kind '%s'" \ 108077b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin %(kwargs.get('name'), kwargs.get('kind')) 108177b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin 108277b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin # Attributes are Read-Only, but edges may be mutated by 108377b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin # Metadata, particularly during construct_graph 108477b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin 108577b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin self._name = kwargs['name'] 108677b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin self._type = kwargs['type'] 108777b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin self._kind = kwargs['kind'] # static, dynamic, or controls 108877b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin 108977b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin self._init_common(**kwargs) 109077b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin 109177b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin @property 109277b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin def type(self): 109377b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin return self._type 109477b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin 109577b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin @property 109677b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin def kind(self): 109777b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin return self._kind 109877b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin 109977b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin @property 1100f384f0a06cf156c51c4ca584a4323e132c15f64fEino-Ville Talvala def visibility(self): 1101f384f0a06cf156c51c4ca584a4323e132c15f64fEino-Ville Talvala return self._visibility 1102f384f0a06cf156c51c4ca584a4323e132c15f64fEino-Ville Talvala 1103f384f0a06cf156c51c4ca584a4323e132c15f64fEino-Ville Talvala @property 1104f384f0a06cf156c51c4ca584a4323e132c15f64fEino-Ville Talvala def applied_visibility(self): 1105f384f0a06cf156c51c4ca584a4323e132c15f64fEino-Ville Talvala return self._visibility or 'system' 1106f384f0a06cf156c51c4ca584a4323e132c15f64fEino-Ville Talvala 1107f384f0a06cf156c51c4ca584a4323e132c15f64fEino-Ville Talvala @property 1108ef40ad6249555a0a45c57907f4b9509b59e3e9f5Alex Ray def optional(self): 1109ef40ad6249555a0a45c57907f4b9509b59e3e9f5Alex Ray return self._optional 1110ef40ad6249555a0a45c57907f4b9509b59e3e9f5Alex Ray 1111ef40ad6249555a0a45c57907f4b9509b59e3e9f5Alex Ray @property 1112ef40ad6249555a0a45c57907f4b9509b59e3e9f5Alex Ray def applied_optional(self): 1113ef40ad6249555a0a45c57907f4b9509b59e3e9f5Alex Ray return self._optional or False 1114ef40ad6249555a0a45c57907f4b9509b59e3e9f5Alex Ray 1115ef40ad6249555a0a45c57907f4b9509b59e3e9f5Alex Ray @property 111677b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin def name_short(self): 111777b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin return self.get_name_minimal() 111877b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin 111977b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin @property 112077b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin def container(self): 112177b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin return self._container 112277b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin 112377b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin @property 112477b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin def container_sizes(self): 112577b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin if self._container_sizes is None: 112677b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin return None 112777b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin else: 112877b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin return (i for i in self._container_sizes) 112977b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin 113077b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin @property 113177b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin def tuple_values(self): 113277b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin if self._tuple_values is None: 113377b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin return None 113477b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin else: 113577b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin return (i for i in self._tuple_values) 113677b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin 113777b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin @property 113877b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin def description(self): 113977b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin return self._description 114077b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin 114177b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin @property 114277b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin def range(self): 114377b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin return self._range 114477b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin 114577b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin @property 114677b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin def units(self): 114777b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin return self._units 114877b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin 114977b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin @property 115077b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin def notes(self): 115177b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin return self._notes 115277b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin 115377b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin @property 115477b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin def tags(self): 115577b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin if self._tags is None: 115677b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin return None 115777b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin else: 115877b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin return (i for i in self._tags) 115977b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin 116077b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin @property 116177b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin def type_notes(self): 116277b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin return self._type_notes 116377b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin 116477b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin @property 1165b8dc88148bca2e5a267c2ff39aff94b98b00ad6dIgor Murashkin def typedef(self): 1166b8dc88148bca2e5a267c2ff39aff94b98b00ad6dIgor Murashkin return self._typedef 1167b8dc88148bca2e5a267c2ff39aff94b98b00ad6dIgor Murashkin 1168b8dc88148bca2e5a267c2ff39aff94b98b00ad6dIgor Murashkin @property 116977b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin def enum(self): 117077b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin return self._enum 117177b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin 117277b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin def _get_children(self): 1173375cfd3889aa72160273af802370c8f47f5c64d1Igor Murashkin if self.enum: 1174375cfd3889aa72160273af802370c8f47f5c64d1Igor Murashkin yield self.enum 117577b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin 117677b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin def sort_children(self): 117777b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin return None 117877b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin 117977b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin def is_clone(self): 118077b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin """ 118177b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin Whether or not this is a Clone instance. 118277b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin 118377b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin Returns: 118477b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin False 118577b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin """ 118677b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin return False 118777b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin 118877b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin def _init_common(self, **kwargs): 118977b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin 1190b8dc88148bca2e5a267c2ff39aff94b98b00ad6dIgor Murashkin self._parent = None # filled in by Metadata::_construct_entries 119177b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin 119277b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin self._container = kwargs.get('container') 119377b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin self._container_sizes = kwargs.get('container_sizes') 119477b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin 119577b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin # access these via the 'enum' prop 119677b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin enum_values = kwargs.get('enum_values') 119777b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin enum_optionals = kwargs.get('enum_optionals') 1198aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin enum_notes = kwargs.get('enum_notes') # { value => notes } 1199aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin enum_ids = kwargs.get('enum_ids') # { value => notes } 120077b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin self._tuple_values = kwargs.get('tuple_values') 120177b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin 120277b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin self._description = kwargs.get('description') 120377b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin self._range = kwargs.get('range') 120477b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin self._units = kwargs.get('units') 120577b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin self._notes = kwargs.get('notes') 120677b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin 120777b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin self._tag_ids = kwargs.get('tag_ids', []) 1208b8dc88148bca2e5a267c2ff39aff94b98b00ad6dIgor Murashkin self._tags = None # Filled in by Metadata::_construct_tags 120977b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin 121077b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin self._type_notes = kwargs.get('type_notes') 1211b8dc88148bca2e5a267c2ff39aff94b98b00ad6dIgor Murashkin self._type_name = kwargs.get('type_name') 1212b8dc88148bca2e5a267c2ff39aff94b98b00ad6dIgor Murashkin self._typedef = None # Filled in by Metadata::_construct_types 121377b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin 1214b556bc47068d816cb319a5d0e2f6841b007b38f2Igor Murashkin if kwargs.get('enum', False): 121577b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin self._enum = Enum(self, enum_values, enum_ids, enum_optionals, enum_notes) 1216617da1675f9ea7b6ea33d9e6f47e0a07379f14b1Igor Murashkin else: 1217617da1675f9ea7b6ea33d9e6f47e0a07379f14b1Igor Murashkin self._enum = None 121877b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin 1219f384f0a06cf156c51c4ca584a4323e132c15f64fEino-Ville Talvala self._visibility = kwargs.get('visibility') 1220ef40ad6249555a0a45c57907f4b9509b59e3e9f5Alex Ray self._optional = kwargs.get('optional') 1221f384f0a06cf156c51c4ca584a4323e132c15f64fEino-Ville Talvala 122277b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin self._property_keys = kwargs 122377b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin 1224617da1675f9ea7b6ea33d9e6f47e0a07379f14b1Igor Murashkin def merge(self): 1225617da1675f9ea7b6ea33d9e6f47e0a07379f14b1Igor Murashkin """ 1226617da1675f9ea7b6ea33d9e6f47e0a07379f14b1Igor Murashkin Copy the attributes into a new entry, merging it with the target entry 1227617da1675f9ea7b6ea33d9e6f47e0a07379f14b1Igor Murashkin if it's a clone. 1228617da1675f9ea7b6ea33d9e6f47e0a07379f14b1Igor Murashkin """ 1229617da1675f9ea7b6ea33d9e6f47e0a07379f14b1Igor Murashkin return MergedEntry(self) 1230617da1675f9ea7b6ea33d9e6f47e0a07379f14b1Igor Murashkin 123177b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin # Helpers for accessing less than the fully qualified name 123277b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin 123377b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin def get_name_as_list(self): 123477b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin """ 123577b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin Returns the name as a list split by a period. 123677b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin 123777b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin For example: 123877b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin entry.name is 'android.lens.info.shading' 123977b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin entry.get_name_as_list() == ['android', 'lens', 'info', 'shading'] 124077b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin """ 124177b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin return self.name.split(".") 124277b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin 124377b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin def get_inner_namespace_list(self): 124477b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin """ 124577b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin Returns the inner namespace part of the name as a list 124677b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin 124777b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin For example: 124877b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin entry.name is 'android.lens.info.shading' 124977b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin entry.get_inner_namespace_list() == ['info'] 125077b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin """ 125177b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin return self.get_name_as_list()[2:-1] 125277b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin 125377b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin def get_outer_namespace(self): 125477b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin """ 125577b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin Returns the outer namespace as a string. 125677b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin 125777b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin For example: 125877b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin entry.name is 'android.lens.info.shading' 125977b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin entry.get_outer_namespace() == 'android' 126077b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin 126177b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin Remarks: 126277b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin Since outer namespaces are non-recursive, 126377b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin and each entry has one, this does not need to be a list. 126477b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin """ 126577b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin return self.get_name_as_list()[0] 126677b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin 126777b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin def get_section(self): 126877b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin """ 126977b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin Returns the section as a string. 127077b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin 127177b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin For example: 127277b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin entry.name is 'android.lens.info.shading' 127377b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin entry.get_section() == '' 127477b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin 127577b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin Remarks: 127677b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin Since outer namespaces are non-recursive, 127777b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin and each entry has one, this does not need to be a list. 127877b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin """ 127977b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin return self.get_name_as_list()[1] 128077b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin 128177b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin def get_name_minimal(self): 128277b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin """ 128377b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin Returns only the last component of the fully qualified name as a string. 128477b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin 128577b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin For example: 128677b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin entry.name is 'android.lens.info.shading' 128777b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin entry.get_name_minimal() == 'shading' 128877b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin 128977b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin Remarks: 129077b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin entry.name_short it an alias for this 129177b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin """ 129277b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin return self.get_name_as_list()[-1] 129377b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin 12947b9a2dccf20bac314258708e55d8c75b2ecf892aIgor Murashkin def get_path_without_name(self): 12957b9a2dccf20bac314258708e55d8c75b2ecf892aIgor Murashkin """ 12967b9a2dccf20bac314258708e55d8c75b2ecf892aIgor Murashkin Returns a string path to the entry, with the name component excluded. 12977b9a2dccf20bac314258708e55d8c75b2ecf892aIgor Murashkin 12987b9a2dccf20bac314258708e55d8c75b2ecf892aIgor Murashkin For example: 12997b9a2dccf20bac314258708e55d8c75b2ecf892aIgor Murashkin entry.name is 'android.lens.info.shading' 13007b9a2dccf20bac314258708e55d8c75b2ecf892aIgor Murashkin entry.get_path_without_name() == 'android.lens.info' 13017b9a2dccf20bac314258708e55d8c75b2ecf892aIgor Murashkin """ 13027b9a2dccf20bac314258708e55d8c75b2ecf892aIgor Murashkin return ".".join(self.get_name_as_list()[0:-1]) 13037b9a2dccf20bac314258708e55d8c75b2ecf892aIgor Murashkin 13047b9a2dccf20bac314258708e55d8c75b2ecf892aIgor Murashkin 130577b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkinclass Clone(Entry): 130677b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin """ 130777b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin A Node corresponding to a <clone> element. It has all the attributes of an 130877b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin <entry> element (Entry) plus the additions specified below. 130977b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin 131077b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin Attributes (Read-Only): 131177b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin entry: an edge to an Entry object that this targets 131277b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin target_kind: A string describing the kind of the target entry. 131377b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin name: a string of the name, same as entry.name 131477b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin kind: a string of the Kind ancestor, one of 'static', 'controls', 'dynamic' 131577b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin for the <clone> element. 131677b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin type: always None, since a clone cannot override the type. 131777b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin """ 131877b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin def __init__(self, entry=None, **kwargs): 131977b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin """ 132077b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin Instantiate a new Clone node. 132177b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin 132277b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin Args: 132377b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin name: A string with the fully qualified name, e.g. 'android.shading.mode' 132477b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin type: A string describing the type, e.g. 'int32' 132577b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin kind: A string describing the kind, e.g. 'static' 132677b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin target_kind: A string for the kind of the target entry, e.g. 'dynamic' 132777b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin 132877b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin Args (if container): 132977b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin container: A string describing the container, e.g. 'array' or 'tuple' 133077b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin container_sizes: A list of string sizes if a container, or None otherwise 133177b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin 133277b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin Args (if container is 'tuple'): 133377b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin tuple_values: A list of tuple values, e.g. ['width', 'height'] 133477b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin 1335b556bc47068d816cb319a5d0e2f6841b007b38f2Igor Murashkin Args (if the 'enum' attribute is true): 1336b556bc47068d816cb319a5d0e2f6841b007b38f2Igor Murashkin enum: A boolean, True if this is an enum, False otherwise 133777b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin enum_values: A list of value strings, e.g. ['ON', 'OFF'] 133877b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin enum_optionals: A list of optional enum values, e.g. ['OFF'] 133977b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin enum_notes: A dictionary of value->notes strings. 134077b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin enum_ids: A dictionary of value->id strings. 134177b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin 134277b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin Args (optional): 134377b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin entry: An edge to the corresponding target Entry. 134477b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin description: A string with a description of the entry. 134577b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin range: A string with the range of the values of the entry, e.g. '>= 0' 134677b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin units: A string with the units of the values, e.g. 'inches' 134777b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin notes: A string with the notes for the entry 134877b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin tag_ids: A list of tag ID strings, e.g. ['BC', 'V1'] 134977b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin type_notes: A string with the notes for the type 135077b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin 135177b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin Remarks: 135277b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin Note that type is not specified since it has to be the same as the 135377b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin entry.type. 135477b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin """ 1355aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin self._entry = entry # Entry object 135677b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin self._target_kind = kwargs['target_kind'] 1357aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin self._name = kwargs['name'] # same as entry.name 135877b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin self._kind = kwargs['kind'] 135977b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin 136077b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin # illegal to override the type, it should be the same as the entry 136177b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin self._type = None 136277b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin # the rest of the kwargs are optional 136377b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin # can be used to override the regular entry data 136477b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin self._init_common(**kwargs) 136577b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin 136677b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin @property 136777b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin def entry(self): 136877b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin return self._entry 136977b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin 137077b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin @property 137177b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin def target_kind(self): 137277b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin return self._target_kind 137377b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin 137477b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin def is_clone(self): 137577b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin """ 137677b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin Whether or not this is a Clone instance. 137777b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin 137877b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin Returns: 137977b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin True 138077b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin """ 138177b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin return True 138277b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin 1383617da1675f9ea7b6ea33d9e6f47e0a07379f14b1Igor Murashkinclass MergedEntry(Entry): 1384617da1675f9ea7b6ea33d9e6f47e0a07379f14b1Igor Murashkin """ 1385617da1675f9ea7b6ea33d9e6f47e0a07379f14b1Igor Murashkin A MergedEntry has all the attributes of a Clone and its target Entry merged 1386617da1675f9ea7b6ea33d9e6f47e0a07379f14b1Igor Murashkin together. 1387617da1675f9ea7b6ea33d9e6f47e0a07379f14b1Igor Murashkin 1388617da1675f9ea7b6ea33d9e6f47e0a07379f14b1Igor Murashkin Remarks: 1389617da1675f9ea7b6ea33d9e6f47e0a07379f14b1Igor Murashkin Useful when we want to 'unfold' a clone into a real entry by copying out 1390617da1675f9ea7b6ea33d9e6f47e0a07379f14b1Igor Murashkin the target entry data. In this case we don't care about distinguishing 1391617da1675f9ea7b6ea33d9e6f47e0a07379f14b1Igor Murashkin a clone vs an entry. 1392617da1675f9ea7b6ea33d9e6f47e0a07379f14b1Igor Murashkin """ 1393617da1675f9ea7b6ea33d9e6f47e0a07379f14b1Igor Murashkin def __init__(self, entry): 1394617da1675f9ea7b6ea33d9e6f47e0a07379f14b1Igor Murashkin """ 1395617da1675f9ea7b6ea33d9e6f47e0a07379f14b1Igor Murashkin Create a new instance of MergedEntry. 139677b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin 1397617da1675f9ea7b6ea33d9e6f47e0a07379f14b1Igor Murashkin Args: 1398617da1675f9ea7b6ea33d9e6f47e0a07379f14b1Igor Murashkin entry: An Entry or Clone instance 1399617da1675f9ea7b6ea33d9e6f47e0a07379f14b1Igor Murashkin """ 1400617da1675f9ea7b6ea33d9e6f47e0a07379f14b1Igor Murashkin props_distinct = ['description', 'units', 'range', 'notes', 'tags', 'kind'] 140177b63ca0447545a4dac3ac062f218d878ce01ba0Igor Murashkin 1402617da1675f9ea7b6ea33d9e6f47e0a07379f14b1Igor Murashkin for p in props_distinct: 1403baacf9a9f032ca392b37b4982eafa43b0a8d4b52Igor Murashkin p = '_' + p 1404617da1675f9ea7b6ea33d9e6f47e0a07379f14b1Igor Murashkin if entry.is_clone(): 1405baacf9a9f032ca392b37b4982eafa43b0a8d4b52Igor Murashkin setattr(self, p, getattr(entry, p) or getattr(entry.entry, p)) 1406617da1675f9ea7b6ea33d9e6f47e0a07379f14b1Igor Murashkin else: 1407baacf9a9f032ca392b37b4982eafa43b0a8d4b52Igor Murashkin setattr(self, p, getattr(entry, p)) 1408617da1675f9ea7b6ea33d9e6f47e0a07379f14b1Igor Murashkin 1409baacf9a9f032ca392b37b4982eafa43b0a8d4b52Igor Murashkin props_common = ['parent', 'name', 'container', 1410617da1675f9ea7b6ea33d9e6f47e0a07379f14b1Igor Murashkin 'container_sizes', 'enum', 1411617da1675f9ea7b6ea33d9e6f47e0a07379f14b1Igor Murashkin 'tuple_values', 1412617da1675f9ea7b6ea33d9e6f47e0a07379f14b1Igor Murashkin 'type', 1413617da1675f9ea7b6ea33d9e6f47e0a07379f14b1Igor Murashkin 'type_notes', 1414b8dc88148bca2e5a267c2ff39aff94b98b00ad6dIgor Murashkin 'visibility', 1415ef40ad6249555a0a45c57907f4b9509b59e3e9f5Alex Ray 'optional', 1416b8dc88148bca2e5a267c2ff39aff94b98b00ad6dIgor Murashkin 'typedef' 1417617da1675f9ea7b6ea33d9e6f47e0a07379f14b1Igor Murashkin ] 1418617da1675f9ea7b6ea33d9e6f47e0a07379f14b1Igor Murashkin 1419617da1675f9ea7b6ea33d9e6f47e0a07379f14b1Igor Murashkin for p in props_common: 1420baacf9a9f032ca392b37b4982eafa43b0a8d4b52Igor Murashkin p = '_' + p 1421617da1675f9ea7b6ea33d9e6f47e0a07379f14b1Igor Murashkin if entry.is_clone(): 1422baacf9a9f032ca392b37b4982eafa43b0a8d4b52Igor Murashkin setattr(self, p, getattr(entry.entry, p)) 1423617da1675f9ea7b6ea33d9e6f47e0a07379f14b1Igor Murashkin else: 1424baacf9a9f032ca392b37b4982eafa43b0a8d4b52Igor Murashkin setattr(self, p, getattr(entry, p)) 1425