1# Copyright 2004-2008 Roman Yakovenko. 2# Distributed under the Boost Software License, Version 1.0. (See 3# accompanying file LICENSE_1_0.txt or copy at 4# http://www.boost.org/LICENSE_1_0.txt) 5 6import os 7from . import custom 8from . import license 9from . import include 10from . import compound 11from . import namespace 12from . import algorithm 13from . import module_body 14from . import library_reference 15from . import declaration_based 16from . import include_directories 17from pygccxml.utils import utils 18 19 20 21class module_t(compound.compound_t): 22 """This class represents the source code for the entire extension module. 23 24 The root of the code creator tree is always a module_t object. 25 """ 26 def __init__(self, global_ns, code_generator_type): 27 """Constructor. 28 """ 29 compound.compound_t.__init__(self) 30 self.__global_ns = global_ns 31 self._code_generator = code_generator_type 32 33 @property 34 def global_ns(self): 35 "reference to global_ns ( namespace_t ) declaration" 36 return self.__global_ns 37 38 def _get_license( self ): 39 if isinstance( self.creators[0], license.license_t ): 40 return self.creators[0] 41 return None 42 43 def _set_license( self, license_text ): 44 if not isinstance( license_text, license.license_t ): 45 license_inst = license.license_t( license_text ) 46 if isinstance( self.creators[0], license.license_t ): 47 self.remove_creator( self.creators[0] ) 48 self.adopt_creator( license_inst, 0 ) 49 license = property( _get_license, _set_license, 50 doc="""License text. 51 52 The license text will always be the first children node. 53 @type: str or :class:`code_creators.license_t`""") 54 55 def _get_system_files_impl( self ): 56 return [] 57 58 @utils.cached 59 def specially_exposed_decls(self): 60 """list of exposed declarations, which were not ``included``, but still 61 were exposed. For example, std containers. 62 """ 63 decls = set() 64 #select all declaration based code creators 65 ccs = [cc for cc in algorithm.make_flatten_list( self ) if isinstance( cc, declaration_based.declaration_based_t )] 66 #leave only "ignored" 67 ccs = [cc for cc in ccs if cc.declaration.ignore == True] 68 69 decls = [cc.declaration for cc in ccs] 70 71 return set( decls ) 72 73 def update_documentation( self, doc_extractor ): 74 if not doc_extractor: 75 return 76 visited = set() 77 for cc in algorithm.make_flatten( self ): 78 if not isinstance( cc, declaration_based.declaration_based_t ): 79 continue 80 if id( cc.declaration ) in visited: 81 continue 82 cc.declaration.documentation = doc_extractor( cc.declaration ) 83 visited.add( id( cc.declaration ) ) 84 85class bpmodule_t(module_t): 86 """This class represents the source code for the entire extension module. 87 88 The root of the code creator tree is always a module_t object. 89 """ 90 def __init__(self, global_ns): 91 """Constructor. 92 """ 93 module_t.__init__(self, global_ns, bpmodule_t.CODE_GENERATOR_TYPES.BOOST_PYTHON) 94 self.__body = None 95 96 def _get_include_dirs(self): 97 include_dirs = algorithm.creator_finder.find_by_class_instance( 98 what=include_directories.include_directories_t 99 , where=self.creators 100 , recursive=False) 101 if 0 == len( include_dirs ): 102 include_dirs = include_directories.include_directories_t() 103 if self.license: 104 self.adopt_creator( include_dirs, 1 ) 105 else: 106 self.adopt_creator( include_dirs, 0 ) 107 return include_dirs 108 elif 1 == len( include_dirs ): 109 return include_dirs[0] 110 else: 111 assert not "only single instance of include_directories_t should exist" 112 113 def _get_std_directories(self): 114 include_dirs = self._get_include_dirs() 115 return include_dirs.std 116 std_directories = property( _get_std_directories ) 117 118 def _get_user_defined_directories(self): 119 include_dirs = self._get_include_dirs() 120 return include_dirs.user_defined 121 user_defined_directories = property( _get_user_defined_directories ) 122 123 @property 124 def body(self): 125 """Return reference to :class:`code_creators.module_body_t` code creator""" 126 if None is self.__body: 127 found = algorithm.creator_finder.find_by_class_instance( what=module_body.module_body_t 128 , where=self.creators 129 , recursive=False ) 130 if found: 131 self.__body = found[0] 132 return self.__body 133 134 def last_include_index(self): 135 """ 136 return the children index of the last :class:`code_creators.include_t` object. 137 138 An exception is raised when there is no include_t object among 139 the children creators. 140 141 :rtype: int 142 """ 143 for i in range( len(self.creators) - 1, -1, -1 ): 144 if isinstance( self.creators[i], include.include_t ): 145 return i 146 else: 147 return 0 148 149 def replace_included_headers( self, headers, leave_system_headers=True ): 150 to_be_removed = [] 151 for creator in self.creators: 152 if isinstance( creator, include.include_t ): 153 to_be_removed.append( creator ) 154 elif isinstance( creator, module_body.module_body_t ): 155 break 156 157 for creator in to_be_removed: 158 if creator.is_system: 159 if not leave_system_headers: 160 self.remove_creator( creator ) 161 elif creator.is_user_defined: 162 pass 163 else: 164 self.remove_creator( creator ) 165 for header in headers: 166 self.adopt_include( include.include_t( header=header ) ) 167 168 def adopt_include(self, include_creator): 169 """Insert an :class:`code_creators.include_t` object. 170 171 The include creator is inserted right after the last include file. 172 173 :param include_creator: Include creator object 174 :type include_creator: :class:`code_creators.include_t` 175 """ 176 lii = self.last_include_index() 177 if lii == 0: 178 if not self.creators: 179 lii = -1 180 elif not isinstance( self.creators[0], include.include_t ): 181 lii = -1 182 else: 183 pass 184 self.adopt_creator( include_creator, lii + 1 ) 185 186 def do_include_dirs_optimization(self): 187 include_dirs = self._get_include_dirs() 188 includes = [creator for creator in self.creators if isinstance( creator, include.include_t )] 189 for include_creator in includes: 190 include_creator.include_dirs_optimization = include_dirs 191 192 def _create_impl(self): 193 self.do_include_dirs_optimization() 194 index = 0 195 code = [] 196 for index in range( len( self.creators ) ): 197 if not isinstance( self.creators[index], include.include_t ): 198 break 199 else: 200 code.append( self.creators[index].create() ) 201 if code: 202 code.append( 2* os.linesep ) 203 code.append( self.create_internal_code( self.creators[index:], indent_code=False )) 204 code.append( os.linesep ) 205 return os.linesep.join( code ) 206 207 def add_include( self, header, user_defined=True, system=False ): 208 creator = include.include_t( header=header, user_defined=user_defined, system=system ) 209 self.adopt_include( creator ) 210 211 def add_namespace_usage( self, namespace_name ): 212 self.adopt_creator( namespace.namespace_using_t( namespace_name ) 213 , self.last_include_index() + 1 ) 214 215 def add_namespace_alias( self, alias, full_namespace_name ): 216 self.adopt_creator( namespace.namespace_alias_t( 217 alias=alias 218 , full_namespace_name=full_namespace_name ) 219 , self.last_include_index() + 1 ) 220 221 def adopt_declaration_creator( self, creator ): 222 self.adopt_creator( creator, self.creators.index( self.body ) ) 223 224 def add_declaration_code( self, code, position ): 225 self.adopt_declaration_creator( custom.custom_text_t( code ) ) 226 227 228 229class ctypes_module_t(module_t): 230 """This class represents the source code for the entire extension module. 231 232 The root of the code creator tree is always a module_t object. 233 """ 234 def __init__(self, global_ns): 235 """Constructor. 236 """ 237 module_t.__init__(self, global_ns, ctypes_module_t.CODE_GENERATOR_TYPES.CTYPES) 238 self.treat_char_ptr_as_binary_data = False 239 240 def _create_impl(self): 241 return self.create_internal_code( self.creators, indent_code=False ) 242 243 @utils.cached 244 def library_var_name(self): 245 for creator in self.creators: 246 if isinstance( creator, library_reference.library_reference_t ): 247 return creator.library_var_name 248 else: 249 raise RuntimeError( "Internal Error: library_reference_t creator was not created" ) 250