[pygccxml-commit] SF.net SVN: pygccxml:[1713] pyplusplus_dev
Brought to you by:
mbaas,
roman_yakovenko
|
From: <rom...@us...> - 2009-05-11 07:44:56
|
Revision: 1713
http://pygccxml.svn.sourceforge.net/pygccxml/?rev=1713&view=rev
Author: roman_yakovenko
Date: 2009-05-11 07:44:51 +0000 (Mon, 11 May 2009)
Log Message:
-----------
update docs
Modified Paths:
--------------
pygccxml_dev/pygccxml/declarations/matchers.py
pyplusplus_dev/pyplusplus/function_transformers/function_transformation.py
pyplusplus_dev/pyplusplus/module_builder/boost_python_builder.py
pyplusplus_dev/pyplusplus/module_builder/ctypes_builder.py
pyplusplus_dev/unittests/ctypes_tester.py
pyplusplus_dev/unittests/custom_smart_ptr_classes_tester.py
pyplusplus_dev/unittests/test_all.py
pyplusplus_dev/unittests/virtual_inheritance_tester.py
Modified: pygccxml_dev/pygccxml/declarations/matchers.py
===================================================================
--- pygccxml_dev/pygccxml/declarations/matchers.py 2009-05-11 07:27:29 UTC (rev 1712)
+++ pygccxml_dev/pygccxml/declarations/matchers.py 2009-05-11 07:44:51 UTC (rev 1713)
@@ -1,542 +1,545 @@
-# Copyright 2004-2008 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)
-
-"""
-defines all "built-in" classes that implement declarations compare functionality
-according to some criteria
-"""
-
-import os
-import re
-import types
-import algorithm
-import variable
-import namespace
-import calldef
-import cpptypes
-import templates
-import class_declaration
-from pygccxml import utils
-
-class matcher_base_t(object):
- """matcher_base_t class defines interface for classes that will implement
- compare functionality according to some criteria.
- """
- def __init__( self ):
- object.__init__( self )
-
- def __call__(self, decl):
- raise NotImplementedError( "matcher must always implement the __call__() method." )
-
- def __invert__(self):
- """not-operator (~)"""
- return not_matcher_t(self)
-
- def __and__(self, other):
- """and-operator (&)"""
- return and_matcher_t([self, other])
-
- def __or__(self, other):
- """or-operator (|)"""
- return or_matcher_t([self, other])
-
- def __str__( self ):
- return "base class for all matchers"
-
-class and_matcher_t(matcher_base_t):
- """
- Combine several other matchers with "&" (and) operator.
-
- For example: find all private functions with name XXX
-
- .. code-block:: python
-
- matcher = access_type_matcher_t( 'private' ) & calldef_matcher_t( name='XXX' )
- """
- def __init__(self, matchers):
- matcher_base_t.__init__(self)
- self.matchers = matchers
-
- def __call__(self, decl):
- for matcher in self.matchers:
- if not matcher(decl):
- return False
- return True
-
- def __str__(self):
- return " & ".join( map( lambda x: "(%s)" % str( x ), self.matchers ) )
-
-
-class or_matcher_t(matcher_base_t):
- """Combine several other matchers with "|" (or) operator.
-
- For example: find all functions and variables with name 'XXX'
-
- .. code-block:: python
-
- matcher = variable_matcher_t( name='XXX' ) | calldef_matcher_t( name='XXX' )
-
- """
- def __init__(self, matchers):
- matcher_base_t.__init__(self)
- self.matchers = matchers
-
- def __call__(self, decl):
- for matcher in self.matchers:
- if matcher(decl):
- return True
- return False
-
- def __str__(self):
- return " | ".join( map( lambda x: "(%s)" % str( x ), self.matchers ) )
-
-
-class not_matcher_t(matcher_base_t):
- """
- return the inverse result of a matcher
-
- For example: find all public and protected declarations
-
- .. code-block:: python
-
- matcher = ~access_type_matcher_t( 'private' )
- """
- def __init__(self, matcher):
- matcher_base_t.__init__(self)
- self.matcher = matcher
-
- def __call__(self, decl):
- return not self.matcher(decl)
-
- def __str__(self):
- return "~(%s)"%str(self.matcher)
-
-class declaration_matcher_t( matcher_base_t ):
- """
- Instance of this class will match declarations by next criteria:
- - declaration name, also could be fully qualified name
- Example: `wstring` or `::std::wstring`
- - declaration type
- Example: :class:`class_t`, :class:`namespace_t`, :class:`enumeration_t`
- - location within file system ( file or directory )
- """
- def __init__( self, name=None, decl_type=None, header_dir=None, header_file=None ):
- """
- :param decl_type: declaration type to match by. For example :class:`enumeration_t`.
- :type decl_type: any class that derives from :class:`declaration_t` class
-
- :param name: declaration name, could be full name.
- :type name: str
-
- :param header_dir: absolute directory path
- :type header_dir: str
-
- :param header_file: absolute file path
- :type header_file: str
-
- """
- #An other option is that pygccxml will create absolute path using
- #os.path.abspath function. But I think this is just wrong, because abspath
- #builds path using current working directory. This behavior is fragile
- #and very difficult to find a bug.
- matcher_base_t.__init__( self )
- self.decl_type = decl_type
- self.__name = None
- self.__opt_is_tmpl_inst = None
- self.__opt_tmpl_name = None
- self.__opt_is_full_name = None
- self.__decl_name_only = None
-
- self._set_name( name )
-
- self.header_dir = header_dir
- self.header_file = header_file
-
- if self.header_dir:
- self.header_dir = utils.normalize_path( self.header_dir )
- if not os.path.isabs( self.header_dir ):
- raise RuntimeError( "Path to header directory should be absolute!" )
-
- if self.header_file:
- self.header_file = utils.normalize_path( self.header_file )
- if not os.path.isabs( self.header_file ):
- raise RuntimeError( "Path to header file should be absolute!" )
-
- def _get_name(self):
- return self.__name
-
- def _set_name( self, name ):
- self.__name = name
- if not self.__name:
- self.__opt_is_tmpl_inst = None
- self.__opt_tmpl_name = None
- self.__opt_is_full_name = None
- self.__decl_name_only = None
- else:
- self.__opt_is_tmpl_inst = templates.is_instantiation( self.__name )
- self.__opt_tmpl_name = templates.name( self.__name )
- if self.__opt_is_tmpl_inst:
- if '::' in self.__opt_tmpl_name:
- self.__opt_is_full_name = True
- self.__decl_name_only = self.__opt_tmpl_name.split('::')[-1]
- else:
- self.__opt_is_full_name = False
- self.__decl_name_only = self.__opt_tmpl_name
- self.__name = templates.normalize( name )
- else:
- if '::' in self.__name:
- self.__opt_is_full_name = True
- self.__decl_name_only = self.__name.split('::')[-1]
- else:
- self.__opt_is_full_name = False
- self.__decl_name_only = self.__name
-
-
- name = property( _get_name, _set_name )
-
- def __str__( self ):
- msg = []
- if not None is self.decl_type:
- msg.append( '(decl type==%s)' % self.decl_type.__name__ )
- if not None is self.name:
- msg.append( '(name==%s)' % self.name )
- if not None is self.header_dir:
- msg.append( '(header dir==%s)' % self.header_dir )
- if not None is self.header_file:
- msg.append( '(header file==%s)' % self.header_file )
- if not msg:
- msg.append( 'any' )
- return ' and '.join( msg )
-
- def __call__( self, decl ):
- if not None is self.decl_type:
- if not isinstance( decl, self.decl_type ):
- return False
- if not None is self.name:
- if not self.check_name( decl ):
- return False
- if not None is self.header_dir:
- if decl.location:
- decl_dir = os.path.abspath( os.path.dirname( decl.location.file_name ) )
- decl_dir = utils.normalize_path( decl_dir )
- if decl_dir[:len(self.header_dir)] != self.header_dir:
- return False
- else:
- return False
- if not None is self.header_file:
- if decl.location:
- decl_file = os.path.abspath( decl.location.file_name )
- decl_file = utils.normalize_path( decl_file )
- if decl_file != self.header_file:
- return False
- else:
- return False
- return True
-
- def check_name( self, decl ):
- assert not None is self.name
- if self.__opt_is_tmpl_inst:
- if not self.__opt_is_full_name:
- if self.name != templates.normalize( decl.name ) \
- and self.name != templates.normalize( decl.partial_name ):
- return False
- else:
- if self.name != templates.normalize( algorithm.full_name( decl, with_defaults=True ) ) \
- and self.name != templates.normalize( algorithm.full_name( decl, with_defaults=False ) ):
- return False
- else:
- if not self.__opt_is_full_name:
- if self.name != decl.name and self.name != decl.partial_name:
- return False
- else:
- if self.name != algorithm.full_name( decl, with_defaults=True ) \
- and self.name != algorithm.full_name( decl, with_defaults=False ):
- return False
- return True
-
- def is_full_name(self):
- return self.__opt_is_full_name
-
- def _get_decl_name_only(self):
- return self.__decl_name_only
- decl_name_only = property( _get_decl_name_only )
-
-class variable_matcher_t( declaration_matcher_t ):
- """
- Instance of this class will match variables by next criteria:
- - :class:`declaration_matcher_t` criteria
- - variable type. Example: :class:`int_t` or 'int'
- """
- def __init__( self, name=None, type=None, header_dir=None, header_file=None ):
- """
- :param type: variable type
- :type type: string or instance of :class:`type_t` derived class
- """
- declaration_matcher_t.__init__( self
- , name=name
- , decl_type=variable.variable_t
- , header_dir=header_dir
- , header_file=header_file )
- self.type = type
-
- def __call__( self, decl ):
- if not super( variable_matcher_t, self ).__call__( decl ):
- return False
- if not None is self.type:
- if isinstance( self.type, cpptypes.type_t ):
- if self.type != decl.type:
- return False
- else:
- if self.type != decl.type.decl_string:
- return False
- return True
-
- def __str__( self ):
- msg = [ super( variable_matcher_t, self ).__str__() ]
- if msg == [ 'any' ]:
- msg = []
- if not None is self.type:
- msg.append( '(value type==%s)' % str(self.type) )
- if not msg:
- msg.append( 'any' )
- return ' and '.join( msg )
-
-
-class namespace_matcher_t( declaration_matcher_t ):
- """Instance of this class will match namespaces by name."""
-
- def __init__( self, name=None ):
- declaration_matcher_t.__init__( self, name=name, decl_type=namespace.namespace_t)
-
- def __call__( self, decl ):
- if self.name and decl.name == '':
- #unnamed namespace have same name as thier parent, we should prevent
- #this happens. The price is: user should search for unnamed namespace
- #directly.
- return False
- return super( namespace_matcher_t, self ).__call__( decl )
-
-
-class calldef_matcher_t( declaration_matcher_t ):
- """
- Instance of this class will match callable by the following criteria:
- * :class:`declaration_matcher_t` criteria
- * return type. For example: :class:`int_t` or 'int'
- * argument types
- """
-
- def __init__( self, name=None, return_type=None, arg_types=None, decl_type=None, header_dir=None, header_file=None):
- """
- :param return_type: callable return type
- :type return_type: string or instance of :class:`type_t` derived class
-
- :param arg_types: list of function argument types. `arg_types` can contain.
- Any item within the list could be string or instance of :class:`type_t` derived
- class. If you don't want some argument to participate in match you can
- put None. For example:
-
- .. code-block:: python
-
- calldef_matcher_t( arg_types=[ 'int &', None ] )
-
- will match all functions that takes 2 arguments, where the first one is
- reference to integer and second any
-
- :type arg_types: list
- """
- if None is decl_type:
- decl_type = calldef.calldef_t
- declaration_matcher_t.__init__( self
- , name=name
- , decl_type=decl_type
- , header_dir=header_dir
- , header_file=header_file )
-
- self.return_type = return_type
- self.arg_types = arg_types
-
- def __call__( self, decl ):
- if not super( calldef_matcher_t, self ).__call__( decl ):
- return False
- if not None is self.return_type \
- and not self.__compare_types( self.return_type, decl.return_type ):
- return False
- if self.arg_types:
- if isinstance( self.arg_types, (types.ListType, types.TupleType)):
- if len(self.arg_types) != len( decl.arguments ):
- return False
- for type_or_str, arg in zip( self.arg_types, decl.arguments ):
- if None == type_or_str:
- continue
- else:
- if not self.__compare_types( type_or_str, arg.type ):
- return False
- return True
-
- def __compare_types( self, type_or_str, type ):
- assert type_or_str
- if type is None:
- return False
- if isinstance( type_or_str, cpptypes.type_t ):
- if type_or_str != type:
- return False
- else:
- if type_or_str != type.decl_string:
- return False
- return True
-
- def __str__( self ):
- msg = [ super( calldef_matcher_t, self ).__str__() ]
- if msg == [ 'any' ]:
- msg = []
- if not None is self.return_type:
- msg.append( '(return type==%s)' % str(self.return_type) )
- if self.arg_types:
- for i in range( len( self.arg_types ) ):
- if self.arg_types[i] is None:
- msg.append( '(arg %d type==any)' % i )
- else:
- msg.append( '(arg %d type==%s)' % ( i, str( self.arg_types[i] ) ) )
- if not msg:
- msg.append( 'any' )
- return ' and '.join( msg )
-
-
-class operator_matcher_t( calldef_matcher_t ):
- """
- Instance of this class will match operators by next criteria:
- * :class:`calldef_matcher_t` criteria
- * operator symbol: =, !=, (), [] and etc
- """
- def __init__( self, name=None, symbol=None, return_type=None, arg_types=None, decl_type=None, header_dir=None, header_file=None):
- """
- :param symbol: operator symbol
- :type symbol: str
- """
- if None is decl_type:
- decl_type = calldef.operator_t
- calldef_matcher_t.__init__( self
- , name=name
- , return_type=return_type
- , arg_types=arg_types
- , decl_type=decl_type
- , header_dir=header_dir
- , header_file=header_file)
- self.symbol = symbol
-
- def __call__( self, decl ):
- if not super( operator_matcher_t, self ).__call__( decl ):
- return False
- if not None is self.symbol:
- if self.symbol != decl.symbol:
- return False
- return True
-
- def __str__( self ):
- msg = [ super( operator_matcher_t, self ).__str__() ]
- if msg == [ 'any' ]:
- msg = []
- if not None is self.symbol:
- msg.append( '(symbol==%s)' % str(self.symbol) )
- if not msg:
- msg.append( 'any' )
- return ' and '.join( msg )
-
-class regex_matcher_t( matcher_base_t ):
- """
- Instance of this class will match declaration using regular expression.
- User should supply a function that will extract from declaration desired
- information as string. Later, this matcher will match that string using
- user regular expression.
- """
- def __init__( self, regex, function=None ):
- """
- :param regex: regular expression
- :type regex: string, an instance of this class will compile it for you
-
- :param function: function that will be called to get an information from
- declaration as string. As input this function takes 1 argument: reference
- to declaration. Return value should be string. If function is None, then
- the matcher will use declaration name.
-
- """
- matcher_base_t.__init__(self)
- self.regex = re.compile( regex )
- self.function = function
- if None is self.function:
- self.function = lambda decl: decl.name
-
- def __call__( self, decl ):
- text = self.function( decl )
- return bool( self.regex.match( text ) )
-
- def __str__( self ):
- return '(regex=%s)' % self.regex
-
-class access_type_matcher_t( matcher_base_t ):
- """
- Instance of this class will match declaration by its access type: public,
- private or protected. If declarations does not have access type, for example
- free function, then `False` will be returned.
- """
-
- def __init__( self, access_type ):
- """
- :param access_type: declaration access type, could be "public", "private", "protected"
- :type access_type: :class: `str`
- """
- matcher_base_t.__init__( self )
- self.access_type = access_type
-
- def __call__( self, decl ):
- if not isinstance( decl.parent, class_declaration.class_t ):
- return False
- return self.access_type == decl.parent.find_out_member_access_type( decl )
-
- def __str__( self ):
- return '(access type=%s)' % self.access_type
-
-class virtuality_type_matcher_t( matcher_base_t ):
- """
- Instance of this class will match declaration by its virtual type: not virtual,
- virtual or pure virtual. If declarations does not have "virtual" property,
- for example free function, then `False` will be returned.
- """
-
- def __init__( self, virtuality_type ):
- """
- :param access_type: declaration access type
- :type access_type: :class:VIRTUALITY_TYPES defines few constants for your convenience.
- """
- matcher_base_t.__init__( self )
- self.virtuality_type = virtuality_type
-
- def __call__( self, decl ):
- if not isinstance( decl.parent, class_declaration.class_t ):
- return False
- return self.virtuality_type == decl.virtuality
-
- def __str__( self ):
- return '(virtuality type=%s)' % self.virtuality_type
-
-
-class custom_matcher_t( matcher_base_t ):
- """
- Instance of this class will match declaration by user custom criteria.
- """
-
- def __init__( self, function ):
- """
- :param function: callable, that takes single argument - declaration instance
- should return True or False
- """
- matcher_base_t.__init__( self )
- self.function = function
-
- def __call__( self, decl ):
- return bool( self.function( decl ) )
-
- def __str__( self ):
- return '(user criteria)'
+# Copyright 2004-2008 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)
+
+"""
+defines all "built-in" classes that implement declarations compare functionality
+according to some criteria
+"""
+
+import os
+import re
+import types
+import algorithm
+import variable
+import namespace
+import calldef
+import cpptypes
+import templates
+import class_declaration
+from pygccxml import utils
+
+class matcher_base_t(object):
+ """matcher_base_t class defines interface for classes that will implement
+ compare functionality according to some criteria.
+ """
+ def __init__( self ):
+ object.__init__( self )
+
+ def __call__(self, decl):
+ raise NotImplementedError( "matcher must always implement the __call__() method." )
+
+ def __invert__(self):
+ """not-operator (~)"""
+ return not_matcher_t(self)
+
+ def __and__(self, other):
+ """and-operator (&)"""
+ return and_matcher_t([self, other])
+
+ def __or__(self, other):
+ """or-operator (|)"""
+ return or_matcher_t([self, other])
+
+ def __str__( self ):
+ return "base class for all matchers"
+
+class and_matcher_t(matcher_base_t):
+ """
+ Combine several other matchers with "&" (and) operator.
+
+ For example: find all private functions with name XXX
+
+ .. code-block:: python
+
+ matcher = access_type_matcher_t( 'private' ) & calldef_matcher_t( name='XXX' )
+ """
+ def __init__(self, matchers):
+ matcher_base_t.__init__(self)
+ self.matchers = matchers
+
+ def __call__(self, decl):
+ for matcher in self.matchers:
+ if not matcher(decl):
+ return False
+ return True
+
+ def __str__(self):
+ return " & ".join( map( lambda x: "(%s)" % str( x ), self.matchers ) )
+
+
+class or_matcher_t(matcher_base_t):
+ """Combine several other matchers with "|" (or) operator.
+
+ For example: find all functions and variables with name 'XXX'
+
+ .. code-block:: python
+
+ matcher = variable_matcher_t( name='XXX' ) | calldef_matcher_t( name='XXX' )
+
+ """
+ def __init__(self, matchers):
+ matcher_base_t.__init__(self)
+ self.matchers = matchers
+
+ def __call__(self, decl):
+ for matcher in self.matchers:
+ if matcher(decl):
+ return True
+ return False
+
+ def __str__(self):
+ return " | ".join( map( lambda x: "(%s)" % str( x ), self.matchers ) )
+
+
+class not_matcher_t(matcher_base_t):
+ """
+ return the inverse result of a matcher
+
+ For example: find all public and protected declarations
+
+ .. code-block:: python
+
+ matcher = ~access_type_matcher_t( 'private' )
+ """
+ def __init__(self, matcher):
+ matcher_base_t.__init__(self)
+ self.matcher = matcher
+
+ def __call__(self, decl):
+ return not self.matcher(decl)
+
+ def __str__(self):
+ return "~(%s)"%str(self.matcher)
+
+class declaration_matcher_t( matcher_base_t ):
+ """
+ Instance of this class will match declarations by next criteria:
+ - declaration name, also could be fully qualified name
+ Example: `wstring` or `::std::wstring`
+ - declaration type
+ Example: :class:`class_t`, :class:`namespace_t`, :class:`enumeration_t`
+ - location within file system ( file or directory )
+ """
+ def __init__( self, name=None, decl_type=None, header_dir=None, header_file=None ):
+ """
+ :param decl_type: declaration type to match by. For example :class:`enumeration_t`.
+ :type decl_type: any class that derives from :class:`declaration_t` class
+
+ :param name: declaration name, could be full name.
+ :type name: str
+
+ :param header_dir: absolute directory path
+ :type header_dir: str
+
+ :param header_file: absolute file path
+ :type header_file: str
+
+ """
+ #An other option is that pygccxml will create absolute path using
+ #os.path.abspath function. But I think this is just wrong, because abspath
+ #builds path using current working directory. This behavior is fragile
+ #and very difficult to find a bug.
+ matcher_base_t.__init__( self )
+ self.decl_type = decl_type
+ self.__name = None
+ self.__opt_is_tmpl_inst = None
+ self.__opt_tmpl_name = None
+ self.__opt_is_full_name = None
+ self.__decl_name_only = None
+
+ self._set_name( name )
+
+ self.header_dir = header_dir
+ self.header_file = header_file
+
+ if self.header_dir:
+ self.header_dir = utils.normalize_path( self.header_dir )
+ if not os.path.isabs( self.header_dir ):
+ raise RuntimeError( "Path to header directory should be absolute!" )
+
+ if self.header_file:
+ self.header_file = utils.normalize_path( self.header_file )
+ if not os.path.isabs( self.header_file ):
+ raise RuntimeError( "Path to header file should be absolute!" )
+
+ def _get_name(self):
+ return self.__name
+
+ def _set_name( self, name ):
+ self.__name = name
+ if not self.__name:
+ self.__opt_is_tmpl_inst = None
+ self.__opt_tmpl_name = None
+ self.__opt_is_full_name = None
+ self.__decl_name_only = None
+ else:
+ self.__opt_is_tmpl_inst = templates.is_instantiation( self.__name )
+ self.__opt_tmpl_name = templates.name( self.__name )
+ if self.__opt_is_tmpl_inst:
+ if '::' in self.__opt_tmpl_name:
+ self.__opt_is_full_name = True
+ self.__decl_name_only = self.__opt_tmpl_name.split('::')[-1]
+ else:
+ self.__opt_is_full_name = False
+ self.__decl_name_only = self.__opt_tmpl_name
+ self.__name = templates.normalize( name )
+ else:
+ if '::' in self.__name:
+ self.__opt_is_full_name = True
+ self.__decl_name_only = self.__name.split('::')[-1]
+ else:
+ self.__opt_is_full_name = False
+ self.__decl_name_only = self.__name
+
+
+ name = property( _get_name, _set_name )
+
+ def __str__( self ):
+ msg = []
+ if not None is self.decl_type:
+ msg.append( '(decl type==%s)' % self.decl_type.__name__ )
+ if not None is self.name:
+ msg.append( '(name==%s)' % self.name )
+ if not None is self.header_dir:
+ msg.append( '(header dir==%s)' % self.header_dir )
+ if not None is self.header_file:
+ msg.append( '(header file==%s)' % self.header_file )
+ if not msg:
+ msg.append( 'any' )
+ return ' and '.join( msg )
+
+ def __call__( self, decl ):
+ if not None is self.decl_type:
+ if not isinstance( decl, self.decl_type ):
+ return False
+ if not None is self.name:
+ if not self.check_name( decl ):
+ return False
+ if not None is self.header_dir:
+ if decl.location:
+ decl_dir = os.path.abspath( os.path.dirname( decl.location.file_name ) )
+ decl_dir = utils.normalize_path( decl_dir )
+ if decl_dir[:len(self.header_dir)] != self.header_dir:
+ return False
+ else:
+ return False
+ if not None is self.header_file:
+ if decl.location:
+ decl_file = os.path.abspath( decl.location.file_name )
+ decl_file = utils.normalize_path( decl_file )
+ if decl_file != self.header_file:
+ return False
+ else:
+ return False
+ return True
+
+ def check_name( self, decl ):
+ assert not None is self.name
+ if self.__opt_is_tmpl_inst:
+ if not self.__opt_is_full_name:
+ if self.name != templates.normalize( decl.name ) \
+ and self.name != templates.normalize( decl.partial_name ):
+ return False
+ else:
+ if self.name != templates.normalize( algorithm.full_name( decl, with_defaults=True ) ) \
+ and self.name != templates.normalize( algorithm.full_name( decl, with_defaults=False ) ):
+ return False
+ else:
+ if not self.__opt_is_full_name:
+ if self.name != decl.name and self.name != decl.partial_name:
+ return False
+ else:
+ if self.name != algorithm.full_name( decl, with_defaults=True ) \
+ and self.name != algorithm.full_name( decl, with_defaults=False ):
+ return False
+ return True
+
+ def is_full_name(self):
+ return self.__opt_is_full_name
+
+ def _get_decl_name_only(self):
+ return self.__decl_name_only
+ decl_name_only = property( _get_decl_name_only )
+
+class variable_matcher_t( declaration_matcher_t ):
+ """
+ Instance of this class will match variables by next criteria:
+ - :class:`declaration_matcher_t` criteria
+ - variable type. Example: :class:`int_t` or 'int'
+ """
+ def __init__( self, name=None, type=None, header_dir=None, header_file=None ):
+ """
+ :param type: variable type
+ :type type: string or instance of :class:`type_t` derived class
+ """
+ declaration_matcher_t.__init__( self
+ , name=name
+ , decl_type=variable.variable_t
+ , header_dir=header_dir
+ , header_file=header_file )
+ self.type = type
+
+ def __call__( self, decl ):
+ if not super( variable_matcher_t, self ).__call__( decl ):
+ return False
+ if not None is self.type:
+ if isinstance( self.type, cpptypes.type_t ):
+ if self.type != decl.type:
+ return False
+ else:
+ if self.type != decl.type.decl_string:
+ return False
+ return True
+
+ def __str__( self ):
+ msg = [ super( variable_matcher_t, self ).__str__() ]
+ if msg == [ 'any' ]:
+ msg = []
+ if not None is self.type:
+ msg.append( '(value type==%s)' % str(self.type) )
+ if not msg:
+ msg.append( 'any' )
+ return ' and '.join( msg )
+
+
+class namespace_matcher_t( declaration_matcher_t ):
+ """Instance of this class will match namespaces by name."""
+
+ def __init__( self, name=None ):
+ declaration_matcher_t.__init__( self, name=name, decl_type=namespace.namespace_t)
+
+ def __call__( self, decl ):
+ if self.name and decl.name == '':
+ #unnamed namespace have same name as thier parent, we should prevent
+ #this happens. The price is: user should search for unnamed namespace
+ #directly.
+ return False
+ return super( namespace_matcher_t, self ).__call__( decl )
+
+
+class calldef_matcher_t( declaration_matcher_t ):
+ """
+ Instance of this class will match callable by the following criteria:
+ * :class:`declaration_matcher_t` criteria
+ * return type. For example: :class:`int_t` or 'int'
+ * argument types
+
+ """
+
+ def __init__( self, name=None, return_type=None, arg_types=None, decl_type=None, header_dir=None, header_file=None):
+ """
+ :param return_type: callable return type
+ :type return_type: string or instance of :class:`type_t` derived class
+
+ :type arg_types: list
+ :param arg_types: list of function argument types. `arg_types` can contain.
+ Any item within the list could be string or instance
+ of :class:`type_t` derived class. If you don't want
+ some argument to participate in match you can put None.
+
+ For example:
+
+ .. code-block:: python
+
+ calldef_matcher_t( arg_types=[ 'int &', None ] )
+
+ will match all functions that takes 2 arguments, where the first one is
+ reference to integer and second any
+ """
+ if None is decl_type:
+ decl_type = calldef.calldef_t
+ declaration_matcher_t.__init__( self
+ , name=name
+ , decl_type=decl_type
+ , header_dir=header_dir
+ , header_file=header_file )
+
+ self.return_type = return_type
+ self.arg_types = arg_types
+
+ def __call__( self, decl ):
+ if not super( calldef_matcher_t, self ).__call__( decl ):
+ return False
+ if not None is self.return_type \
+ and not self.__compare_types( self.return_type, decl.return_type ):
+ return False
+ if self.arg_types:
+ if isinstance( self.arg_types, (types.ListType, types.TupleType)):
+ if len(self.arg_types) != len( decl.arguments ):
+ return False
+ for type_or_str, arg in zip( self.arg_types, decl.arguments ):
+ if None == type_or_str:
+ continue
+ else:
+ if not self.__compare_types( type_or_str, arg.type ):
+ return False
+ return True
+
+ def __compare_types( self, type_or_str, type ):
+ assert type_or_str
+ if type is None:
+ return False
+ if isinstance( type_or_str, cpptypes.type_t ):
+ if type_or_str != type:
+ return False
+ else:
+ if type_or_str != type.decl_string:
+ return False
+ return True
+
+ def __str__( self ):
+ msg = [ super( calldef_matcher_t, self ).__str__() ]
+ if msg == [ 'any' ]:
+ msg = []
+ if not None is self.return_type:
+ msg.append( '(return type==%s)' % str(self.return_type) )
+ if self.arg_types:
+ for i in range( len( self.arg_types ) ):
+ if self.arg_types[i] is None:
+ msg.append( '(arg %d type==any)' % i )
+ else:
+ msg.append( '(arg %d type==%s)' % ( i, str( self.arg_types[i] ) ) )
+ if not msg:
+ msg.append( 'any' )
+ return ' and '.join( msg )
+
+
+class operator_matcher_t( calldef_matcher_t ):
+ """
+ Instance of this class will match operators by next criteria:
+ * :class:`calldef_matcher_t` criteria
+ * operator symbol: =, !=, (), [] and etc
+ """
+ def __init__( self, name=None, symbol=None, return_type=None, arg_types=None, decl_type=None, header_dir=None, header_file=None):
+ """
+ :param symbol: operator symbol
+ :type symbol: str
+ """
+ if None is decl_type:
+ decl_type = calldef.operator_t
+ calldef_matcher_t.__init__( self
+ , name=name
+ , return_type=return_type
+ , arg_types=arg_types
+ , decl_type=decl_type
+ , header_dir=header_dir
+ , header_file=header_file)
+ self.symbol = symbol
+
+ def __call__( self, decl ):
+ if not super( operator_matcher_t, self ).__call__( decl ):
+ return False
+ if not None is self.symbol:
+ if self.symbol != decl.symbol:
+ return False
+ return True
+
+ def __str__( self ):
+ msg = [ super( operator_matcher_t, self ).__str__() ]
+ if msg == [ 'any' ]:
+ msg = []
+ if not None is self.symbol:
+ msg.append( '(symbol==%s)' % str(self.symbol) )
+ if not msg:
+ msg.append( 'any' )
+ return ' and '.join( msg )
+
+class regex_matcher_t( matcher_base_t ):
+ """
+ Instance of this class will match declaration using regular expression.
+ User should supply a function that will extract from declaration desired
+ information as string. Later, this matcher will match that string using
+ user regular expression.
+ """
+ def __init__( self, regex, function=None ):
+ """
+ :param regex: regular expression
+ :type regex: string, an instance of this class will compile it for you
+
+ :param function: function that will be called to get an information from
+ declaration as string. As input this function takes single
+ argument - reference to a declaration. Return value
+ should be string. If function is None, then the matcher
+ will use declaration name.
+
+ """
+ matcher_base_t.__init__(self)
+ self.regex = re.compile( regex )
+ self.function = function
+ if None is self.function:
+ self.function = lambda decl: decl.name
+
+ def __call__( self, decl ):
+ text = self.function( decl )
+ return bool( self.regex.match( text ) )
+
+ def __str__( self ):
+ return '(regex=%s)' % self.regex
+
+class access_type_matcher_t( matcher_base_t ):
+ """
+ Instance of this class will match declaration by its access type: public,
+ private or protected. If declarations does not have access type, for example
+ free function, then `False` will be returned.
+ """
+
+ def __init__( self, access_type ):
+ """
+ :param access_type: declaration access type, could be "public", "private", "protected"
+ :type access_type: :class: `str`
+ """
+ matcher_base_t.__init__( self )
+ self.access_type = access_type
+
+ def __call__( self, decl ):
+ if not isinstance( decl.parent, class_declaration.class_t ):
+ return False
+ return self.access_type == decl.parent.find_out_member_access_type( decl )
+
+ def __str__( self ):
+ return '(access type=%s)' % self.access_type
+
+class virtuality_type_matcher_t( matcher_base_t ):
+ """
+ Instance of this class will match declaration by its virtual type: not virtual,
+ virtual or pure virtual. If declarations does not have "virtual" property,
+ for example free function, then `False` will be returned.
+ """
+
+ def __init__( self, virtuality_type ):
+ """
+ :param access_type: declaration access type
+ :type access_type: :class:VIRTUALITY_TYPES defines few constants for your convenience.
+ """
+ matcher_base_t.__init__( self )
+ self.virtuality_type = virtuality_type
+
+ def __call__( self, decl ):
+ if not isinstance( decl.parent, class_declaration.class_t ):
+ return False
+ return self.virtuality_type == decl.virtuality
+
+ def __str__( self ):
+ return '(virtuality type=%s)' % self.virtuality_type
+
+
+class custom_matcher_t( matcher_base_t ):
+ """
+ Instance of this class will match declaration by user custom criteria.
+ """
+
+ def __init__( self, function ):
+ """
+ :param function: callable, that takes single argument - declaration instance
+ should return True or False
+ """
+ matcher_base_t.__init__( self )
+ self.function = function
+
+ def __call__( self, decl ):
+ return bool( self.function( decl ) )
+
+ def __str__( self ):
+ return '(user criteria)'
Modified: pyplusplus_dev/pyplusplus/function_transformers/function_transformation.py
===================================================================
--- pyplusplus_dev/pyplusplus/function_transformers/function_transformation.py 2009-05-11 07:27:29 UTC (rev 1712)
+++ pyplusplus_dev/pyplusplus/function_transformers/function_transformation.py 2009-05-11 07:44:51 UTC (rev 1713)
@@ -1,73 +1,73 @@
-# Copyright 2006 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)
-
-"""defines :class:function_transformation_t class"""
-
-import md5
-import controllers
-from pygccxml import declarations
-from pyplusplus import code_repository
-
-class function_transformation_t:
- """the class holds function transformation definition - all transformations that should be applied"""
- def __init__(self, function, transformer_creator, **keywd):
- self.__function = function
- self.__controller = None
- if isinstance( function.parent, declarations.class_t ):
- if declarations.VIRTUALITY_TYPES.NOT_VIRTUAL == function.virtuality:
- self.__controller = controllers.mem_fun_controller_t( function )
- elif declarations.VIRTUALITY_TYPES.PURE_VIRTUAL == function.virtuality:
- self.__controller = controllers.pure_virtual_mem_fun_controller_t( function )
- else:
- self.__controller = controllers.virtual_mem_fun_controller_t( function )
- else:
- self.__controller = controllers.free_fun_controller_t( function )
- self.__transformers = map( lambda tr_creator: tr_creator( function ), transformer_creator )
- self.__thread_safe = keywd.get( 'thread_safe', False )
- self.__controller.apply( self.__transformers )
- self.__unique_name = None
- self.__alias = keywd.get( 'alias', None )
-
- @property
- def unique_name( self ):
- if None is self.__unique_name:
- obj = md5.new()
- if self.__function.mangled: # free functions don't have a mangled value
- obj.update( self.__function.mangled )
- else:
- obj.update( self.__function.decl_string )
- obj.update( self.__function.location.file_name )
- obj.update( str( self.__function.location.line ) )
- self.__unique_name = self.__function.name + '_' + obj.hexdigest ()
- return self.__unique_name
-
- @property
- def alias( self ):
- if None is self.__alias:
- if self.__function.overloads:
- self.__alias = self.unique_name
- else:
- self.__alias = self.__function.alias
- return self.__alias
-
- @property
- def transformers( self ):
- return self.__transformers
-
- @property
- def controller( self ):
- return self.__controller
-
- def required_headers( self ):
- headers = []
- map( lambda transformer: headers.extend( transformer.required_headers() )
- , self.transformers )
- if self.__function.call_policies:
- headers.append( code_repository.call_policies.file_name )
- return headers
-
- @property
- def thread_safe( self ):
- return self.__thread_safe
+# Copyright 2006 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)
+
+"""defines :class:function_transformation_t class"""
+
+import hashlib
+import controllers
+from pygccxml import declarations
+from pyplusplus import code_repository
+
+class function_transformation_t:
+ """the class holds function transformation definition - all transformations that should be applied"""
+ def __init__(self, function, transformer_creator, **keywd):
+ self.__function = function
+ self.__controller = None
+ if isinstance( function.parent, declarations.class_t ):
+ if declarations.VIRTUALITY_TYPES.NOT_VIRTUAL == function.virtuality:
+ self.__controller = controllers.mem_fun_controller_t( function )
+ elif declarations.VIRTUALITY_TYPES.PURE_VIRTUAL == function.virtuality:
+ self.__controller = controllers.pure_virtual_mem_fun_controller_t( function )
+ else:
+ self.__controller = controllers.virtual_mem_fun_controller_t( function )
+ else:
+ self.__controller = controllers.free_fun_controller_t( function )
+ self.__transformers = map( lambda tr_creator: tr_creator( function ), transformer_creator )
+ self.__thread_safe = keywd.get( 'thread_safe', False )
+ self.__controller.apply( self.__transformers )
+ self.__unique_name = None
+ self.__alias = keywd.get( 'alias', None )
+
+ @property
+ def unique_name( self ):
+ if None is self.__unique_name:
+ obj = hashlib.md5()
+ if self.__function.mangled: # free functions don't have a mangled value
+ obj.update( self.__function.mangled )
+ else:
+ obj.update( self.__function.decl_string )
+ obj.update( self.__function.location.file_name )
+ obj.update( str( self.__function.location.line ) )
+ self.__unique_name = self.__function.name + '_' + obj.hexdigest ()
+ return self.__unique_name
+
+ @property
+ def alias( self ):
+ if None is self.__alias:
+ if self.__function.overloads:
+ self.__alias = self.unique_name
+ else:
+ self.__alias = self.__function.alias
+ return self.__alias
+
+ @property
+ def transformers( self ):
+ return self.__transformers
+
+ @property
+ def controller( self ):
+ return self.__controller
+
+ def required_headers( self ):
+ headers = []
+ map( lambda transformer: headers.extend( transformer.required_headers() )
+ , self.transformers )
+ if self.__function.call_policies:
+ headers.append( code_repository.call_policies.file_name )
+ return headers
+
+ @property
+ def thread_safe( self ):
+ return self.__thread_safe
Modified: pyplusplus_dev/pyplusplus/module_builder/boost_python_builder.py
===================================================================
--- pyplusplus_dev/pyplusplus/module_builder/boost_python_builder.py 2009-05-11 07:27:29 UTC (rev 1712)
+++ pyplusplus_dev/pyplusplus/module_builder/boost_python_builder.py 2009-05-11 07:44:51 UTC (rev 1713)
@@ -1,424 +1,427 @@
-# Copyright 2004-2008 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 time
-import types
-import warnings
-import module_builder
-
-from pygccxml import parser
-from pygccxml import utils as pygccxml_utils
-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
-from pyplusplus import code_creators
-from pyplusplus import creators_factory
-
-class builder_t(module_builder.module_builder_t):
- """
- This class provides users with simple and intuitive interface to `Py++`
- and/or pygccxml functionality. If this is your first attempt to use `Py++`
- consider to read tutorials. You can find them on `web site <http://www.language-binding.net>`_.
- """
-
- def __init__( self
- , files
- , gccxml_path=''
- , working_directory='.'
- , include_paths=None
- , define_symbols=None
- , undefine_symbols=None
- , start_with_declarations=None
- , compilation_mode=None
- , cache=None
- , optimize_queries=True
- , ignore_gccxml_output=False
- , indexing_suite_version=1
- , cflags=""
- , encoding='ascii'
- , compiler=None
- , gccxml_config=None):
- """
- :param files: list of files, declarations from them you want to export
- :type files: list of strings or :class:`parser.file_configuration_t` instances
-
- :param gccxml_path: path to gccxml binary. If you don't pass this argument,
- pygccxml parser will try to locate it using you environment PATH variable
- :type gccxml_path: str
-
- :param include_paths: additional header files location. You don't have to
- specify system and standard directories.
- :type include_paths: list of strings
-
- :param define_symbols: list of symbols to be defined for preprocessor.
- :param define_symbols: list of strings
-
- :param undefine_symbols: list of symbols to be undefined for preprocessor.
- :param undefine_symbols: list of strings
-
- :param cflags: Raw string to be added to gccxml command line.
-
- :param gccxml_config: instance of pygccxml.parser.config_t class, holds
- gccxml( compiler ) configuration. You can use this argument instead of
- passing the compiler configuration separately.
- """
- module_builder.module_builder_t.__init__( self, global_ns=None, encoding=encoding )
-
- if not gccxml_config:
- gccxml_config = parser.config_t( gccxml_path=gccxml_path
- , working_directory=working_directory
- , include_paths=include_paths
- , define_symbols=define_symbols
- , undefine_symbols=undefine_symbols
- , start_with_declarations=start_with_declarations
- , ignore_gccxml_output=ignore_gccxml_output
- , cflags=cflags
- , compiler=compiler)
-
- #may be in future I will add those directories to user_defined_directories to self.__code_creator.
- self.__parsed_files = map( pygccxml_utils.normalize_path
- , parser.project_reader_t.get_os_file_names( files ) )
- tmp = map( lambda file_: os.path.split( file_ )[0], self.__parsed_files )
- self.__parsed_dirs = filter( None, tmp )
-
- self.global_ns = self.__parse_declarations( files
- , gccxml_config
- , compilation_mode
- , cache
- , indexing_suite_version)
- self.global_ns.decls(recursive=True, allow_empty=True)._code_generator = decl_wrappers.CODE_GENERATOR_TYPES.CTYPES
-
- self.__code_creator = None
- if optimize_queries:
- self.run_query_optimizer()
-
- self.__declarations_code_head = []
- self.__declarations_code_tail = []
-
- self.__registrations_code_head = []
- self.__registrations_code_tail = []
-
-
-
- def register_module_dependency( self, other_module_generated_code_dir ):
- """
- `already_exposed` solution is pretty good when you mix hand-written
- modules with `Py++` generated. It doesn't work/scale for "true"
- multi-module development. This is exactly the reason why `Py++`
- offers "semi automatic" solution.
-
- For every exposed module, `Py++` generates `exposed_decl.pypp.txt` file.
- This file contains the list of all parsed declarations and whether they
- were included or excluded. Later, when you work on another module, you
- can tell `Py++` that the current module depends on the previously
- generated one. `Py++` will load `exposed_decl.pypp.txt` file and update
- the declarations.
- """
-
- db = utils.exposed_decls_db_t()
- db.load( other_module_generated_code_dir )
- db.update_decls( self.global_ns )
-
-
- def __parse_declarations( self, files, gccxml_config, compilation_mode, cache, indexing_suite_version ):
- if None is gccxml_config:
- gccxml_config = parser.config_t()
- if None is compilation_mode:
- compilation_mode = parser.COMPILATION_MODE.FILE_BY_FILE
- start_time = time.clock()
- self.logger.debug( 'parsing files - started' )
- reader = parser.project_reader_t( gccxml_config, cache, decl_wrappers.dwfactory_t() )
- decls = reader.read_files( files, compilation_mode )
-
- self.logger.debug( 'parsing files - done( %f seconds )' % ( time.clock() - start_time ) )
- self.logger.debug( 'settings declarations defaults - started' )
-
- global_ns = decls_package.matcher.get_single(
- decls_package.namespace_matcher_t( name='::' )
- , decls )
- if indexing_suite_version != 1:
- for cls in global_ns.classes():
- cls.indexing_suite_version = indexing_suite_version
- for cls in global_ns.decls(decl_type=decls_package.class_declaration_t):
- cls.indexing_suite_version = indexing_suite_version
-
- start_time = time.clock()
- self.__apply_decls_defaults(decls)
- self.logger.debug( 'settings declarations defaults - done( %f seconds )'
- % ( time.clock() - start_time ) )
- return global_ns
-
- def __filter_by_location( self, flatten_decls ):
- for decl in flatten_decls:
- if not decl.location:
- continue
- fpath = pygccxml_utils.normalize_path( decl.location.file_name )
- if pygccxml_utils.contains_parent_dir( fpath, self.__parsed_dirs ):
- continue
- if fpath in self.__parsed_files:
- continue
- found = False
- for pfile in self.__parsed_files:
- if fpath.endswith( pfile ):
- found = True
- break
- if not found:
- decl.exclude()
-
- def __apply_decls_defaults(self, decls):
- flatten_decls = decls_package.make_flatten( decls )
- self.__filter_by_location( flatten_decls )
- call_policies_resolver = creators_factory.built_in_resolver_t()
- calldefs = filter( lambda decl: isinstance( decl, decls_package.calldef_t )
- , flatten_decls )
- map( lambda calldef: calldef.set_call_policies( call_policies_resolver( calldef ) )
- , calldefs )
- mem_vars = filter( lambda decl: isinstance( decl, decls_package.variable_t )
- and isinstance( decl.parent, decls_package.class_t )
- , flatten_decls )
- map( lambda mem_var: mem_var.set_getter_call_policies( call_policies_resolver( mem_var, 'get' ) )
- , mem_vars )
- map( lambda mem_var: mem_var.set_setter_call_policies( call_policies_resolver( mem_var, 'set' ) )
- , mem_vars )
-
- @property
- def declarations_code_head( self ):
- "List of user code, that will be added to the head of the declarations section."
- return self.__declarations_code_head
-
- @property
- def declarations_code_tail( self ):
- "List of user code, that will be added to the tail of the declarations section."
- return self.__declarations_code_tail
-
- @property
- def registrations_code_head( self ):
- "List of user code, that will be added to the head of the registrations section."
- return self.__registrations_code_head
-
- @property
- def registrations_code_tail( self ):
- "List of user code, that will be added to the tail of the registrations section."
- return self.__registrations_code_tail
-
- def build_code_creator( self
- , module_name
- , boost_python_ns_name='bp'
- , call_policies_resolver_=None
- , types_db=None
- , target_configuration=None
- , enable_indexing_suite=True
- , doc_extractor=None):
- """
- Creates :class:`code_creators.bpmodule_t` code creator.
-
- :param module_name: module name
- :type module_name: str
-
- :param boost_python_ns_name: boost::python namespace alias, by default it is `bp`
- :type boost_python_ns_name: str
-
- :param call_policies_resolver_: callable, that will be invoked on every calldef object. It should return call policies.
- :type call_policies_resolver_: callable
- :param doc_extractor: callable, that takes as argument reference to declaration and returns documentation string
- :type doc_extractor: callable or None
- """
-
- creator = creators_factory.bpcreator_t( self.global_ns
- , module_name
- , boost_python_ns_name
- , call_policies_resolver_
- , types_db
- , target_configuration
- , enable_indexing_suite )
- self.__code_creator = creator.create()
- self.__code_creator.replace_included_headers(self.__parsed_files)
- self.__code_creator.update_documentation( doc_extractor )
- return self.__code_creator
-
- @property
- def code_creator( self ):
- "reference to :class:`code_creators.bpmodule_t` instance"
- if not self.__code_creator:
- raise RuntimeError( "self.module is equal to None. Did you forget to call build_code_creator function?" )
- return self.__code_creator
-
- def has_code_creator( self ):
- """
- Function, that will return True if build_code_creator function has been
- called and False otherwise
- """
- return not ( None is self.__code_creator )
-
- def add_declaration_code( self, code, tail=True ):
- if tail:
- self.__declarations_code_tail.append( code )
- else:
- self.__declarations_code_head.append( code )
-
- def add_registration_code( self, code, tail=True ):
- if tail:
- self.__registrations_code_tail.append( code )
- else:
- self.__registrations_code_head.append( code )
-
- def add_constants( self, **keywds ):
- """
- adds code that exposes some constants to Python.
-
- For example:
- .. code-block:: python
-
- mb.add_constants( version='"1.2.3"' )
- # or
- constants = dict( version:'"1.2.3"' )
- mb.add_constants( \\*\\*constants )
-
- will generate the following code:
-
- .. code-block:: c++
-
- boost::python::scope().attr("version") = "1.2.3";
-
- """
- tmpl = 'boost::python::scope().attr("%(name)s") = %(value)s;'
- for name, value in keywds.items():
- if not isinstance( value, types.StringTypes ):
- value = str( value )
- self.add_regi...
[truncated message content] |