def testFields(self, mapper, CallLater): basePtr, deallocBase = MakeTypePtr(mapper, {}) typePtr, deallocType = MakeTypePtr(mapper, {}) CallLater(deallocBase) CallLater(deallocType) # The purpose of this rigmarole is to enable me to use SOME_VALUE # for every field, rather than creating 'proper' values for every # field -- once I've Retrieved the types, I won't actualise them # again, so I can put any old non-zero nonsense in any field to # check that it gets inherited (or not) mapper.Retrieve(basePtr) mapper.Retrieve(typePtr) CPyMarshal.WriteIntField(typePtr, PyTypeObject, "tp_flags", int(Py_TPFLAGS.HAVE_CLASS)) # end rigmarole CPyMarshal.WritePtrField(typePtr, PyTypeObject, "tp_base", basePtr) for field in INHERIT_FIELDS + DONT_INHERIT_FIELDS: CPyMarshal.WritePtrField(typePtr, PyTypeObject, field, NO_VALUE) CPyMarshal.WritePtrField(basePtr, PyTypeObject, field, SOME_VALUE) mapper.PyType_Ready(typePtr) for field in INHERIT_FIELDS: self.assertEquals(CPyMarshal.ReadPtrField(typePtr, PyTypeObject, field), SOME_VALUE) for field in DONT_INHERIT_FIELDS: self.assertEquals(CPyMarshal.ReadPtrField(typePtr, PyTypeObject, field), NO_VALUE)
def testDestroysObjectsOfUnmanagedTypesFirst(self): frees = [] mapper = PythonMapper(GetAllocatingTestAllocator([], frees)) deallocTypes = CreateTypes(mapper) modulePtr = MakeAndAddEmptyModule(mapper) module = mapper.Retrieve(modulePtr) calls = [] def Del(instancePtr): calls.append(("del", instancePtr)) mapper.PyObject_Free(instancePtr) typeSpec = {'tp_name': 'klass', 'tp_dealloc': Del} typePtr, deallocType = MakeTypePtr(mapper, typeSpec) mapper.PyModule_AddObject(modulePtr, 'klass', typePtr) easyptr = mapper.Store(123) instance1 = module.klass() hardptr = mapper.Store(instance1) instance2 = module.klass() brokenptr = mapper.Store(instance2) CPyMarshal.WritePtrField(brokenptr, PyObject, 'ob_type', IntPtr.Zero) mapper.Dispose() self.assertEquals( frees.index(hardptr) < frees.index(easyptr), True, "failed to dealloc in correct order") self.assertEquals(calls, [('del', hardptr)], "failed to clean up klass instance") deallocType() deallocTypes()
def testSomeItems(self): allocs = [] mapper = PythonMapper(GetAllocatingTestAllocator(allocs, [])) deallocTypes = CreateTypes(mapper) typeSpec = { "tp_basicsize": 32, "tp_itemsize": 64, } typePtr, deallocType = MakeTypePtr(mapper, typeSpec) del allocs[:] result = mapper.PyType_GenericAlloc(typePtr, 3) self.assertEquals(allocs, [(result, 224)], "allocated wrong") refcount = CPyMarshal.ReadIntField(result, PyObject, "ob_refcnt") self.assertEquals(refcount, 1, "bad initialisation") instanceType = CPyMarshal.ReadPtrField(result, PyObject, "ob_type") self.assertEquals(instanceType, typePtr, "bad type ptr") size = CPyMarshal.ReadIntField(result, PyVarObject, "ob_size") self.assertEquals(size, 3, "bad ob_size") headerSize = Marshal.SizeOf(PyVarObject) zerosPtr = OffsetPtr(result, headerSize) for i in range(224 - headerSize): self.assertEquals(CPyMarshal.ReadByte(zerosPtr), 0, "not zeroed") zerosPtr = OffsetPtr(zerosPtr, 1) mapper.Dispose() deallocTypes() deallocType()
def testExtensionTypesAutoActualisable(self): discoveryModes = { "IncRef": lambda f, o: self.assertMaps(mapper, f, o, 5), "Retrieve": lambda f, o: self.assertMaps(mapper, f, o, 4), "DecRef": lambda f, o: self.assertMaps(mapper, f, o, 3), "RefCount": lambda f, o: self.assertMaps(mapper, f, o, 4), } allocator = HGlobalAllocator() mapper = PythonMapper(allocator) deallocTypes = CreateTypes(mapper) # delay deallocs to avoid types with the same addresses causing confusion userTypeDeallocs = [] try: for (mode, TestFunc) in discoveryModes.items(): typePtr, deallocType = MakeTypePtr(mapper, {"tp_name": mode + "Class"}) userTypeDeallocs.append(deallocType) objPtr = allocator.Alloc(Marshal.SizeOf(PyObject)) CPyMarshal.WriteIntField(objPtr, PyObject, "ob_refcnt", 2) CPyMarshal.WritePtrField(objPtr, PyObject, "ob_type", typePtr) discoveryFunc = getattr(mapper, mode) TestFunc(discoveryFunc, objPtr) finally: mapper.Dispose() for deallocFunc in userTypeDeallocs: deallocFunc() deallocTypes()
def testPySequence_Repeat_TypeWithSequenceRepeat(self, mapper, addToCleanUp): RESULT_PTR = IntPtr(123) calls = [] def RepeatFunc(selfPtr, count): calls.append((selfPtr, count)) return RESULT_PTR def Multiply(selfPtr, otherPtr): raise Exception("don't multiply if we can repeat!") seqPtr, deallocSeq = MakeNumSeqMapMethods(PySequenceMethods, {'sq_repeat': RepeatFunc}) addToCleanUp(deallocSeq) numPtr, deallocNum = MakeNumSeqMapMethods(PyNumberMethods, {'nb_multiply': Multiply}) addToCleanUp(deallocNum) typeSpec = { "tp_as_sequence": seqPtr, "tp_as_number": numPtr, } typePtr, deallocType = MakeTypePtr(mapper, typeSpec) addToCleanUp(deallocType) instance = mapper.Retrieve(typePtr)() instancePtr = mapper.Store(instance) self.assertEquals(mapper.PySequence_Repeat(instancePtr, 3), RESULT_PTR) self.assertEquals(calls, [(instancePtr, 3)])
def testBaseTypeMissing(self, mapper, CallLater): mapper.PyType_Ready(mapper.PyBaseObject_Type) self.assertEquals(CPyMarshal.ReadPtrField(mapper.PyBaseObject_Type, PyTypeObject, "tp_base"), IntPtr.Zero) typePtr, deallocType = MakeTypePtr(mapper, {}) CallLater(deallocType) CPyMarshal.WritePtrField(typePtr, PyTypeObject, "tp_base", NO_VALUE) mapper.PyType_Ready(typePtr) self.assertEquals(CPyMarshal.ReadPtrField(typePtr, PyTypeObject, "tp_base"), mapper.PyBaseObject_Type)
def testPyDict_SetItemString_UnknownType(self, mapper, addToCleanUp): typePtr, deallocType = MakeTypePtr(mapper, {'tp_name': 'klass'}) addToCleanUp(deallocType) _dict = {} dictPtr = mapper.Store(_dict) self.assertEquals( mapper.PyDict_SetItemString(dictPtr, 'klass', typePtr), 0, "reported failure") klass = _dict['klass'] self.assertEquals(klass.__name__, 'klass', "failed")
def testPyObject_Init(self, mapper, addToCleanUp): typePtr, deallocType = MakeTypePtr(mapper, {'tp_name': 'FooType'}) addToCleanUp(deallocType) objPtr = Marshal.AllocHGlobal(Marshal.SizeOf(PyObject())) addToCleanUp(lambda: Marshal.FreeHGlobal(objPtr)) self.assertEquals(mapper.PyObject_Init(objPtr, typePtr), objPtr, 'did not return the "new instance"') self.assertEquals(CPyMarshal.ReadPtrField(objPtr, PyObject, "ob_type"), typePtr, "wrong type") self.assertEquals(CPyMarshal.ReadIntField(objPtr, PyObject, "ob_refcnt"), 1, "wrong refcount") self.assertEquals(mapper.HasPtr(objPtr), False)
def testCallsTypeAllocFunction(self, mapper, addToCleanUp): calls = [] def Alloc(typePtr, nItems): calls.append((typePtr, nItems)) return IntPtr(999) typeSpec = { "tp_alloc": Alloc, } typePtr, deallocType = MakeTypePtr(mapper, typeSpec) addToCleanUp(deallocType) result = mapper.PyType_GenericNew(typePtr, IntPtr(222), IntPtr(333)) self.assertEquals(result, IntPtr(999), "did not use type's tp_alloc function") self.assertEquals(calls, [(typePtr, 0)], "passed wrong args")
def assertAddsTypeWithData(self, tp_name, itemName, class__module__, class__name__, class__doc__, mapper, addDealloc): modulePtr = MakeAndAddEmptyModule(mapper) module = mapper.Retrieve(modulePtr) typeSpec = { "tp_name": tp_name, "tp_doc": class__doc__ } typePtr, deallocType = MakeTypePtr(mapper, typeSpec) addDealloc(deallocType) result = mapper.PyModule_AddObject(modulePtr, itemName, typePtr) self.assertEquals(result, 0, "reported failure") mappedClass = mapper.Retrieve(typePtr) generatedClass = getattr(module, itemName) self.assertEquals(mappedClass, generatedClass, "failed to add new type to module") self.assertEquals(mappedClass.__doc__, class__doc__, "unexpected docstring") self.assertEquals(mappedClass.__name__, class__name__, "unexpected __name__") self.assertEquals(mappedClass.__module__, class__module__, "unexpected __module__")