diff --git a/pykd/pymod.cpp b/pykd/pymod.cpp index 90f32a9..eaab63b 100644 --- a/pykd/pymod.cpp +++ b/pykd/pymod.cpp @@ -893,30 +893,32 @@ void pykd_init() .def("__contains__", ModuleAdapter::isContainedSymbol) .def( "__str__", &ModuleAdapter::print ); - python::class_<kdlib::TypeInfo, kdlib::TypeInfoPtr, python::bases<kdlib::NumConvertable>, boost::noncopyable >("typeInfo", "Class representing typeInfo", python::no_init ) - .def("__init__", python::make_constructor( pykd::getTypeInfoByName ) ) - .def( "name", TypeInfoAdapter::getName, - "Return type name" ) + python::class_<kdlib::TypeInfo, kdlib::TypeInfoPtr, python::bases<kdlib::NumConvertable>, boost::noncopyable >("typeInfo", "Class representing typeInfo", python::no_init) + .def("__init__", python::make_constructor(pykd::getTypeInfoByName)) + .def("name", TypeInfoAdapter::getName, + "Return type name") .def("scopeName", TypeInfoAdapter::getScopeName, - "Return name of type scope ( module name )" ) - .def( "size", TypeInfoAdapter::getSize, - "Return type size" ) - .def( "staticOffset", TypeInfoAdapter::getStaticOffset, - "Return offset of the static field" ) - .def( "fieldOffset", TypeInfoAdapter::getElementOffset, - "Return offset of the nonstatic field" ) + "Return name of type scope ( module name )") + .def("size", TypeInfoAdapter::getSize, + "Return type size") + .def("staticOffset", TypeInfoAdapter::getStaticOffset, + "Return offset of the static field") + .def("fieldOffset", TypeInfoAdapter::getElementOffset, + "Return offset of the nonstatic field") .def("fieldOffset", TypeInfoAdapter::getElementOffsetByIndex, "Return offset of the nonstatic field by index") - .def( "bitOffset", TypeInfoAdapter::getBitOffset, - "Return bit field's offset" ) - .def( "bitWidth", TypeInfoAdapter::getBitWidth, - "Return bit field's length" ) - .def( "getNumberFields", TypeInfoAdapter::getElementCount, - "Return number of fields" ) - .def( "field", TypeInfoAdapter::getElementByIndex, - "Return field's type by index" ) - .def( "field", TypeInfoAdapter::getElementByName, - "Return field's type" ) + .def("bitOffset", TypeInfoAdapter::getBitOffset, + "Return bit field's offset") + .def("bitWidth", TypeInfoAdapter::getBitWidth, + "Return bit field's length") + .def("getNumberFields", TypeInfoAdapter::getElementCount, + "Return number of fields") + .def("field", TypeInfoAdapter::getElementByIndex, + "Return field's type by index") + .def("field", TypeInfoAdapter::getElementByName, + "Return field's type") + .def("hasField", TypeInfoAdapter::hasField, + "Return True if type has a field with the specified name") .def( "fieldName", TypeInfoAdapter::getElementName, "Return name of struct field by index" ) .def( "fields", TypeInfoAdapter::getFields, @@ -927,6 +929,8 @@ void pykd_init() "Return method's type by name") .def( "method", TypeInfoAdapter::getMethodByIndex, "Return method's by index") + .def("hasMethod", TypeInfoAdapter::hasMethod, + "Return True if type has a method with the specified name") .def( "methodName", TypeInfoAdapter::getMethodName, "Return method's name") .def( "methods", TypeInfoAdapter::getMethods, @@ -986,7 +990,7 @@ void pykd_init() .def( "__getitem__", TypeInfoAdapter::getElementByIndex ) .def( "__getitem__", TypeInfoAdapter::getElementByKey ) .def( "__dir__", TypeInfoAdapter::getElementDir ) - .def("__contains__", TypeInfoAdapter::isContainedField) + .def("__contains__", TypeInfoAdapter::hasFieldOrMethod) #if PY_VERSION_HEX >= 0x03000000 .def("__bool__", TypeInfoAdapter::isZero ) #else diff --git a/pykd/pytypedvar.cpp b/pykd/pytypedvar.cpp index ed448f6..5ef12c9 100644 --- a/pykd/pytypedvar.cpp +++ b/pykd/pytypedvar.cpp @@ -184,6 +184,9 @@ python::list TypedVarAdapter::getElementsDir(kdlib::TypedVar& typedVar) kdlib::TypedVarPtr TypedVarAdapter::getFieldAttr(kdlib::TypedVar& typedVar, const std::wstring &name) { + if (name == L"__name__") + throw AttributeException("no __name__ attribute"); + AutoRestorePyState pystate; try diff --git a/pykd/pytypeinfo.cpp b/pykd/pytypeinfo.cpp index ea6b194..7f02b3b 100644 --- a/pykd/pytypeinfo.cpp +++ b/pykd/pytypeinfo.cpp @@ -103,9 +103,8 @@ python::list TypeInfoAdapter::getFields( kdlib::TypeInfo &typeInfo ) return pylst; } -bool TypeInfoAdapter::isContainedField(kdlib::TypeInfoPtr& typeInfo, const std::wstring& fieldName) +bool TypeInfoAdapter::hasFieldOrMethod(kdlib::TypeInfoPtr& typeInfo, const std::wstring& fieldName) { - AutoRestorePyState pystate; for (size_t i = 0; i < typeInfo->getElementCount(); ++i) @@ -115,6 +114,41 @@ bool TypeInfoAdapter::isContainedField(kdlib::TypeInfoPtr& typeInfo, const std:: return true; } + for (size_t i = 0; i < typeInfo->getMethodsCount(); ++i) + { + std::wstring name = typeInfo->getMethodName(i); + if (name == fieldName) + return true; + } + + return false; +} + +bool TypeInfoAdapter::hasField(kdlib::TypeInfoPtr &typeInfo, const std::wstring &fieldName) +{ + AutoRestorePyState pystate; + + for (size_t i = 0; i < typeInfo->getElementCount(); ++i) + { + std::wstring name = typeInfo->getElementName(i); + if (name == fieldName) + return true; + } + + return false; +} + +bool TypeInfoAdapter::hasMethod(kdlib::TypeInfoPtr &typeInfo, const std::wstring &fieldName) +{ + AutoRestorePyState pystate; + + for (size_t i = 0; i < typeInfo->getMethodsCount(); ++i) + { + std::wstring name = typeInfo->getMethodName(i); + if (name == fieldName) + return true; + } + return false; } diff --git a/pykd/pytypeinfo.h b/pykd/pytypeinfo.h index ab4adda..09b3579 100644 --- a/pykd/pytypeinfo.h +++ b/pykd/pytypeinfo.h @@ -150,6 +150,10 @@ struct TypeInfoAdapter : public kdlib::TypeInfo { return typeInfo.getElement(name); } + static bool hasField(kdlib::TypeInfoPtr &typeInfo, const std::wstring &name); + + static bool hasMethod(kdlib::TypeInfoPtr &typeInfo, const std::wstring &fieldName); + static kdlib::TypeInfoPtr getElementAttr(kdlib::TypeInfo &typeInfo, const std::wstring &name); static kdlib::TypeInfoPtr getElementByKey(kdlib::TypeInfo &typeInfo, const std::wstring &name); @@ -334,7 +338,7 @@ struct TypeInfoAdapter : public kdlib::TypeInfo { return false; } - static bool isContainedField(kdlib::TypeInfoPtr& typedVar, const std::wstring& fieldName); + static bool hasFieldOrMethod(kdlib::TypeInfoPtr& typedVar, const std::wstring& name); }; diff --git a/test/scripts/typeinfo.py b/test/scripts/typeinfo.py index aea9cd4..718223f 100644 --- a/test/scripts/typeinfo.py +++ b/test/scripts/typeinfo.py @@ -40,11 +40,9 @@ class TypeInfoTest( unittest.TestCase ): """ get field of the complex type """ ti1 = target.module.type( "structTest" ) self.assertTrue( "UInt4B", ti1.m_field0.name() ) - #self.assertTrue( "UInt4B", ti1["m_field0"].name() ) - self.assertTrue( hasattr( ti1, "m_field0" ) ) - self.assertFalse( hasattr( ti1, "not_exists" ) ) + self.assertTrue( "m_field0" in ti1 ) + self.assertFalse( "not_exist" in ti1) # non-exsisting field self.assertRaises( pykd.SymbolException, lambda t: t.not_exists, ti1) # non-exsisting field - #self.assertRaises( KeyError, lambda t: t["not_exists"], ti1) # non-exsisting field def testBaseTypes( self ): @@ -171,14 +169,14 @@ class TypeInfoTest( unittest.TestCase ): def testNestedStruct( self ): ti = target.module.type("structWithNested") - self.assertTrue( hasattr( ti, "m_field" ) ) - self.assertTrue( hasattr( ti, "m_field3" ) ) - self.assertTrue( hasattr( ti, "m_unnameStruct" ) ) - self.assertTrue( hasattr( ti.m_unnameStruct, "m_field2" ) ) - self.assertFalse( hasattr( ti, "m_field2" ) ) - self.assertFalse( hasattr( ti, "m_nestedFiled" ) ) + self.assertTrue( ti.hasField("m_field")) + self.assertTrue( ti.hasField("m_field3")) + self.assertTrue( ti.hasField("m_unnameStruct")) + self.assertTrue( ti.m_unnameStruct.hasField("m_field2")) + self.assertFalse( ti.hasField( "m_field2" ) ) + self.assertFalse( ti.hasField( "m_nestedFiled" ) ) ti = target.module.type("structWithNested::Nested") - self.assertTrue( hasattr( ti, "m_nestedFiled" ) ) + self.assertTrue( ti.hasField( "m_nestedFiled" ) ) def testPrint(self): self.assertTrue( str(target.module.type( "ucharVar" ) ) )