metadata_helpers.py revision c6c2416a812ddb8bcb32fdefce1eff3a7ded9b61
1da1c314e080d33eb6b93a1d3da070c99b41e7b22Igor Murashkin# 2da1c314e080d33eb6b93a1d3da070c99b41e7b22Igor Murashkin# Copyright (C) 2012 The Android Open Source Project 3da1c314e080d33eb6b93a1d3da070c99b41e7b22Igor Murashkin# 4da1c314e080d33eb6b93a1d3da070c99b41e7b22Igor Murashkin# Licensed under the Apache License, Version 2.0 (the "License"); 5da1c314e080d33eb6b93a1d3da070c99b41e7b22Igor Murashkin# you may not use this file except in compliance with the License. 6da1c314e080d33eb6b93a1d3da070c99b41e7b22Igor Murashkin# You may obtain a copy of the License at 7da1c314e080d33eb6b93a1d3da070c99b41e7b22Igor Murashkin# 8da1c314e080d33eb6b93a1d3da070c99b41e7b22Igor Murashkin# http://www.apache.org/licenses/LICENSE-2.0 9da1c314e080d33eb6b93a1d3da070c99b41e7b22Igor Murashkin# 10da1c314e080d33eb6b93a1d3da070c99b41e7b22Igor Murashkin# Unless required by applicable law or agreed to in writing, software 11da1c314e080d33eb6b93a1d3da070c99b41e7b22Igor Murashkin# distributed under the License is distributed on an "AS IS" BASIS, 12da1c314e080d33eb6b93a1d3da070c99b41e7b22Igor Murashkin# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13da1c314e080d33eb6b93a1d3da070c99b41e7b22Igor Murashkin# See the License for the specific language governing permissions and 14da1c314e080d33eb6b93a1d3da070c99b41e7b22Igor Murashkin# limitations under the License. 15da1c314e080d33eb6b93a1d3da070c99b41e7b22Igor Murashkin# 16da1c314e080d33eb6b93a1d3da070c99b41e7b22Igor Murashkin 17da1c314e080d33eb6b93a1d3da070c99b41e7b22Igor Murashkin""" 18da1c314e080d33eb6b93a1d3da070c99b41e7b22Igor MurashkinA set of helpers for rendering Mako templates with a Metadata model. 19da1c314e080d33eb6b93a1d3da070c99b41e7b22Igor Murashkin""" 20da1c314e080d33eb6b93a1d3da070c99b41e7b22Igor Murashkin 21da1c314e080d33eb6b93a1d3da070c99b41e7b22Igor Murashkinimport metadata_model 22aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkinimport re 238aa2a11bbff97d9789bb06cdc2e28dadb6c5926aIgor Murashkinimport markdown 248aa2a11bbff97d9789bb06cdc2e28dadb6c5926aIgor Murashkinimport textwrap 2563c0fb27d923a32d9a398471ad318bfe84befbebEino-Ville Talvalaimport sys 260b080452cca90f215d10d636abfb47701d7518daIgor Murashkinimport bs4 270b080452cca90f215d10d636abfb47701d7518daIgor Murashkin# Monkey-patch BS4. WBR element must not have an end tag. 280b080452cca90f215d10d636abfb47701d7518daIgor Murashkinbs4.builder.HTMLTreeBuilder.empty_element_tags.add("wbr") 298aa2a11bbff97d9789bb06cdc2e28dadb6c5926aIgor Murashkin 30586c861e6dab3fdf48fc8440c719ad0b59d49d72Igor Murashkinfrom collections import OrderedDict 31da1c314e080d33eb6b93a1d3da070c99b41e7b22Igor Murashkin 321dd4ecb0ea0589610b3616459b707c2898889153Igor Murashkin# Relative path from HTML file to the base directory used by <img> tags 331dd4ecb0ea0589610b3616459b707c2898889153Igor MurashkinIMAGE_SRC_METADATA="images/camera2/metadata/" 341dd4ecb0ea0589610b3616459b707c2898889153Igor Murashkin 351dd4ecb0ea0589610b3616459b707c2898889153Igor Murashkin# Prepend this path to each <img src="foo"> in javadocs 361dd4ecb0ea0589610b3616459b707c2898889153Igor MurashkinJAVADOC_IMAGE_SRC_METADATA="../../../../" + IMAGE_SRC_METADATA 371dd4ecb0ea0589610b3616459b707c2898889153Igor Murashkin 38da1c314e080d33eb6b93a1d3da070c99b41e7b22Igor Murashkin_context_buf = None 39da1c314e080d33eb6b93a1d3da070c99b41e7b22Igor Murashkin 40da1c314e080d33eb6b93a1d3da070c99b41e7b22Igor Murashkindef _is_sec_or_ins(x): 41da1c314e080d33eb6b93a1d3da070c99b41e7b22Igor Murashkin return isinstance(x, metadata_model.Section) or \ 42da1c314e080d33eb6b93a1d3da070c99b41e7b22Igor Murashkin isinstance(x, metadata_model.InnerNamespace) 43da1c314e080d33eb6b93a1d3da070c99b41e7b22Igor Murashkin 44da1c314e080d33eb6b93a1d3da070c99b41e7b22Igor Murashkin## 45da1c314e080d33eb6b93a1d3da070c99b41e7b22Igor Murashkin## Metadata Helpers 46da1c314e080d33eb6b93a1d3da070c99b41e7b22Igor Murashkin## 47da1c314e080d33eb6b93a1d3da070c99b41e7b22Igor Murashkin 48da1c314e080d33eb6b93a1d3da070c99b41e7b22Igor Murashkindef find_all_sections(root): 49da1c314e080d33eb6b93a1d3da070c99b41e7b22Igor Murashkin """ 50da1c314e080d33eb6b93a1d3da070c99b41e7b22Igor Murashkin Find all descendants that are Section or InnerNamespace instances. 51da1c314e080d33eb6b93a1d3da070c99b41e7b22Igor Murashkin 52da1c314e080d33eb6b93a1d3da070c99b41e7b22Igor Murashkin Args: 53da1c314e080d33eb6b93a1d3da070c99b41e7b22Igor Murashkin root: a Metadata instance 54da1c314e080d33eb6b93a1d3da070c99b41e7b22Igor Murashkin 55da1c314e080d33eb6b93a1d3da070c99b41e7b22Igor Murashkin Returns: 56da1c314e080d33eb6b93a1d3da070c99b41e7b22Igor Murashkin A list of Section/InnerNamespace instances 57da1c314e080d33eb6b93a1d3da070c99b41e7b22Igor Murashkin 58da1c314e080d33eb6b93a1d3da070c99b41e7b22Igor Murashkin Remarks: 59da1c314e080d33eb6b93a1d3da070c99b41e7b22Igor Murashkin These are known as "sections" in the generated C code. 60da1c314e080d33eb6b93a1d3da070c99b41e7b22Igor Murashkin """ 61da1c314e080d33eb6b93a1d3da070c99b41e7b22Igor Murashkin return root.find_all(_is_sec_or_ins) 62da1c314e080d33eb6b93a1d3da070c99b41e7b22Igor Murashkin 63da1c314e080d33eb6b93a1d3da070c99b41e7b22Igor Murashkindef find_parent_section(entry): 64da1c314e080d33eb6b93a1d3da070c99b41e7b22Igor Murashkin """ 65da1c314e080d33eb6b93a1d3da070c99b41e7b22Igor Murashkin Find the closest ancestor that is either a Section or InnerNamespace. 66da1c314e080d33eb6b93a1d3da070c99b41e7b22Igor Murashkin 67da1c314e080d33eb6b93a1d3da070c99b41e7b22Igor Murashkin Args: 68da1c314e080d33eb6b93a1d3da070c99b41e7b22Igor Murashkin entry: an Entry or Clone node 69da1c314e080d33eb6b93a1d3da070c99b41e7b22Igor Murashkin 70da1c314e080d33eb6b93a1d3da070c99b41e7b22Igor Murashkin Returns: 71da1c314e080d33eb6b93a1d3da070c99b41e7b22Igor Murashkin An instance of Section or InnerNamespace 72da1c314e080d33eb6b93a1d3da070c99b41e7b22Igor Murashkin """ 73da1c314e080d33eb6b93a1d3da070c99b41e7b22Igor Murashkin return entry.find_parent_first(_is_sec_or_ins) 74da1c314e080d33eb6b93a1d3da070c99b41e7b22Igor Murashkin 75da1c314e080d33eb6b93a1d3da070c99b41e7b22Igor Murashkin# find uniquely named entries (w/o recursing through inner namespaces) 76da1c314e080d33eb6b93a1d3da070c99b41e7b22Igor Murashkindef find_unique_entries(node): 77da1c314e080d33eb6b93a1d3da070c99b41e7b22Igor Murashkin """ 78da1c314e080d33eb6b93a1d3da070c99b41e7b22Igor Murashkin Find all uniquely named entries, without recursing through inner namespaces. 79da1c314e080d33eb6b93a1d3da070c99b41e7b22Igor Murashkin 80da1c314e080d33eb6b93a1d3da070c99b41e7b22Igor Murashkin Args: 81da1c314e080d33eb6b93a1d3da070c99b41e7b22Igor Murashkin node: a Section or InnerNamespace instance 82da1c314e080d33eb6b93a1d3da070c99b41e7b22Igor Murashkin 83da1c314e080d33eb6b93a1d3da070c99b41e7b22Igor Murashkin Yields: 84da1c314e080d33eb6b93a1d3da070c99b41e7b22Igor Murashkin A sequence of MergedEntry nodes representing an entry 85da1c314e080d33eb6b93a1d3da070c99b41e7b22Igor Murashkin 86da1c314e080d33eb6b93a1d3da070c99b41e7b22Igor Murashkin Remarks: 87da1c314e080d33eb6b93a1d3da070c99b41e7b22Igor Murashkin This collapses multiple entries with the same fully qualified name into 88da1c314e080d33eb6b93a1d3da070c99b41e7b22Igor Murashkin one entry (e.g. if there are multiple entries in different kinds). 89da1c314e080d33eb6b93a1d3da070c99b41e7b22Igor Murashkin """ 90da1c314e080d33eb6b93a1d3da070c99b41e7b22Igor Murashkin if not isinstance(node, metadata_model.Section) and \ 91da1c314e080d33eb6b93a1d3da070c99b41e7b22Igor Murashkin not isinstance(node, metadata_model.InnerNamespace): 92da1c314e080d33eb6b93a1d3da070c99b41e7b22Igor Murashkin raise TypeError("expected node to be a Section or InnerNamespace") 93da1c314e080d33eb6b93a1d3da070c99b41e7b22Igor Murashkin 94586c861e6dab3fdf48fc8440c719ad0b59d49d72Igor Murashkin d = OrderedDict() 95da1c314e080d33eb6b93a1d3da070c99b41e7b22Igor Murashkin # remove the 'kinds' from the path between sec and the closest entries 96da1c314e080d33eb6b93a1d3da070c99b41e7b22Igor Murashkin # then search the immediate children of the search path 97da1c314e080d33eb6b93a1d3da070c99b41e7b22Igor Murashkin search_path = isinstance(node, metadata_model.Section) and node.kinds \ 98da1c314e080d33eb6b93a1d3da070c99b41e7b22Igor Murashkin or [node] 99da1c314e080d33eb6b93a1d3da070c99b41e7b22Igor Murashkin for i in search_path: 100da1c314e080d33eb6b93a1d3da070c99b41e7b22Igor Murashkin for entry in i.entries: 101da1c314e080d33eb6b93a1d3da070c99b41e7b22Igor Murashkin d[entry.name] = entry 102da1c314e080d33eb6b93a1d3da070c99b41e7b22Igor Murashkin 103da1c314e080d33eb6b93a1d3da070c99b41e7b22Igor Murashkin for k,v in d.iteritems(): 104da1c314e080d33eb6b93a1d3da070c99b41e7b22Igor Murashkin yield v.merge() 105da1c314e080d33eb6b93a1d3da070c99b41e7b22Igor Murashkin 106da1c314e080d33eb6b93a1d3da070c99b41e7b22Igor Murashkindef path_name(node): 107da1c314e080d33eb6b93a1d3da070c99b41e7b22Igor Murashkin """ 108da1c314e080d33eb6b93a1d3da070c99b41e7b22Igor Murashkin Calculate a period-separated string path from the root to this element, 109da1c314e080d33eb6b93a1d3da070c99b41e7b22Igor Murashkin by joining the names of each node and excluding the Metadata/Kind nodes 110da1c314e080d33eb6b93a1d3da070c99b41e7b22Igor Murashkin from the path. 111da1c314e080d33eb6b93a1d3da070c99b41e7b22Igor Murashkin 112da1c314e080d33eb6b93a1d3da070c99b41e7b22Igor Murashkin Args: 113da1c314e080d33eb6b93a1d3da070c99b41e7b22Igor Murashkin node: a Node instance 114da1c314e080d33eb6b93a1d3da070c99b41e7b22Igor Murashkin 115da1c314e080d33eb6b93a1d3da070c99b41e7b22Igor Murashkin Returns: 116da1c314e080d33eb6b93a1d3da070c99b41e7b22Igor Murashkin A string path 117da1c314e080d33eb6b93a1d3da070c99b41e7b22Igor Murashkin """ 118da1c314e080d33eb6b93a1d3da070c99b41e7b22Igor Murashkin 119da1c314e080d33eb6b93a1d3da070c99b41e7b22Igor Murashkin isa = lambda x,y: isinstance(x, y) 120da1c314e080d33eb6b93a1d3da070c99b41e7b22Igor Murashkin fltr = lambda x: not isa(x, metadata_model.Metadata) and \ 121da1c314e080d33eb6b93a1d3da070c99b41e7b22Igor Murashkin not isa(x, metadata_model.Kind) 122da1c314e080d33eb6b93a1d3da070c99b41e7b22Igor Murashkin 123da1c314e080d33eb6b93a1d3da070c99b41e7b22Igor Murashkin path = node.find_parents(fltr) 124da1c314e080d33eb6b93a1d3da070c99b41e7b22Igor Murashkin path = list(path) 125da1c314e080d33eb6b93a1d3da070c99b41e7b22Igor Murashkin path.reverse() 126da1c314e080d33eb6b93a1d3da070c99b41e7b22Igor Murashkin path.append(node) 127da1c314e080d33eb6b93a1d3da070c99b41e7b22Igor Murashkin 128da1c314e080d33eb6b93a1d3da070c99b41e7b22Igor Murashkin return ".".join((i.name for i in path)) 129da1c314e080d33eb6b93a1d3da070c99b41e7b22Igor Murashkin 130ea7662f32e3b6e6e74f0fedbd558b35784e6e219Yin-Chia Yehdef ndk(name): 131ea7662f32e3b6e6e74f0fedbd558b35784e6e219Yin-Chia Yeh """ 132ea7662f32e3b6e6e74f0fedbd558b35784e6e219Yin-Chia Yeh Return the NDK version of given name, which replace 133ea7662f32e3b6e6e74f0fedbd558b35784e6e219Yin-Chia Yeh the leading "android" to "acamera" 134ea7662f32e3b6e6e74f0fedbd558b35784e6e219Yin-Chia Yeh 135ea7662f32e3b6e6e74f0fedbd558b35784e6e219Yin-Chia Yeh Args: 136ea7662f32e3b6e6e74f0fedbd558b35784e6e219Yin-Chia Yeh name: name string of an entry 137ea7662f32e3b6e6e74f0fedbd558b35784e6e219Yin-Chia Yeh 138ea7662f32e3b6e6e74f0fedbd558b35784e6e219Yin-Chia Yeh Returns: 139ea7662f32e3b6e6e74f0fedbd558b35784e6e219Yin-Chia Yeh A NDK version name string of the input name 140ea7662f32e3b6e6e74f0fedbd558b35784e6e219Yin-Chia Yeh """ 141ea7662f32e3b6e6e74f0fedbd558b35784e6e219Yin-Chia Yeh name_list = name.split(".") 142ea7662f32e3b6e6e74f0fedbd558b35784e6e219Yin-Chia Yeh if name_list[0] == "android": 143ea7662f32e3b6e6e74f0fedbd558b35784e6e219Yin-Chia Yeh name_list[0] = "acamera" 144ea7662f32e3b6e6e74f0fedbd558b35784e6e219Yin-Chia Yeh return ".".join(name_list) 145ea7662f32e3b6e6e74f0fedbd558b35784e6e219Yin-Chia Yeh 146c9b27dd2a92203ee914485cbc52a4f583d763142Yin-Chia Yehdef protobuf_type(entry): 147c9b27dd2a92203ee914485cbc52a4f583d763142Yin-Chia Yeh """ 148c9b27dd2a92203ee914485cbc52a4f583d763142Yin-Chia Yeh Return the protocol buffer message type for input metadata entry. 149c9b27dd2a92203ee914485cbc52a4f583d763142Yin-Chia Yeh Only support types used by static metadata right now 150c9b27dd2a92203ee914485cbc52a4f583d763142Yin-Chia Yeh 151c9b27dd2a92203ee914485cbc52a4f583d763142Yin-Chia Yeh Returns: 152c9b27dd2a92203ee914485cbc52a4f583d763142Yin-Chia Yeh A string of protocol buffer type. Ex: "optional int32" or "repeated RangeInt" 153c9b27dd2a92203ee914485cbc52a4f583d763142Yin-Chia Yeh """ 154c9b27dd2a92203ee914485cbc52a4f583d763142Yin-Chia Yeh typeName = None 155c9b27dd2a92203ee914485cbc52a4f583d763142Yin-Chia Yeh if entry.typedef is None: 156c9b27dd2a92203ee914485cbc52a4f583d763142Yin-Chia Yeh typeName = entry.type 157c9b27dd2a92203ee914485cbc52a4f583d763142Yin-Chia Yeh else: 158c9b27dd2a92203ee914485cbc52a4f583d763142Yin-Chia Yeh typeName = entry.typedef.name 159c9b27dd2a92203ee914485cbc52a4f583d763142Yin-Chia Yeh 160c9b27dd2a92203ee914485cbc52a4f583d763142Yin-Chia Yeh typename_to_protobuftype = { 161c9b27dd2a92203ee914485cbc52a4f583d763142Yin-Chia Yeh "rational" : "Rational", 162c9b27dd2a92203ee914485cbc52a4f583d763142Yin-Chia Yeh "size" : "Size", 163c9b27dd2a92203ee914485cbc52a4f583d763142Yin-Chia Yeh "sizeF" : "SizeF", 164c9b27dd2a92203ee914485cbc52a4f583d763142Yin-Chia Yeh "rectangle" : "Rect", 165c9b27dd2a92203ee914485cbc52a4f583d763142Yin-Chia Yeh "streamConfigurationMap" : "StreamConfigurations", 166c9b27dd2a92203ee914485cbc52a4f583d763142Yin-Chia Yeh "rangeInt" : "RangeInt", 167c9b27dd2a92203ee914485cbc52a4f583d763142Yin-Chia Yeh "rangeLong" : "RangeLong", 168c9b27dd2a92203ee914485cbc52a4f583d763142Yin-Chia Yeh "colorSpaceTransform" : "ColorSpaceTransform", 169c9b27dd2a92203ee914485cbc52a4f583d763142Yin-Chia Yeh "blackLevelPattern" : "BlackLevelPattern", 170c9b27dd2a92203ee914485cbc52a4f583d763142Yin-Chia Yeh "byte" : "int32", # protocol buffer don't support byte 171c9b27dd2a92203ee914485cbc52a4f583d763142Yin-Chia Yeh "boolean" : "bool", 172c9b27dd2a92203ee914485cbc52a4f583d763142Yin-Chia Yeh "float" : "float", 173c9b27dd2a92203ee914485cbc52a4f583d763142Yin-Chia Yeh "double" : "double", 174c9b27dd2a92203ee914485cbc52a4f583d763142Yin-Chia Yeh "int32" : "int32", 175c9b27dd2a92203ee914485cbc52a4f583d763142Yin-Chia Yeh "int64" : "int64", 176c9b27dd2a92203ee914485cbc52a4f583d763142Yin-Chia Yeh "enumList" : "int32" 177c9b27dd2a92203ee914485cbc52a4f583d763142Yin-Chia Yeh } 178c9b27dd2a92203ee914485cbc52a4f583d763142Yin-Chia Yeh 179c9b27dd2a92203ee914485cbc52a4f583d763142Yin-Chia Yeh if typeName not in typename_to_protobuftype: 180c9b27dd2a92203ee914485cbc52a4f583d763142Yin-Chia Yeh print >> sys.stderr,\ 181c9b27dd2a92203ee914485cbc52a4f583d763142Yin-Chia Yeh " ERROR: Could not find protocol buffer type for {%s} type {%s} typedef {%s}" % \ 182c9b27dd2a92203ee914485cbc52a4f583d763142Yin-Chia Yeh (entry.name, entry.type, entry.typedef) 183c9b27dd2a92203ee914485cbc52a4f583d763142Yin-Chia Yeh 184c9b27dd2a92203ee914485cbc52a4f583d763142Yin-Chia Yeh proto_type = typename_to_protobuftype[typeName] 185c9b27dd2a92203ee914485cbc52a4f583d763142Yin-Chia Yeh 186c9b27dd2a92203ee914485cbc52a4f583d763142Yin-Chia Yeh prefix = "optional" 187c9b27dd2a92203ee914485cbc52a4f583d763142Yin-Chia Yeh if entry.container == 'array': 188c9b27dd2a92203ee914485cbc52a4f583d763142Yin-Chia Yeh has_variable_size = False 189c9b27dd2a92203ee914485cbc52a4f583d763142Yin-Chia Yeh for size in entry.container_sizes: 190c9b27dd2a92203ee914485cbc52a4f583d763142Yin-Chia Yeh try: 191c9b27dd2a92203ee914485cbc52a4f583d763142Yin-Chia Yeh size_int = int(size) 192c9b27dd2a92203ee914485cbc52a4f583d763142Yin-Chia Yeh except ValueError: 193c9b27dd2a92203ee914485cbc52a4f583d763142Yin-Chia Yeh has_variable_size = True 194c9b27dd2a92203ee914485cbc52a4f583d763142Yin-Chia Yeh 195c9b27dd2a92203ee914485cbc52a4f583d763142Yin-Chia Yeh if has_variable_size: 196c9b27dd2a92203ee914485cbc52a4f583d763142Yin-Chia Yeh prefix = "repeated" 197c9b27dd2a92203ee914485cbc52a4f583d763142Yin-Chia Yeh 198c9b27dd2a92203ee914485cbc52a4f583d763142Yin-Chia Yeh return "%s %s" %(prefix, proto_type) 199c9b27dd2a92203ee914485cbc52a4f583d763142Yin-Chia Yeh 200c9b27dd2a92203ee914485cbc52a4f583d763142Yin-Chia Yeh 201c9b27dd2a92203ee914485cbc52a4f583d763142Yin-Chia Yehdef protobuf_name(entry): 202c9b27dd2a92203ee914485cbc52a4f583d763142Yin-Chia Yeh """ 203c9b27dd2a92203ee914485cbc52a4f583d763142Yin-Chia Yeh Return the protocol buffer field name for input metadata entry 204c9b27dd2a92203ee914485cbc52a4f583d763142Yin-Chia Yeh 205c9b27dd2a92203ee914485cbc52a4f583d763142Yin-Chia Yeh Returns: 206c9b27dd2a92203ee914485cbc52a4f583d763142Yin-Chia Yeh A string. Ex: "android_colorCorrection_availableAberrationModes" 207c9b27dd2a92203ee914485cbc52a4f583d763142Yin-Chia Yeh """ 208c9b27dd2a92203ee914485cbc52a4f583d763142Yin-Chia Yeh return entry.name.replace(".", "_") 209c9b27dd2a92203ee914485cbc52a4f583d763142Yin-Chia Yeh 210aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkindef has_descendants_with_enums(node): 211aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin """ 212aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin Determine whether or not the current node is or has any descendants with an 213aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin Enum node. 214aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin 215aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin Args: 216aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin node: a Node instance 217aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin 218aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin Returns: 219aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin True if it finds an Enum node in the subtree, False otherwise 220aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin """ 221aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin return bool(node.find_first(lambda x: isinstance(x, metadata_model.Enum))) 222aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin 223aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkindef get_children_by_throwing_away_kind(node, member='entries'): 224aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin """ 225aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin Get the children of this node by compressing the subtree together by removing 226aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin the kind and then combining any children nodes with the same name together. 227aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin 228aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin Args: 229aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin node: An instance of Section, InnerNamespace, or Kind 230aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin 231aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin Returns: 232aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin An iterable over the combined children of the subtree of node, 233aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin as if the Kinds never existed. 234aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin 235aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin Remarks: 236aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin Not recursive. Call this function repeatedly on each child. 237aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin """ 238aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin 239aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin if isinstance(node, metadata_model.Section): 240aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin # Note that this makes jump from Section to Kind, 241aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin # skipping the Kind entirely in the tree. 242aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin node_to_combine = node.combine_kinds_into_single_node() 243aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin else: 244aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin node_to_combine = node 245aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin 246aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin combined_kind = node_to_combine.combine_children_by_name() 247aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin 248aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin return (i for i in getattr(combined_kind, member)) 249aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin 250aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkindef get_children_by_filtering_kind(section, kind_name, member='entries'): 251aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin """ 25223d4b2c087bd4286bf16bda83b6d9f72c5bb1718Eino-Ville Talvala Takes a section and yields the children of the merged kind under this section. 253aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin 254aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin Args: 255aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin section: An instance of Section 256aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin kind_name: A name of the kind, i.e. 'dynamic' or 'static' or 'controls' 257aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin 258aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin Returns: 25923d4b2c087bd4286bf16bda83b6d9f72c5bb1718Eino-Ville Talvala An iterable over the children of the specified merged kind. 260aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin """ 261aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin 26223d4b2c087bd4286bf16bda83b6d9f72c5bb1718Eino-Ville Talvala matched_kind = next((i for i in section.merged_kinds if i.name == kind_name), None) 263aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin 264aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin if matched_kind: 265aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin return getattr(matched_kind, member) 266aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin else: 267aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin return () 268aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin 269da1c314e080d33eb6b93a1d3da070c99b41e7b22Igor Murashkin## 270da1c314e080d33eb6b93a1d3da070c99b41e7b22Igor Murashkin## Filters 271da1c314e080d33eb6b93a1d3da070c99b41e7b22Igor Murashkin## 272da1c314e080d33eb6b93a1d3da070c99b41e7b22Igor Murashkin 273da1c314e080d33eb6b93a1d3da070c99b41e7b22Igor Murashkin# abcDef.xyz -> ABC_DEF_XYZ 274da1c314e080d33eb6b93a1d3da070c99b41e7b22Igor Murashkindef csym(name): 275da1c314e080d33eb6b93a1d3da070c99b41e7b22Igor Murashkin """ 276da1c314e080d33eb6b93a1d3da070c99b41e7b22Igor Murashkin Convert an entry name string into an uppercase C symbol. 277da1c314e080d33eb6b93a1d3da070c99b41e7b22Igor Murashkin 278da1c314e080d33eb6b93a1d3da070c99b41e7b22Igor Murashkin Returns: 279da1c314e080d33eb6b93a1d3da070c99b41e7b22Igor Murashkin A string 280da1c314e080d33eb6b93a1d3da070c99b41e7b22Igor Murashkin 281da1c314e080d33eb6b93a1d3da070c99b41e7b22Igor Murashkin Example: 282da1c314e080d33eb6b93a1d3da070c99b41e7b22Igor Murashkin csym('abcDef.xyz') == 'ABC_DEF_XYZ' 283da1c314e080d33eb6b93a1d3da070c99b41e7b22Igor Murashkin """ 284da1c314e080d33eb6b93a1d3da070c99b41e7b22Igor Murashkin newstr = name 285da1c314e080d33eb6b93a1d3da070c99b41e7b22Igor Murashkin newstr = "".join([i.isupper() and ("_" + i) or i for i in newstr]).upper() 286da1c314e080d33eb6b93a1d3da070c99b41e7b22Igor Murashkin newstr = newstr.replace(".", "_") 287da1c314e080d33eb6b93a1d3da070c99b41e7b22Igor Murashkin return newstr 288da1c314e080d33eb6b93a1d3da070c99b41e7b22Igor Murashkin 289da1c314e080d33eb6b93a1d3da070c99b41e7b22Igor Murashkin# abcDef.xyz -> abc_def_xyz 290da1c314e080d33eb6b93a1d3da070c99b41e7b22Igor Murashkindef csyml(name): 291da1c314e080d33eb6b93a1d3da070c99b41e7b22Igor Murashkin """ 292da1c314e080d33eb6b93a1d3da070c99b41e7b22Igor Murashkin Convert an entry name string into a lowercase C symbol. 293da1c314e080d33eb6b93a1d3da070c99b41e7b22Igor Murashkin 294da1c314e080d33eb6b93a1d3da070c99b41e7b22Igor Murashkin Returns: 295da1c314e080d33eb6b93a1d3da070c99b41e7b22Igor Murashkin A string 296da1c314e080d33eb6b93a1d3da070c99b41e7b22Igor Murashkin 297da1c314e080d33eb6b93a1d3da070c99b41e7b22Igor Murashkin Example: 298da1c314e080d33eb6b93a1d3da070c99b41e7b22Igor Murashkin csyml('abcDef.xyz') == 'abc_def_xyz' 299da1c314e080d33eb6b93a1d3da070c99b41e7b22Igor Murashkin """ 300da1c314e080d33eb6b93a1d3da070c99b41e7b22Igor Murashkin return csym(name).lower() 301da1c314e080d33eb6b93a1d3da070c99b41e7b22Igor Murashkin 302da1c314e080d33eb6b93a1d3da070c99b41e7b22Igor Murashkin# pad with spaces to make string len == size. add new line if too big 303da1c314e080d33eb6b93a1d3da070c99b41e7b22Igor Murashkindef ljust(size, indent=4): 304da1c314e080d33eb6b93a1d3da070c99b41e7b22Igor Murashkin """ 305da1c314e080d33eb6b93a1d3da070c99b41e7b22Igor Murashkin Creates a function that given a string will pad it with spaces to make 306da1c314e080d33eb6b93a1d3da070c99b41e7b22Igor Murashkin the string length == size. Adds a new line if the string was too big. 307da1c314e080d33eb6b93a1d3da070c99b41e7b22Igor Murashkin 308da1c314e080d33eb6b93a1d3da070c99b41e7b22Igor Murashkin Args: 309da1c314e080d33eb6b93a1d3da070c99b41e7b22Igor Murashkin size: an integer representing how much spacing should be added 310da1c314e080d33eb6b93a1d3da070c99b41e7b22Igor Murashkin indent: an integer representing the initial indendation level 311da1c314e080d33eb6b93a1d3da070c99b41e7b22Igor Murashkin 312da1c314e080d33eb6b93a1d3da070c99b41e7b22Igor Murashkin Returns: 313da1c314e080d33eb6b93a1d3da070c99b41e7b22Igor Murashkin A function that takes a string and returns a string. 314da1c314e080d33eb6b93a1d3da070c99b41e7b22Igor Murashkin 315da1c314e080d33eb6b93a1d3da070c99b41e7b22Igor Murashkin Example: 316da1c314e080d33eb6b93a1d3da070c99b41e7b22Igor Murashkin ljust(8)("hello") == 'hello ' 317da1c314e080d33eb6b93a1d3da070c99b41e7b22Igor Murashkin 318da1c314e080d33eb6b93a1d3da070c99b41e7b22Igor Murashkin Remarks: 319da1c314e080d33eb6b93a1d3da070c99b41e7b22Igor Murashkin Deprecated. Use pad instead since it works for non-first items in a 320da1c314e080d33eb6b93a1d3da070c99b41e7b22Igor Murashkin Mako template. 321da1c314e080d33eb6b93a1d3da070c99b41e7b22Igor Murashkin """ 322da1c314e080d33eb6b93a1d3da070c99b41e7b22Igor Murashkin def inner(what): 323da1c314e080d33eb6b93a1d3da070c99b41e7b22Igor Murashkin newstr = what.ljust(size) 324da1c314e080d33eb6b93a1d3da070c99b41e7b22Igor Murashkin if len(newstr) > size: 325da1c314e080d33eb6b93a1d3da070c99b41e7b22Igor Murashkin return what + "\n" + "".ljust(indent + size) 326da1c314e080d33eb6b93a1d3da070c99b41e7b22Igor Murashkin else: 327da1c314e080d33eb6b93a1d3da070c99b41e7b22Igor Murashkin return newstr 328da1c314e080d33eb6b93a1d3da070c99b41e7b22Igor Murashkin return inner 329da1c314e080d33eb6b93a1d3da070c99b41e7b22Igor Murashkin 330da1c314e080d33eb6b93a1d3da070c99b41e7b22Igor Murashkindef _find_new_line(): 331da1c314e080d33eb6b93a1d3da070c99b41e7b22Igor Murashkin 332da1c314e080d33eb6b93a1d3da070c99b41e7b22Igor Murashkin if _context_buf is None: 333da1c314e080d33eb6b93a1d3da070c99b41e7b22Igor Murashkin raise ValueError("Context buffer was not set") 334da1c314e080d33eb6b93a1d3da070c99b41e7b22Igor Murashkin 335da1c314e080d33eb6b93a1d3da070c99b41e7b22Igor Murashkin buf = _context_buf 336da1c314e080d33eb6b93a1d3da070c99b41e7b22Igor Murashkin x = -1 # since the first read is always '' 337da1c314e080d33eb6b93a1d3da070c99b41e7b22Igor Murashkin cur_pos = buf.tell() 338da1c314e080d33eb6b93a1d3da070c99b41e7b22Igor Murashkin while buf.tell() > 0 and buf.read(1) != '\n': 339da1c314e080d33eb6b93a1d3da070c99b41e7b22Igor Murashkin buf.seek(cur_pos - x) 340da1c314e080d33eb6b93a1d3da070c99b41e7b22Igor Murashkin x = x + 1 341da1c314e080d33eb6b93a1d3da070c99b41e7b22Igor Murashkin 342da1c314e080d33eb6b93a1d3da070c99b41e7b22Igor Murashkin buf.seek(cur_pos) 343da1c314e080d33eb6b93a1d3da070c99b41e7b22Igor Murashkin 344da1c314e080d33eb6b93a1d3da070c99b41e7b22Igor Murashkin return int(x) 345da1c314e080d33eb6b93a1d3da070c99b41e7b22Igor Murashkin 346da1c314e080d33eb6b93a1d3da070c99b41e7b22Igor Murashkin# Pad the string until the buffer reaches the desired column. 347da1c314e080d33eb6b93a1d3da070c99b41e7b22Igor Murashkin# If string is too long, insert a new line with 'col' spaces instead 348da1c314e080d33eb6b93a1d3da070c99b41e7b22Igor Murashkindef pad(col): 349da1c314e080d33eb6b93a1d3da070c99b41e7b22Igor Murashkin """ 350da1c314e080d33eb6b93a1d3da070c99b41e7b22Igor Murashkin Create a function that given a string will pad it to the specified column col. 351da1c314e080d33eb6b93a1d3da070c99b41e7b22Igor Murashkin If the string overflows the column, put the string on a new line and pad it. 352da1c314e080d33eb6b93a1d3da070c99b41e7b22Igor Murashkin 353da1c314e080d33eb6b93a1d3da070c99b41e7b22Igor Murashkin Args: 354da1c314e080d33eb6b93a1d3da070c99b41e7b22Igor Murashkin col: an integer specifying the column number 355da1c314e080d33eb6b93a1d3da070c99b41e7b22Igor Murashkin 356da1c314e080d33eb6b93a1d3da070c99b41e7b22Igor Murashkin Returns: 357da1c314e080d33eb6b93a1d3da070c99b41e7b22Igor Murashkin A function that given a string will produce a padded string. 358da1c314e080d33eb6b93a1d3da070c99b41e7b22Igor Murashkin 359da1c314e080d33eb6b93a1d3da070c99b41e7b22Igor Murashkin Example: 360da1c314e080d33eb6b93a1d3da070c99b41e7b22Igor Murashkin pad(8)("hello") == 'hello ' 361da1c314e080d33eb6b93a1d3da070c99b41e7b22Igor Murashkin 362da1c314e080d33eb6b93a1d3da070c99b41e7b22Igor Murashkin Remarks: 363da1c314e080d33eb6b93a1d3da070c99b41e7b22Igor Murashkin This keeps track of the line written by Mako so far, so it will always 364da1c314e080d33eb6b93a1d3da070c99b41e7b22Igor Murashkin align to the column number correctly. 365da1c314e080d33eb6b93a1d3da070c99b41e7b22Igor Murashkin """ 366da1c314e080d33eb6b93a1d3da070c99b41e7b22Igor Murashkin def inner(what): 367da1c314e080d33eb6b93a1d3da070c99b41e7b22Igor Murashkin wut = int(col) 368da1c314e080d33eb6b93a1d3da070c99b41e7b22Igor Murashkin current_col = _find_new_line() 369da1c314e080d33eb6b93a1d3da070c99b41e7b22Igor Murashkin 370da1c314e080d33eb6b93a1d3da070c99b41e7b22Igor Murashkin if len(what) > wut - current_col: 371da1c314e080d33eb6b93a1d3da070c99b41e7b22Igor Murashkin return what + "\n".ljust(col) 372da1c314e080d33eb6b93a1d3da070c99b41e7b22Igor Murashkin else: 373da1c314e080d33eb6b93a1d3da070c99b41e7b22Igor Murashkin return what.ljust(wut - current_col) 374da1c314e080d33eb6b93a1d3da070c99b41e7b22Igor Murashkin return inner 375da1c314e080d33eb6b93a1d3da070c99b41e7b22Igor Murashkin 376da1c314e080d33eb6b93a1d3da070c99b41e7b22Igor Murashkin# int32 -> TYPE_INT32, byte -> TYPE_BYTE, etc. note that enum -> TYPE_INT32 377da1c314e080d33eb6b93a1d3da070c99b41e7b22Igor Murashkindef ctype_enum(what): 378da1c314e080d33eb6b93a1d3da070c99b41e7b22Igor Murashkin """ 379da1c314e080d33eb6b93a1d3da070c99b41e7b22Igor Murashkin Generate a camera_metadata_type_t symbol from a type string. 380da1c314e080d33eb6b93a1d3da070c99b41e7b22Igor Murashkin 381da1c314e080d33eb6b93a1d3da070c99b41e7b22Igor Murashkin Args: 382da1c314e080d33eb6b93a1d3da070c99b41e7b22Igor Murashkin what: a type string 383da1c314e080d33eb6b93a1d3da070c99b41e7b22Igor Murashkin 384da1c314e080d33eb6b93a1d3da070c99b41e7b22Igor Murashkin Returns: 385da1c314e080d33eb6b93a1d3da070c99b41e7b22Igor Murashkin A string representing the camera_metadata_type_t 386da1c314e080d33eb6b93a1d3da070c99b41e7b22Igor Murashkin 387da1c314e080d33eb6b93a1d3da070c99b41e7b22Igor Murashkin Example: 388da1c314e080d33eb6b93a1d3da070c99b41e7b22Igor Murashkin ctype_enum('int32') == 'TYPE_INT32' 389da1c314e080d33eb6b93a1d3da070c99b41e7b22Igor Murashkin ctype_enum('int64') == 'TYPE_INT64' 390da1c314e080d33eb6b93a1d3da070c99b41e7b22Igor Murashkin ctype_enum('float') == 'TYPE_FLOAT' 391da1c314e080d33eb6b93a1d3da070c99b41e7b22Igor Murashkin 392da1c314e080d33eb6b93a1d3da070c99b41e7b22Igor Murashkin Remarks: 393e6b664671e35984156e06e17531311a09864ac8bIgor Murashkin An enum is coerced to a byte since the rest of the camera_metadata 394da1c314e080d33eb6b93a1d3da070c99b41e7b22Igor Murashkin code doesn't support enums directly yet. 395da1c314e080d33eb6b93a1d3da070c99b41e7b22Igor Murashkin """ 396da1c314e080d33eb6b93a1d3da070c99b41e7b22Igor Murashkin return 'TYPE_%s' %(what.upper()) 397aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin 398b8dc88148bca2e5a267c2ff39aff94b98b00ad6dIgor Murashkin 399b8dc88148bca2e5a267c2ff39aff94b98b00ad6dIgor Murashkin# Calculate a java type name from an entry with a Typedef node 400b8dc88148bca2e5a267c2ff39aff94b98b00ad6dIgor Murashkindef _jtypedef_type(entry): 401b8dc88148bca2e5a267c2ff39aff94b98b00ad6dIgor Murashkin typedef = entry.typedef 402b8dc88148bca2e5a267c2ff39aff94b98b00ad6dIgor Murashkin additional = '' 403b8dc88148bca2e5a267c2ff39aff94b98b00ad6dIgor Murashkin 404b8dc88148bca2e5a267c2ff39aff94b98b00ad6dIgor Murashkin # Hacky way to deal with arrays. Assume that if we have 405b8dc88148bca2e5a267c2ff39aff94b98b00ad6dIgor Murashkin # size 'Constant x N' the Constant is part of the Typedef size. 406b8dc88148bca2e5a267c2ff39aff94b98b00ad6dIgor Murashkin # So something sized just 'Constant', 'Constant1 x Constant2', etc 407b8dc88148bca2e5a267c2ff39aff94b98b00ad6dIgor Murashkin # is not treated as a real java array. 408b8dc88148bca2e5a267c2ff39aff94b98b00ad6dIgor Murashkin if entry.container == 'array': 409b8dc88148bca2e5a267c2ff39aff94b98b00ad6dIgor Murashkin has_variable_size = False 410b8dc88148bca2e5a267c2ff39aff94b98b00ad6dIgor Murashkin for size in entry.container_sizes: 411b8dc88148bca2e5a267c2ff39aff94b98b00ad6dIgor Murashkin try: 412b8dc88148bca2e5a267c2ff39aff94b98b00ad6dIgor Murashkin size_int = int(size) 413b8dc88148bca2e5a267c2ff39aff94b98b00ad6dIgor Murashkin except ValueError: 414b8dc88148bca2e5a267c2ff39aff94b98b00ad6dIgor Murashkin has_variable_size = True 415b8dc88148bca2e5a267c2ff39aff94b98b00ad6dIgor Murashkin 416b8dc88148bca2e5a267c2ff39aff94b98b00ad6dIgor Murashkin if has_variable_size: 417b8dc88148bca2e5a267c2ff39aff94b98b00ad6dIgor Murashkin additional = '[]' 418b8dc88148bca2e5a267c2ff39aff94b98b00ad6dIgor Murashkin 419b8dc88148bca2e5a267c2ff39aff94b98b00ad6dIgor Murashkin try: 420b8dc88148bca2e5a267c2ff39aff94b98b00ad6dIgor Murashkin name = typedef.languages['java'] 421b8dc88148bca2e5a267c2ff39aff94b98b00ad6dIgor Murashkin 422b8dc88148bca2e5a267c2ff39aff94b98b00ad6dIgor Murashkin return "%s%s" %(name, additional) 423b8dc88148bca2e5a267c2ff39aff94b98b00ad6dIgor Murashkin except KeyError: 424b8dc88148bca2e5a267c2ff39aff94b98b00ad6dIgor Murashkin return None 425b8dc88148bca2e5a267c2ff39aff94b98b00ad6dIgor Murashkin 426b8dc88148bca2e5a267c2ff39aff94b98b00ad6dIgor Murashkin# Box if primitive. Otherwise leave unboxed. 427b8dc88148bca2e5a267c2ff39aff94b98b00ad6dIgor Murashkindef _jtype_box(type_name): 428b8dc88148bca2e5a267c2ff39aff94b98b00ad6dIgor Murashkin mapping = { 429b8dc88148bca2e5a267c2ff39aff94b98b00ad6dIgor Murashkin 'boolean': 'Boolean', 430b8dc88148bca2e5a267c2ff39aff94b98b00ad6dIgor Murashkin 'byte': 'Byte', 431b8dc88148bca2e5a267c2ff39aff94b98b00ad6dIgor Murashkin 'int': 'Integer', 432b8dc88148bca2e5a267c2ff39aff94b98b00ad6dIgor Murashkin 'float': 'Float', 433b8dc88148bca2e5a267c2ff39aff94b98b00ad6dIgor Murashkin 'double': 'Double', 434b8dc88148bca2e5a267c2ff39aff94b98b00ad6dIgor Murashkin 'long': 'Long' 435b8dc88148bca2e5a267c2ff39aff94b98b00ad6dIgor Murashkin } 436b8dc88148bca2e5a267c2ff39aff94b98b00ad6dIgor Murashkin 437b8dc88148bca2e5a267c2ff39aff94b98b00ad6dIgor Murashkin return mapping.get(type_name, type_name) 438b8dc88148bca2e5a267c2ff39aff94b98b00ad6dIgor Murashkin 439b8dc88148bca2e5a267c2ff39aff94b98b00ad6dIgor Murashkindef jtype_unboxed(entry): 440aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin """ 441b8dc88148bca2e5a267c2ff39aff94b98b00ad6dIgor Murashkin Calculate the Java type from an entry type string, to be used whenever we 442b8dc88148bca2e5a267c2ff39aff94b98b00ad6dIgor Murashkin need the regular type in Java. It's not boxed, so it can't be used as a 443b8dc88148bca2e5a267c2ff39aff94b98b00ad6dIgor Murashkin generic type argument when the entry type happens to resolve to a primitive. 444aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin 445aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin Remarks: 446aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin Since Java generics cannot be instantiated with primitives, this version 447b8dc88148bca2e5a267c2ff39aff94b98b00ad6dIgor Murashkin is not applicable in that case. Use jtype_boxed instead for that. 448aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin 449aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin Returns: 450aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin The string representing the Java type. 451aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin """ 452aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin if not isinstance(entry, metadata_model.Entry): 453aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin raise ValueError("Expected entry to be an instance of Entry") 454aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin 455b8dc88148bca2e5a267c2ff39aff94b98b00ad6dIgor Murashkin metadata_type = entry.type 456aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin 457b8dc88148bca2e5a267c2ff39aff94b98b00ad6dIgor Murashkin java_type = None 458aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin 459b8dc88148bca2e5a267c2ff39aff94b98b00ad6dIgor Murashkin if entry.typedef: 460b8dc88148bca2e5a267c2ff39aff94b98b00ad6dIgor Murashkin typedef_name = _jtypedef_type(entry) 461b8dc88148bca2e5a267c2ff39aff94b98b00ad6dIgor Murashkin if typedef_name: 462b8dc88148bca2e5a267c2ff39aff94b98b00ad6dIgor Murashkin java_type = typedef_name # already takes into account arrays 463aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin 464b8dc88148bca2e5a267c2ff39aff94b98b00ad6dIgor Murashkin if not java_type: 465e04dbd44c7d2043c31107ff3f9efdad71f438071Zhijun He if not java_type and entry.enum and metadata_type == 'byte': 466e04dbd44c7d2043c31107ff3f9efdad71f438071Zhijun He # Always map byte enums to Java ints, unless there's a typedef override 467d4e240adc06f10372f6e18b8ed23e14c4a4138d9Eino-Ville Talvala base_type = 'int' 468aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin 469b8dc88148bca2e5a267c2ff39aff94b98b00ad6dIgor Murashkin else: 470b8dc88148bca2e5a267c2ff39aff94b98b00ad6dIgor Murashkin mapping = { 471b8dc88148bca2e5a267c2ff39aff94b98b00ad6dIgor Murashkin 'int32': 'int', 472b8dc88148bca2e5a267c2ff39aff94b98b00ad6dIgor Murashkin 'int64': 'long', 473b8dc88148bca2e5a267c2ff39aff94b98b00ad6dIgor Murashkin 'float': 'float', 474b8dc88148bca2e5a267c2ff39aff94b98b00ad6dIgor Murashkin 'double': 'double', 475b8dc88148bca2e5a267c2ff39aff94b98b00ad6dIgor Murashkin 'byte': 'byte', 476b8dc88148bca2e5a267c2ff39aff94b98b00ad6dIgor Murashkin 'rational': 'Rational' 477b8dc88148bca2e5a267c2ff39aff94b98b00ad6dIgor Murashkin } 478b8dc88148bca2e5a267c2ff39aff94b98b00ad6dIgor Murashkin 479b8dc88148bca2e5a267c2ff39aff94b98b00ad6dIgor Murashkin base_type = mapping[metadata_type] 480b8dc88148bca2e5a267c2ff39aff94b98b00ad6dIgor Murashkin 481b8dc88148bca2e5a267c2ff39aff94b98b00ad6dIgor Murashkin # Convert to array (enums, basic types) 482b8dc88148bca2e5a267c2ff39aff94b98b00ad6dIgor Murashkin if entry.container == 'array': 483b8dc88148bca2e5a267c2ff39aff94b98b00ad6dIgor Murashkin additional = '[]' 484b8dc88148bca2e5a267c2ff39aff94b98b00ad6dIgor Murashkin else: 485b8dc88148bca2e5a267c2ff39aff94b98b00ad6dIgor Murashkin additional = '' 486b8dc88148bca2e5a267c2ff39aff94b98b00ad6dIgor Murashkin 487b8dc88148bca2e5a267c2ff39aff94b98b00ad6dIgor Murashkin java_type = '%s%s' %(base_type, additional) 488b8dc88148bca2e5a267c2ff39aff94b98b00ad6dIgor Murashkin 489b8dc88148bca2e5a267c2ff39aff94b98b00ad6dIgor Murashkin # Now box this sucker. 490b8dc88148bca2e5a267c2ff39aff94b98b00ad6dIgor Murashkin return java_type 491b8dc88148bca2e5a267c2ff39aff94b98b00ad6dIgor Murashkin 492b8dc88148bca2e5a267c2ff39aff94b98b00ad6dIgor Murashkindef jtype_boxed(entry): 493b8dc88148bca2e5a267c2ff39aff94b98b00ad6dIgor Murashkin """ 494b8dc88148bca2e5a267c2ff39aff94b98b00ad6dIgor Murashkin Calculate the Java type from an entry type string, to be used as a generic 495b8dc88148bca2e5a267c2ff39aff94b98b00ad6dIgor Murashkin type argument in Java. The type is guaranteed to inherit from Object. 496b8dc88148bca2e5a267c2ff39aff94b98b00ad6dIgor Murashkin 497b8dc88148bca2e5a267c2ff39aff94b98b00ad6dIgor Murashkin It will only box when absolutely necessary, i.e. int -> Integer[], but 498b8dc88148bca2e5a267c2ff39aff94b98b00ad6dIgor Murashkin int[] -> int[]. 499aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin 500b8dc88148bca2e5a267c2ff39aff94b98b00ad6dIgor Murashkin Remarks: 501b8dc88148bca2e5a267c2ff39aff94b98b00ad6dIgor Murashkin Since Java generics cannot be instantiated with primitives, this version 502b8dc88148bca2e5a267c2ff39aff94b98b00ad6dIgor Murashkin will use boxed types when absolutely required. 503aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin 504b8dc88148bca2e5a267c2ff39aff94b98b00ad6dIgor Murashkin Returns: 505b8dc88148bca2e5a267c2ff39aff94b98b00ad6dIgor Murashkin The string representing the boxed Java type. 506b8dc88148bca2e5a267c2ff39aff94b98b00ad6dIgor Murashkin """ 507b8dc88148bca2e5a267c2ff39aff94b98b00ad6dIgor Murashkin unboxed_type = jtype_unboxed(entry) 508b8dc88148bca2e5a267c2ff39aff94b98b00ad6dIgor Murashkin return _jtype_box(unboxed_type) 509b8dc88148bca2e5a267c2ff39aff94b98b00ad6dIgor Murashkin 51035a108fbfe7d174682187fa6a87f0590837924d0Igor Murashkindef _is_jtype_generic(entry): 51135a108fbfe7d174682187fa6a87f0590837924d0Igor Murashkin """ 51235a108fbfe7d174682187fa6a87f0590837924d0Igor Murashkin Determine whether or not the Java type represented by the entry type 51335a108fbfe7d174682187fa6a87f0590837924d0Igor Murashkin string and/or typedef is a Java generic. 51435a108fbfe7d174682187fa6a87f0590837924d0Igor Murashkin 51535a108fbfe7d174682187fa6a87f0590837924d0Igor Murashkin For example, "Range<Integer>" would be considered a generic, whereas 51635a108fbfe7d174682187fa6a87f0590837924d0Igor Murashkin a "MeteringRectangle" or a plain "Integer" would not be considered a generic. 51735a108fbfe7d174682187fa6a87f0590837924d0Igor Murashkin 51835a108fbfe7d174682187fa6a87f0590837924d0Igor Murashkin Args: 51935a108fbfe7d174682187fa6a87f0590837924d0Igor Murashkin entry: An instance of an Entry node 52035a108fbfe7d174682187fa6a87f0590837924d0Igor Murashkin 52135a108fbfe7d174682187fa6a87f0590837924d0Igor Murashkin Returns: 52235a108fbfe7d174682187fa6a87f0590837924d0Igor Murashkin True if it's a java generic, False otherwise. 52335a108fbfe7d174682187fa6a87f0590837924d0Igor Murashkin """ 52435a108fbfe7d174682187fa6a87f0590837924d0Igor Murashkin if entry.typedef: 52535a108fbfe7d174682187fa6a87f0590837924d0Igor Murashkin local_typedef = _jtypedef_type(entry) 52635a108fbfe7d174682187fa6a87f0590837924d0Igor Murashkin if local_typedef: 52735a108fbfe7d174682187fa6a87f0590837924d0Igor Murashkin match = re.search(r'<.*>', local_typedef) 52835a108fbfe7d174682187fa6a87f0590837924d0Igor Murashkin return bool(match) 52935a108fbfe7d174682187fa6a87f0590837924d0Igor Murashkin return False 53035a108fbfe7d174682187fa6a87f0590837924d0Igor Murashkin 531b8dc88148bca2e5a267c2ff39aff94b98b00ad6dIgor Murashkindef _jtype_primitive(what): 532aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin """ 533aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin Calculate the Java type from an entry type string. 534aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin 535aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin Remarks: 536aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin Makes a special exception for Rational, since it's a primitive in terms of 537aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin the C-library camera_metadata type system. 538aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin 539aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin Returns: 540aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin The string representing the primitive type 541aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin """ 542aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin mapping = { 543aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin 'int32': 'int', 544aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin 'int64': 'long', 545aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin 'float': 'float', 546aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin 'double': 'double', 547aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin 'byte': 'byte', 548aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin 'rational': 'Rational' 549aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin } 550aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin 551aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin try: 552aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin return mapping[what] 553aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin except KeyError as e: 554aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin raise ValueError("Can't map '%s' to a primitive, not supported" %what) 555aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin 556aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkindef jclass(entry): 557aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin """ 558aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin Calculate the java Class reference string for an entry. 559aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin 560aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin Args: 561aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin entry: an Entry node 562aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin 563aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin Example: 564aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin <entry name="some_int" type="int32"/> 565aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin <entry name="some_int_array" type="int32" container='array'/> 566aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin 567aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin jclass(some_int) == 'int.class' 568aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin jclass(some_int_array) == 'int[].class' 569aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin 570aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin Returns: 571aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin The ClassName.class string 572aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin """ 573aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin 574b8dc88148bca2e5a267c2ff39aff94b98b00ad6dIgor Murashkin return "%s.class" %jtype_unboxed(entry) 575aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin 57635a108fbfe7d174682187fa6a87f0590837924d0Igor Murashkindef jkey_type_token(entry): 57735a108fbfe7d174682187fa6a87f0590837924d0Igor Murashkin """ 57835a108fbfe7d174682187fa6a87f0590837924d0Igor Murashkin Calculate the java type token compatible with a Key constructor. 57935a108fbfe7d174682187fa6a87f0590837924d0Igor Murashkin This will be the Java Class<T> for non-generic classes, and a 58035a108fbfe7d174682187fa6a87f0590837924d0Igor Murashkin TypeReference<T> for generic classes. 58135a108fbfe7d174682187fa6a87f0590837924d0Igor Murashkin 58235a108fbfe7d174682187fa6a87f0590837924d0Igor Murashkin Args: 58335a108fbfe7d174682187fa6a87f0590837924d0Igor Murashkin entry: An entry node 58435a108fbfe7d174682187fa6a87f0590837924d0Igor Murashkin 58535a108fbfe7d174682187fa6a87f0590837924d0Igor Murashkin Returns: 58635a108fbfe7d174682187fa6a87f0590837924d0Igor Murashkin The ClassName.class string, or 'new TypeReference<ClassName>() {{ }}' string 58735a108fbfe7d174682187fa6a87f0590837924d0Igor Murashkin """ 58835a108fbfe7d174682187fa6a87f0590837924d0Igor Murashkin if _is_jtype_generic(entry): 58935a108fbfe7d174682187fa6a87f0590837924d0Igor Murashkin return "new TypeReference<%s>() {{ }}" %(jtype_boxed(entry)) 59035a108fbfe7d174682187fa6a87f0590837924d0Igor Murashkin else: 59135a108fbfe7d174682187fa6a87f0590837924d0Igor Murashkin return jclass(entry) 59235a108fbfe7d174682187fa6a87f0590837924d0Igor Murashkin 593aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkindef jidentifier(what): 594aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin """ 595aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin Convert the input string into a valid Java identifier. 596aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin 597aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin Args: 598aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin what: any identifier string 599aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin 600aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin Returns: 601aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin String with added underscores if necessary. 602aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin """ 603aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin if re.match("\d", what): 604aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin return "_%s" %what 605aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin else: 606aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin return what 607aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin 608aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkindef enum_calculate_value_string(enum_value): 609aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin """ 610aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin Calculate the value of the enum, even if it does not have one explicitly 611aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin defined. 612aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin 613aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin This looks back for the first enum value that has a predefined value and then 614aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin applies addition until we get the right value, using C-enum semantics. 615aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin 616aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin Args: 617aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin enum_value: an EnumValue node with a valid Enum parent 618aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin 619aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin Example: 620aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin <enum> 621aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin <value>X</value> 622aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin <value id="5">Y</value> 623aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin <value>Z</value> 624aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin </enum> 625aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin 626aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin enum_calculate_value_string(X) == '0' 627aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin enum_calculate_Value_string(Y) == '5' 628aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin enum_calculate_value_string(Z) == '6' 629aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin 630aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin Returns: 631aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin String that represents the enum value as an integer literal. 632aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin """ 633aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin 634aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin enum_value_siblings = list(enum_value.parent.values) 635aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin this_index = enum_value_siblings.index(enum_value) 636aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin 637aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin def is_hex_string(instr): 638aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin return bool(re.match('0x[a-f0-9]+$', instr, re.IGNORECASE)) 639aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin 640aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin base_value = 0 641aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin base_offset = 0 642aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin emit_as_hex = False 643aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin 644aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin this_id = enum_value_siblings[this_index].id 645aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin while this_index != 0 and not this_id: 646aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin this_index -= 1 647aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin base_offset += 1 648aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin this_id = enum_value_siblings[this_index].id 649aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin 650aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin if this_id: 651aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin base_value = int(this_id, 0) # guess base 652aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin emit_as_hex = is_hex_string(this_id) 653aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin 654aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin if emit_as_hex: 655aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin return "0x%X" %(base_value + base_offset) 656aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin else: 657aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin return "%d" %(base_value + base_offset) 658aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin 659aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkindef enumerate_with_last(iterable): 660aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin """ 661aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin Enumerate a sequence of iterable, while knowing if this element is the last in 662aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin the sequence or not. 663aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin 664aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin Args: 665aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin iterable: an Iterable of some sequence 666aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin 667aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin Yields: 668aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin (element, bool) where the bool is True iff the element is last in the seq. 669aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin """ 670aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin it = (i for i in iterable) 671aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin 672aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin first = next(it) # OK: raises exception if it is empty 673aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin 674aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin second = first # for when we have only 1 element in iterable 675aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin 676aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin try: 677aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin while True: 678aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin second = next(it) 679aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin # more elements remaining. 680aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin yield (first, False) 681aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin first = second 682aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin except StopIteration: 683aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin # last element. no more elements left 684aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin yield (second, True) 685aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin 686aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkindef pascal_case(what): 687aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin """ 688aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin Convert the first letter of a string to uppercase, to make the identifier 689aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin conform to PascalCase. 690aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin 6915250aa1d42dea0773ab98fc0b2cd3f172067c050Timothy Knight If there are dots, remove the dots, and capitalize the letter following 6925250aa1d42dea0773ab98fc0b2cd3f172067c050Timothy Knight where the dot was. Letters that weren't following dots are left unchanged, 6935250aa1d42dea0773ab98fc0b2cd3f172067c050Timothy Knight except for the first letter of the string (which is made upper-case). 6945250aa1d42dea0773ab98fc0b2cd3f172067c050Timothy Knight 695aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin Args: 696aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin what: a string representing some identifier 697aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin 698aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin Returns: 699aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin String with first letter capitalized 700aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin 701aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin Example: 702aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin pascal_case("helloWorld") == "HelloWorld" 703aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin pascal_case("foo") == "Foo" 7045250aa1d42dea0773ab98fc0b2cd3f172067c050Timothy Knight pascal_case("hello.world") = "HelloWorld" 7055250aa1d42dea0773ab98fc0b2cd3f172067c050Timothy Knight pascal_case("fooBar.fooBar") = "FooBarFooBar" 7065250aa1d42dea0773ab98fc0b2cd3f172067c050Timothy Knight """ 7075250aa1d42dea0773ab98fc0b2cd3f172067c050Timothy Knight return "".join([s[0:1].upper() + s[1:] for s in what.split('.')]) 7085250aa1d42dea0773ab98fc0b2cd3f172067c050Timothy Knight 7095250aa1d42dea0773ab98fc0b2cd3f172067c050Timothy Knightdef jkey_identifier(what): 7105250aa1d42dea0773ab98fc0b2cd3f172067c050Timothy Knight """ 7115250aa1d42dea0773ab98fc0b2cd3f172067c050Timothy Knight Return a Java identifier from a property name. 7125250aa1d42dea0773ab98fc0b2cd3f172067c050Timothy Knight 7135250aa1d42dea0773ab98fc0b2cd3f172067c050Timothy Knight Args: 7145250aa1d42dea0773ab98fc0b2cd3f172067c050Timothy Knight what: a string representing a property name. 7155250aa1d42dea0773ab98fc0b2cd3f172067c050Timothy Knight 7165250aa1d42dea0773ab98fc0b2cd3f172067c050Timothy Knight Returns: 7175250aa1d42dea0773ab98fc0b2cd3f172067c050Timothy Knight Java identifier corresponding to the property name. May need to be 7185250aa1d42dea0773ab98fc0b2cd3f172067c050Timothy Knight prepended with the appropriate Java class name by the caller of this 7195250aa1d42dea0773ab98fc0b2cd3f172067c050Timothy Knight function. Note that the outer namespace is stripped from the property 7205250aa1d42dea0773ab98fc0b2cd3f172067c050Timothy Knight name. 7215250aa1d42dea0773ab98fc0b2cd3f172067c050Timothy Knight 7225250aa1d42dea0773ab98fc0b2cd3f172067c050Timothy Knight Example: 723d4e240adc06f10372f6e18b8ed23e14c4a4138d9Eino-Ville Talvala jkey_identifier("android.lens.facing") == "LENS_FACING" 724aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin """ 725d4e240adc06f10372f6e18b8ed23e14c4a4138d9Eino-Ville Talvala return csym(what[what.find('.') + 1:]) 726aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin 727d4e240adc06f10372f6e18b8ed23e14c4a4138d9Eino-Ville Talvaladef jenum_value(enum_entry, enum_value): 728aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin """ 729d4e240adc06f10372f6e18b8ed23e14c4a4138d9Eino-Ville Talvala Calculate the Java name for an integer enum value 730aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin 731aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin Args: 732d4e240adc06f10372f6e18b8ed23e14c4a4138d9Eino-Ville Talvala enum: An enum-typed Entry node 733d4e240adc06f10372f6e18b8ed23e14c4a4138d9Eino-Ville Talvala value: An EnumValue node for the enum 734aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin 735aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin Returns: 736aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin String representing the Java symbol 737aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin """ 738aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin 739d4e240adc06f10372f6e18b8ed23e14c4a4138d9Eino-Ville Talvala cname = csym(enum_entry.name) 740d4e240adc06f10372f6e18b8ed23e14c4a4138d9Eino-Ville Talvala return cname[cname.find('_') + 1:] + '_' + enum_value.name 741d4e240adc06f10372f6e18b8ed23e14c4a4138d9Eino-Ville Talvala 742567167ac6be36e732e98089d6e5d7d4f041f3323Eino-Ville Talvaladef generate_extra_javadoc_detail(entry): 743567167ac6be36e732e98089d6e5d7d4f041f3323Eino-Ville Talvala """ 744567167ac6be36e732e98089d6e5d7d4f041f3323Eino-Ville Talvala Returns a function to add extra details for an entry into a string for inclusion into 745567167ac6be36e732e98089d6e5d7d4f041f3323Eino-Ville Talvala javadoc. Adds information about units, the list of enum values for this key, and the valid 746567167ac6be36e732e98089d6e5d7d4f041f3323Eino-Ville Talvala range. 747567167ac6be36e732e98089d6e5d7d4f041f3323Eino-Ville Talvala """ 748567167ac6be36e732e98089d6e5d7d4f041f3323Eino-Ville Talvala def inner(text): 749567167ac6be36e732e98089d6e5d7d4f041f3323Eino-Ville Talvala if entry.units: 750567167ac6be36e732e98089d6e5d7d4f041f3323Eino-Ville Talvala text += '\n\n<b>Units</b>: %s\n' % (dedent(entry.units)) 751567167ac6be36e732e98089d6e5d7d4f041f3323Eino-Ville Talvala if entry.enum and not (entry.typedef and entry.typedef.languages.get('java')): 752567167ac6be36e732e98089d6e5d7d4f041f3323Eino-Ville Talvala text += '\n\n<b>Possible values:</b>\n<ul>\n' 753567167ac6be36e732e98089d6e5d7d4f041f3323Eino-Ville Talvala for value in entry.enum.values: 754567167ac6be36e732e98089d6e5d7d4f041f3323Eino-Ville Talvala if not value.hidden: 755567167ac6be36e732e98089d6e5d7d4f041f3323Eino-Ville Talvala text += ' <li>{@link #%s %s}</li>\n' % ( jenum_value(entry, value ), value.name ) 756567167ac6be36e732e98089d6e5d7d4f041f3323Eino-Ville Talvala text += '</ul>\n' 757567167ac6be36e732e98089d6e5d7d4f041f3323Eino-Ville Talvala if entry.range: 758567167ac6be36e732e98089d6e5d7d4f041f3323Eino-Ville Talvala if entry.enum and not (entry.typedef and entry.typedef.languages.get('java')): 759567167ac6be36e732e98089d6e5d7d4f041f3323Eino-Ville Talvala text += '\n\n<b>Available values for this device:</b><br>\n' 760567167ac6be36e732e98089d6e5d7d4f041f3323Eino-Ville Talvala else: 761567167ac6be36e732e98089d6e5d7d4f041f3323Eino-Ville Talvala text += '\n\n<b>Range of valid values:</b><br>\n' 762567167ac6be36e732e98089d6e5d7d4f041f3323Eino-Ville Talvala text += '%s\n' % (dedent(entry.range)) 763567167ac6be36e732e98089d6e5d7d4f041f3323Eino-Ville Talvala if entry.hwlevel != 'legacy': # covers any of (None, 'limited', 'full') 764567167ac6be36e732e98089d6e5d7d4f041f3323Eino-Ville Talvala text += '\n\n<b>Optional</b> - This value may be {@code null} on some devices.\n' 765567167ac6be36e732e98089d6e5d7d4f041f3323Eino-Ville Talvala if entry.hwlevel == 'full': 766567167ac6be36e732e98089d6e5d7d4f041f3323Eino-Ville Talvala text += \ 767567167ac6be36e732e98089d6e5d7d4f041f3323Eino-Ville Talvala '\n<b>Full capability</b> - \n' + \ 768567167ac6be36e732e98089d6e5d7d4f041f3323Eino-Ville Talvala 'Present on all camera devices that report being {@link CameraCharacteristics#INFO_SUPPORTED_HARDWARE_LEVEL_FULL HARDWARE_LEVEL_FULL} devices in the\n' + \ 769567167ac6be36e732e98089d6e5d7d4f041f3323Eino-Ville Talvala 'android.info.supportedHardwareLevel key\n' 770567167ac6be36e732e98089d6e5d7d4f041f3323Eino-Ville Talvala if entry.hwlevel == 'limited': 771567167ac6be36e732e98089d6e5d7d4f041f3323Eino-Ville Talvala text += \ 772567167ac6be36e732e98089d6e5d7d4f041f3323Eino-Ville Talvala '\n<b>Limited capability</b> - \n' + \ 773567167ac6be36e732e98089d6e5d7d4f041f3323Eino-Ville Talvala 'Present on all camera devices that report being at least {@link CameraCharacteristics#INFO_SUPPORTED_HARDWARE_LEVEL_LIMITED HARDWARE_LEVEL_LIMITED} devices in the\n' + \ 774567167ac6be36e732e98089d6e5d7d4f041f3323Eino-Ville Talvala 'android.info.supportedHardwareLevel key\n' 775567167ac6be36e732e98089d6e5d7d4f041f3323Eino-Ville Talvala if entry.hwlevel == 'legacy': 776567167ac6be36e732e98089d6e5d7d4f041f3323Eino-Ville Talvala text += "\nThis key is available on all devices." 777567167ac6be36e732e98089d6e5d7d4f041f3323Eino-Ville Talvala 778567167ac6be36e732e98089d6e5d7d4f041f3323Eino-Ville Talvala return text 779567167ac6be36e732e98089d6e5d7d4f041f3323Eino-Ville Talvala return inner 780567167ac6be36e732e98089d6e5d7d4f041f3323Eino-Ville Talvala 781567167ac6be36e732e98089d6e5d7d4f041f3323Eino-Ville Talvala 78263c0fb27d923a32d9a398471ad318bfe84befbebEino-Ville Talvaladef javadoc(metadata, indent = 4): 783d4e240adc06f10372f6e18b8ed23e14c4a4138d9Eino-Ville Talvala """ 78463c0fb27d923a32d9a398471ad318bfe84befbebEino-Ville Talvala Returns a function to format a markdown syntax text block as a 78563c0fb27d923a32d9a398471ad318bfe84befbebEino-Ville Talvala javadoc comment section, given a set of metadata 786d4e240adc06f10372f6e18b8ed23e14c4a4138d9Eino-Ville Talvala 787d4e240adc06f10372f6e18b8ed23e14c4a4138d9Eino-Ville Talvala Args: 78863c0fb27d923a32d9a398471ad318bfe84befbebEino-Ville Talvala metadata: A Metadata instance, representing the the top-level root 78963c0fb27d923a32d9a398471ad318bfe84befbebEino-Ville Talvala of the metadata for cross-referencing 790d4e240adc06f10372f6e18b8ed23e14c4a4138d9Eino-Ville Talvala indent: baseline level of indentation for javadoc block 791d4e240adc06f10372f6e18b8ed23e14c4a4138d9Eino-Ville Talvala Returns: 79263c0fb27d923a32d9a398471ad318bfe84befbebEino-Ville Talvala A function that transforms a String text block as follows: 793d4e240adc06f10372f6e18b8ed23e14c4a4138d9Eino-Ville Talvala - Indent and * for insertion into a Javadoc comment block 7948aa2a11bbff97d9789bb06cdc2e28dadb6c5926aIgor Murashkin - Trailing whitespace removed 7958aa2a11bbff97d9789bb06cdc2e28dadb6c5926aIgor Murashkin - Entire body rendered via markdown to generate HTML 79663c0fb27d923a32d9a398471ad318bfe84befbebEino-Ville Talvala - All tag names converted to appropriate Javadoc {@link} with @see 79763c0fb27d923a32d9a398471ad318bfe84befbebEino-Ville Talvala for each tag 798d4e240adc06f10372f6e18b8ed23e14c4a4138d9Eino-Ville Talvala 799d4e240adc06f10372f6e18b8ed23e14c4a4138d9Eino-Ville Talvala Example: 800d4e240adc06f10372f6e18b8ed23e14c4a4138d9Eino-Ville Talvala "This is a comment for Javadoc\n" + 801d4e240adc06f10372f6e18b8ed23e14c4a4138d9Eino-Ville Talvala " with multiple lines, that should be \n" + 802d4e240adc06f10372f6e18b8ed23e14c4a4138d9Eino-Ville Talvala " formatted better\n" + 803d4e240adc06f10372f6e18b8ed23e14c4a4138d9Eino-Ville Talvala "\n" + 804d4e240adc06f10372f6e18b8ed23e14c4a4138d9Eino-Ville Talvala " That covers multiple lines as well\n" 80563c0fb27d923a32d9a398471ad318bfe84befbebEino-Ville Talvala " And references android.control.mode\n" 806d4e240adc06f10372f6e18b8ed23e14c4a4138d9Eino-Ville Talvala 807d4e240adc06f10372f6e18b8ed23e14c4a4138d9Eino-Ville Talvala transforms to 8088aa2a11bbff97d9789bb06cdc2e28dadb6c5926aIgor Murashkin " * <p>This is a comment for Javadoc\n" + 809d4e240adc06f10372f6e18b8ed23e14c4a4138d9Eino-Ville Talvala " * with multiple lines, that should be\n" + 8108aa2a11bbff97d9789bb06cdc2e28dadb6c5926aIgor Murashkin " * formatted better</p>\n" + 8118aa2a11bbff97d9789bb06cdc2e28dadb6c5926aIgor Murashkin " * <p>That covers multiple lines as well</p>\n" + 81263c0fb27d923a32d9a398471ad318bfe84befbebEino-Ville Talvala " * and references {@link CaptureRequest#CONTROL_MODE android.control.mode}\n" + 81363c0fb27d923a32d9a398471ad318bfe84befbebEino-Ville Talvala " *\n" + 81463c0fb27d923a32d9a398471ad318bfe84befbebEino-Ville Talvala " * @see CaptureRequest#CONTROL_MODE\n" 815d4e240adc06f10372f6e18b8ed23e14c4a4138d9Eino-Ville Talvala """ 81663c0fb27d923a32d9a398471ad318bfe84befbebEino-Ville Talvala def javadoc_formatter(text): 81763c0fb27d923a32d9a398471ad318bfe84befbebEino-Ville Talvala comment_prefix = " " * indent + " * "; 818d4e240adc06f10372f6e18b8ed23e14c4a4138d9Eino-Ville Talvala 81963c0fb27d923a32d9a398471ad318bfe84befbebEino-Ville Talvala # render with markdown => HTML 82063c0fb27d923a32d9a398471ad318bfe84befbebEino-Ville Talvala javatext = md(text, JAVADOC_IMAGE_SRC_METADATA) 821d4e240adc06f10372f6e18b8ed23e14c4a4138d9Eino-Ville Talvala 822ddda2bb917a1eb725c85d8c2b61bff2abf568a95Eino-Ville Talvala # Identity transform for javadoc links 823ddda2bb917a1eb725c85d8c2b61bff2abf568a95Eino-Ville Talvala def javadoc_link_filter(target, shortname): 824ddda2bb917a1eb725c85d8c2b61bff2abf568a95Eino-Ville Talvala return '{@link %s %s}' % (target, shortname) 825ddda2bb917a1eb725c85d8c2b61bff2abf568a95Eino-Ville Talvala 826ddda2bb917a1eb725c85d8c2b61bff2abf568a95Eino-Ville Talvala javatext = filter_links(javatext, javadoc_link_filter) 827ddda2bb917a1eb725c85d8c2b61bff2abf568a95Eino-Ville Talvala 82863c0fb27d923a32d9a398471ad318bfe84befbebEino-Ville Talvala # Crossref tag names 82963c0fb27d923a32d9a398471ad318bfe84befbebEino-Ville Talvala kind_mapping = { 83063c0fb27d923a32d9a398471ad318bfe84befbebEino-Ville Talvala 'static': 'CameraCharacteristics', 83163c0fb27d923a32d9a398471ad318bfe84befbebEino-Ville Talvala 'dynamic': 'CaptureResult', 83263c0fb27d923a32d9a398471ad318bfe84befbebEino-Ville Talvala 'controls': 'CaptureRequest' } 833aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin 83463c0fb27d923a32d9a398471ad318bfe84befbebEino-Ville Talvala # Convert metadata entry "android.x.y.z" to form 83563c0fb27d923a32d9a398471ad318bfe84befbebEino-Ville Talvala # "{@link CaptureRequest#X_Y_Z android.x.y.z}" 83663c0fb27d923a32d9a398471ad318bfe84befbebEino-Ville Talvala def javadoc_crossref_filter(node): 837c6c2416a812ddb8bcb32fdefce1eff3a7ded9b61Yin-Chia Yeh if node.applied_visibility in ('public', 'java_public'): 83863c0fb27d923a32d9a398471ad318bfe84befbebEino-Ville Talvala return '{@link %s#%s %s}' % (kind_mapping[node.kind], 83963c0fb27d923a32d9a398471ad318bfe84befbebEino-Ville Talvala jkey_identifier(node.name), 84063c0fb27d923a32d9a398471ad318bfe84befbebEino-Ville Talvala node.name) 84163c0fb27d923a32d9a398471ad318bfe84befbebEino-Ville Talvala else: 84263c0fb27d923a32d9a398471ad318bfe84befbebEino-Ville Talvala return node.name 843aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin 84463c0fb27d923a32d9a398471ad318bfe84befbebEino-Ville Talvala # For each public tag "android.x.y.z" referenced, add a 84563c0fb27d923a32d9a398471ad318bfe84befbebEino-Ville Talvala # "@see CaptureRequest#X_Y_Z" 846ddda2bb917a1eb725c85d8c2b61bff2abf568a95Eino-Ville Talvala def javadoc_crossref_see_filter(node_set): 847c6c2416a812ddb8bcb32fdefce1eff3a7ded9b61Yin-Chia Yeh node_set = (x for x in node_set if x.applied_visibility in ('public', 'java_public')) 84863c0fb27d923a32d9a398471ad318bfe84befbebEino-Ville Talvala 84963c0fb27d923a32d9a398471ad318bfe84befbebEino-Ville Talvala text = '\n' 85063c0fb27d923a32d9a398471ad318bfe84befbebEino-Ville Talvala for node in node_set: 85163c0fb27d923a32d9a398471ad318bfe84befbebEino-Ville Talvala text = text + '\n@see %s#%s' % (kind_mapping[node.kind], 85263c0fb27d923a32d9a398471ad318bfe84befbebEino-Ville Talvala jkey_identifier(node.name)) 85363c0fb27d923a32d9a398471ad318bfe84befbebEino-Ville Talvala 85463c0fb27d923a32d9a398471ad318bfe84befbebEino-Ville Talvala return text if text != '\n' else '' 85563c0fb27d923a32d9a398471ad318bfe84befbebEino-Ville Talvala 856ddda2bb917a1eb725c85d8c2b61bff2abf568a95Eino-Ville Talvala javatext = filter_tags(javatext, metadata, javadoc_crossref_filter, javadoc_crossref_see_filter) 85763c0fb27d923a32d9a398471ad318bfe84befbebEino-Ville Talvala 85863c0fb27d923a32d9a398471ad318bfe84befbebEino-Ville Talvala def line_filter(line): 85963c0fb27d923a32d9a398471ad318bfe84befbebEino-Ville Talvala # Indent each line 86063c0fb27d923a32d9a398471ad318bfe84befbebEino-Ville Talvala # Add ' * ' to it for stylistic reasons 86163c0fb27d923a32d9a398471ad318bfe84befbebEino-Ville Talvala # Strip right side of trailing whitespace 862567167ac6be36e732e98089d6e5d7d4f041f3323Eino-Ville Talvala return (comment_prefix + line).rstrip() 86363c0fb27d923a32d9a398471ad318bfe84befbebEino-Ville Talvala 86463c0fb27d923a32d9a398471ad318bfe84befbebEino-Ville Talvala # Process each line with above filter 86563c0fb27d923a32d9a398471ad318bfe84befbebEino-Ville Talvala javatext = "\n".join(line_filter(i) for i in javatext.split("\n")) + "\n" 86663c0fb27d923a32d9a398471ad318bfe84befbebEino-Ville Talvala 86763c0fb27d923a32d9a398471ad318bfe84befbebEino-Ville Talvala return javatext 86863c0fb27d923a32d9a398471ad318bfe84befbebEino-Ville Talvala 86963c0fb27d923a32d9a398471ad318bfe84befbebEino-Ville Talvala return javadoc_formatter 870aa133d352a42aebf93320eded40c75b4d7cff6e7Igor Murashkin 87188b858d5e4db3eb66fe570647626a592ebb6af91Igor Murashkindef dedent(text): 87288b858d5e4db3eb66fe570647626a592ebb6af91Igor Murashkin """ 87388b858d5e4db3eb66fe570647626a592ebb6af91Igor Murashkin Remove all common indentation from every line but the 0th. 87488b858d5e4db3eb66fe570647626a592ebb6af91Igor Murashkin This will avoid getting <code> blocks when rendering text via markdown. 87588b858d5e4db3eb66fe570647626a592ebb6af91Igor Murashkin Ignoring the 0th line will also allow the 0th line not to be aligned. 87688b858d5e4db3eb66fe570647626a592ebb6af91Igor Murashkin 87788b858d5e4db3eb66fe570647626a592ebb6af91Igor Murashkin Args: 87888b858d5e4db3eb66fe570647626a592ebb6af91Igor Murashkin text: A string of text to dedent. 87988b858d5e4db3eb66fe570647626a592ebb6af91Igor Murashkin 88088b858d5e4db3eb66fe570647626a592ebb6af91Igor Murashkin Returns: 88188b858d5e4db3eb66fe570647626a592ebb6af91Igor Murashkin String dedented by above rules. 88288b858d5e4db3eb66fe570647626a592ebb6af91Igor Murashkin 88388b858d5e4db3eb66fe570647626a592ebb6af91Igor Murashkin For example: 88488b858d5e4db3eb66fe570647626a592ebb6af91Igor Murashkin assertEquals("bar\nline1\nline2", dedent("bar\n line1\n line2")) 88588b858d5e4db3eb66fe570647626a592ebb6af91Igor Murashkin assertEquals("bar\nline1\nline2", dedent(" bar\n line1\n line2")) 88688b858d5e4db3eb66fe570647626a592ebb6af91Igor Murashkin assertEquals("bar\n line1\nline2", dedent(" bar\n line1\n line2")) 88788b858d5e4db3eb66fe570647626a592ebb6af91Igor Murashkin """ 88888b858d5e4db3eb66fe570647626a592ebb6af91Igor Murashkin text = textwrap.dedent(text) 88988b858d5e4db3eb66fe570647626a592ebb6af91Igor Murashkin text_lines = text.split('\n') 89088b858d5e4db3eb66fe570647626a592ebb6af91Igor Murashkin text_not_first = "\n".join(text_lines[1:]) 89188b858d5e4db3eb66fe570647626a592ebb6af91Igor Murashkin text_not_first = textwrap.dedent(text_not_first) 89288b858d5e4db3eb66fe570647626a592ebb6af91Igor Murashkin text = text_lines[0] + "\n" + text_not_first 89388b858d5e4db3eb66fe570647626a592ebb6af91Igor Murashkin 89488b858d5e4db3eb66fe570647626a592ebb6af91Igor Murashkin return text 89588b858d5e4db3eb66fe570647626a592ebb6af91Igor Murashkin 8961dd4ecb0ea0589610b3616459b707c2898889153Igor Murashkindef md(text, img_src_prefix=""): 8978aa2a11bbff97d9789bb06cdc2e28dadb6c5926aIgor Murashkin """ 8988aa2a11bbff97d9789bb06cdc2e28dadb6c5926aIgor Murashkin Run text through markdown to produce HTML. 8998aa2a11bbff97d9789bb06cdc2e28dadb6c5926aIgor Murashkin 9008aa2a11bbff97d9789bb06cdc2e28dadb6c5926aIgor Murashkin This also removes all common indentation from every line but the 0th. 9018aa2a11bbff97d9789bb06cdc2e28dadb6c5926aIgor Murashkin This will avoid getting <code> blocks in markdown. 9028aa2a11bbff97d9789bb06cdc2e28dadb6c5926aIgor Murashkin Ignoring the 0th line will also allow the 0th line not to be aligned. 9038aa2a11bbff97d9789bb06cdc2e28dadb6c5926aIgor Murashkin 9041dd4ecb0ea0589610b3616459b707c2898889153Igor Murashkin Args: 9051dd4ecb0ea0589610b3616459b707c2898889153Igor Murashkin text: A markdown-syntax using block of text to format. 9061dd4ecb0ea0589610b3616459b707c2898889153Igor Murashkin img_src_prefix: An optional string to prepend to each <img src="target"/> 9071dd4ecb0ea0589610b3616459b707c2898889153Igor Murashkin 9081dd4ecb0ea0589610b3616459b707c2898889153Igor Murashkin Returns: 9091dd4ecb0ea0589610b3616459b707c2898889153Igor Murashkin String rendered by markdown and other rules applied (see above). 9101dd4ecb0ea0589610b3616459b707c2898889153Igor Murashkin 9118aa2a11bbff97d9789bb06cdc2e28dadb6c5926aIgor Murashkin For example, this avoids the following situation: 9128aa2a11bbff97d9789bb06cdc2e28dadb6c5926aIgor Murashkin 9138aa2a11bbff97d9789bb06cdc2e28dadb6c5926aIgor Murashkin <!-- Input --> 9148aa2a11bbff97d9789bb06cdc2e28dadb6c5926aIgor Murashkin 9158aa2a11bbff97d9789bb06cdc2e28dadb6c5926aIgor Murashkin <!--- can't use dedent directly since 'foo' has no indent --> 9168aa2a11bbff97d9789bb06cdc2e28dadb6c5926aIgor Murashkin <notes>foo 9178aa2a11bbff97d9789bb06cdc2e28dadb6c5926aIgor Murashkin bar 9188aa2a11bbff97d9789bb06cdc2e28dadb6c5926aIgor Murashkin bar 9198aa2a11bbff97d9789bb06cdc2e28dadb6c5926aIgor Murashkin </notes> 9208aa2a11bbff97d9789bb06cdc2e28dadb6c5926aIgor Murashkin 9218aa2a11bbff97d9789bb06cdc2e28dadb6c5926aIgor Murashkin <!-- Bad Output -- > 9228aa2a11bbff97d9789bb06cdc2e28dadb6c5926aIgor Murashkin <!-- if no dedent is done generated code looks like --> 9238aa2a11bbff97d9789bb06cdc2e28dadb6c5926aIgor Murashkin <p>foo 9248aa2a11bbff97d9789bb06cdc2e28dadb6c5926aIgor Murashkin <code><pre> 9258aa2a11bbff97d9789bb06cdc2e28dadb6c5926aIgor Murashkin bar 9268aa2a11bbff97d9789bb06cdc2e28dadb6c5926aIgor Murashkin bar</pre></code> 9278aa2a11bbff97d9789bb06cdc2e28dadb6c5926aIgor Murashkin </p> 9288aa2a11bbff97d9789bb06cdc2e28dadb6c5926aIgor Murashkin 9298aa2a11bbff97d9789bb06cdc2e28dadb6c5926aIgor Murashkin Instead we get the more natural expected result: 9308aa2a11bbff97d9789bb06cdc2e28dadb6c5926aIgor Murashkin 9318aa2a11bbff97d9789bb06cdc2e28dadb6c5926aIgor Murashkin <!-- Good Output --> 9328aa2a11bbff97d9789bb06cdc2e28dadb6c5926aIgor Murashkin <p>foo 9338aa2a11bbff97d9789bb06cdc2e28dadb6c5926aIgor Murashkin bar 9348aa2a11bbff97d9789bb06cdc2e28dadb6c5926aIgor Murashkin bar</p> 9358aa2a11bbff97d9789bb06cdc2e28dadb6c5926aIgor Murashkin 9368aa2a11bbff97d9789bb06cdc2e28dadb6c5926aIgor Murashkin """ 93788b858d5e4db3eb66fe570647626a592ebb6af91Igor Murashkin text = dedent(text) 9381dd4ecb0ea0589610b3616459b707c2898889153Igor Murashkin 939a48441daa766098190b40d5187ce1963d8a980afIgor Murashkin # full list of extensions at http://pythonhosted.org/Markdown/extensions/ 940a48441daa766098190b40d5187ce1963d8a980afIgor Murashkin md_extensions = ['tables'] # make <table> with ASCII |_| tables 9418aa2a11bbff97d9789bb06cdc2e28dadb6c5926aIgor Murashkin # render with markdown 942a48441daa766098190b40d5187ce1963d8a980afIgor Murashkin text = markdown.markdown(text, md_extensions) 9431dd4ecb0ea0589610b3616459b707c2898889153Igor Murashkin 9441dd4ecb0ea0589610b3616459b707c2898889153Igor Murashkin # prepend a prefix to each <img src="foo"> -> <img src="${prefix}foo"> 9451dd4ecb0ea0589610b3616459b707c2898889153Igor Murashkin text = re.sub(r'src="([^"]*)"', 'src="' + img_src_prefix + r'\1"', text) 9461dd4ecb0ea0589610b3616459b707c2898889153Igor Murashkin return text 9478aa2a11bbff97d9789bb06cdc2e28dadb6c5926aIgor Murashkin 94863c0fb27d923a32d9a398471ad318bfe84befbebEino-Ville Talvaladef filter_tags(text, metadata, filter_function, summary_function = None): 94963c0fb27d923a32d9a398471ad318bfe84befbebEino-Ville Talvala """ 95063c0fb27d923a32d9a398471ad318bfe84befbebEino-Ville Talvala Find all references to tags in the form outer_namespace.xxx.yyy[.zzz] in 95163c0fb27d923a32d9a398471ad318bfe84befbebEino-Ville Talvala the provided text, and pass them through filter_function and summary_function. 95263c0fb27d923a32d9a398471ad318bfe84befbebEino-Ville Talvala 95363c0fb27d923a32d9a398471ad318bfe84befbebEino-Ville Talvala Used to linkify entry names in HMTL, javadoc output. 95463c0fb27d923a32d9a398471ad318bfe84befbebEino-Ville Talvala 95563c0fb27d923a32d9a398471ad318bfe84befbebEino-Ville Talvala Args: 95663c0fb27d923a32d9a398471ad318bfe84befbebEino-Ville Talvala text: A string representing a block of text destined for output 95763c0fb27d923a32d9a398471ad318bfe84befbebEino-Ville Talvala metadata: A Metadata instance, the root of the metadata properties tree 95863c0fb27d923a32d9a398471ad318bfe84befbebEino-Ville Talvala filter_function: A Node->string function to apply to each node 95963c0fb27d923a32d9a398471ad318bfe84befbebEino-Ville Talvala when found in text; the string returned replaces the tag name in text. 96050f45c4d120ea1ad00017e5b850ed5bcf3261efeEino-Ville Talvala summary_function: A Node list->string function that is provided the list of 96150f45c4d120ea1ad00017e5b850ed5bcf3261efeEino-Ville Talvala unique tag nodes found in text, and which must return a string that is 96250f45c4d120ea1ad00017e5b850ed5bcf3261efeEino-Ville Talvala then appended to the end of the text. The list is sorted alphabetically 96350f45c4d120ea1ad00017e5b850ed5bcf3261efeEino-Ville Talvala by node name. 96463c0fb27d923a32d9a398471ad318bfe84befbebEino-Ville Talvala """ 96563c0fb27d923a32d9a398471ad318bfe84befbebEino-Ville Talvala 96663c0fb27d923a32d9a398471ad318bfe84befbebEino-Ville Talvala tag_set = set() 96763c0fb27d923a32d9a398471ad318bfe84befbebEino-Ville Talvala def name_match(name): 96863c0fb27d923a32d9a398471ad318bfe84befbebEino-Ville Talvala return lambda node: node.name == name 96963c0fb27d923a32d9a398471ad318bfe84befbebEino-Ville Talvala 97063c0fb27d923a32d9a398471ad318bfe84befbebEino-Ville Talvala # Match outer_namespace.x.y or outer_namespace.x.y.z, making sure 97163c0fb27d923a32d9a398471ad318bfe84befbebEino-Ville Talvala # to grab .z and not just outer_namespace.x.y. (sloppy, but since we 972ddda2bb917a1eb725c85d8c2b61bff2abf568a95Eino-Ville Talvala # check for validity, a few false positives don't hurt). 973ddda2bb917a1eb725c85d8c2b61bff2abf568a95Eino-Ville Talvala # Try to ignore items of the form {@link <outer_namespace>... 97463c0fb27d923a32d9a398471ad318bfe84befbebEino-Ville Talvala for outer_namespace in metadata.outer_namespaces: 97563c0fb27d923a32d9a398471ad318bfe84befbebEino-Ville Talvala 976ddda2bb917a1eb725c85d8c2b61bff2abf568a95Eino-Ville Talvala tag_match = r"(?<!\{@link\s)" + outer_namespace.name + \ 9777fabc1e635ee4213c8414c24f621e55a6aece1f1Eino-Ville Talvala r"\.([a-zA-Z0-9\n]+)\.([a-zA-Z0-9\n]+)(\.[a-zA-Z0-9\n]+)?([/]?)" 97863c0fb27d923a32d9a398471ad318bfe84befbebEino-Ville Talvala 97963c0fb27d923a32d9a398471ad318bfe84befbebEino-Ville Talvala def filter_sub(match): 98063c0fb27d923a32d9a398471ad318bfe84befbebEino-Ville Talvala whole_match = match.group(0) 98163c0fb27d923a32d9a398471ad318bfe84befbebEino-Ville Talvala section1 = match.group(1) 98263c0fb27d923a32d9a398471ad318bfe84befbebEino-Ville Talvala section2 = match.group(2) 98363c0fb27d923a32d9a398471ad318bfe84befbebEino-Ville Talvala section3 = match.group(3) 9847fabc1e635ee4213c8414c24f621e55a6aece1f1Eino-Ville Talvala end_slash = match.group(4) 9857fabc1e635ee4213c8414c24f621e55a6aece1f1Eino-Ville Talvala 9867fabc1e635ee4213c8414c24f621e55a6aece1f1Eino-Ville Talvala # Don't linkify things ending in slash (urls, for example) 9877fabc1e635ee4213c8414c24f621e55a6aece1f1Eino-Ville Talvala if end_slash: 9887fabc1e635ee4213c8414c24f621e55a6aece1f1Eino-Ville Talvala return whole_match 9897fabc1e635ee4213c8414c24f621e55a6aece1f1Eino-Ville Talvala 9907fabc1e635ee4213c8414c24f621e55a6aece1f1Eino-Ville Talvala candidate = "" 99163c0fb27d923a32d9a398471ad318bfe84befbebEino-Ville Talvala 99263c0fb27d923a32d9a398471ad318bfe84befbebEino-Ville Talvala # First try a two-level match 9937fabc1e635ee4213c8414c24f621e55a6aece1f1Eino-Ville Talvala candidate2 = "%s.%s.%s" % (outer_namespace.name, section1, section2) 99463c0fb27d923a32d9a398471ad318bfe84befbebEino-Ville Talvala got_two_level = False 99563c0fb27d923a32d9a398471ad318bfe84befbebEino-Ville Talvala 9967fabc1e635ee4213c8414c24f621e55a6aece1f1Eino-Ville Talvala node = metadata.find_first(name_match(candidate2.replace('\n',''))) 9977fabc1e635ee4213c8414c24f621e55a6aece1f1Eino-Ville Talvala if not node and '\n' in section2: 9987fabc1e635ee4213c8414c24f621e55a6aece1f1Eino-Ville Talvala # Linefeeds are ambiguous - was the intent to add a space, 9997fabc1e635ee4213c8414c24f621e55a6aece1f1Eino-Ville Talvala # or continue a lengthy name? Try the former now. 10007fabc1e635ee4213c8414c24f621e55a6aece1f1Eino-Ville Talvala candidate2b = "%s.%s.%s" % (outer_namespace.name, section1, section2[:section2.find('\n')]) 10017fabc1e635ee4213c8414c24f621e55a6aece1f1Eino-Ville Talvala node = metadata.find_first(name_match(candidate2b)) 10027fabc1e635ee4213c8414c24f621e55a6aece1f1Eino-Ville Talvala if node: 10037fabc1e635ee4213c8414c24f621e55a6aece1f1Eino-Ville Talvala candidate2 = candidate2b 100463c0fb27d923a32d9a398471ad318bfe84befbebEino-Ville Talvala 100563c0fb27d923a32d9a398471ad318bfe84befbebEino-Ville Talvala if node: 10067fabc1e635ee4213c8414c24f621e55a6aece1f1Eino-Ville Talvala # Have two-level match 100763c0fb27d923a32d9a398471ad318bfe84befbebEino-Ville Talvala got_two_level = True 10087fabc1e635ee4213c8414c24f621e55a6aece1f1Eino-Ville Talvala candidate = candidate2 10097fabc1e635ee4213c8414c24f621e55a6aece1f1Eino-Ville Talvala elif section3: 10107fabc1e635ee4213c8414c24f621e55a6aece1f1Eino-Ville Talvala # Try three-level match 10117fabc1e635ee4213c8414c24f621e55a6aece1f1Eino-Ville Talvala candidate3 = "%s%s" % (candidate2, section3) 10127fabc1e635ee4213c8414c24f621e55a6aece1f1Eino-Ville Talvala node = metadata.find_first(name_match(candidate3.replace('\n',''))) 10137fabc1e635ee4213c8414c24f621e55a6aece1f1Eino-Ville Talvala 10147fabc1e635ee4213c8414c24f621e55a6aece1f1Eino-Ville Talvala if not node and '\n' in section3: 10157fabc1e635ee4213c8414c24f621e55a6aece1f1Eino-Ville Talvala # Linefeeds are ambiguous - was the intent to add a space, 10167fabc1e635ee4213c8414c24f621e55a6aece1f1Eino-Ville Talvala # or continue a lengthy name? Try the former now. 10177fabc1e635ee4213c8414c24f621e55a6aece1f1Eino-Ville Talvala candidate3b = "%s%s" % (candidate2, section3[:section3.find('\n')]) 10187fabc1e635ee4213c8414c24f621e55a6aece1f1Eino-Ville Talvala node = metadata.find_first(name_match(candidate3b)) 10197fabc1e635ee4213c8414c24f621e55a6aece1f1Eino-Ville Talvala if node: 10207fabc1e635ee4213c8414c24f621e55a6aece1f1Eino-Ville Talvala candidate3 = candidate3b 10217fabc1e635ee4213c8414c24f621e55a6aece1f1Eino-Ville Talvala 10227fabc1e635ee4213c8414c24f621e55a6aece1f1Eino-Ville Talvala if node: 10237fabc1e635ee4213c8414c24f621e55a6aece1f1Eino-Ville Talvala # Have 3-level match 10247fabc1e635ee4213c8414c24f621e55a6aece1f1Eino-Ville Talvala candidate = candidate3 10257fabc1e635ee4213c8414c24f621e55a6aece1f1Eino-Ville Talvala 10267fabc1e635ee4213c8414c24f621e55a6aece1f1Eino-Ville Talvala # Replace match with crossref or complain if a likely match couldn't be matched 102763c0fb27d923a32d9a398471ad318bfe84befbebEino-Ville Talvala 102863c0fb27d923a32d9a398471ad318bfe84befbebEino-Ville Talvala if node: 102963c0fb27d923a32d9a398471ad318bfe84befbebEino-Ville Talvala tag_set.add(node) 103063c0fb27d923a32d9a398471ad318bfe84befbebEino-Ville Talvala return whole_match.replace(candidate,filter_function(node)) 103163c0fb27d923a32d9a398471ad318bfe84befbebEino-Ville Talvala else: 103263c0fb27d923a32d9a398471ad318bfe84befbebEino-Ville Talvala print >> sys.stderr,\ 103363c0fb27d923a32d9a398471ad318bfe84befbebEino-Ville Talvala " WARNING: Could not crossref likely reference {%s}" % (match.group(0)) 103463c0fb27d923a32d9a398471ad318bfe84befbebEino-Ville Talvala return whole_match 103563c0fb27d923a32d9a398471ad318bfe84befbebEino-Ville Talvala 103663c0fb27d923a32d9a398471ad318bfe84befbebEino-Ville Talvala text = re.sub(tag_match, filter_sub, text) 103763c0fb27d923a32d9a398471ad318bfe84befbebEino-Ville Talvala 103863c0fb27d923a32d9a398471ad318bfe84befbebEino-Ville Talvala if summary_function is not None: 103950f45c4d120ea1ad00017e5b850ed5bcf3261efeEino-Ville Talvala return text + summary_function(sorted(tag_set, key=lambda x: x.name)) 104063c0fb27d923a32d9a398471ad318bfe84befbebEino-Ville Talvala else: 104163c0fb27d923a32d9a398471ad318bfe84befbebEino-Ville Talvala return text 104263c0fb27d923a32d9a398471ad318bfe84befbebEino-Ville Talvala 1043ddda2bb917a1eb725c85d8c2b61bff2abf568a95Eino-Ville Talvaladef filter_links(text, filter_function, summary_function = None): 1044ddda2bb917a1eb725c85d8c2b61bff2abf568a95Eino-Ville Talvala """ 1045ddda2bb917a1eb725c85d8c2b61bff2abf568a95Eino-Ville Talvala Find all references to tags in the form {@link xxx#yyy [zzz]} in the 1046ddda2bb917a1eb725c85d8c2b61bff2abf568a95Eino-Ville Talvala provided text, and pass them through filter_function and 1047ddda2bb917a1eb725c85d8c2b61bff2abf568a95Eino-Ville Talvala summary_function. 1048ddda2bb917a1eb725c85d8c2b61bff2abf568a95Eino-Ville Talvala 1049ddda2bb917a1eb725c85d8c2b61bff2abf568a95Eino-Ville Talvala Used to linkify documentation cross-references in HMTL, javadoc output. 1050ddda2bb917a1eb725c85d8c2b61bff2abf568a95Eino-Ville Talvala 1051ddda2bb917a1eb725c85d8c2b61bff2abf568a95Eino-Ville Talvala Args: 1052ddda2bb917a1eb725c85d8c2b61bff2abf568a95Eino-Ville Talvala text: A string representing a block of text destined for output 1053ddda2bb917a1eb725c85d8c2b61bff2abf568a95Eino-Ville Talvala metadata: A Metadata instance, the root of the metadata properties tree 1054ddda2bb917a1eb725c85d8c2b61bff2abf568a95Eino-Ville Talvala filter_function: A (string, string)->string function to apply to each 'xxx#yyy', 1055ddda2bb917a1eb725c85d8c2b61bff2abf568a95Eino-Ville Talvala zzz pair when found in text; the string returned replaces the tag name in text. 1056ddda2bb917a1eb725c85d8c2b61bff2abf568a95Eino-Ville Talvala summary_function: A string list->string function that is provided the list of 1057ddda2bb917a1eb725c85d8c2b61bff2abf568a95Eino-Ville Talvala unique targets found in text, and which must return a string that is 1058ddda2bb917a1eb725c85d8c2b61bff2abf568a95Eino-Ville Talvala then appended to the end of the text. The list is sorted alphabetically 1059ddda2bb917a1eb725c85d8c2b61bff2abf568a95Eino-Ville Talvala by node name. 1060ddda2bb917a1eb725c85d8c2b61bff2abf568a95Eino-Ville Talvala 1061ddda2bb917a1eb725c85d8c2b61bff2abf568a95Eino-Ville Talvala """ 1062ddda2bb917a1eb725c85d8c2b61bff2abf568a95Eino-Ville Talvala 1063ddda2bb917a1eb725c85d8c2b61bff2abf568a95Eino-Ville Talvala target_set = set() 1064ddda2bb917a1eb725c85d8c2b61bff2abf568a95Eino-Ville Talvala def name_match(name): 1065ddda2bb917a1eb725c85d8c2b61bff2abf568a95Eino-Ville Talvala return lambda node: node.name == name 1066ddda2bb917a1eb725c85d8c2b61bff2abf568a95Eino-Ville Talvala 1067ddda2bb917a1eb725c85d8c2b61bff2abf568a95Eino-Ville Talvala tag_match = r"\{@link\s+([^\s\}]+)([^\}]*)\}" 1068ddda2bb917a1eb725c85d8c2b61bff2abf568a95Eino-Ville Talvala 1069ddda2bb917a1eb725c85d8c2b61bff2abf568a95Eino-Ville Talvala def filter_sub(match): 1070ddda2bb917a1eb725c85d8c2b61bff2abf568a95Eino-Ville Talvala whole_match = match.group(0) 1071ddda2bb917a1eb725c85d8c2b61bff2abf568a95Eino-Ville Talvala target = match.group(1) 1072ddda2bb917a1eb725c85d8c2b61bff2abf568a95Eino-Ville Talvala shortname = match.group(2).strip() 1073ddda2bb917a1eb725c85d8c2b61bff2abf568a95Eino-Ville Talvala 1074ddda2bb917a1eb725c85d8c2b61bff2abf568a95Eino-Ville Talvala #print "Found link '%s' as '%s' -> '%s'" % (target, shortname, filter_function(target, shortname)) 1075ddda2bb917a1eb725c85d8c2b61bff2abf568a95Eino-Ville Talvala 1076ddda2bb917a1eb725c85d8c2b61bff2abf568a95Eino-Ville Talvala # Replace match with crossref 1077ddda2bb917a1eb725c85d8c2b61bff2abf568a95Eino-Ville Talvala target_set.add(target) 1078ddda2bb917a1eb725c85d8c2b61bff2abf568a95Eino-Ville Talvala return filter_function(target, shortname) 1079ddda2bb917a1eb725c85d8c2b61bff2abf568a95Eino-Ville Talvala 1080ddda2bb917a1eb725c85d8c2b61bff2abf568a95Eino-Ville Talvala text = re.sub(tag_match, filter_sub, text) 1081ddda2bb917a1eb725c85d8c2b61bff2abf568a95Eino-Ville Talvala 1082ddda2bb917a1eb725c85d8c2b61bff2abf568a95Eino-Ville Talvala if summary_function is not None: 1083ddda2bb917a1eb725c85d8c2b61bff2abf568a95Eino-Ville Talvala return text + summary_function(sorted(target_set)) 1084ddda2bb917a1eb725c85d8c2b61bff2abf568a95Eino-Ville Talvala else: 1085ddda2bb917a1eb725c85d8c2b61bff2abf568a95Eino-Ville Talvala return text 1086ddda2bb917a1eb725c85d8c2b61bff2abf568a95Eino-Ville Talvala 1087f384f0a06cf156c51c4ca584a4323e132c15f64fEino-Ville Talvaladef any_visible(section, kind_name, visibilities): 1088f384f0a06cf156c51c4ca584a4323e132c15f64fEino-Ville Talvala """ 1089f384f0a06cf156c51c4ca584a4323e132c15f64fEino-Ville Talvala Determine if entries in this section have an applied visibility that's in 1090f384f0a06cf156c51c4ca584a4323e132c15f64fEino-Ville Talvala the list of given visibilities. 1091f384f0a06cf156c51c4ca584a4323e132c15f64fEino-Ville Talvala 1092f384f0a06cf156c51c4ca584a4323e132c15f64fEino-Ville Talvala Args: 1093f384f0a06cf156c51c4ca584a4323e132c15f64fEino-Ville Talvala section: A section of metadata 1094f384f0a06cf156c51c4ca584a4323e132c15f64fEino-Ville Talvala kind_name: A name of the kind, i.e. 'dynamic' or 'static' or 'controls' 1095f384f0a06cf156c51c4ca584a4323e132c15f64fEino-Ville Talvala visibilities: An iterable of visibilities to match against 1096f384f0a06cf156c51c4ca584a4323e132c15f64fEino-Ville Talvala 1097f384f0a06cf156c51c4ca584a4323e132c15f64fEino-Ville Talvala Returns: 1098f384f0a06cf156c51c4ca584a4323e132c15f64fEino-Ville Talvala True if the section has any entries with any of the given visibilities. False otherwise. 1099f384f0a06cf156c51c4ca584a4323e132c15f64fEino-Ville Talvala """ 1100f384f0a06cf156c51c4ca584a4323e132c15f64fEino-Ville Talvala 1101f384f0a06cf156c51c4ca584a4323e132c15f64fEino-Ville Talvala for inner_namespace in get_children_by_filtering_kind(section, kind_name, 1102f384f0a06cf156c51c4ca584a4323e132c15f64fEino-Ville Talvala 'namespaces'): 1103f384f0a06cf156c51c4ca584a4323e132c15f64fEino-Ville Talvala if any(filter_visibility(inner_namespace.merged_entries, visibilities)): 1104f384f0a06cf156c51c4ca584a4323e132c15f64fEino-Ville Talvala return True 1105f384f0a06cf156c51c4ca584a4323e132c15f64fEino-Ville Talvala 1106f384f0a06cf156c51c4ca584a4323e132c15f64fEino-Ville Talvala return any(filter_visibility(get_children_by_filtering_kind(section, kind_name, 1107f384f0a06cf156c51c4ca584a4323e132c15f64fEino-Ville Talvala 'merged_entries'), 1108f384f0a06cf156c51c4ca584a4323e132c15f64fEino-Ville Talvala visibilities)) 1109f384f0a06cf156c51c4ca584a4323e132c15f64fEino-Ville Talvala 1110f384f0a06cf156c51c4ca584a4323e132c15f64fEino-Ville Talvala 1111f384f0a06cf156c51c4ca584a4323e132c15f64fEino-Ville Talvaladef filter_visibility(entries, visibilities): 1112f384f0a06cf156c51c4ca584a4323e132c15f64fEino-Ville Talvala """ 1113f384f0a06cf156c51c4ca584a4323e132c15f64fEino-Ville Talvala Remove entries whose applied visibility is not in the supplied visibilities. 1114f384f0a06cf156c51c4ca584a4323e132c15f64fEino-Ville Talvala 1115f384f0a06cf156c51c4ca584a4323e132c15f64fEino-Ville Talvala Args: 1116f384f0a06cf156c51c4ca584a4323e132c15f64fEino-Ville Talvala entries: An iterable of Entry nodes 1117f384f0a06cf156c51c4ca584a4323e132c15f64fEino-Ville Talvala visibilities: An iterable of visibilities to filter against 1118f384f0a06cf156c51c4ca584a4323e132c15f64fEino-Ville Talvala 1119f384f0a06cf156c51c4ca584a4323e132c15f64fEino-Ville Talvala Yields: 1120f384f0a06cf156c51c4ca584a4323e132c15f64fEino-Ville Talvala An iterable of Entry nodes 1121f384f0a06cf156c51c4ca584a4323e132c15f64fEino-Ville Talvala """ 1122f384f0a06cf156c51c4ca584a4323e132c15f64fEino-Ville Talvala return (e for e in entries if e.applied_visibility in visibilities) 11230b080452cca90f215d10d636abfb47701d7518daIgor Murashkin 11246c936c18e02b122baaa3d5056b0555b6cff256f8Igor Murashkindef remove_synthetic(entries): 11256c936c18e02b122baaa3d5056b0555b6cff256f8Igor Murashkin """ 11266c936c18e02b122baaa3d5056b0555b6cff256f8Igor Murashkin Filter the given entries by removing those that are synthetic. 11276c936c18e02b122baaa3d5056b0555b6cff256f8Igor Murashkin 11286c936c18e02b122baaa3d5056b0555b6cff256f8Igor Murashkin Args: 11296c936c18e02b122baaa3d5056b0555b6cff256f8Igor Murashkin entries: An iterable of Entry nodes 11306c936c18e02b122baaa3d5056b0555b6cff256f8Igor Murashkin 11316c936c18e02b122baaa3d5056b0555b6cff256f8Igor Murashkin Yields: 11326c936c18e02b122baaa3d5056b0555b6cff256f8Igor Murashkin An iterable of Entry nodes 11336c936c18e02b122baaa3d5056b0555b6cff256f8Igor Murashkin """ 11346c936c18e02b122baaa3d5056b0555b6cff256f8Igor Murashkin return (e for e in entries if not e.synthetic) 11356c936c18e02b122baaa3d5056b0555b6cff256f8Igor Murashkin 1136c6c2416a812ddb8bcb32fdefce1eff3a7ded9b61Yin-Chia Yehdef filter_ndk_visible(entries): 1137c6c2416a812ddb8bcb32fdefce1eff3a7ded9b61Yin-Chia Yeh """ 1138c6c2416a812ddb8bcb32fdefce1eff3a7ded9b61Yin-Chia Yeh Filter the given entries by removing those that are not NDK visible. 1139c6c2416a812ddb8bcb32fdefce1eff3a7ded9b61Yin-Chia Yeh 1140c6c2416a812ddb8bcb32fdefce1eff3a7ded9b61Yin-Chia Yeh Args: 1141c6c2416a812ddb8bcb32fdefce1eff3a7ded9b61Yin-Chia Yeh entries: An iterable of Entry nodes 1142c6c2416a812ddb8bcb32fdefce1eff3a7ded9b61Yin-Chia Yeh 1143c6c2416a812ddb8bcb32fdefce1eff3a7ded9b61Yin-Chia Yeh Yields: 1144c6c2416a812ddb8bcb32fdefce1eff3a7ded9b61Yin-Chia Yeh An iterable of Entry nodes 1145c6c2416a812ddb8bcb32fdefce1eff3a7ded9b61Yin-Chia Yeh """ 1146c6c2416a812ddb8bcb32fdefce1eff3a7ded9b61Yin-Chia Yeh return (e for e in entries if e.applied_ndk_visible == 'true') 1147c6c2416a812ddb8bcb32fdefce1eff3a7ded9b61Yin-Chia Yeh 11480b080452cca90f215d10d636abfb47701d7518daIgor Murashkindef wbr(text): 11490b080452cca90f215d10d636abfb47701d7518daIgor Murashkin """ 11500b080452cca90f215d10d636abfb47701d7518daIgor Murashkin Insert word break hints for the browser in the form of <wbr> HTML tags. 11510b080452cca90f215d10d636abfb47701d7518daIgor Murashkin 11520b080452cca90f215d10d636abfb47701d7518daIgor Murashkin Word breaks are inserted inside an HTML node only, so the nodes themselves 11530b080452cca90f215d10d636abfb47701d7518daIgor Murashkin will not be changed. Attributes are also left unchanged. 11540b080452cca90f215d10d636abfb47701d7518daIgor Murashkin 11550b080452cca90f215d10d636abfb47701d7518daIgor Murashkin The following rules apply to insert word breaks: 11560b080452cca90f215d10d636abfb47701d7518daIgor Murashkin - For characters in [ '.', '/', '_' ] 11570b080452cca90f215d10d636abfb47701d7518daIgor Murashkin - For uppercase letters inside a multi-word X.Y.Z (at least 3 parts) 11580b080452cca90f215d10d636abfb47701d7518daIgor Murashkin 11590b080452cca90f215d10d636abfb47701d7518daIgor Murashkin Args: 11600b080452cca90f215d10d636abfb47701d7518daIgor Murashkin text: A string of text containing HTML content. 11610b080452cca90f215d10d636abfb47701d7518daIgor Murashkin 11620b080452cca90f215d10d636abfb47701d7518daIgor Murashkin Returns: 11630b080452cca90f215d10d636abfb47701d7518daIgor Murashkin A string with <wbr> inserted by the above rules. 11640b080452cca90f215d10d636abfb47701d7518daIgor Murashkin """ 11650b080452cca90f215d10d636abfb47701d7518daIgor Murashkin SPLIT_CHARS_LIST = ['.', '_', '/'] 11660b080452cca90f215d10d636abfb47701d7518daIgor Murashkin SPLIT_CHARS = r'([.|/|_/,]+)' # split by these characters 11670b080452cca90f215d10d636abfb47701d7518daIgor Murashkin CAP_LETTER_MIN = 3 # at least 3 components split by above chars, i.e. x.y.z 11680b080452cca90f215d10d636abfb47701d7518daIgor Murashkin def wbr_filter(text): 11690b080452cca90f215d10d636abfb47701d7518daIgor Murashkin new_txt = text 11700b080452cca90f215d10d636abfb47701d7518daIgor Murashkin 11710b080452cca90f215d10d636abfb47701d7518daIgor Murashkin # for johnyOrange.appleCider.redGuardian also insert wbr before the caps 11720b080452cca90f215d10d636abfb47701d7518daIgor Murashkin # => johny<wbr>Orange.apple<wbr>Cider.red<wbr>Guardian 11730b080452cca90f215d10d636abfb47701d7518daIgor Murashkin for words in text.split(" "): 11740b080452cca90f215d10d636abfb47701d7518daIgor Murashkin for char in SPLIT_CHARS_LIST: 11750b080452cca90f215d10d636abfb47701d7518daIgor Murashkin # match at least x.y.z, don't match x or x.y 11760b080452cca90f215d10d636abfb47701d7518daIgor Murashkin if len(words.split(char)) >= CAP_LETTER_MIN: 11770b080452cca90f215d10d636abfb47701d7518daIgor Murashkin new_word = re.sub(r"([a-z])([A-Z])", r"\1<wbr>\2", words) 11780b080452cca90f215d10d636abfb47701d7518daIgor Murashkin new_txt = new_txt.replace(words, new_word) 11790b080452cca90f215d10d636abfb47701d7518daIgor Murashkin 11800b080452cca90f215d10d636abfb47701d7518daIgor Murashkin # e.g. X/Y/Z -> X/<wbr>Y/<wbr>/Z. also for X.Y.Z, X_Y_Z. 11810b080452cca90f215d10d636abfb47701d7518daIgor Murashkin new_txt = re.sub(SPLIT_CHARS, r"\1<wbr>", new_txt) 11820b080452cca90f215d10d636abfb47701d7518daIgor Murashkin 11830b080452cca90f215d10d636abfb47701d7518daIgor Murashkin return new_txt 11840b080452cca90f215d10d636abfb47701d7518daIgor Murashkin 11850b080452cca90f215d10d636abfb47701d7518daIgor Murashkin # Do not mangle HTML when doing the replace by using BeatifulSoup 11860b080452cca90f215d10d636abfb47701d7518daIgor Murashkin # - Use the 'html.parser' to avoid inserting <html><body> when decoding 11870b080452cca90f215d10d636abfb47701d7518daIgor Murashkin soup = bs4.BeautifulSoup(text, features='html.parser') 11880b080452cca90f215d10d636abfb47701d7518daIgor Murashkin wbr_tag = lambda: soup.new_tag('wbr') # must generate new tag every time 11890b080452cca90f215d10d636abfb47701d7518daIgor Murashkin 11900b080452cca90f215d10d636abfb47701d7518daIgor Murashkin for navigable_string in soup.findAll(text=True): 11910b080452cca90f215d10d636abfb47701d7518daIgor Murashkin parent = navigable_string.parent 11920b080452cca90f215d10d636abfb47701d7518daIgor Murashkin 11930b080452cca90f215d10d636abfb47701d7518daIgor Murashkin # Insert each '$text<wbr>$foo' before the old '$text$foo' 11940b080452cca90f215d10d636abfb47701d7518daIgor Murashkin split_by_wbr_list = wbr_filter(navigable_string).split("<wbr>") 11950b080452cca90f215d10d636abfb47701d7518daIgor Murashkin for (split_string, last) in enumerate_with_last(split_by_wbr_list): 11960b080452cca90f215d10d636abfb47701d7518daIgor Murashkin navigable_string.insert_before(split_string) 11970b080452cca90f215d10d636abfb47701d7518daIgor Murashkin 11980b080452cca90f215d10d636abfb47701d7518daIgor Murashkin if not last: 11990b080452cca90f215d10d636abfb47701d7518daIgor Murashkin # Note that 'insert' will move existing tags to this spot 12000b080452cca90f215d10d636abfb47701d7518daIgor Murashkin # so make a new tag instead 12010b080452cca90f215d10d636abfb47701d7518daIgor Murashkin navigable_string.insert_before(wbr_tag()) 12020b080452cca90f215d10d636abfb47701d7518daIgor Murashkin 12030b080452cca90f215d10d636abfb47701d7518daIgor Murashkin # Remove the old unmodified text 12040b080452cca90f215d10d636abfb47701d7518daIgor Murashkin navigable_string.extract() 12050b080452cca90f215d10d636abfb47701d7518daIgor Murashkin 12060b080452cca90f215d10d636abfb47701d7518daIgor Murashkin return soup.decode() 1207