Skip to content

Commit

Permalink
Added functions to the new converters API to check if a type is value…
Browse files Browse the repository at this point in the history
… or object.

Comes with unit tests.
  • Loading branch information
Marcelo Lira committed Dec 9, 2011
1 parent fd34818 commit d427000
Show file tree
Hide file tree
Showing 8 changed files with 85 additions and 5 deletions.
2 changes: 1 addition & 1 deletion libshiboken/basewrapper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -832,7 +832,7 @@ void releaseOwnership(SbkObject* self)
{
// skip if the ownership have already moved to c++
SbkObjectType* selfType = reinterpret_cast<SbkObjectType*>(Py_TYPE(self));
if (!self->d->hasOwnership || selfType->d->type_behaviour == BEHAVIOUR_VALUETYPE)
if (!self->d->hasOwnership || Shiboken::Conversions::pythonTypeIsValueType(selfType->d->converter))
return;

// remove object ownership
Expand Down
2 changes: 2 additions & 0 deletions libshiboken/basewrapper_p.h
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,7 @@ struct SbkObjectPrivate
}
};

// TODO-CONVERTERS: to be deprecated/removed
/// The type behaviour was not defined yet
#define BEHAVIOUR_UNDEFINED 0
/// The type is a value type
Expand All @@ -115,6 +116,7 @@ struct SbkObjectTypePrivate
/// True if this type was defined by the user.
int is_user_type : 1;
/// Tells is the type is a value type or an object-type, see BEHAVIOUR_* constants.
// TODO-CONVERTERS: to be deprecated/removed
int type_behaviour : 2;
/// C++ name
char* original_name;
Expand Down
11 changes: 11 additions & 0 deletions libshiboken/sbkconverter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -438,4 +438,15 @@ PyTypeObject* getPythonTypeObject(const char* typeName)
return getPythonTypeObject(getConverter(typeName));
}

bool pythonTypeIsValueType(SbkConverter* converter)
{
assert(converter);
return converter->pointerToPython && converter->copyToPython;
}

bool pythonTypeIsObjectType(SbkConverter* converter)
{
return converter->pointerToPython && !converter->copyToPython;
}

} } // namespace Shiboken::Conversions
6 changes: 6 additions & 0 deletions libshiboken/sbkconverter.h
Original file line number Diff line number Diff line change
Expand Up @@ -248,6 +248,12 @@ LIBSHIBOKEN_API PyTypeObject* getPythonTypeObject(SbkConverter* converter);
/// Returns the Python type object for the given \p typeName.
LIBSHIBOKEN_API PyTypeObject* getPythonTypeObject(const char* typeName);

/// Returns true if the Python type associated with the converter is a value type.
LIBSHIBOKEN_API bool pythonTypeIsValueType(SbkConverter* converter);

/// Returns true if the Python type associated with the converter is an object type.
LIBSHIBOKEN_API bool pythonTypeIsObjectType(SbkConverter* converter);

#define SBK_PY_LONG_LONG_IDX 0
#define SBK_BOOL_IDX 1
#define SBK_CHAR_IDX 2
Expand Down
6 changes: 2 additions & 4 deletions libshiboken/sbkconverter_p.h
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,6 @@ typedef std::list<ToCppConversion> ToCppConversionList;
struct SbkConverter
{
/**
* TODO: it certainly will be empty in some cases, like with PyDate.
* TODO: probably a setPythonType(SbkConverter*, PyTypeObject*) function will be required.
* Python type associated with this converter. If the type is a Shiboken
* wrapper, then it must be a SbkObjectType; otherwise it will be the
* Python type to which the C++ value will be converted (note that the
Expand All @@ -62,8 +60,8 @@ struct SbkConverter
CppToPythonFunc pointerToPython;
/**
* This function converts a C++ object to a Python object of the type
* indicated in pythonType. The identity of the is not kept, because a
* new instance of the C++ object is created.
* indicated in pythonType. The identity of the object is not kept,
* because a new instance of the C++ object is created.
* It is used to convert objects passed by value, or reference, if said
* reference can't be traced to an object that already has a Python
* wrapper assigned for it.
Expand Down
1 change: 1 addition & 0 deletions libshiboken/typeresolver.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@ TypeResolver* TypeResolver::createTypeResolver(const char* typeName,
*/
if (pyType && PyType_IsSubtype(pyType, reinterpret_cast<PyTypeObject*>(&SbkObject_Type))) {
SbkObjectType* sbkType = reinterpret_cast<SbkObjectType*>(pyType);
// TODO-CONVERTERS: to be deprecated
if (!sbkType->d->type_behaviour) {
int len = strlen(typeName);
sbkType->d->type_behaviour = typeName[len -1] == '*' ? BEHAVIOUR_OBJECTTYPE : BEHAVIOUR_VALUETYPE;
Expand Down
35 changes: 35 additions & 0 deletions tests/samplebinding/typeconverters_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -77,5 +77,40 @@ def testMapContainerType(self):
self.assertEqual(pyType, dict)


class CheckValueAndObjectTypeByNameTest(unittest.TestCase):

'''Uses an added function with inject code that uses the libshiboken
functions that check if a type is Object or Value, based on its converter.'''

def testErrors(self):
'''not existent type'''
self.assertRaises(ValueError, sample.cppTypeIsValueType, 'NotExistentType')
self.assertRaises(ValueError, sample.cppTypeIsObjectType, 'NotExistentType')

def testObjectType1(self):
self.assertTrue(sample.cppTypeIsObjectType('ObjectType'))
self.assertFalse(sample.cppTypeIsValueType('ObjectType'))

def testObjectType2(self):
self.assertTrue(sample.cppTypeIsObjectType('ObjectType*'))
self.assertFalse(sample.cppTypeIsValueType('ObjectType*'))

def testValueType1(self):
self.assertTrue(sample.cppTypeIsValueType('Point'))
self.assertFalse(sample.cppTypeIsObjectType('Point'))

def testValueType2(self):
self.assertTrue(sample.cppTypeIsValueType('Point*'))
self.assertFalse(sample.cppTypeIsObjectType('Point*'))

def testUsersPrimitiveType(self):
self.assertFalse(sample.cppTypeIsValueType('Complex'))
self.assertFalse(sample.cppTypeIsObjectType('Complex'))

def testContainerType(self):
self.assertFalse(sample.cppTypeIsValueType('std::list<int >'))
self.assertFalse(sample.cppTypeIsObjectType('std::list<int >'))


if __name__ == '__main__':
unittest.main()
27 changes: 27 additions & 0 deletions tests/samplebinding/typesystem_sample.xml
Original file line number Diff line number Diff line change
Expand Up @@ -258,6 +258,33 @@
</inject-code>
</add-function>

<template name="cpp_type_is_object_or_value_type">
SbkConverter* converter = Shiboken::Conversions::getConverter(%1);
if (converter) {
if (Shiboken::Conversions::pythonTypeIs$TYPEType(converter))
%PYARG_0 = Py_True;
else
%PYARG_0 = Py_False;
Py_INCREF(%PYARG_0);
} else {
PyErr_Format(PyExc_ValueError, "Type '%s' has no converter associated to it", %1);
}
</template>
<add-function signature="cppTypeIsObjectType(const char*)" return-type="bool">
<inject-code class="target" position="beginning">
<insert-template name="cpp_type_is_object_or_value_type">
<replace from="$TYPE" to="Object" />
</insert-template>
</inject-code>
</add-function>
<add-function signature="cppTypeIsValueType(const char*)" return-type="bool">
<inject-code class="target" position="beginning">
<insert-template name="cpp_type_is_object_or_value_type">
<replace from="$TYPE" to="Value" />
</insert-template>
</inject-code>
</add-function>

<container-type name="std::pair" type="pair">
<include file-name="utility" location="global"/>
<conversion-rule file="pair_conversions.h">
Expand Down

0 comments on commit d427000

Please sign in to comment.