[pygccxml-commit] SF.net SVN: pygccxml: [1111] pyplusplus_dev
Brought to you by:
mbaas,
roman_yakovenko
|
From: <rom...@us...> - 2007-08-19 19:42:35
|
Revision: 1111
http://pygccxml.svn.sourceforge.net/pygccxml/?rev=1111&view=rev
Author: roman_yakovenko
Date: 2007-08-19 12:42:34 -0700 (Sun, 19 Aug 2007)
Log Message:
-----------
adding better support for mutli-module development - initial implementation
Modified Paths:
--------------
pyplusplus_dev/pyplusplus/code_creators/code_creator.py
pyplusplus_dev/pyplusplus/code_creators/compound.py
pyplusplus_dev/pyplusplus/code_creators/declaration_based.py
pyplusplus_dev/pyplusplus/code_creators/scoped.py
pyplusplus_dev/pyplusplus/file_writers/multiple_files.py
pyplusplus_dev/pyplusplus/file_writers/single_file.py
pyplusplus_dev/pyplusplus/file_writers/writer.py
pyplusplus_dev/pyplusplus/module_builder/builder.py
pyplusplus_dev/pyplusplus/module_creator/creator.py
pyplusplus_dev/pyplusplus/module_creator/dependencies_manager.py
pyplusplus_dev/pyplusplus/utils/__init__.py
pyplusplus_dev/unittests/exposed_decls_db_tester.py
pyplusplus_dev/unittests/test_all.py
Added Paths:
-----------
pyplusplus_dev/unittests/already_exposed_tester.py
pyplusplus_dev/unittests/data/already_exposed_to_be_exported.hpp
Modified: pyplusplus_dev/pyplusplus/code_creators/code_creator.py
===================================================================
--- pyplusplus_dev/pyplusplus/code_creators/code_creator.py 2007-08-18 05:54:28 UTC (rev 1110)
+++ pyplusplus_dev/pyplusplus/code_creators/code_creator.py 2007-08-19 19:42:34 UTC (rev 1111)
@@ -178,3 +178,12 @@
assert isinstance( line, types.StringTypes )
l = line.lstrip()
return l.startswith( '//' ) or l.startswith( '/*' )
+
+ def register_exposed( self, exposed_db ):
+ """Register exposed declaration in L{exposed data base<utils.exposed_decls_db_t>}
+
+ The default implementation of the function does nothing.
+ """
+ pass
+
+
\ No newline at end of file
Modified: pyplusplus_dev/pyplusplus/code_creators/compound.py
===================================================================
--- pyplusplus_dev/pyplusplus/code_creators/compound.py 2007-08-18 05:54:28 UTC (rev 1110)
+++ pyplusplus_dev/pyplusplus/code_creators/compound.py 2007-08-19 19:42:34 UTC (rev 1111)
@@ -86,4 +86,11 @@
if unique:
files = self.unique_headers( files )
return files
-
\ No newline at end of file
+
+ def register_exposed( self, exposed_db ):
+ """Register exposed declaration in L{exposed data base<utils.exposed_decls_db_t>}
+
+ The default implementation of the function does nothing.
+ """
+ map( lambda creator: creator.register_exposed( exposed_db )
+ , self._creators )
Modified: pyplusplus_dev/pyplusplus/code_creators/declaration_based.py
===================================================================
--- pyplusplus_dev/pyplusplus/code_creators/declaration_based.py 2007-08-18 05:54:28 UTC (rev 1110)
+++ pyplusplus_dev/pyplusplus/code_creators/declaration_based.py 2007-08-19 19:42:34 UTC (rev 1111)
@@ -54,3 +54,7 @@
def get_user_headers( self, recursive=False, unique=False ):
"""return list of user header files to be included from the generated file"""
return self.declaration.include_files
+
+ def register_exposed( self, exposed_db ):
+ """Register exposed declaration in L{exposed data base<utils.exposed_decls_db_t>}"""
+ exposed_db.expose( self.declaration )
Modified: pyplusplus_dev/pyplusplus/code_creators/scoped.py
===================================================================
--- pyplusplus_dev/pyplusplus/code_creators/scoped.py 2007-08-18 05:54:28 UTC (rev 1110)
+++ pyplusplus_dev/pyplusplus/code_creators/scoped.py 2007-08-19 19:42:34 UTC (rev 1111)
@@ -14,4 +14,11 @@
def _create_impl(self):
#template method pattern should be used.
- raise NotImplementedError()
\ No newline at end of file
+ raise NotImplementedError()
+
+ def register_exposed( self, exposed_db ):
+ """Register exposed declaration in L{exposed data base<utils.exposed_decls_db_t>}"""
+ exposed_db.expose( self.declaration )
+ map( lambda creator: creator.register_exposed( exposed_db )
+ , self._creators )
+
Modified: pyplusplus_dev/pyplusplus/file_writers/multiple_files.py
===================================================================
--- pyplusplus_dev/pyplusplus/file_writers/multiple_files.py 2007-08-18 05:54:28 UTC (rev 1110)
+++ pyplusplus_dev/pyplusplus/file_writers/multiple_files.py 2007-08-19 19:42:34 UTC (rev 1111)
@@ -375,7 +375,8 @@
"""
self.write_code_repository( self.__directory_path )
-
+ self.save_exposed_decls_db( self.__directory_path )
+
self.extmodule.do_include_dirs_optimization()
map( self.split_value_traits, self.__value_traits )
Modified: pyplusplus_dev/pyplusplus/file_writers/single_file.py
===================================================================
--- pyplusplus_dev/pyplusplus/file_writers/single_file.py 2007-08-18 05:54:28 UTC (rev 1110)
+++ pyplusplus_dev/pyplusplus/file_writers/single_file.py 2007-08-19 19:42:34 UTC (rev 1111)
@@ -20,9 +20,10 @@
return self.__fname
def write(self):
+ target_dir = os.path.split( self.file_name )[0]
headers = self.get_user_headers( [self.extmodule] )
map( lambda header: self.extmodule.add_include( header )
, headers )
- self.write_code_repository( os.path.split( self.file_name )[0] )
+ self.write_code_repository( target_dir )
self.write_file( self.file_name, self.extmodule.create(), encoding=self.encoding )
-
+ self.save_exposed_decls_db( target_dir )
\ No newline at end of file
Modified: pyplusplus_dev/pyplusplus/file_writers/writer.py
===================================================================
--- pyplusplus_dev/pyplusplus/file_writers/writer.py 2007-08-18 05:54:28 UTC (rev 1110)
+++ pyplusplus_dev/pyplusplus/file_writers/writer.py 2007-08-19 19:42:34 UTC (rev 1111)
@@ -8,10 +8,11 @@
import os
import time
import codecs
+import md5sum_repository
+from pyplusplus import utils
from pyplusplus import _logging_
from pyplusplus import code_creators
from pyplusplus import code_repository
-import md5sum_repository
class writer_t(object):
"""Base class for all module/code writers.
@@ -30,6 +31,8 @@
self.__encoding=encoding
if None is files_sum_repository:
self.__files_sum_repository = md5sum_repository.dummy_repository_t()
+ self.__exposed_decls_db = utils.exposed_decls_db_t()
+ self.__extmodule.register_exposed( self.__exposed_decls_db )
@property
def encoding( self ):
@@ -136,3 +139,8 @@
map( lambda creator: headers.extend( creator.get_user_headers() )
, creators )
return code_creators.code_creator_t.unique_headers( headers )
+
+ def save_exposed_decls_db( self, file_path ):
+ self.__exposed_decls_db.save( file_path )
+
+
\ No newline at end of file
Modified: pyplusplus_dev/pyplusplus/module_builder/builder.py
===================================================================
--- pyplusplus_dev/pyplusplus/module_builder/builder.py 2007-08-18 05:54:28 UTC (rev 1110)
+++ pyplusplus_dev/pyplusplus/module_builder/builder.py 2007-08-19 19:42:34 UTC (rev 1111)
@@ -12,6 +12,7 @@
from pygccxml import parser
from pygccxml import declarations as decls_package
+from pyplusplus import utils
from pyplusplus import _logging_
from pyplusplus import decl_wrappers
from pyplusplus import file_writers
@@ -96,7 +97,8 @@
self.__registrations_code_head = []
self.__registrations_code_tail = []
-
+ self.__already_exposed_modules = []
+
@property
def global_ns( self ):
"""reference to global namespace"""
@@ -106,6 +108,9 @@
def encoding( self ):
return self.__encoding
+ def register_module_dependency( self, other_module_generate_code_dir ):
+ self.__already_exposed_modules.append( other_module_generate_code_dir )
+
def run_query_optimizer(self):
"""
It is possible to optimze time that takes to execute queries. In most cases
@@ -250,7 +255,8 @@
, types_db
, target_configuration
, enable_indexing_suite
- , doc_extractor)
+ , doc_extractor
+ , self.__already_exposed_modules)
self.__code_creator = creator.create()
self.__code_creator.replace_included_headers(self.__parsed_files)
#I think I should ask users, what they expect
Modified: pyplusplus_dev/pyplusplus/module_creator/creator.py
===================================================================
--- pyplusplus_dev/pyplusplus/module_creator/creator.py 2007-08-18 05:54:28 UTC (rev 1110)
+++ pyplusplus_dev/pyplusplus/module_creator/creator.py 2007-08-19 19:42:34 UTC (rev 1111)
@@ -52,7 +52,8 @@
, types_db=None
, target_configuration=None
, enable_indexing_suite=True
- , doc_extractor=None):
+ , doc_extractor=None
+ , already_exposed_dbs=None):
"""Constructor.
@param decls: Declarations that should be exposed in the final module.
@@ -62,6 +63,7 @@
@param types_db: ...todo...
@param target_configuration: A target configuration object can be used to customize the generated source code to a particular compiler or a particular version of Boost.Python.
@param doc_extractor: callable, that takes as argument declaration reference and returns documentation string
+ @param already_exposed_dbs: list of files/directories other modules, this module depends on, generated their code too
@type decls: list of declaration_t
@type module_name: str
@type boost_python_ns_name: str
@@ -69,6 +71,7 @@
@type types_db: L{types_database_t<types_database.types_database_t>}
@type target_configuration: L{target_configuration_t<code_creators.target_configuration_t>}
@type doc_extractor: callable
+ @type already_exposed_dbs: list of strings
"""
declarations.decl_visitor_t.__init__(self)
self.logger = _logging_.loggers.module_builder
@@ -95,8 +98,12 @@
self.__extmodule.adopt_creator( bp_ns_alias )
self.__module_body = code_creators.module_body_t( name=module_name )
+
self.__extmodule.adopt_creator( self.__module_body )
-
+
+ self.__opaque_types_manager = opaque_types_manager.manager_t( self.__extmodule )
+ self.__dependencies_manager = dependencies_manager.manager_t(self.decl_logger, already_exposed_dbs)
+
prepared_decls = self._prepare_decls( decls, doc_extractor )
self.__decls = sort_algorithms.sort( prepared_decls )
@@ -105,19 +112,43 @@
self.__array_1_registered = set() #(type.decl_string,size)
self.__free_operators = []
self.__exposed_free_fun_overloads = set()
- self.__opaque_types_manager = opaque_types_manager.manager_t( self.__extmodule )
- self.__dependencies_manager = dependencies_manager.manager_t(self.decl_logger)
+
+
+ def __print_readme( self, decl ):
+ readme = decl.readme()
+ if not readme:
+ return
+ if not decl.exportable:
+ reason = readme[0]
+ readme = readme[1:]
+ self.decl_logger.warn( "%s;%s" % ( decl, reason ) )
+
+ for msg in readme:
+ self.decl_logger.warn( "%s;%s" % ( decl, msg ) )
+
def _prepare_decls( self, decls, doc_extractor ):
- decls = declarations.make_flatten( decls )
-
- for decl in decls:
+ to_be_exposed = []
+ for decl in declarations.make_flatten( decls ):
if decl.ignore:
continue
+
+ if isinstance( decl, declarations.namespace_t ):
+ continue
- if decl.already_exposed:
+ if not decl.exportable:
+ #leave only decls that user wants to export and that could be exported
+ self.__print_readme( decl )
continue
+ if self.__dependencies_manager.is_already_exposed( decl ):
+ #check wether this is already exposed in other module
+ continue
+
+ if isinstance( decl.parent, declarations.namespace_t ):
+ #leave only declarations defined under namespace, but remove namespaces
+ to_be_exposed.append( decl )
+
#Right now this functionality introduce a bug: declarations that should
#not be exported for some reason are not marked as such. I will need to
#find out.
@@ -128,30 +159,14 @@
#if isinstance( decl, declarations.variable_t ):
#self.__types_db.update( decl )
- if doc_extractor and decl.exportable:
+
+ if doc_extractor:
decl.documentation = doc_extractor( decl )
- readme = decl.readme()
- if not readme:
- continue
+ self.__print_readme( decl )
- if not decl.exportable:
- reason = readme[0]
- readme = readme[1:]
- self.decl_logger.warn( "%s;%s" % ( decl, reason ) )
+ return to_be_exposed
- for msg in readme:
- self.decl_logger.warn( "%s;%s" % ( decl, msg ) )
-
- #leave only declarations defined under namespace, but remove namespaces
- decls = filter( lambda x: not isinstance( x, declarations.namespace_t ) \
- and isinstance( x.parent, declarations.namespace_t )
- , decls )
- #leave only decls that user wants to export and that could be exported
- decls = filter( lambda x: x.ignore == False and x.exportable == True, decls )
-
- return decls
-
def _adopt_free_operator( self, operator ):
def adopt_operator_impl( operator, found_creators ):
creator = filter( lambda creator: isinstance( creator, code_creators.class_t )
Modified: pyplusplus_dev/pyplusplus/module_creator/dependencies_manager.py
===================================================================
--- pyplusplus_dev/pyplusplus/module_creator/dependencies_manager.py 2007-08-18 05:54:28 UTC (rev 1110)
+++ pyplusplus_dev/pyplusplus/module_creator/dependencies_manager.py 2007-08-19 19:42:34 UTC (rev 1111)
@@ -6,19 +6,27 @@
"""defines class, which informs user about used, but unexposed declarations"""
import os
+from pyplusplus import utils
from pyplusplus import messages
from pygccxml import declarations
from pyplusplus import decl_wrappers
+
class manager_t( object ):
- def __init__( self, logger ):
+ def __init__( self, logger, already_exposed=None ):
object.__init__( self )
self.__exported_decls = []
self.__logger = logger
-
+ self.__already_exposed_db = utils.exposed_decls_db_t()
+ if already_exposed:
+ map( self.__already_exposed_db.load, already_exposed )
+
def add_exported( self, decl ):
self.__exported_decls.append( decl )
+ def is_already_exposed( self, decl ):
+ return decl.already_exposed or self.__already_exposed_db.is_exposed( decl )
+
def __select_duplicate_aliases( self, decls ):
duplicated = {}
for decl in decls:
@@ -71,7 +79,7 @@
if self.__is_std_decl( decl ):
#TODO add element_type to the list of dependencies
return [] #std declarations should be exported by Py++!
- if decl.already_exposed:
+ if self.is_already_exposed( decl ):
return []
dependencies = decl.i_depend_on_them(recursive=False)
if isinstance( decl, declarations.class_t ):
Modified: pyplusplus_dev/pyplusplus/utils/__init__.py
===================================================================
--- pyplusplus_dev/pyplusplus/utils/__init__.py 2007-08-18 05:54:28 UTC (rev 1110)
+++ pyplusplus_dev/pyplusplus/utils/__init__.py 2007-08-19 19:42:34 UTC (rev 1111)
@@ -54,6 +54,7 @@
class exposed_decls_db_t( object ):
+ DEFAULT_FILE_NAME = 'exposed_decl.pypp.txt'
class row_creator_t( declarations.decl_visitor_t ):
def __init__( self, field_delimiter ):
self.__decl = None
@@ -64,8 +65,6 @@
return declarations.full_name( self.__decl )
def __call__( self, decl ):
- if not isinstance( decl.parent, declarations.namespace_t ):
- return None #we don't want to dump class internal declarations
self.__decl = decl
self.__formatted = None
try:
@@ -91,32 +90,15 @@
def visit_variable(self ):
self.__formatted = self.get_full_name()
- def __init__( self, activated=False ):
- self.__activated = activated
+ def __init__( self ):
self.__exposed = {}
self.__row_creator = self.row_creator_t(field_delimiter='@')
self.__key_delimiter = '?'
self.__row_delimiter = os.linesep
- def __create_key( self, decl ):
- return decl.__class__.__name__
-
- @property
- def activated( self ):
- return self.__activated
-
- def expose( self, decl ):
- if not self.__activated:
- return None
- row = self.__row_creator( decl )
- if row is None:
- return None
- key = self.__create_key( decl )
- if not self.__exposed.has_key( key ):
- self.__exposed[ key ] = set()
- self.__exposed[ key ].add( row )
-
def save( self, fpath ):
+ if os.path.isdir( fpath ):
+ fpath = os.path.join( fpath, self.DEFAULT_FILE_NAME )
f = file( fpath, 'w+b' )
for key, items in self.__exposed.iteritems():
for item in items:
@@ -124,18 +106,43 @@
f.close()
def load( self, fpath ):
- self.__exposed = {}
+ if os.path.isdir( fpath ):
+ fpath = os.path.join( fpath, self.DEFAULT_FILE_NAME )
f = file( fpath, 'r+b' )
for line in f:
key, row = line.split( self.__key_delimiter)
+ row = row.replace( self.__row_delimiter, '' )
if not self.__exposed.has_key( key ):
self.__exposed[ key ] = set()
- self.__exposed[ key ].add( row[:len(self.__row_delimiter)] )
+ self.__exposed[ key ].add( row )
- def is_exposed( self, decl ):
- assert self.activated
+ def __create_key( self, decl ):
+ return decl.__class__.__name__
+
+ def expose( self, decl ):
+ if not isinstance( decl.parent, declarations.namespace_t ):
+ return None #we don't want to dump class internal declarations
+ row = self.__row_creator( decl )
+ if row is None:
+ return None
key = self.__create_key( decl )
if not self.__exposed.has_key( key ):
+ self.__exposed[ key ] = set()
+ self.__exposed[ key ].add( row )
+
+ def __get_under_ns_decl( self, decl ):
+ while True:
+ if isinstance( decl.parent, declarations.namespace_t ):
+ return decl
+ else:
+ decl = decl.parent
+
+ def is_exposed( self, decl_ ):
+ if isinstance( decl_, declarations.namespace_t ):
+ return False#namespaces are always exposed
+ decl = self.__get_under_ns_decl( decl_ )
+ key = self.__create_key( decl )
+ if not self.__exposed.has_key( key ):
return False
row = self.__row_creator( decl )
return row in self.__exposed[ key ]
Added: pyplusplus_dev/unittests/already_exposed_tester.py
===================================================================
--- pyplusplus_dev/unittests/already_exposed_tester.py (rev 0)
+++ pyplusplus_dev/unittests/already_exposed_tester.py 2007-08-19 19:42:34 UTC (rev 1111)
@@ -0,0 +1,43 @@
+# Copyright 2004 Roman Yakovenko.
+# Distributed under the Boost Software License, Version 1.0. (See
+# accompanying file LICENSE_1_0.txt or copy at
+# http://www.boost.org/LICENSE_1_0.txt)
+
+import os
+import sys
+import unittest
+import autoconfig
+from pyplusplus import utils
+import fundamental_tester_base
+
+class tester_t(fundamental_tester_base.fundamental_tester_base_t):
+ EXTENSION_NAME = 'already_exposed'
+
+ def __init__( self, *args ):
+ fundamental_tester_base.fundamental_tester_base_t.__init__(
+ self
+ , tester_t.EXTENSION_NAME
+ , *args )
+
+ def customize(self, mb ):
+ exposed_db = utils.exposed_decls_db_t()
+ map( exposed_db.expose, mb.decls(recursive=True) )
+ exposed_db.save( autoconfig.build_dir )
+ mb.register_module_dependency( autoconfig.build_dir )
+ mb.decls().exclude()
+ mb.namespace( 'already_exposed' ).include()
+
+ def run_tests(self, module):
+ self.failUnless( 'ae_t' not in dir( module ) )
+ self.failUnless( 'ae_e' not in dir( module ) )
+
+def create_suite():
+ suite = unittest.TestSuite()
+ suite.addTest( unittest.makeSuite(tester_t))
+ return suite
+
+def run_suite():
+ unittest.TextTestRunner(verbosity=2).run( create_suite() )
+
+if __name__ == "__main__":
+ run_suite()
Added: pyplusplus_dev/unittests/data/already_exposed_to_be_exported.hpp
===================================================================
--- pyplusplus_dev/unittests/data/already_exposed_to_be_exported.hpp (rev 0)
+++ pyplusplus_dev/unittests/data/already_exposed_to_be_exported.hpp 2007-08-19 19:42:34 UTC (rev 1111)
@@ -0,0 +1,17 @@
+// Copyright 2004 Roman Yakovenko.
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef __already_exposed_to_be_exported_hpp__
+#define __already_exposed_to_be_exported_hpp__
+
+namespace already_exposed{
+
+struct ae_t{};
+
+enum ae_e { x1, x2 };
+
+}
+
+#endif//__already_exposed_to_be_exported_hpp__
Modified: pyplusplus_dev/unittests/exposed_decls_db_tester.py
===================================================================
--- pyplusplus_dev/unittests/exposed_decls_db_tester.py 2007-08-18 05:54:28 UTC (rev 1110)
+++ pyplusplus_dev/unittests/exposed_decls_db_tester.py 2007-08-19 19:42:34 UTC (rev 1111)
@@ -28,32 +28,45 @@
int VVV;
void FFF( int );
}
+ namespace ns_skip{
+ enum a123{ a1=1 };
+ struct b123{
+ struct c123{};
+ };
+ int fff();
+ int i;
+ }
"""
def __init__(self, *args ):
unittest.TestCase.__init__(self, *args)
def test(self):
- db = pypp_utils.exposed_decls_db_t(activated=True)
+ db = pypp_utils.exposed_decls_db_t()
config = parser.config_t( gccxml_path=autoconfig.gccxml.executable )
global_ns = declarations.get_global_namespace( parser.parse_string( self.CODE, config ) )
ns = global_ns.namespace( 'ns' )
for d in ns.decls(recursive=True):
db.expose( d )
-
- select_exposed = lambda decl: decl.name == decl.name.upper() \
- and not isinstance( decl, declarations.member_calldef_t )
-
- for x in ns.decls( select_exposed ):
+
+ for x in ns.decls(recursive=True):
self.failUnless( db.is_exposed( x ) == True )
-
+
+ ns_skip = global_ns.namespace( 'ns_skip' )
+ for x in ns_skip.decls(recursive=True):
+ self.failUnless( db.is_exposed( x ) == False )
+
db.save( os.path.join( autoconfig.build_dir, 'exposed.db.pypp' ) )
-
- db2 = pypp_utils.exposed_decls_db_t(activated=True)
+
+ db2 = pypp_utils.exposed_decls_db_t()
db2.load( os.path.join( autoconfig.build_dir, 'exposed.db.pypp' ) )
- for x in ns.decls( select_exposed ):
+ for x in ns.decls(recursive=True):
self.failUnless( db.is_exposed( x ) == True )
-
+ ns_skip = global_ns.namespace( 'ns_skip' )
+ for x in ns_skip.decls(recursive=True):
+ self.failUnless( db.is_exposed( x ) == False )
+
+
def create_suite():
suite = unittest.TestSuite()
suite.addTest( unittest.makeSuite(tester_t))
Modified: pyplusplus_dev/unittests/test_all.py
===================================================================
--- pyplusplus_dev/unittests/test_all.py 2007-08-18 05:54:28 UTC (rev 1110)
+++ pyplusplus_dev/unittests/test_all.py 2007-08-19 19:42:34 UTC (rev 1111)
@@ -72,6 +72,7 @@
import duplicate_aliases_tester
import non_overridable_tester
import exposed_decls_db_tester
+import already_exposed_tester
def create_suite(times):
testers = [
@@ -140,6 +141,7 @@
, duplicate_aliases_tester
, non_overridable_tester
, exposed_decls_db_tester
+ , already_exposed_tester
]
main_suite = unittest.TestSuite()
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|