From d476e6706792ad67961abca6e041765ed940aed4 Mon Sep 17 00:00:00 2001
From: Bruno da Silva de Oliveira
-Suppose that you want to add a function to a class, turning it into a method:
struct World
{
@@ -38,7 +39,7 @@ Suppose that you want to add a function to a class, turning it into a method:
-Here, we want to make greet work as a method of the class World. We do +Here, we want to make greet work as a member function of the class World. We do that using the add_method construct:
W = Class("World", "hello.h")
@@ -46,7 +47,7 @@ that using the add_method construct:
Notice also that then you can rename it, set its policy, just like a regular -method:
+member function:
rename(W.greet, 'Greet')
diff --git a/pyste/doc/policies.html b/pyste/doc/policies.html
index 3ad28a1d..704aa33b 100644
--- a/pyste/doc/policies.html
+++ b/pyste/doc/policies.html
@@ -26,9 +26,9 @@
Even thought Pyste can identify various elements in the C++ code, like virtual -methods, attributes, and so on, one thing that it can't do is to guess the -semantics of functions that return pointers or references. In this case, the -user must manually specify the policy. Policies are explained in the +member functions, attributes, and so on, one thing that it can't do is to +guess the semantics of functions that return pointers or references. In this +case, the user must manually specify the policy. Policies are explained in the tutorial.
@@ -44,8 +44,8 @@ becomes in Pyste:
return_internal_reference(1, with_custodian_and_ward(1, 2))-The user can specify policies for functions and methods with the set_policy -function:
+The user can specify policies for functions and virtual member functions with +the set_policy function:
set_policy(f, return_internal_reference())
set_policy(C.foo, return_value_policy(manage_new_object))
@@ -54,10 +54,11 @@ function:
-
What if a function or method needs a policy and the user
-doesn't set one?
If a function/method needs a policy and one was not
-set, Pyste will issue a error. The user should then go in the interface file
-and set the policy for it, otherwise the generated cpp won't compile.
+
What if a function or member function needs a policy and
+the user doesn't set one?
If a function needs a policy and one
+was not set, Pyste will issue a error. The user should then go in the
+interface file and set the policy for it, otherwise the generated cpp won't
+compile.
@@ -66,7 +67,7 @@ and set the policy for it, otherwise the generated cpp won't compile.
-Note that, for functions/methods that return const T&, the policy
+Note that, for functions that return const T&, the policy
return_value_policy<copy_const_reference>() wil be used by default, because
that's normally what you want. You can change it to something else if you need
to, though.
diff --git a/pyste/doc/renaming_and_excluding.html b/pyste/doc/renaming_and_excluding.html
index 4f56bb92..e06e0496 100644
--- a/pyste/doc/renaming_and_excluding.html
+++ b/pyste/doc/renaming_and_excluding.html
@@ -25,7 +25,7 @@
-You can easily rename functions, classes, methods, attributes, etc. Just use the
+You can easily rename functions, classes, member functions, attributes, etc. Just use the
function rename, like this:
World = Class("World", "hello.h")
@@ -34,7 +34,7 @@ function rename, like this:
rename(show, "Show")
-You can rename methods and attributes using this syntax:
+You can rename member functions and attributes using this syntax:
rename(World.greet, "Greet")
rename(World.set, "Set")
@@ -43,7 +43,7 @@ You can rename methods and attributes using this syntax:
rename(choice.blue, "Blue")
-You can exclude functions, classes, methods, attributes, etc, in the same way,
+You can exclude functions, classes, member functions, attributes, etc, in the same way,
with the function exclude:
exclude(World.greet)
@@ -59,6 +59,18 @@ To access the operators of a class, access the member operator like thi
The string inside the brackets is the same as the name of the operator in C++.
+Virtual Member Functions
+Pyste automatically generates wrappers for virtual member functions, but you
+may want to disable this behaviour (for performance reasons, or to let the
+code more clean) if you do not plan to override the functions in Python. To do
+this, use the function final:
+
+ C = Class('C', 'C.h')
+ final(C.foo) ##C::foo is a virtual member function
+
+
+No virtual wrapper code will be generated for the virtual member function
+C::foo that way.

diff --git a/pyste/doc/the_interface_files.html b/pyste/doc/the_interface_files.html
index 0e78e4ec..33ab7103 100644
--- a/pyste/doc/the_interface_files.html
+++ b/pyste/doc/the_interface_files.html
@@ -32,8 +32,8 @@ cpp file with
Boost.Python code, with all the classes and functions exported.
Besides declaring the classes and functions, the user has a number of other
-options, like renaming classes and methods, excluding methods and attributes,
-and so on.
+options, like renaming e excluding classes and member functionis. Those are
+explained later on.
Basics
Suppose we have a class and some functions that we want to expose to Python
declared in the header hello.h:
diff --git a/pyste/doc/wrappers.html b/pyste/doc/wrappers.html
index a850a250..3265a350 100644
--- a/pyste/doc/wrappers.html
+++ b/pyste/doc/wrappers.html
@@ -75,10 +75,9 @@ You can optionally declare the function in the interface file itself:
set_wrapper(names, names_wrapper)
-The same mechanism can be used with methods too. Just remember that the first
-parameter of wrappers for methods is a pointer to the class, like in
-
-Boost.Python:
+The same mechanism can be used with member functions too. Just remember that
+the first parameter of wrappers for member functions is a pointer to the
+class, as in:
struct C
{
@@ -104,7 +103,7 @@ And then in the interface file:
Boost.Python accepts either a pointer or a
reference to the class in wrappers for member functions as the first parameter,
Pyste expects them to be a pointer. Doing otherwise will prevent your
-code to compile when you set a wrapper for a virtual method.
+code to compile when you set a wrapper for a virtual member function.
diff --git a/pyste/src/ClassExporter.py b/pyste/src/ClassExporter.py
index e0f97077..b95a37ca 100644
--- a/pyste/src/ClassExporter.py
+++ b/pyste/src/ClassExporter.py
@@ -46,24 +46,24 @@ class ClassExporter(Exporter):
def ScopeName(self):
- return makeid(self.class_.FullName()) + '_scope'
+ return makeid(self.class_._FullName()) + '_scope'
def Unit(self):
- return makeid(self.class_.name)
+ return makeid(self.class_._name)
def Name(self):
- return self.class_.FullName()
+ return self.class_._FullName()
def SetDeclarations(self, declarations):
Exporter.SetDeclarations(self, declarations)
decl = self.GetDeclaration(self.info.name)
if isinstance(decl, Typedef):
- self.class_ = self.GetDeclaration(decl.type.name)
+ self.class_ = self.GetDeclaration(decl._type._name)
if not self.info.rename:
- self.info.rename = decl.name
+ self.info.rename = decl._name
else:
self.class_ = decl
self.class_ = copy.deepcopy(self.class_)
@@ -72,10 +72,10 @@ class ClassExporter(Exporter):
def ClassBases(self):
all_bases = []
- for level in self.class_.hierarchy:
+ for level in self.class_._hierarchy:
for base in level:
all_bases.append(base)
- return [self.GetDeclaration(x.name) for x in all_bases]
+ return [self.GetDeclaration(x._name) for x in all_bases]
def Order(self):
@@ -83,15 +83,13 @@ class ClassExporter(Exporter):
bases' bases. Do this because base classes must be instantialized
before the derived classes in the module definition.
'''
- return '%s_%s' % (len(self.ClassBases()), self.class_.FullName())
+ return '%s_%s' % (len(self.ClassBases()), self.class_._FullName())
def Export(self, codeunit, exported_names):
self.InheritMethods(exported_names)
self.MakeNonVirtual()
if not self.info.exclude:
- self.CheckIsForwardDeclared()
- self.CheckForwardDeclarations()
self.ExportBasics()
self.ExportBases(exported_names)
self.ExportConstructors()
@@ -110,43 +108,31 @@ class ClassExporter(Exporter):
'''Go up in the class hierarchy looking for classes that were not
exported yet, and then add their public members to this classes
members, as if they were members of this class. This allows the user to
- just export one type and automatically get all the methods from the
+ just export one type and automatically get all the members from the
base classes.
'''
valid_members = (Method, ClassVariable, NestedClass, ClassOperator,
ConverterOperator, ClassEnumeration)
- for level in self.class_.hierarchy:
+ for level in self.class_._hierarchy:
level_exported = False
for base in level:
- base = self.GetDeclaration(base.name)
- if base.FullName() not in exported_names:
- for member in base.members:
+ base = self.GetDeclaration(base._name)
+ if base._FullName() not in exported_names:
+ for member in base:
if type(member) in valid_members:
member = copy.deepcopy(member)
#if type(member) not in (ClassVariable,:
- # member.class_ = self.class_.FullName()
- self.class_.members.append(member)
+ # member.class_ = self.class_._FullName()
+ self.class_._AddMember(member)
else:
level_exported = True
if level_exported:
break
- self.public_members = \
- [x for x in self.class_.members if x.visibility == Scope.public]
+ def IsValid(member):
+ return isinstance(member, valid_members) and member._visibility == Scope.public
+ self.public_members = [x for x in self.class_ if IsValid(x)]
- def CheckIsForwardDeclared(self):
- if self.class_.incomplete:
- print "--> Error: Class %s is forward declared! " \
- "Please use the header with its complete definition." \
- % self.class_.FullName()
- print
-
-
- def CheckForwardDeclarations(self):
- for m in self.public_members:
- if isinstance(m, Function):
- exporterutils.WarnForwardDeclarations(m)
-
def Write(self, codeunit):
indent = self.INDENT
boost_ns = namespaces.python
@@ -210,23 +196,22 @@ class ClassExporter(Exporter):
def ExportBasics(self):
'Export the name of the class and its class_ statement'
- self.Add('template', self.class_.FullName())
- name = self.info.rename or self.class_.name
+ self.Add('template', self.class_._FullName())
+ name = self.info.rename or self.class_._name
self.Add('constructor', '"%s"' % name)
def ExportBases(self, exported_names):
'Expose the bases of the class into the template section'
- hierarchy = self.class_.hierarchy
+ hierarchy = self.class_._hierarchy
for level in hierarchy:
exported = []
for base in level:
- if base.visibility == Scope.public and base.name in exported_names:
- exported.append(base.name)
+ if base._visibility == Scope.public and base._name in exported_names:
+ exported.append(base._name)
if exported:
code = namespaces.python + 'bases< %s > ' % (', '.join(exported))
self.Add('template', code)
- return
def ExportConstructors(self):
@@ -238,9 +223,9 @@ class ClassExporter(Exporter):
def init_code(cons):
'return the init<>() code for the given contructor'
- param_list = [p.FullName() for p in cons.parameters]
- min_params_list = param_list[:cons.minArgs]
- max_params_list = param_list[cons.minArgs:]
+ param_list = [p._FullName() for p in cons._parameters]
+ min_params_list = param_list[:cons._minArgs]
+ max_params_list = param_list[cons._minArgs:]
min_params = ', '.join(min_params_list)
max_params = ', '.join(max_params_list)
init = py_ns + 'init< '
@@ -255,9 +240,9 @@ class ClassExporter(Exporter):
constructors = [x for x in self.public_members if isinstance(x, Constructor)]
self.constructors = constructors[:]
# don't export the copy constructor if the class is abstract
- if self.class_.abstract:
+ if self.class_._abstract:
for cons in constructors:
- if cons.IsCopy():
+ if cons._IsCopy():
constructors.remove(cons)
break
if not constructors:
@@ -267,7 +252,7 @@ class ClassExporter(Exporter):
# write the constructor with less parameters to the constructor section
smaller = None
for cons in constructors:
- if smaller is None or len(cons.parameters) < len(smaller.parameters):
+ if smaller is None or len(cons._parameters) < len(smaller._parameters):
smaller = cons
assert smaller is not None
self.Add('constructor', init_code(smaller))
@@ -277,7 +262,7 @@ class ClassExporter(Exporter):
code = '.def(%s)' % init_code(cons)
self.Add('inside', code)
# check if the class is copyable
- if not self.class_.HasCopyConstructor() or self.class_.abstract:
+ if not self.class_._HasCopyConstructor() or self.class_._abstract:
self.Add('template', namespaces.boost + 'noncopyable')
@@ -285,11 +270,11 @@ class ClassExporter(Exporter):
'Export the variables of the class, both static and simple variables'
vars = [x for x in self.public_members if isinstance(x, Variable)]
for var in vars:
- if self.info[var.name].exclude:
+ if self.info[var._name].exclude:
continue
- name = self.info[var.name].rename or var.name
- fullname = var.FullName()
- if var.type.const:
+ name = self.info[var._name].rename or var._name
+ fullname = var._FullName()
+ if var._type._const:
def_ = '.def_readonly'
else:
def_ = '.def_readwrite'
@@ -299,8 +284,8 @@ class ClassExporter(Exporter):
def OverloadName(self, method):
'Returns the name of the overloads struct for the given method'
- name = makeid(method.FullName())
- overloads = '_overloads_%i_%i' % (method.minArgs, method.maxArgs)
+ name = makeid(method._FullName())
+ overloads = '_overloads_%i_%i' % (method._minArgs, method._maxArgs)
return name + overloads
@@ -322,13 +307,13 @@ class ClassExporter(Exporter):
declared = {}
def DeclareOverloads(m):
'Declares the macro for the generation of the overloads'
- if (isinstance(m, Method) and m.static) or type(m) == Function:
- func = m.FullName()
+ if (isinstance(m, Method) and m._static) or type(m) == Function:
+ func = m._FullName()
macro = 'BOOST_PYTHON_FUNCTION_OVERLOADS'
else:
- func = m.name
+ func = m._name
macro = 'BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS'
- code = '%s(%s, %s, %i, %i)\n' % (macro, self.OverloadName(m), func, m.minArgs, m.maxArgs)
+ code = '%s(%s, %s, %i, %i)\n' % (macro, self.OverloadName(m), func, m._minArgs, m._maxArgs)
if code not in declared:
declared[code] = True
self.Add('declaration', code)
@@ -337,37 +322,29 @@ class ClassExporter(Exporter):
def Pointer(m):
'returns the correct pointer declaration for the method m'
# check if this method has a wrapper set for him
- wrapper = self.info[method.name].wrapper
+ wrapper = self.info[m._name].wrapper
if wrapper:
return '&' + wrapper.FullName()
- # return normal pointers to the methods of the class
- if isinstance(m, Method):
- is_unique = self.class_.IsUnique(m.name)
else:
- # function
- is_unique = len(self.GetDeclarations(m.FullName())) == 1
- if is_unique:
- return '&' + method.FullName()
- else:
- return method.PointerDeclaration()
+ return m._PointerDeclaration()
def IsExportable(m):
'Returns true if the given method is exportable by this routine'
ignore = (Constructor, ClassOperator, Destructor)
- return isinstance(m, Function) and not isinstance(m, ignore) and not m.virtual
+ return isinstance(m, Function) and not isinstance(m, ignore) and not m._virtual
methods = [x for x in self.public_members if IsExportable(x)]
methods.extend(self.GetAddedMethods())
for method in methods:
- method_info = self.info[method.name]
+ method_info = self.info[method._name]
# skip this method if it was excluded by the user
if method_info.exclude:
continue
# rename the method if the user requested
- name = method_info.rename or method.name
+ name = method_info.rename or method._name
# warn the user if this method needs a policy and doesn't have one
method_info.policy = exporterutils.HandlePolicy(method, method_info.policy)
@@ -378,7 +355,7 @@ class ClassExporter(Exporter):
policy = ', %s%s()' % (namespaces.python, policy.Code())
# check for overloads
overload = ''
- if method.minArgs != method.maxArgs:
+ if method._minArgs != method._maxArgs:
# add the overloads for this method
DeclareOverloads(method)
overload_name = self.OverloadName(method)
@@ -392,7 +369,7 @@ class ClassExporter(Exporter):
code += ')'
self.Add('inside', code)
# static method
- if isinstance(method, Method) and method.static:
+ if isinstance(method, Method) and method._static:
code = '.staticmethod("%s")' % name
self.Add('inside', code)
# add wrapper code if this method has one
@@ -404,16 +381,16 @@ class ClassExporter(Exporter):
def MakeNonVirtual(self):
'''Make all methods that the user indicated to no_override no more virtual, delegating their
export to the ExportMethods routine'''
- for member in self.class_.members:
- if type(member) == Method and member.virtual:
- member.virtual = not self.info[member.name].no_override
+ for member in self.class_:
+ if type(member) == Method and member._virtual:
+ member._virtual = not self.info[member._name].no_override
def ExportVirtualMethods(self):
# check if this class has any virtual methods
has_virtual_methods = False
- for member in self.class_.members:
- if type(member) == Method and member.virtual:
+ for member in self.class_:
+ if type(member) == Method and member._virtual:
has_virtual_methods = True
break
@@ -432,7 +409,7 @@ class ClassExporter(Exporter):
BOOST_SUPPORTED_OPERATORS = dict(zip(BOOST_SUPPORTED_OPERATORS, range(len(BOOST_SUPPORTED_OPERATORS))))
# a dict of operators that are not directly supported by boost, but can be exposed
- # simply as a function with a special signature
+ # simply as a function with a special name
BOOST_RENAME_OPERATORS = {
'()' : '__call__',
}
@@ -459,26 +436,26 @@ class ClassExporter(Exporter):
for decl in self.declarations:
if isinstance(decl, Operator):
# check if one of the params is this class
- for param in decl.parameters:
- if param.name == self.class_.FullName():
+ for param in decl._parameters:
+ if param._name == self.class_._FullName():
operators.append(decl)
break
return operators
def GetOperand(param):
'Returns the operand of this parameter (either "self", or "other")'
- if param.name == self.class_.FullName():
+ if param._name == self.class_._FullName():
return namespaces.python + 'self'
else:
- return namespaces.python + ('other< %s >()' % param.name)
+ return namespaces.python + ('other< %s >()' % param._name)
def HandleSpecialOperator(operator):
# gatter information about the operator and its parameters
- result_name = operator.result.name
+ result_name = operator._result._name
param1_name = ''
- if operator.parameters:
- param1_name = operator.parameters[0].name
+ if operator._parameters:
+ param1_name = operator._parameters[0]._name
# check for str
ostream = 'basic_ostream'
@@ -496,23 +473,21 @@ class ClassExporter(Exporter):
frees = GetFreeOperators()
members = [x for x in self.public_members if type(x) == ClassOperator]
all_operators = frees + members
- operators = [x for x in all_operators if not self.info['operator'][x.name].exclude]
+ operators = [x for x in all_operators if not self.info['operator'][x._name].exclude]
for operator in operators:
# gatter information about the operator, for use later
- wrapper = self.info['operator'][operator.name].wrapper
+ wrapper = self.info['operator'][operator._name].wrapper
if wrapper:
pointer = '&' + wrapper.FullName()
if wrapper.code:
self.Add('declaration', wrapper.code)
- elif isinstance(operator, ClassOperator) and self.class_.IsUnique(operator.name):
- pointer = '&' + operator.FullName()
else:
- pointer = operator.PointerDeclaration()
- rename = self.info['operator'][operator.name].rename
+ pointer = operator._PointerDeclaration()
+ rename = self.info['operator'][operator._name].rename
# check if this operator will be exported as a method
- export_as_method = wrapper or rename or operator.name in self.BOOST_RENAME_OPERATORS
+ export_as_method = wrapper or rename or operator._name in self.BOOST_RENAME_OPERATORS
# check if this operator has a special representation in boost
special_code = HandleSpecialOperator(operator)
@@ -524,9 +499,9 @@ class ClassExporter(Exporter):
if wrapper:
rename = wrapper.name
else:
- rename = self.BOOST_RENAME_OPERATORS[operator.name]
+ rename = self.BOOST_RENAME_OPERATORS[operator._name]
policy = ''
- policy_obj = self.info['operator'][operator.name].policy
+ policy_obj = self.info['operator'][operator._name].policy
if policy_obj:
policy = ', %s()' % policy_obj.Code()
self.Add('inside', '.def("%s", %s%s)' % (rename, pointer, policy))
@@ -534,24 +509,24 @@ class ClassExporter(Exporter):
elif has_special_representation:
self.Add('inside', special_code)
- elif operator.name in self.BOOST_SUPPORTED_OPERATORS:
+ elif operator._name in self.BOOST_SUPPORTED_OPERATORS:
# export this operator using boost's facilities
op = operator
- is_unary = isinstance(op, Operator) and len(op.parameters) == 1 or\
- isinstance(op, ClassOperator) and len(op.parameters) == 0
+ is_unary = isinstance(op, Operator) and len(op._parameters) == 1 or\
+ isinstance(op, ClassOperator) and len(op._parameters) == 0
if is_unary:
self.Add('inside', '.def( %s%sself )' % \
- (operator.name, namespaces.python))
+ (operator._name, namespaces.python))
else:
# binary operator
- if len(operator.parameters) == 2:
- left_operand = GetOperand(operator.parameters[0])
- right_operand = GetOperand(operator.parameters[1])
+ if len(operator._parameters) == 2:
+ left_operand = GetOperand(operator._parameters[0])
+ right_operand = GetOperand(operator._parameters[1])
else:
left_operand = namespaces.python + 'self'
- right_operand = GetOperand(operator.parameters[0])
+ right_operand = GetOperand(operator._parameters[0])
self.Add('inside', '.def( %s %s %s )' % \
- (left_operand, operator.name, right_operand))
+ (left_operand, operator._name, right_operand))
# export the converters.
# export them as simple functions with a pre-determined name
@@ -559,8 +534,8 @@ class ClassExporter(Exporter):
converters = [x for x in self.public_members if type(x) == ConverterOperator]
def ConverterMethodName(converter):
- result_fullname = converter.result.FullName()
- result_name = converter.result.name
+ result_fullname = converter._result._FullName()
+ result_name = converter._result._name
for regex, method_name in self.SPECIAL_CONVERTERS.items():
if regex.match(result_fullname):
return method_name
@@ -570,7 +545,7 @@ class ClassExporter(Exporter):
return 'to_' + result_name
for converter in converters:
- info = self.info['operator'][converter.result.FullName()]
+ info = self.info['operator'][converter._result._FullName()]
# check if this operator should be excluded
if info.exclude:
continue
@@ -579,10 +554,7 @@ class ClassExporter(Exporter):
if info.rename or not special_code:
# export as method
name = info.rename or ConverterMethodName(converter)
- if self.class_.IsUnique(converter.name):
- pointer = '&' + converter.FullName()
- else:
- pointer = converter.PointerDeclaration()
+ pointer = converter._PointerDeclaration()
policy_code = ''
if info.policy:
policy_code = ', %s()' % info.policy.Code()
@@ -596,9 +568,9 @@ class ClassExporter(Exporter):
def ExportNestedClasses(self, exported_names):
nested_classes = [x for x in self.public_members if isinstance(x, NestedClass)]
for nested_class in nested_classes:
- nested_info = self.info[nested_class.name]
+ nested_info = self.info[nested_class._name]
nested_info.include = self.info.include
- nested_info.name = nested_class.FullName()
+ nested_info.name = nested_class._FullName()
exporter = ClassExporter(nested_info)
exporter.SetDeclarations(self.declarations)
codeunit = SingleCodeUnit(None, None)
@@ -609,9 +581,9 @@ class ClassExporter(Exporter):
def ExportNestedEnums(self):
nested_enums = [x for x in self.public_members if isinstance(x, ClassEnumeration)]
for enum in nested_enums:
- enum_info = self.info[enum.name]
+ enum_info = self.info[enum._name]
enum_info.include = self.info.include
- enum_info.name = enum.FullName()
+ enum_info.name = enum._FullName()
exporter = EnumExporter(enum_info)
exporter.SetDeclarations(self.declarations)
codeunit = SingleCodeUnit(None, None)
@@ -622,17 +594,9 @@ class ClassExporter(Exporter):
def ExportSmartPointer(self):
smart_ptr = self.info.smart_ptr
if smart_ptr:
- class_name = self.class_.FullName()
+ class_name = self.class_._FullName()
smart_ptr = smart_ptr % class_name
- #self.Add('template', smart_ptr)
-
- self.Add('scope', '// Temporary code for smart pointers')
- self.Add('scope', namespaces.python + 'objects::class_value_wrapper< ')
- self.Add('scope', ' %s, objects::make_ptr_instance< ' % smart_ptr)
- self.Add('scope', ' %s, objects::pointer_holder< ' % class_name)
- self.Add('scope', ' %s, %s >' % (smart_ptr, class_name))
- self.Add('scope', ' >')
- self.Add('scope', '>();')
+ self.Add('scope', '%s::register_ptr_to_python< %s >();' % (namespaces.python, smart_ptr))
def ExportOpaquePointerPolicies(self):
@@ -640,8 +604,8 @@ class ClassExporter(Exporter):
methods = [x for x in self.public_members if isinstance(x, Method)]
for method in methods:
return_opaque_policy = return_value_policy(return_opaque_pointer)
- if self.info[method.name].policy == return_opaque_policy:
- macro = 'BOOST_PYTHON_OPAQUE_SPECIALIZED_TYPE_ID(%s)' % method.result.name
+ if self.info[method._name].policy == return_opaque_policy:
+ macro = 'BOOST_PYTHON_OPAQUE_SPECIALIZED_TYPE_ID(%s)' % method._result._name
if macro not in self._exported_opaque_pointers:
self.Add('declaration-outside', macro)
self._exported_opaque_pointers[macro] = 1
@@ -653,9 +617,9 @@ class ClassExporter(Exporter):
def _ParamsInfo(m, count=None):
if count is None:
- count = len(m.parameters)
+ count = len(m._parameters)
param_names = ['p%i' % i for i in range(count)]
- param_types = [x.FullName() for x in m.parameters[:count]]
+ param_types = [x._FullName() for x in m._parameters[:count]]
params = ['%s %s' % (t, n) for t, n in zip(param_types, param_names)]
#for i, p in enumerate(m.parameters[:count]):
# if p.default is not None:
@@ -672,7 +636,7 @@ class _VirtualWrapperGenerator(object):
self.class_ = class_
self.bases = bases[:]
self.info = info
- self.wrapper_name = makeid(class_.FullName()) + '_Wrapper'
+ self.wrapper_name = makeid(class_._FullName()) + '_Wrapper'
self.virtual_methods = None
self._method_count = {}
self.GenerateVirtualMethods()
@@ -683,9 +647,9 @@ class _VirtualWrapperGenerator(object):
number of default arguments. Always returns at least one name, and return from
the one with most arguments to the one with the least.
'''
- base_name = 'default_' + method.name
- minArgs = method.minArgs
- maxArgs = method.maxArgs
+ base_name = 'default_' + method._name
+ minArgs = method._minArgs
+ maxArgs = method._maxArgs
if minArgs == maxArgs:
return [base_name]
else:
@@ -699,18 +663,18 @@ class _VirtualWrapperGenerator(object):
'''
pyste = namespaces.pyste
python = namespaces.python
- rename = self.info[method.name].rename or method.name
- result = method.result.FullName()
+ rename = self.info[method._name].rename or method._name
+ result = method._result._FullName()
return_str = 'return '
if result == 'void':
return_str = ''
params, param_names, param_types = _ParamsInfo(method)
constantness = ''
- if method.const:
+ if method._const:
constantness = ' const'
# call_method callback
- decl = indent + '%s %s(%s)%s {\n' % (result, method.name, params, constantness)
+ decl = indent + '%s %s(%s)%s {\n' % (result, method._name, params, constantness)
param_names_str = ', '.join(param_names)
if param_names_str:
param_names_str = ', ' + param_names_str
@@ -721,19 +685,19 @@ class _VirtualWrapperGenerator(object):
# default implementations (with overloading)
def DefaultImpl(method, param_names):
'Return the body of a default implementation wrapper'
- wrapper = self.info[method.name].wrapper
+ wrapper = self.info[method._name].wrapper
if not wrapper:
# return the default implementation of the class
return '%s%s::%s(%s);\n' % \
- (return_str, self.class_.FullName(), method.name, ', '.join(param_names))
+ (return_str, self.class_._FullName(), method._name, ', '.join(param_names))
else:
# return a call for the wrapper
params = ', '.join(['this'] + param_names)
return '%s%s(%s);\n' % (return_str, wrapper.FullName(), params)
- if not method.abstract and method.visibility != Scope.private:
- minArgs = method.minArgs
- maxArgs = method.maxArgs
+ if not method._abstract and method._visibility != Scope.private:
+ minArgs = method._minArgs
+ maxArgs = method._maxArgs
impl_names = self.DefaultImplementationNames(method)
for impl_name, argNum in zip(impl_names, range(minArgs, maxArgs+1)):
params, param_names, param_types = _ParamsInfo(method, argNum)
@@ -749,38 +713,35 @@ class _VirtualWrapperGenerator(object):
statement to export this method.'''
# dont define abstract methods
pyste = namespaces.pyste
- rename = self.info[method.name].rename or method.name
+ rename = self.info[method._name].rename or method._name
default_names = self.DefaultImplementationNames(method)
- class_name = self.class_.FullName()
+ class_name = self.class_._FullName()
wrapper_name = pyste + self.wrapper_name
- result = method.result.FullName()
- is_method_unique = self.IsMethodUnique(method.name)
+ result = method._result._FullName()
+ is_method_unique = method._is_unique
constantness = ''
- if method.const:
+ if method._const:
constantness = ' const'
# create a list of default-impl pointers
- minArgs = method.minArgs
- maxArgs = method.maxArgs
+ minArgs = method._minArgs
+ maxArgs = method._maxArgs
if is_method_unique:
default_pointers = ['&%s::%s' % (wrapper_name, x) for x in default_names]
else:
default_pointers = []
for impl_name, argNum in zip(default_names, range(minArgs, maxArgs+1)):
- param_list = [x.FullName() for x in method.parameters[:argNum]]
+ param_list = [x._FullName() for x in method._parameters[:argNum]]
params = ', '.join(param_list)
signature = '%s (%s::*)(%s)%s' % (result, wrapper_name, params, constantness)
default_pointer = '(%s)&%s::%s' % (signature, wrapper_name, impl_name)
default_pointers.append(default_pointer)
# get the pointer of the method
- if is_method_unique:
- pointer = '&' + method.FullName()
- else:
- pointer = method.PointerDeclaration()
+ pointer = method._PointerDeclaration()
# Add policy to overloaded methods also
- policy = self.info[method.name].policy or ''
+ policy = self.info[method._name].policy or ''
if policy:
policy = ', %s%s()' % (namespaces.python, policy.Code())
@@ -805,14 +766,14 @@ class _VirtualWrapperGenerator(object):
'''
def IsVirtual(m):
return type(m) is Method and \
- m.virtual and \
- m.visibility != Scope.private
+ m._virtual and \
+ m._visibility != Scope.private
- all_methods = [x for x in self.class_.members if IsVirtual(x)]
+ all_methods = [x for x in self.class_ if IsVirtual(x)]
for base in self.bases:
- base_methods = [x.Copy() for x in base if IsVirtual(x)]
+ base_methods = [copy.deepcopy(x) for x in base if IsVirtual(x)]
for base_method in base_methods:
- base_method.class_ = self.class_.FullName()
+ base_method.class_ = self.class_._FullName()
all_methods.append(base_method)
# extract the virtual methods, avoiding duplications. The duplication
@@ -820,16 +781,16 @@ class _VirtualWrapperGenerator(object):
# that inherited members are correctly excluded if the subclass overrides
# them.
def MethodSig(method):
- if method.const:
+ if method._const:
const = 'const'
else:
const = ''
- if method.result:
- result = method.result.FullName()
+ if method._result:
+ result = method._result._FullName()
else:
result = ''
- params = ', '.join([x.FullName() for x in method.parameters])
- return '%s %s(%s) %s' % (result, method.name, params, const)
+ params = ', '.join([x._FullName() for x in method._parameters])
+ return '%s %s(%s) %s' % (result, method._name, params, const)
self.virtual_methods = []
already_added = {}
@@ -840,25 +801,16 @@ class _VirtualWrapperGenerator(object):
already_added[sig] = 0
- def IsMethodUnique(self, method):
- if not self._method_count:
- for m in self.virtual_methods:
- self._method_count[m.name] = self._method_count.get(m.name, 0) + 1
- return self._method_count[method] == 1
-
-
def Constructors(self):
- def IsValid(m):
- return isinstance(m, Constructor) and m.visibility == Scope.public
- return [m for m in self.class_.members if IsValid(m)]
+ return self.class_._Constructors(publics_only=True)
def GenerateDefinitions(self):
defs = []
for method in self.virtual_methods:
- exclude = self.info[method.name].exclude
+ exclude = self.info[method._name].exclude
# generate definitions only for public methods and non-abstract methods
- if method.visibility == Scope.public and not method.abstract and not exclude:
+ if method._visibility == Scope.public and not method._abstract and not exclude:
defs.extend(self.MethodDefinition(method))
return defs
@@ -867,13 +819,13 @@ class _VirtualWrapperGenerator(object):
'Return the wrapper for this class'
# generate the class code
- class_name = self.class_.FullName()
+ class_name = self.class_._FullName()
code = 'struct %s: %s\n' % (self.wrapper_name, class_name)
code += '{\n'
# generate constructors (with the overloads for each one)
for cons in self.Constructors(): # only public constructors
- minArgs = cons.minArgs
- maxArgs = cons.maxArgs
+ minArgs = cons._minArgs
+ maxArgs = cons._maxArgs
# from the min number of arguments to the max number, generate
# all version of the given constructor
cons_code = ''
@@ -889,7 +841,7 @@ class _VirtualWrapperGenerator(object):
# generate the body
body = []
for method in self.virtual_methods:
- if not self.info[method.name].exclude:
+ if not self.info[method._name].exclude:
body.append(self.Declaration(method, indent))
body = '\n'.join(body)
code += body + '\n'
diff --git a/pyste/src/EnumExporter.py b/pyste/src/EnumExporter.py
index c36b8888..6a76507c 100644
--- a/pyste/src/EnumExporter.py
+++ b/pyste/src/EnumExporter.py
@@ -21,16 +21,16 @@ class EnumExporter(Exporter):
if not self.info.exclude:
indent = self.INDENT
in_indent = self.INDENT*2
- rename = self.info.rename or self.enum.name
- full_name = self.enum.FullName()
+ rename = self.info.rename or self.enum._name
+ full_name = self.enum._FullName()
if rename == "$_0" or rename == '._0':
full_name = "int"
rename = "unnamed"
code = indent + namespaces.python
code += 'enum_< %s >("%s")\n' % (full_name, rename)
- for name in self.enum.values:
+ for name in self.enum._values:
rename = self.info[name].rename or name
- value_fullname = self.enum.ValueFullName(name)
+ value_fullname = self.enum._ValueFullName(name)
code += in_indent + '.value("%s", %s)\n' % (rename, value_fullname)
code += indent + ';\n\n'
codeunit.Write('module', code)
diff --git a/pyste/src/Exporter.py b/pyste/src/Exporter.py
index f37ed21e..8c6ed6bd 100644
--- a/pyste/src/Exporter.py
+++ b/pyste/src/Exporter.py
@@ -55,7 +55,7 @@ class Exporter:
def GetDeclarations(self, fullname):
decls = []
for decl in self.declarations:
- if decl.FullName() == fullname:
+ if decl._FullName() == fullname:
decls.append(decl)
if not decls:
raise RuntimeError, 'no %s declaration found!' % fullname
diff --git a/pyste/src/FunctionExporter.py b/pyste/src/FunctionExporter.py
index 927de474..50d80c0b 100644
--- a/pyste/src/FunctionExporter.py
+++ b/pyste/src/FunctionExporter.py
@@ -22,22 +22,19 @@ class FunctionExporter(Exporter):
decls = self.GetDeclarations(self.info.name)
for decl in decls:
self.info.policy = exporterutils.HandlePolicy(decl, self.info.policy)
- exporterutils.WarnForwardDeclarations(decl)
self.ExportDeclaration(decl, len(decls) == 1, codeunit)
self.ExportOpaquePointer(decl, codeunit)
self.GenerateOverloads(decls, codeunit)
def ExportDeclaration(self, decl, unique, codeunit):
- name = self.info.rename or decl.name
+ name = self.info.rename or decl._name
defs = namespaces.python + 'def("%s", ' % name
wrapper = self.info.wrapper
if wrapper:
pointer = '&' + wrapper.FullName()
- elif not unique:
- pointer = decl.PointerDeclaration()
else:
- pointer = '&' + decl.FullName()
+ pointer = decl._PointerDeclaration()
defs += pointer
defs += self.PolicyCode()
overload = self.OverloadName(decl)
@@ -51,9 +48,9 @@ class FunctionExporter(Exporter):
def OverloadName(self, decl):
- if decl.minArgs != decl.maxArgs:
+ if decl._minArgs != decl._maxArgs:
return '%s_overloads_%i_%i' % \
- (decl.name, decl.minArgs, decl.maxArgs)
+ (decl._name, decl._minArgs, decl._maxArgs)
else:
return ''
@@ -64,7 +61,7 @@ class FunctionExporter(Exporter):
overload = self.OverloadName(decl)
if overload and overload not in codes:
code = 'BOOST_PYTHON_FUNCTION_OVERLOADS(%s, %s, %i, %i)' %\
- (overload, decl.FullName(), decl.minArgs, decl.maxArgs)
+ (overload, decl._FullName(), decl._minArgs, decl_.maxArgs)
codeunit.Write('declaration', code + '\n')
codes[overload] = None
@@ -80,7 +77,7 @@ class FunctionExporter(Exporter):
def ExportOpaquePointer(self, function, codeunit):
if self.info.policy == return_value_policy(return_opaque_pointer):
- type = function.result.name
+ type = function._result._name
macro = 'BOOST_PYTHON_OPAQUE_SPECIALIZED_TYPE_ID(%s)' % type
if macro not in self._exported_opaque_pointers:
codeunit.Write('declaration-outside', macro)
diff --git a/pyste/src/GCCXMLParser.py b/pyste/src/GCCXMLParser.py
index 31b6814b..54a34485 100644
--- a/pyste/src/GCCXMLParser.py
+++ b/pyste/src/GCCXMLParser.py
@@ -5,6 +5,9 @@ from copy import deepcopy
from utils import enumerate
+#==============================================================================
+# Exceptions
+#==============================================================================
class InvalidXMLError(Exception): pass
class ParserError(Exception): pass
@@ -12,6 +15,9 @@ class ParserError(Exception): pass
class InvalidContextError(ParserError): pass
+#==============================================================================
+# GCCXMLParser
+#==============================================================================
class GCCXMLParser(object):
'Parse a GCC_XML file and extract the top-level declarations.'
@@ -21,6 +27,7 @@ class GCCXMLParser(object):
self.elements = self.GetElementsFromXML(filename)
# high level declarations
self.declarations = []
+ self._names = {}
# parse the elements
for id in self.elements:
element, decl = self.elements[id]
@@ -37,6 +44,12 @@ class GCCXMLParser(object):
def AddDecl(self, decl):
+ if decl._FullName() in self._names:
+ decl._is_unique= False
+ for d in self.declarations:
+ if d._FullName() == decl._FullName():
+ d._is_unique = False
+ self._names[decl._FullName()] = 0
self.declarations.append(decl)
@@ -102,18 +115,17 @@ class GCCXMLParser(object):
restricted, id = Check(id, 'r')
decl = self.GetDecl(id)
if isinstance(decl, Type):
- res = decl.Copy()
+ res = deepcopy(decl)
if const:
- res.const = const
+ res._const = const
if volatile:
- res.volatile = volatile
+ res._volatile = volatile
if restricted:
- res.restricted = restricted
+ res._restricted = restricted
else:
- res = Type(decl.FullName(), const)
- res.volatile = volatile
- res.restricted = restricted
- res.incomplete = decl.incomplete
+ res = Type(decl._FullName(), const)
+ res._volatile = volatile
+ res._restricted = restricted
return res
@@ -130,8 +142,7 @@ class GCCXMLParser(object):
def ParseUnknown(self, id, element):
name = '__Unknown_Element_%s' % id
- namespace = '::'
- decl = Declaration(name, namespace)
+ decl = Unknown(name)
self.Update(id, decl)
@@ -139,10 +150,10 @@ class GCCXMLParser(object):
namespace = element.get('name')
context = element.get('context')
if context:
- outerns = self.GetDecl(context)
- if not outerns.endswith('::'):
- outerns += '::'
- namespace = outerns + namespace
+ outer = self.GetDecl(context)
+ if not outer.endswith('::'):
+ outer += '::'
+ namespace = outer + namespace
if namespace.startswith('::'):
namespace = namespace[2:]
self.Update(id, namespace)
@@ -155,19 +166,19 @@ class GCCXMLParser(object):
def ParseVariable(self, id, element):
# in gcc_xml, a static Field is declared as a Variable, so we check
- # this and call the Field parser if apply.
+ # this and call the Field parser.
context = self.GetDecl(element.get('context'))
if isinstance(context, Class):
self.ParseField(id, element)
elem, decl = self.elements[id]
- decl.static = True
+ decl._static = True
else:
namespace = context
name = element.get('name')
type_ = self.GetType(element.get('type'))
location = self.GetLocation(element.get('location'))
variable = Variable(type_, name, namespace)
- variable.location = location
+ variable._location = location
self.AddDecl(variable)
self.Update(id, variable)
@@ -176,9 +187,9 @@ class GCCXMLParser(object):
args = []
for child in element:
if child.tag == 'Argument':
- type_ = self.GetType(child.get('type'))
- type_.default = child.get('default')
- args.append(type_)
+ type = self.GetType(child.get('type'))
+ type._default = child.get('default')
+ args.append(type)
return args
@@ -190,8 +201,9 @@ class GCCXMLParser(object):
namespace = self.GetDecl(element.get('context'))
location = self.GetLocation(element.get('location'))
params = self.GetArguments(element)
+ incomplete = bool(int(element.get('incomplete', 0)))
function = functionType(name, namespace, returns, params)
- function.location = location
+ function._location = location
self.AddDecl(function)
self.Update(id, function)
@@ -225,10 +237,10 @@ class GCCXMLParser(object):
# "Unimplemented" tag, but we are not interested in this classes
# anyway
continue
- base = Base(decl.FullName(), visib)
+ base = Base(decl._FullName(), visib)
this_level.append(base)
# normalize with the other levels
- for index, level in enumerate(decl.hierarchy):
+ for index, level in enumerate(decl._hierarchy):
if index < len(next_levels):
next_levels[index] = next_levels[index] + level
else:
@@ -256,25 +268,27 @@ class GCCXMLParser(object):
abstract = bool(int(element.get('abstract', '0')))
location = self.GetLocation(element.get('location'))
context = self.GetDecl(element.get('context'))
- incomplete = bool(element.get('incomplete', False))
+ incomplete = bool(int(element.get('incomplete', 0)))
if isinstance(context, str):
class_ = Class(name, context, [], abstract)
else:
# a nested class
visib = element.get('access', Scope.public)
class_ = NestedClass(
- name, context.FullName(), visib, [], abstract)
- self.AddDecl(class_)
+ name, context._FullName(), visib, [], abstract)
+ class_._incomplete = incomplete
# we have to add the declaration of the class before trying
# to parse its members and bases, to avoid recursion.
- class_.location = location
- class_.incomplete = incomplete
+ self.AddDecl(class_)
+ class_._location = location
self.Update(id, class_)
# now we can get the members and the bases
- class_.hierarchy = self.GetHierarchy(element.get('bases'))
- if class_.hierarchy:
- class_.bases = class_.hierarchy[0]
- class_.members = self.GetMembers(element.get('members'))
+ class_._hierarchy = self.GetHierarchy(element.get('bases'))
+ if class_._hierarchy:
+ class_._bases = class_._hierarchy[0]
+ members = self.GetMembers(element.get('members'))
+ for member in members:
+ class_._AddMember(member)
def ParseStruct(self, id, element):
@@ -288,26 +302,24 @@ class GCCXMLParser(object):
def ParseArrayType(self, id, element):
- type_ = self.GetType(element.get('type'))
+ type = self.GetType(element.get('type'))
min = element.get('min')
max = element.get('max')
- array = ArrayType(type_.name, type_.const)
- array.min = min
- array.max = max
+ array = ArrayType(type._name, type._const, min, max)
self.Update(id, array)
def ParseReferenceType(self, id, element):
- type_ = self.GetType(element.get('type'))
- expand = not isinstance(type_, FunctionType)
- ref = ReferenceType(type_.name, type_.const, None, type_.incomplete, expand)
+ type = self.GetType(element.get('type'))
+ expand = not isinstance(type, FunctionType)
+ ref = ReferenceType(type._name, type._const, None, expand, type._suffix)
self.Update(id, ref)
def ParsePointerType(self, id, element):
- type_ = self.GetType(element.get('type'))
- expand = not isinstance(type_, FunctionType)
- ref = PointerType(type_.name, type_.const, None, type_.incomplete, expand)
+ type = self.GetType(element.get('type'))
+ expand = not isinstance(type, FunctionType)
+ ref = PointerType(type._name, type._const, None, expand, type._suffix)
self.Update(id, ref)
@@ -319,7 +331,7 @@ class GCCXMLParser(object):
def ParseMethodType(self, id, element):
- class_ = self.GetDecl(element.get('basetype')).FullName()
+ class_ = self.GetDecl(element.get('basetype'))._FullName()
result = self.GetType(element.get('returns'))
args = self.GetArguments(element)
method = MethodType(result, args, class_)
@@ -329,19 +341,19 @@ class GCCXMLParser(object):
def ParseField(self, id, element):
name = element.get('name')
visib = element.get('access', Scope.public)
- classname = self.GetDecl(element.get('context')).FullName()
+ classname = self.GetDecl(element.get('context'))._FullName()
type_ = self.GetType(element.get('type'))
static = bool(int(element.get('extern', '0')))
location = self.GetLocation(element.get('location'))
var = ClassVariable(type_, name, classname, visib, static)
- var.location = location
+ var._location = location
self.Update(id, var)
def ParseMethod(self, id, element, methodType=Method):
name = element.get('name')
result = self.GetType(element.get('returns'))
- classname = self.GetDecl(element.get('context')).FullName()
+ classname = self.GetDecl(element.get('context'))._FullName()
visib = element.get('access', Scope.public)
static = bool(int(element.get('static', '0')))
virtual = bool(int(element.get('virtual', '0')))
@@ -351,7 +363,7 @@ class GCCXMLParser(object):
params = self.GetArguments(element)
method = methodType(
name, classname, result, params, visib, virtual, abstract, static, const)
- method.location = location
+ method._location = location
self.Update(id, method)
@@ -362,22 +374,22 @@ class GCCXMLParser(object):
def ParseConstructor(self, id, element):
name = element.get('name')
visib = element.get('access', Scope.public)
- classname = self.GetDecl(element.get('context')).FullName()
+ classname = self.GetDecl(element.get('context'))._FullName()
location = self.GetLocation(element.get('location'))
params = self.GetArguments(element)
ctor = Constructor(name, classname, params, visib)
- ctor.location = location
+ ctor._location = location
self.Update(id, ctor)
def ParseDestructor(self, id, element):
name = element.get('name')
visib = element.get('access', Scope.public)
- classname = self.GetDecl(element.get('context')).FullName()
+ classname = self.GetDecl(element.get('context'))._FullName()
virtual = bool(int(element.get('virtual', '0')))
location = self.GetLocation(element.get('location'))
des = Destructor(name, classname, visib, virtual)
- des.location = location
+ des._location = location
self.Update(id, des)
@@ -390,7 +402,7 @@ class GCCXMLParser(object):
type = self.GetType(element.get('type'))
context = self.GetDecl(element.get('context'))
if isinstance(context, Class):
- context = context.FullName()
+ context = context._FullName()
typedef = Typedef(type, name, context)
self.Update(id, typedef)
self.AddDecl(typedef)
@@ -400,41 +412,23 @@ class GCCXMLParser(object):
name = element.get('name')
location = self.GetLocation(element.get('location'))
context = self.GetDecl(element.get('context'))
+ incomplete = bool(int(element.get('incomplete', 0)))
if isinstance(context, str):
enum = Enumeration(name, context)
else:
visib = element.get('access', Scope.public)
- enum = ClassEnumeration(name, context.FullName(), visib)
+ enum = ClassEnumeration(name, context._FullName(), visib)
self.AddDecl(enum)
- enum.location = location
+ enum._location = location
for child in element:
if child.tag == 'EnumValue':
name = child.get('name')
value = int(child.get('init'))
- enum.values[name] = value
+ enum._values[name] = value
+ enum._incomplete = incomplete
self.Update(id, enum)
- def ParseUnimplemented(self, id, element):
- 'No idea of what this is'
- self.Update(id, Declaration('', ''))
-
-
- def ParseUnion(self, id, element):
- name = element.get('name')
- context = self.GetDecl(element.get('context'))
- location = self.GetLocation(element.get('location'))
- if isinstance(context, str):
- # a free union
- union = Union(name, context)
- self.AddDecl(union)
- else:
- visib = element.get('access', Scope.public)
- union = ClassUnion(name, context.FullName(), visib)
- union.location = location
- self.Update(id, union)
-
-
def ParseDeclarations(filename):
'Returns a list of the top declarations found in the gcc_xml file.'
diff --git a/pyste/src/HeaderExporter.py b/pyste/src/HeaderExporter.py
index 4449508b..b2f4e133 100644
--- a/pyste/src/HeaderExporter.py
+++ b/pyste/src/HeaderExporter.py
@@ -32,8 +32,8 @@ class HeaderExporter(Exporter):
header = os.path.normpath(self.parser_header)
for decl in self.declarations:
# check if this declaration is in the header
- location = os.path.normpath(decl.location[0])
- if location == header and not self.IsInternalName(decl.name):
+ location = os.path.normpath(decl._location[0])
+ if location == header and not self.IsInternalName(decl._name):
# ok, check the type of the declaration and export it accordingly
self.HandleDeclaration(decl, codeunit, exported_names)
@@ -57,9 +57,9 @@ class HeaderExporter(Exporter):
def HandleExporter(self, decl, exporter_type, codeunit, exported_names):
# only export complete declarations
- if not getattr(decl, "incomplete", False):
- info = self.info[decl.name]
- info.name = decl.FullName()
+ if not getattr(decl, "_incomplete", False):
+ info = self.info[decl._name]
+ info.name = decl._FullName()
info.include = self.info.include
exporter = exporter_type(info)
exporter.SetDeclarations(self.declarations)
@@ -69,7 +69,7 @@ class HeaderExporter(Exporter):
def Unit(self):
- return None # doesn't write anything by himself
+ return None # doesn't write anything by itself
def Order(self):
diff --git a/pyste/src/VarExporter.py b/pyste/src/VarExporter.py
index 461551a2..89f1af40 100644
--- a/pyste/src/VarExporter.py
+++ b/pyste/src/VarExporter.py
@@ -16,7 +16,7 @@ class VarExporter(Exporter):
def Export(self, codeunit, exported_names):
if self.info.exclude: return
decl = self.GetDeclaration(self.info.name)
- if not decl.type.const:
+ if not decl._type._const:
msg = '---> Warning: The global variable "%s" is non-const:\n' \
' changes in Python will not reflect in C++.'
print msg % self.info.name
diff --git a/pyste/src/declarations.py b/pyste/src/declarations.py
index 20475058..79946aa6 100644
--- a/pyste/src/declarations.py
+++ b/pyste/src/declarations.py
@@ -1,305 +1,386 @@
'''
-Module declarations
-
- Defines classes that represent declarations found in C++ header files.
+Defines classes that represent declarations found in C++ header files.
'''
+#==============================================================================
+# Declaration
+#==============================================================================
class Declaration(object):
- 'Represents a basic declaration.'
+ '''Base class for all declarations.
+ @ivar _name: The name of the declaration.
+ @ivar _namespace: The namespace of the declaration.
+ '''
def __init__(self, name, namespace):
- # the declaration name
- self.name = name
- # all the namespaces, separated by '::' = 'boost::inner'
- self.namespace = namespace
- # tuple (filename, line)
- self.location = '', -1
- # if a declaration is incomplete it means that it was
- # forward declared
- self.incomplete = False
+ '''
+ @type name: string
+ @param name: The name of this declaration
+ @type namespace: string
+ @param namespace: the full namespace where this declaration resides.
+ '''
+ self._name = name
+ self._namespace = namespace
+ self._location = '', -1 # (filename, line)
+ self._incomplete = False
+ self._is_unique = True
- def FullName(self):
- 'Returns the full qualified name: "boost::inner::Test"'
- namespace = self.namespace or ''
- #if not namespace:
- # namespace = ''
+ def _FullName(self):
+ '''
+ Returns the full qualified name: "boost::inner::Test"
+ @rtype: string
+ @return: The full name of the declaration.
+ '''
+ namespace = self._namespace or ''
if namespace and not namespace.endswith('::'):
namespace += '::'
- return namespace + self.name
+ return namespace + self._name
def __repr__(self):
- return '' % (self.FullName(), id(self))
+ return '' % (self._FullName(), id(self))
def __str__(self):
- return 'Declaration of %s' % self.FullName()
+ return 'Declaration of %s' % self._FullName()
+#==============================================================================
+# Class
+#==============================================================================
class Class(Declaration):
- 'The declaration of a class or struct.'
+ '''
+ Represents a C++ class or struct. Iteration through it yields its members.
+
+ @type _abstract: bool
+ @ivar _abstract: if the class has any abstract methods.
+
+ @type _bases: tuple
+ @ivar _bases: tuple with L{Base} instances, representing the most direct
+ inheritance.
+
+ @type _hierarchy: list
+ @ivar _hierarchy: a list of tuples of L{Base} instances, representing
+ the entire hierarchy tree of this object. The first tuple is the parent
+ classes, and the other ones go up in the hierarchy.
+ '''
def __init__(self, name, namespace, members, abstract):
Declaration.__init__(self, name, namespace)
- # list of members
- self.members = members
- # whatever the class has any abstract methods
- self.abstract = abstract
- # instances of Base
- self.bases = ()
- self.hierarchy = ()
- self._members_count = {}
+ self.__members = members
+ self._abstract = abstract
+ self._bases = ()
+ self._hierarchy = ()
+ self.operator = {}
def __iter__(self):
- return iter(self.members)
+ '''iterates through the class' members.
+ '''
+ return iter(self.__members)
- def IsAbstract(self):
- 'Returns True if any method of this class is abstract'
- for member in self.members:
- if isinstance(member, Method):
- if member.abstract:
- return True
- return False
-
-
- def RawName(self):
- 'Returns the raw name of a template class. name = Foo, raw = Foo'
- lesspos = self.name.find('<')
- if lesspos != -1:
- return self.name[:lesspos]
- else:
- return self.name
-
-
- def Constructors(self, publics_only=True):
+ def _Constructors(self, publics_only=True):
+ '''Returns a list of the constructors for this class.
+ @rtype: list
+ '''
constructors = []
for member in self:
if isinstance(member, Constructor):
- if publics_only and member.visibility != Scope.public:
+ if publics_only and member._visibility != Scope.public:
continue
constructors.append(member)
return constructors
- def HasCopyConstructor(self):
- for cons in self.Constructors():
- if cons.IsCopy():
+ def _HasCopyConstructor(self):
+ '''Returns true if this class has a public copy constructor.
+ @rtype: bool
+ '''
+ for cons in self._Constructors():
+ if cons._IsCopy():
return True
return False
- def HasDefaultConstructor(self):
+ def _HasDefaultConstructor(self):
+ '''Returns true if this class has a public default constructor.
+ @rtype: bool
+ '''
for cons in self.Constructors():
- if cons.IsDefault():
+ if cons._IsDefault():
return True
return False
- def IsUnique(self, member_name):
- if not self._members_count:
- for m in self:
- self._members_count[m.name] = self._members_count.get(m.name, 0) + 1
- try:
- return self._members_count[member_name] == 1
- except KeyError:
- print self._members_count
- print 'Key', member_name
-
+ def _AddMember(self, member):
+ slot = getattr(self, member._name, [])
+ if slot:
+ member._is_unique = False
+ for m in slot:
+ m._is_unique = False
+ slot.append(member)
+ setattr(self, member._name, slot)
+ self.__members.append(member)
+ if isinstance(member, ClassOperator):
+ self.operator[member._name] = member
+
+#==============================================================================
+# NestedClass
+#==============================================================================
class NestedClass(Class):
- 'The declaration of a class/struct inside another class/struct.'
+ '''The declaration of a class/struct inside another class/struct.
+
+ @type _class: string
+ @ivar _class: fullname of the class where this class is contained.
- def __init__(self, name, class_, visib, members, abstract):
+ @type _visibility: L{Scope}
+ @ivar _visibility: the visibility of this class.
+ '''
+
+ def __init__(self, name, _class, visib, members, abstract):
Class.__init__(self, name, None, members, abstract)
- self.class_ = class_
- self.visibility = visib
+ self._class = _class
+ self._visibility = visib
- def FullName(self):
- return '%s::%s' % (self.class_, self.name)
+ def _FullName(self):
+ '''The full name of this class, like ns::outer::inner.
+ @rtype: string
+ '''
+ return '%s::%s' % (self._class, self._name)
-
-class Base:
- 'Represents a base class of another class.'
-
- def __init__(self, name, visibility=None):
- # class_ is the full name of the base class
- self.name = name
- # visibility of the derivation
- if visibility is None:
- visibility = Scope.public
- self.visibility = visibility
-
-
-
-class Scope:
+#==============================================================================
+# Scope
+#==============================================================================
+class Scope:
+ '''Used to represent the visibility of various members inside a class.
+ @cvar public: public visibility
+ @cvar private: private visibility
+ @cvar protected: protected visibility
+ '''
public = 'public'
private = 'private'
protected = 'protected'
+
+
+#==============================================================================
+# Base
+#==============================================================================
+class Base:
+ '''Represents a base class of another class.
+ @ivar _name: the full name of the base class.
+ @ivar _visibility: the visibility of the derivation.
+ '''
+ def __init__(self, name, visibility=Scope.public):
+ self._name = name
+ self._visibility = visibility
+#==============================================================================
+# Function
+#==============================================================================
class Function(Declaration):
- 'The declaration of a function.'
+ '''The declaration of a function.
+ @ivar _result: instance of L{Type} or None.
+ @ivar _parameters: list of L{Type} instances.
+ '''
def __init__(self, name, namespace, result, params):
Declaration.__init__(self, name, namespace)
# the result type: instance of Type, or None (constructors)
- self.result = result
+ self._result = result
# the parameters: instances of Type
- self.parameters = params
+ self._parameters = params
- def PointerDeclaration(self):
- 'returns a declaration of a pointer to this function'
- result = self.result.FullName()
- params = ', '.join([x.FullName() for x in self.parameters])
- return '(%s (*)(%s))&%s' % (result, params, self.FullName())
+ def _PointerDeclaration(self, force=False):
+ '''Returns a declaration of a pointer to this function.
+ @param force: If True, returns a complete pointer declaration regardless
+ if this function is unique or not.
+ '''
+ if self._is_unique and not force:
+ return '&%s' % self._FullName()
+ else:
+ result = self._result._FullName()
+ params = ', '.join([x._FullName() for x in self._parameters])
+ return '(%s (*)(%s))&%s' % (result, params, self._FullName())
def _MinArgs(self):
min = 0
- for arg in self.parameters:
- if arg.default is None:
+ for arg in self._parameters:
+ if arg._default is None:
min += 1
return min
- minArgs = property(_MinArgs)
+ _minArgs = property(_MinArgs)
def _MaxArgs(self):
- return len(self.parameters)
+ return len(self._parameters)
- maxArgs = property(_MaxArgs)
+ _maxArgs = property(_MaxArgs)
- def Copy(self):
- return self.__class__(
- self.name, self.namespace, self.result, self.params[:])
-
-
+
+#==============================================================================
+# Operator
+#==============================================================================
class Operator(Function):
- 'The declaration of a custom operator.'
+ '''The declaration of a custom operator. Its name is the same as the
+ operator name in C++, ie, the name of the declaration "operator+(..)" is
+ "+".
+ '''
- def FullName(self):
- namespace = self.namespace or ''
+ def _FullName(self):
+ namespace = self._namespace or ''
if not namespace.endswith('::'):
namespace += '::'
- return namespace + 'operator' + self.name
+ return namespace + 'operator' + self._name
+#==============================================================================
+# Method
+#==============================================================================
class Method(Function):
- 'The declaration of a method.'
+ '''The declaration of a method.
+
+ @ivar _visibility: the visibility of this method.
+ @ivar _virtual: if this method is declared as virtual.
+ @ivar _abstract: if this method is virtual but has no default implementation.
+ @ivar _static: if this method is static.
+ @ivar _class: the full name of the class where this method was declared.
+ @ivar _const: if this method is declared as const.
+ '''
def __init__(self, name, class_, result, params, visib, virtual, abstract, static, const):
Function.__init__(self, name, None, result, params)
- self.visibility = visib
- self.virtual = virtual
- self.abstract = abstract
- self.static = static
- self.class_ = class_
- self.const = const
+ self._visibility = visib
+ self._virtual = virtual
+ self._abstract = abstract
+ self._static = static
+ self._class = class_
+ self._const = const
- def FullName(self):
- return self.class_ + '::' + self.name
+ def _FullName(self):
+ return self._class + '::' + self._name
- def PointerDeclaration(self):
- 'returns a declaration of a pointer to this function'
- if self.static:
+ def _PointerDeclaration(self, force=False):
+ '''Returns a declaration of a pointer to this member function.
+ @param force: If True, returns a complete pointer declaration regardless
+ if this function is unique or not.
+ '''
+ if self._static:
# static methods are like normal functions
- return Function.PointerDeclaration(self)
+ return Function._PointerDeclaration(self, force)
+ if self._is_unique and not force:
+ return '&%s' % self._FullName()
else:
- # using syntax of methods
- result = self.result.FullName()
- params = ', '.join([x.FullName() for x in self.parameters])
+ result = self._result._FullName()
+ params = ', '.join([x._FullName() for x in self._parameters])
const = ''
- if self.const:
+ if self._const:
const = 'const'
return '(%s (%s::*)(%s) %s)&%s' %\
- (result, self.class_, params, const, self.FullName())
+ (result, self._class, params, const, self._FullName())
- def Copy(self):
- return self.__class__(
- self.name,
- self.class_,
- self.result,
- self.parameters[:],
- self.visibility,
- self.virtual,
- self.abstract,
- self.static,
- self.const)
-
-
+#==============================================================================
+# Constructor
+#==============================================================================
class Constructor(Method):
- 'A constructor of a class.'
+ '''A class' constructor.
+ '''
def __init__(self, name, class_, params, visib):
Method.__init__(self, name, class_, None, params, visib, False, False, False, False)
- def IsDefault(self):
- return len(self.parameters) == 0
+ def _IsDefault(self):
+ '''Returns True if this constructor is a default constructor.
+ '''
+ return len(self._parameters) == 0 and self._visibility == Scope.public
- def IsCopy(self):
- if len(self.parameters) != 1:
+ def _IsCopy(self):
+ '''Returns True if this constructor is a copy constructor.
+ '''
+ if len(self._parameters) != 1:
return False
- param = self.parameters[0]
- class_as_param = self.parameters[0].name == self.class_
+ param = self._parameters[0]
+ class_as_param = self._parameters[0]._name == self._class
param_reference = isinstance(param, ReferenceType)
- return param_reference and class_as_param and param.const
+ is_public = self._visibility = Scope.public
+ return param_reference and class_as_param and param._const and is_public
+#==============================================================================
+# Destructor
+#==============================================================================
class Destructor(Method):
'The destructor of a class.'
def __init__(self, name, class_, visib, virtual):
Method.__init__(self, name, class_, None, [], visib, virtual, False, False, False)
- def FullName(self):
- return self.class_ + '::~' + self.name
+ def _FullName(self):
+ return self._class + '::~' + self._name
+#==============================================================================
+# ClassOperator
+#==============================================================================
class ClassOperator(Method):
- 'The declaration of a custom operator in a class.'
+ 'A custom operator in a class.'
- def FullName(self):
- return self.class_ + '::operator ' + self.name
+ def _FullName(self):
+ return self._class + '::operator ' + self._name
-
+
+#==============================================================================
+# ConverterOperator
+#==============================================================================
class ConverterOperator(ClassOperator):
'An operator in the form "operator OtherClass()".'
- def FullName(self):
- return self.class_ + '::operator ' + self.result.FullName()
+ def _FullName(self):
+ return self._class + '::operator ' + self._result._FullName()
+#==============================================================================
+# Type
+#==============================================================================
class Type(Declaration):
- 'Represents a type.'
+ '''Represents the type of a variable or parameter.
+ @ivar _const: if the type is constant.
+ @ivar _default: if this type has a default value associated with it.
+ @ivar _volatile: if this type was declared with the keyword volatile.
+ @ivar _restricted: if this type was declared with the keyword restricted.
+ @ivar _suffix: Suffix to get the full type name. '*' for pointers, for
+ example.
+ '''
- def __init__(self, name, const=False, default=None, incomplete=False):
+ def __init__(self, name, const=False, default=None, suffix=''):
Declaration.__init__(self, name, None)
# whatever the type is constant or not
- self.const = const
+ self._const = const
# used when the Type is a function argument
- self.default = default
- self.volatile = False
- self.restricted = False
- self.incomplete = incomplete
+ self._default = default
+ self._volatile = False
+ self._restricted = False
+ self._suffix = suffix
def __repr__(self):
if self.const:
@@ -309,166 +390,171 @@ class Type(Declaration):
return ''
- def FullName(self):
- if self.const:
+ def _FullName(self):
+ if self._const:
const = 'const '
else:
const = ''
- return const + self.name
-
-
- def Copy(self):
- t = self.__class__(self.name, self.const, self.default, self.incomplete)
- t.volatile = self.volatile
- t.restricted = self.restricted
- return t
+ return const + self._name + self._suffix
+#==============================================================================
+# ArrayType
+#==============================================================================
class ArrayType(Type):
- 'Represents an array.'
+ '''Represents an array.
+ @ivar min: the lower bound of the array, usually 0. Can be None.
+ @ivar max: the upper bound of the array. Can be None.
+ '''
- def __init__(self, name, const=False, default=None, incomplete=False):
+ def __init__(self, name, const, min, max):
'min and max can be None.'
Type.__init__(self, name, const)
- self.min = None
- self.max = None
-
- def Copy(self):
- t = Type.Copy(self)
- t.min = self.min
- t.max = self.max
- return t
+ self.min = min
+ self.max = max
-
+
+#==============================================================================
+# ReferenceType
+#==============================================================================
class ReferenceType(Type):
- 'A reference type.'
+ '''A reference type.'''
- def __init__(self, name, const=False, default=None, incomplete=False, expandRef=True):
- Type.__init__(self, name, const, default, incomplete)
- self.expand = expandRef
+ def __init__(self, name, const=False, default=None, expandRef=True, suffix=''):
+ Type.__init__(self, name, const, default)
+ if expandRef:
+ self._suffix = suffix + '&'
- def FullName(self):
- 'expand is False for function pointers'
- expand = ' &'
- if not self.expand:
- expand = ''
- return Type.FullName(self) + expand
-
-
- def Copy(self):
- t = Type.Copy(self)
- t.expand = self.expand
- return t
-
-
-
+#==============================================================================
+# PointerType
+#==============================================================================
class PointerType(Type):
'A pointer type.'
- def __init__(self, name, const=False, default=None, incomplete=False, expandPointer=False):
- Type.__init__(self, name, const, default, incomplete)
- self.expand = expandPointer
-
-
- def FullName(self):
- 'expand is False for function pointer'
- expand = ' *'
- if not self.expand:
- expand = ''
- return Type.FullName(self) + expand
-
- def Copy(self):
- t = Type.Copy(self)
- t.expand = self.expand
- return t
+ def __init__(self, name, const=False, default=None, expandPointer=False, suffix=''):
+ Type.__init__(self, name, const, default)
+ if expandPointer:
+ self._suffix = suffix + '*'
-
+#==============================================================================
+# FundamentalType
+#==============================================================================
class FundamentalType(Type):
- 'One of the fundamental types (int, void...).'
+ 'One of the fundamental types, like int, void, etc.'
- def __init__(self, name, const=False, default=None, incomplete=False):
- Type.__init__(self, name, const, default, incomplete)
+ def __init__(self, name, const=False, default=None):
+ Type.__init__(self, name, const, default)
+#==============================================================================
+# FunctionType
+#==============================================================================
class FunctionType(Type):
- 'A pointer to a function.'
+ '''A pointer to a function.
+ @ivar _result: the return value
+ @ivar _parameters: a list of Types, indicating the parameters of the function.
+ @ivar _name: the name of the function.
+ '''
def __init__(self, result, parameters):
Type.__init__(self, '', False)
- self.result = result
- self.parameters = parameters
- self.name = self.FullName()
+ self._result = result
+ self._parameters = parameters
+ self._name = self._FullName()
- def FullName(self):
- full = '%s (*)' % self.result.FullName()
- params = [x.FullName() for x in self.parameters]
+ def _FullName(self):
+ full = '%s (*)' % self._result._FullName()
+ params = [x._FullName() for x in self._parameters]
full += '(%s)' % ', '.join(params)
return full
- def Copy(self):
- return FunctionType(self.result, self.parameters[:])
-
-
+#==============================================================================
+# MethodType
+#==============================================================================
class MethodType(FunctionType):
- 'A pointer to a member function of a class.'
+ '''A pointer to a member function of a class.
+ @ivar _class: The fullname of the class that the method belongs to.
+ '''
def __init__(self, result, parameters, class_):
- Type.__init__(self, '', False)
- self.result = result
- self.parameters = parameters
- self.class_ = class_
- self.name = self.FullName()
+ self._class = class_
+ FunctionType.__init__(self, result, parameters)
- def FullName(self):
- full = '%s (%s::*)' % (self.result.FullName(), self.class_)
- params = [x.FullName() for x in self.parameters]
+
+ def _FullName(self):
+ full = '%s (%s::*)' % (self._result._FullName(), self._class)
+ params = [x._FullName() for x in self._parameters]
full += '(%s)' % ', '.join(params)
return full
- def Copy(self):
- return MethodType(self.result, self.parameters[:], self.class_)
-
+#==============================================================================
+# Variable
+#==============================================================================
class Variable(Declaration):
- 'Represents a global variable.'
+ '''Represents a global variable.
+
+ @type _type: L{Type}
+ @ivar _type: The type of the variable.
+ '''
def __init__(self, type, name, namespace):
Declaration.__init__(self, name, namespace)
- # instance of Type
- self.type = type
-
+ self._type = type
+#==============================================================================
+# ClassVariable
+#==============================================================================
class ClassVariable(Variable):
- 'Represents a class variable.'
+ '''Represents a class variable.
+
+ @type _visibility: L{Scope}
+ @ivar _visibility: The visibility of this variable within the class.
+
+ @type _static: bool
+ @ivar _static: Indicates if the variable is static.
+
+ @ivar _class: Full name of the class that this variable belongs to.
+ '''
def __init__(self, type, name, class_, visib, static):
Variable.__init__(self, type, name, None)
- self.visibility = visib
- self.static = static
- self.class_ = class_
+ self._visibility = visib
+ self._static = static
+ self._class = class_
- def FullName(self):
- return self.class_ + '::' + self.name
+ def _FullName(self):
+ return self._class + '::' + self._name
-
+#==============================================================================
+# Enumeration
+#==============================================================================
class Enumeration(Declaration):
+ '''Represents an enum.
+
+ @type _values: dict of str => int
+ @ivar _values: holds the values for this enum.
+ '''
def __init__(self, name, namespace):
Declaration.__init__(self, name, namespace)
- self.values = {} # dict of str => int
+ self._values = {} # dict of str => int
- def ValueFullName(self, name):
- assert name in self.values
- namespace = self.namespace
+
+ def _ValueFullName(self, name):
+ '''Returns the full name for a value in the enum.
+ '''
+ assert name in self._values
+ namespace = self._namespace
if namespace:
namespace += '::'
return namespace + name
@@ -476,45 +562,52 @@ class Enumeration(Declaration):
class ClassEnumeration(Enumeration):
+ '''Represents an enum inside a class.
+
+ @ivar _class: The full name of the class where this enum belongs.
+ @ivar _visibility: The visibility of this enum inside his class.
+ '''
def __init__(self, name, class_, visib):
Enumeration.__init__(self, name, None)
- self.class_ = class_
- self.visibility = visib
+ self._class = class_
+ self._visibility = visib
- def FullName(self):
- return '%s::%s' % (self.class_, self.name)
+ def _FullName(self):
+ return '%s::%s' % (self._class, self._name)
- def ValueFullName(self, name):
- assert name in self.values
- return '%s::%s' % (self.class_, name)
+ def _ValueFullName(self, name):
+ assert name in self._values
+ return '%s::%s' % (self._class, name)
-
+#==============================================================================
+# Typedef
+#==============================================================================
class Typedef(Declaration):
+ '''A Typedef declaration.
+
+ @type _type: L{Type}
+ @ivar _type: The type of the typedef.
+
+ @type _visibility: L{Scope}
+ @ivar _visibility: The visibility of this typedef.
+ '''
def __init__(self, type, name, namespace):
Declaration.__init__(self, name, namespace)
- self.type = type
- self.visibility = Scope.public
+ self._type = type
+ self._visibility = Scope.public
-class Union(Declaration):
- 'Shallow declaration, because Unions are not supported yet'
- def __init__(self, name, namespace):
- Declaration.__init__(self, name, namespace)
-
-
-class ClassUnion(Union):
-
- def __init__(self, name, class_, visib):
- Union.__init__(self, name, None)
- self.class_ = class_
- self.visibility = visib
-
- def FullName(self):
- return '%s::%s' % (self.class_, self.name)
-
+#==============================================================================
+# Unknown
+#==============================================================================
+class Unknown(Declaration):
+ '''A declaration that Pyste does not know how to handle.
+ '''
+ def __init__(self, name):
+ Declaration.__init__(self, name, None)
diff --git a/pyste/src/exporterutils.py b/pyste/src/exporterutils.py
index 27bdd095..1598edfd 100644
--- a/pyste/src/exporterutils.py
+++ b/pyste/src/exporterutils.py
@@ -41,17 +41,17 @@ def HandlePolicy(function, policy):
def IsString(type):
'Return True if the Type instance can be considered a string'
- return type.const and type.name == 'char' and isinstance(type, PointerType)
+ return type._FullName() == 'const char*'
def IsPyObject(type):
- return type.FullName() == '_object *' # internal name of PyObject
+ return type._FullName() == '_object *' # internal name of PyObject
- result = function.result
+ result = function._result
# if the function returns const char*, a policy is not needed
if IsString(result) or IsPyObject(result):
return policy
# if returns a const T&, set the default policy
- if policy is None and result.const and isinstance(result, ReferenceType):
+ if policy is None and result._const and isinstance(result, ReferenceType):
policy = return_value_policy(copy_const_reference)
# basic test if the result type demands a policy
needs_policy = isinstance(result, (ReferenceType, PointerType))
@@ -59,7 +59,7 @@ def HandlePolicy(function, policy):
if needs_policy and policy is None:
global _printed_warnings
warning = '---> Error: %s returns a pointer or a reference, ' \
- 'but no policy was specified.' % function.FullName()
+ 'but no policy was specified.' % function._FullName()
if warning not in _printed_warnings:
print warning
print
@@ -69,23 +69,4 @@ def HandlePolicy(function, policy):
-#==============================================================================
-# WarnForwardDeclarations
-#==============================================================================
-def WarnForwardDeclarations(function):
- '''Checks if any of the parameters or the result of the function are
- incomplete types.'''
- types = [function.result] + function.parameters
- types = [x for x in types if x]
- for type in types:
- if type.incomplete:
- msg = '---> Error: %s is forward declared. Please include the ' \
- 'appropriate header with its definition' % type.name
- # disable this for now... it was reporting too many false
- # forward declarations to be useful
- if 0 and msg not in _printed_warnings:
- print msg
- print
- _printed_warnings[msg] = 1
-
diff --git a/pyste/src/pyste.py b/pyste/src/pyste.py
index 8118b0ca..0f6cb158 100644
--- a/pyste/src/pyste.py
+++ b/pyste/src/pyste.py
@@ -39,7 +39,7 @@ from policies import *
from CppParser import CppParser, CppParserError
import time
-__VERSION__ = '0.9.5'
+__VERSION__ = '0.9.6'
def RecursiveIncludes(include):
'Return a list containg the include dir and all its subdirectories'
diff --git a/pyste/src/utils.py b/pyste/src/utils.py
index 67c2933d..0943762b 100644
--- a/pyste/src/utils.py
+++ b/pyste/src/utils.py
@@ -1,5 +1,6 @@
from __future__ import generators
import string
+import sys
#==============================================================================
# enumerate
@@ -45,3 +46,24 @@ def remove_duplicated_lines(text):
def left_equals(s):
s = '// %s ' % s
return s + ('='*(80-len(s))) + '\n'
+
+
+#==============================================================================
+# post_mortem
+#==============================================================================
+def post_mortem():
+
+ def info(type, value, tb):
+ if hasattr(sys, 'ps1') or not sys.stderr.isatty():
+ # we are in interactive mode or we don't have a tty-like
+ # device, so we call the default hook
+ sys.__excepthook__(type, value, tb)
+ else:
+ import traceback, pdb
+ # we are NOT in interactive mode, print the exception...
+ traceback.print_exception(type, value, tb)
+ print
+ # ...then start the debugger in post-mortem mode.
+ pdb.pm()
+
+ sys.excepthook = info
diff --git a/pyste/tests/GCCXMLParserUT.py b/pyste/tests/GCCXMLParserUT.py
index 3e4d0c0c..4734716b 100644
--- a/pyste/tests/GCCXMLParserUT.py
+++ b/pyste/tests/GCCXMLParserUT.py
@@ -1,5 +1,5 @@
import sys
-sys.path.append('..')
+sys.path.append('../src')
import unittest
import tempfile
import os.path
@@ -11,36 +11,36 @@ class Tester(unittest.TestCase):
def TestConstructor(self, class_, method, visib):
self.assert_(isinstance(method, Constructor))
- self.assertEqual(method.FullName(), class_.FullName() + '::' + method.name)
- self.assertEqual(method.result, None)
- self.assertEqual(method.visibility, visib)
- self.assert_(not method.virtual)
- self.assert_(not method.abstract)
- self.assert_(not method.static)
+ self.assertEqual(method._FullName(), class_._FullName() + '::' + method._name)
+ self.assertEqual(method._result, None)
+ self.assertEqual(method._visibility, visib)
+ self.assert_(not method._virtual)
+ self.assert_(not method._abstract)
+ self.assert_(not method._static)
def TestDefaultConstructor(self, class_, method, visib):
self.TestConstructor(class_, method, visib)
- self.assert_(method.IsDefault())
+ self.assert_(method._IsDefault())
def TestCopyConstructor(self, class_, method, visib):
self.TestConstructor(class_, method, visib)
- self.assertEqual(len(method.parameters), 1)
- param = method.parameters[0]
+ self.assertEqual(len(method._parameters), 1)
+ param = method._parameters[0]
self.TestType(
param,
ReferenceType,
- class_.FullName(),
- 'const %s &' % class_.FullName(),
+ class_._FullName(),
+ 'const %s&' % class_._FullName(),
True)
- self.assert_(method.IsCopy())
+ self.assert_(method._IsCopy())
def TestType(self, type_, classtype_, name, fullname, const):
self.assert_(isinstance(type_, classtype_))
- self.assertEqual(type_.name, name)
- self.assertEqual(type_.namespace, None)
- self.assertEqual(type_.FullName(), fullname)
- self.assertEqual(type_.const, const)
+ self.assertEqual(type_._name, name)
+ self.assertEqual(type_._namespace, None)
+ self.assertEqual(type_._FullName(), fullname)
+ self.assertEqual(type_._const, const)
class ClassBaseTest(Tester):
@@ -51,49 +51,48 @@ class ClassBaseTest(Tester):
def testClass(self):
'test the properties of the class Base'
self.assert_(isinstance(self.base, Class))
- self.assert_(self.base.abstract)
- self.assertEqual(self.base.RawName(), 'Base')
+ self.assert_(self.base._abstract)
def testFoo(self):
'test function foo in class Base'
foo = GetMember(self.base, 'foo')
self.assert_(isinstance(foo, Method))
- self.assertEqual(foo.visibility, Scope.public)
- self.assert_(foo.virtual)
- self.assert_(foo.abstract)
- self.failIf(foo.static)
- self.assertEqual(foo.class_, 'test::Base')
- self.failIf(foo.const)
- self.assertEqual(foo.FullName(), 'test::Base::foo')
- self.assertEqual(foo.result.name, 'void')
- self.assertEqual(len(foo.parameters), 1)
- param = foo.parameters[0]
+ self.assertEqual(foo._visibility, Scope.public)
+ self.assert_(foo._virtual)
+ self.assert_(foo._abstract)
+ self.failIf(foo._static)
+ self.assertEqual(foo._class, 'test::Base')
+ self.failIf(foo._const)
+ self.assertEqual(foo._FullName(), 'test::Base::foo')
+ self.assertEqual(foo._result._name, 'void')
+ self.assertEqual(len(foo._parameters), 1)
+ param = foo._parameters[0]
self.TestType(param, FundamentalType, 'int', 'int', False)
- self.assertEqual(foo.namespace, None)
+ self.assertEqual(foo._namespace, None)
self.assertEqual(
- foo.PointerDeclaration(), '(void (test::Base::*)(int) )&test::Base::foo')
+ foo._PointerDeclaration(1), '(void (test::Base::*)(int) )&test::Base::foo')
def testX(self):
'test the member x in class Base'
x = GetMember(self.base, 'x')
- self.assertEqual(x.class_, 'test::Base')
- self.assertEqual(x.FullName(), 'test::Base::x')
- self.assertEqual(x.namespace, None)
- self.assertEqual(x.visibility, Scope.private)
- self.TestType(x.type, FundamentalType, 'int', 'int', False)
- self.assertEqual(x.static, False)
+ self.assertEqual(x._class, 'test::Base')
+ self.assertEqual(x._FullName(), 'test::Base::x')
+ self.assertEqual(x._namespace, None)
+ self.assertEqual(x._visibility, Scope.private)
+ self.TestType(x._type, FundamentalType, 'int', 'int', False)
+ self.assertEqual(x._static, False)
def testConstructors(self):
'test constructors in class Base'
constructors = GetMembers(self.base, 'Base')
for cons in constructors:
- if len(cons.parameters) == 0:
+ if len(cons._parameters) == 0:
self.TestDefaultConstructor(self.base, cons, Scope.public)
- elif len(cons.parameters) == 1: # copy constructor
+ elif len(cons._parameters) == 1: # copy constructor
self.TestCopyConstructor(self.base, cons, Scope.public)
- elif len(cons.parameters) == 2: # other constructor
- intp, floatp = cons.parameters
+ elif len(cons._parameters) == 2: # other constructor
+ intp, floatp = cons._parameters
self.TestType(intp, FundamentalType, 'int', 'int', False)
self.TestType(floatp, FundamentalType, 'float', 'float', False)
@@ -101,25 +100,25 @@ class ClassBaseTest(Tester):
'test function simple in class Base'
simple = GetMember(self.base, 'simple')
self.assert_(isinstance(simple, Method))
- self.assertEqual(simple.visibility, Scope.protected)
- self.assertEqual(simple.FullName(), 'test::Base::simple')
- self.assertEqual(len(simple.parameters), 1)
- param = simple.parameters[0]
- self.TestType(param, ReferenceType, 'std::string', 'const std::string &', True)
- self.TestType(simple.result, FundamentalType, 'bool', 'bool', False)
+ self.assertEqual(simple._visibility, Scope.protected)
+ self.assertEqual(simple._FullName(), 'test::Base::simple')
+ self.assertEqual(len(simple._parameters), 1)
+ param = simple._parameters[0]
+ self.TestType(param, ReferenceType, 'std::string', 'const std::string&', True)
+ self.TestType(simple._result, FundamentalType, 'bool', 'bool', False)
self.assertEqual(
- simple.PointerDeclaration(),
- '(bool (test::Base::*)(const std::string &) )&test::Base::simple')
+ simple._PointerDeclaration(1),
+ '(bool (test::Base::*)(const std::string&) )&test::Base::simple')
def testZ(self):
z = GetMember(self.base, 'z')
self.assert_(isinstance(z, Variable))
- self.assertEqual(z.visibility, Scope.public)
- self.assertEqual(z.FullName(), 'test::Base::z')
- self.assertEqual(z.type.name, 'int')
- self.assertEqual(z.type.const, False)
- self.assert_(z.static)
+ self.assertEqual(z._visibility, Scope.public)
+ self.assertEqual(z._FullName(), 'test::Base::z')
+ self.assertEqual(z._type._name, 'int')
+ self.assertEqual(z._type._const, False)
+ self.assert_(z._static)
class ClassTemplateTest(Tester):
@@ -130,19 +129,18 @@ class ClassTemplateTest(Tester):
def testClass(self):
'test the properties of the Template class'
self.assert_(isinstance(self.template, Class))
- self.assert_(not self.template.abstract)
- self.assertEqual(self.template.FullName(), 'Template')
- self.assertEqual(self.template.namespace, '')
- self.assertEqual(self.template.name, 'Template')
- self.assertEqual(self.template.RawName(), 'Template')
+ self.assert_(not self.template._abstract)
+ self.assertEqual(self.template._FullName(), 'Template')
+ self.assertEqual(self.template._namespace, '')
+ self.assertEqual(self.template._name, 'Template')
def testConstructors(self):
'test the automatic constructors of the class Template'
constructors = GetMembers(self.template, 'Template')
for cons in constructors:
- if len(cons.parameters) == 0:
+ if len(cons._parameters) == 0:
self.TestDefaultConstructor(self.template, cons, Scope.public)
- elif len(cons.parameters) == 1:
+ elif len(cons._parameters) == 1:
self.TestCopyConstructor(self.template, cons, Scope.public)
@@ -150,21 +148,21 @@ class ClassTemplateTest(Tester):
'test the class variable value'
value = GetMember(self.template, 'value')
self.assert_(isinstance(value, ClassVariable))
- self.assert_(value.name, 'value')
- self.TestType(value.type, FundamentalType, 'int', 'int', False)
- self.assert_(not value.static)
- self.assertEqual(value.visibility, Scope.public)
- self.assertEqual(value.class_, 'Template')
- self.assertEqual(value.FullName(), 'Template::value')
+ self.assert_(value._name, 'value')
+ self.TestType(value._type, FundamentalType, 'int', 'int', False)
+ self.assert_(not value._static)
+ self.assertEqual(value._visibility, Scope.public)
+ self.assertEqual(value._class, 'Template')
+ self.assertEqual(value._FullName(), 'Template::value')
def testBase(self):
'test the superclasses of Template'
- bases = self.template.bases
+ bases = self.template._bases
self.assertEqual(len(bases), 1)
base = bases[0]
self.assert_(isinstance(base, Base))
- self.assertEqual(base.name, 'test::Base')
- self.assertEqual(base.visibility, Scope.protected)
+ self.assertEqual(base._name, 'test::Base')
+ self.assertEqual(base._visibility, Scope.protected)
@@ -176,27 +174,27 @@ class FreeFuncTest(Tester):
def testFunc(self):
'test attributes of FreeFunc'
self.assert_(isinstance(self.func, Function))
- self.assertEqual(self.func.name, 'FreeFunc')
- self.assertEqual(self.func.FullName(), 'test::FreeFunc')
- self.assertEqual(self.func.namespace, 'test')
+ self.assertEqual(self.func._name, 'FreeFunc')
+ self.assertEqual(self.func._FullName(), 'test::FreeFunc')
+ self.assertEqual(self.func._namespace, 'test')
self.assertEqual(
- self.func.PointerDeclaration(),
- '(const test::Base & (*)(const std::string &, int))&test::FreeFunc')
+ self.func._PointerDeclaration(1),
+ '(const test::Base& (*)(const std::string&, int))&test::FreeFunc')
def testResult(self):
'test the return value of FreeFunc'
- res = self.func.result
- self.TestType(res, ReferenceType, 'test::Base', 'const test::Base &', True)
+ res = self.func._result
+ self.TestType(res, ReferenceType, 'test::Base', 'const test::Base&', True)
def testParameters(self):
'test the parameters of FreeFunc'
- self.assertEqual(len(self.func.parameters), 2)
- strp, intp = self.func.parameters
- self.TestType(strp, ReferenceType, 'std::string', 'const std::string &', True)
- self.assertEqual(strp.default, None)
+ self.assertEqual(len(self.func._parameters), 2)
+ strp, intp = self.func._parameters
+ self.TestType(strp, ReferenceType, 'std::string', 'const std::string&', True)
+ self.assertEqual(strp._default, None)
self.TestType(intp, FundamentalType, 'int', 'int', False)
- self.assertEqual(intp.default, '10')
+ self.assertEqual(intp._default, '10')
@@ -205,14 +203,14 @@ class testFunctionPointers(Tester):
def testMethodPointer(self):
'test declaration of a pointer-to-method'
meth = GetDecl('MethodTester')
- param = meth.parameters[0]
+ param = meth._parameters[0]
fullname = 'void (test::Base::*)(int)'
self.TestType(param, PointerType, fullname, fullname, False)
def testFunctionPointer(self):
'test declaration of a pointer-to-function'
func = GetDecl('FunctionTester')
- param = func.parameters[0]
+ param = func._parameters[0]
fullname = 'void (*)(int)'
self.TestType(param, PointerType, fullname, fullname, False)
@@ -297,7 +295,7 @@ declarations = GetDeclarations()
def GetDecl(name):
'returns one of the top declarations given its name'
for decl in declarations:
- if decl.name == name:
+ if decl._name == name:
return decl
else:
raise RuntimeError, 'Declaration not found: %s' % name
@@ -309,7 +307,7 @@ def GetMember(class_, name):
res = None
multipleFound = False
for member in class_:
- if member.name == name:
+ if member._name == name:
if res is not None:
multipleFound = True
break
@@ -317,7 +315,7 @@ def GetMember(class_, name):
if res is None or multipleFound:
raise RuntimeError, \
'No member or more than one member found in class %s: %s' \
- % (class_.name, name)
+ % (class_._name, name)
return res
@@ -325,12 +323,12 @@ def GetMembers(class_, name):
'gets the members of the given class by its name'
res = []
for member in class_:
- if member.name == name:
+ if member._name == name:
res.append(member)
if len(res) in (0, 1):
raise RuntimeError, \
'GetMembers: 0 or 1 members found in class %s: %s' \
- % (class_.name, name)
+ % (class_._name, name)
return res
diff --git a/pyste/tests/basic.h b/pyste/tests/basic.h
index 5ab6ca58..f3d0f241 100644
--- a/pyste/tests/basic.h
+++ b/pyste/tests/basic.h
@@ -19,10 +19,12 @@ struct C
return x+1;
}
- const std::string& name() { return _name; }
- void set_name(const std::string& name) { _name = name; }
- std::string _name;
+ const std::string& get_name() { return name; }
+ void set_name(const std::string& name) { this->name = name; }
+private:
+ std::string name;
+public:
// test data members
static int static_value;
static const int const_static_value;
diff --git a/pyste/tests/operators.h b/pyste/tests/operators.h
index a9d3759e..30ec8ecf 100644
--- a/pyste/tests/operators.h
+++ b/pyste/tests/operators.h
@@ -2,8 +2,6 @@
#define OPERATORS_H
-#include
-
namespace operators {
struct C
diff --git a/pyste/tests/test_all.py b/pyste/tests/test_all.py
index 20f1c2f6..d3e1029b 100644
--- a/pyste/tests/test_all.py
+++ b/pyste/tests/test_all.py
@@ -118,7 +118,7 @@ if __name__ == '__main__':
else:
module = None
try:
- main('--multiple', module)
+ #main('--multiple', module)
main('', module)
except RuntimeError, e:
print e
diff --git a/pyste/tests/unions.h b/pyste/tests/unions.h
deleted file mode 100644
index 06287dec..00000000
--- a/pyste/tests/unions.h
+++ /dev/null
@@ -1,16 +0,0 @@
-namespace unions {
-
-class UnionTest
-{
-public:
- union // unions are not supported for now
- {
- int i;
- short s1;
- short s2;
- } mBad;
-
- int mGood;
-};
-
-}
diff --git a/pyste/tests/unions.pyste b/pyste/tests/unions.pyste
deleted file mode 100644
index 726ab6a2..00000000
--- a/pyste/tests/unions.pyste
+++ /dev/null
@@ -1,2 +0,0 @@
-UnionTest = Class('unions::UnionTest', 'unions.h')
-exclude(UnionTest.mBad)