1d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)# Copyright 2014 The Chromium Authors. All rights reserved. 2d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)# Use of this source code is governed by a BSD-style license that can be 3d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)# found in the LICENSE file. 4d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) 5d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)"""Utility functions (file reading, simple IDL parsing by regexes) for IDL build. 6d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) 7d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)Design doc: http://www.chromium.org/developers/design-documents/idl-build 8d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)""" 9d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) 10d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)import os 11d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)import cPickle as pickle 12d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)import re 13d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)import string 147242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucciimport subprocess 157242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci 167242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci 177242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano TucciKNOWN_COMPONENTS = frozenset(['core', 'modules']) 18d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) 19d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) 20d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)class IdlBadFilenameError(Exception): 21d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) """Raised if an IDL filename disagrees with the interface name in the file.""" 22d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) pass 23d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) 24d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) 25f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)def idl_filename_to_interface_name(idl_filename): 26f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles) # interface name is the root of the basename: InterfaceName.idl 27f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles) return os.path.splitext(os.path.basename(idl_filename))[0] 28f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles) 29f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles) 307242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tuccidef idl_filename_to_component(idl_filename): 317242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci path = os.path.dirname(os.path.realpath(idl_filename)) 327242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci while path: 337242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci dirname, basename = os.path.split(path) 347242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci if basename.lower() in KNOWN_COMPONENTS: 357242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci return basename.lower() 367242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci path = dirname 377242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci raise 'Unknown component type for %s' % idl_filename 387242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci 397242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci 40d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)################################################################################ 41d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)# Basic file reading/writing 42d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)################################################################################ 43d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) 44d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)def get_file_contents(filename): 45d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) with open(filename) as f: 46d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) return f.read() 47d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) 48d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) 49f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)def read_file_to_list(filename): 50f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles) """Returns a list of (stripped) lines for a given filename.""" 51f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles) with open(filename) as f: 52f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles) return [line.rstrip('\n') for line in f] 53f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles) 54f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles) 557242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tuccidef resolve_cygpath(cygdrive_names): 567242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci if not cygdrive_names: 577242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci return [] 587242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci cmd = ['cygpath', '-f', '-', '-wa'] 597242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci process = subprocess.Popen(cmd, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) 607242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci idl_file_names = [] 617242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci for file_name in cygdrive_names: 627242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci process.stdin.write('%s\n' % file_name) 637242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci process.stdin.flush() 647242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci idl_file_names.append(process.stdout.readline().rstrip()) 657242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci process.stdin.close() 667242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci process.wait() 677242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci return idl_file_names 687242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci 697242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci 707242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tuccidef read_idl_files_list_from_file(filename): 717242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci """Similar to read_file_to_list, but also resolves cygpath.""" 727242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci with open(filename) as input_file: 737242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci file_names = sorted([os.path.realpath(line.rstrip('\n')) 747242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci for line in input_file]) 757242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci idl_file_names = [file_name for file_name in file_names 767242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci if not file_name.startswith('/cygdrive')] 777242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci cygdrive_names = [file_name for file_name in file_names 787242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci if file_name.startswith('/cygdrive')] 797242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci idl_file_names.extend(resolve_cygpath(cygdrive_names)) 807242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci return idl_file_names 817242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci 827242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci 83f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)def read_pickle_files(pickle_filenames): 84f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles) for pickle_filename in pickle_filenames: 85f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles) with open(pickle_filename) as pickle_file: 86f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles) yield pickle.load(pickle_file) 87f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles) 88f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles) 89d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)def write_file(new_text, destination_filename, only_if_changed): 90d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) if only_if_changed and os.path.isfile(destination_filename): 91d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) with open(destination_filename) as destination_file: 92d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) if destination_file.read() == new_text: 93d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) return 947242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci destination_dirname = os.path.dirname(destination_filename) 957242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci if not os.path.exists(destination_dirname): 967242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci os.makedirs(destination_dirname) 97d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) with open(destination_filename, 'w') as destination_file: 98d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) destination_file.write(new_text) 99d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) 100d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) 101d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)def write_pickle_file(pickle_filename, data, only_if_changed): 102d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) if only_if_changed and os.path.isfile(pickle_filename): 103d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) with open(pickle_filename) as pickle_file: 104d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles) try: 105d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles) if pickle.load(pickle_file) == data: 106d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles) return 107d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles) except (EOFError, pickle.UnpicklingError): 108d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles) # If trouble unpickling, overwrite 109d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles) pass 110d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) with open(pickle_filename, 'w') as pickle_file: 111d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) pickle.dump(data, pickle_file) 112d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) 113d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) 114d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)################################################################################ 115d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)# IDL parsing 116d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)# 117d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)# We use regular expressions for parsing; this is incorrect (Web IDL is not a 118d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)# regular language), but simple and sufficient in practice. 119d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)# Leading and trailing context (e.g. following '{') used to avoid false matches. 120d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)################################################################################ 121d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) 122d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)def get_partial_interface_name_from_idl(file_contents): 123d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) match = re.search(r'partial\s+interface\s+(\w+)\s*{', file_contents) 124d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) return match and match.group(1) 125d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) 126d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) 127323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)def get_implements_from_idl(file_contents, interface_name): 128323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles) """Returns lists of implementing and implemented interfaces. 129d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) 130323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles) Rule is: identifier-A implements identifier-B; 131323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles) i.e., implement*ing* implements implement*ed*; 132323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles) http://www.w3.org/TR/WebIDL/#idl-implements-statements 133323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles) 134323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles) Returns two lists of interfaces: identifier-As and identifier-Bs. 135323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles) An 'implements' statements can be present in the IDL file for either the 136323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles) implementing or the implemented interface, but not other files. 137323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles) """ 138d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) implements_re = (r'^\s*' 139d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) r'(\w+)\s+' 140d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) r'implements\s+' 141d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) r'(\w+)\s*' 142d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) r';') 143d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) implements_matches = re.finditer(implements_re, file_contents, re.MULTILINE) 144323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles) implements_pairs = [match.groups() for match in implements_matches] 145323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles) 146323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles) foreign_implements = [pair for pair in implements_pairs 147323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles) if interface_name not in pair] 148323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles) if foreign_implements: 149323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles) left, right = foreign_implements.pop() 150323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles) raise IdlBadFilenameError( 151323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles) 'implements statement found in unrelated IDL file.\n' 152323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles) 'Statement is:\n' 153323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles) ' %s implements %s;\n' 154323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles) 'but filename is unrelated "%s.idl"' % 155323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles) (left, right, interface_name)) 156323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles) 157323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles) return ( 158323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles) [left for left, right in implements_pairs if right == interface_name], 159323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles) [right for left, right in implements_pairs if left == interface_name]) 160d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) 161d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) 162d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)def is_callback_interface_from_idl(file_contents): 163d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) match = re.search(r'callback\s+interface\s+\w+\s*{', file_contents) 164d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) return bool(match) 165d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) 166d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) 167c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)def is_dictionary_from_idl(file_contents): 168c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) match = re.search(r'dictionary\s+\w+\s*{', file_contents) 169c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) return bool(match) 170c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) 171c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) 172d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)def get_parent_interface(file_contents): 173d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) match = re.search(r'interface\s+' 174d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) r'\w+\s*' 175d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) r':\s*(\w+)\s*' 176d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) r'{', 177d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) file_contents) 178d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) return match and match.group(1) 179d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) 180d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) 181d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)def get_interface_extended_attributes_from_idl(file_contents): 182323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles) # Strip comments 183323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles) # re.compile needed b/c Python 2.6 doesn't support flags in re.sub 184323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles) single_line_comment_re = re.compile(r'//.*$', flags=re.MULTILINE) 185323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles) block_comment_re = re.compile(r'/\*.*?\*/', flags=re.MULTILINE | re.DOTALL) 186323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles) file_contents = re.sub(single_line_comment_re, '', file_contents) 187323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles) file_contents = re.sub(block_comment_re, '', file_contents) 188323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles) 189d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) match = re.search(r'\[(.*)\]\s*' 190d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) r'((callback|partial)\s+)?' 191d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) r'(interface|exception)\s+' 192d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) r'\w+\s*' 193d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) r'(:\s*\w+\s*)?' 194d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) r'{', 195d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) file_contents, flags=re.DOTALL) 196d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) if not match: 197d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) return {} 198323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles) 199323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles) extended_attributes_string = match.group(1) 200d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) extended_attributes = {} 201e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles) # FIXME: this splitting is WRONG: it fails on extended attributes where lists of 202e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles) # multiple values are used, which are seperated by a comma and a space. 203d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) parts = [extended_attribute.strip() 204e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles) for extended_attribute in re.split(',\s+', extended_attributes_string) 205d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) # Discard empty parts, which may exist due to trailing comma 206d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) if extended_attribute.strip()] 207d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) for part in parts: 208d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) name, _, value = map(string.strip, part.partition('=')) 209d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) extended_attributes[name] = value 210d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) return extended_attributes 211d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) 212d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) 213d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)def get_put_forward_interfaces_from_idl(file_contents): 214d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) put_forwards_pattern = (r'\[[^\]]*PutForwards=[^\]]*\]\s+' 215d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) r'readonly\s+' 216d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) r'attribute\s+' 217d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) r'(\w+)') 218d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) return sorted(set(match.group(1) 219d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) for match in re.finditer(put_forwards_pattern, 220d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) file_contents, 221d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) flags=re.DOTALL))) 222