From af129a9a00b530d55dc8225740e6a49dc1234bac Mon Sep 17 00:00:00 2001 From: "SND\\ussrhero_cp" Date: Tue, 3 Oct 2017 20:38:08 +0000 Subject: [PATCH] [0.3.x] added : typeInfo.__getitem__ (Get a field's type by the field's name ) [0.3.x] added : typedVar.__getitem__ (Get a field's value by the field's name ) [0.3.x] added : typedVar.__settitem__ (Set a value to a field by name ) git-svn-id: https://pykd.svn.codeplex.com/svn@91261 9b283d60-5439-405e-af05-b73fd8c4d996 --- pykd/dbgexcept.h | 14 ++++++++++++ pykd/pymod.cpp | 3 +++ pykd/pytypedvar.cpp | 48 ++++++++++++++++++++++++++++++++++++++++ pykd/pytypedvar.h | 4 ++++ pykd/pytypeinfo.cpp | 27 +++++++++++++++++++++- pykd/pytypeinfo.h | 2 ++ test/scripts/typedvar.py | 3 +++ test/scripts/typeinfo.py | 10 +++++---- 8 files changed, 106 insertions(+), 5 deletions(-) diff --git a/pykd/dbgexcept.h b/pykd/dbgexcept.h index 0956622..776236f 100644 --- a/pykd/dbgexcept.h +++ b/pykd/dbgexcept.h @@ -25,6 +25,14 @@ public: {} }; +class KeyException : public std::exception +{ +public: + + KeyException(const char* desc) : std::exception(desc) + {} +}; + class StopIteration : public std::exception { public: @@ -124,6 +132,11 @@ inline void pykdExceptionTranslate(const std::exception &e) return; } + if (typeid(e).hash_code() == typeid(KeyException).hash_code()) + { + PyErr_SetString(PyExc_KeyError, e.what()); + return; + } } inline void registerExceptions() @@ -139,6 +152,7 @@ inline void registerExceptions() python::register_exception_translator( &pykdExceptionTranslate ); python::register_exception_translator(&pykdExceptionTranslate); python::register_exception_translator(&pykdExceptionTranslate); + python::register_exception_translator(&pykdExceptionTranslate); } ///////////////////////////////////////////////////////////////////////////////////// diff --git a/pykd/pymod.cpp b/pykd/pymod.cpp index 4898929..a2218c4 100644 --- a/pykd/pymod.cpp +++ b/pykd/pymod.cpp @@ -937,6 +937,7 @@ BOOST_PYTHON_MODULE( pykd ) .def( "__getattr__", TypeInfoAdapter::getElementAttr ) .def( "__len__", TypeInfoAdapter::getElementCount ) .def( "__getitem__", TypeInfoAdapter::getElementByIndex ) + .def( "__getitem__", TypeInfoAdapter::getElementByKey ) .def( "__dir__", TypeInfoAdapter::getElementDir ) #if PY_VERSION_HEX >= 0x03000000 .def("__bool__", TypeInfoAdapter::isZero ) @@ -1002,6 +1003,8 @@ BOOST_PYTHON_MODULE( pykd ) .def("__len__", TypedVarAdapter::getElementCount ) .def("__getitem__", TypedVarAdapter::getElementByIndex ) .def("__setitem__", TypedVarAdapter::setElementByIndex ) + .def( "__getitem__", TypedVarAdapter::getFieldByKey ) + .def( "__setitem__", TypedVarAdapter::setFieldByKey ) .def("__dir__", TypedVarAdapter::getElementsDir) .def("__call__", python::raw_function(pykd::callFunctionByVar, 0) ) .def("__iter__", TypedVarAdapter::getArrayIter, python::return_value_policy()) diff --git a/pykd/pytypedvar.cpp b/pykd/pytypedvar.cpp index 0bfba2b..b653701 100644 --- a/pykd/pytypedvar.cpp +++ b/pykd/pytypedvar.cpp @@ -258,5 +258,53 @@ void TypedVarAdapter::setFieldAttr(kdlib::TypedVar& typedVar, const std::wstring /////////////////////////////////////////////////////////////////////////////// +kdlib::TypedVarPtr TypedVarAdapter::getFieldByKey(kdlib::TypedVar& typedVar, const std::wstring &name) +{ + { + + AutoRestorePyState pystate; + + try + { + return typedVar.getElement( name ); + } + catch (kdlib::TypeException&) + {} + + try + { + return typedVar.getMethod( name ); + } + catch (kdlib::TypeException&) + {} + } + + std::wstringstream sstr; + sstr << L"typed var has no field " << L'\'' << name << L'\''; + throw KeyException(std::string(_bstr_t(sstr.str().c_str())).c_str()); +} + +/////////////////////////////////////////////////////////////////////////////// + +void TypedVarAdapter::setFieldByKey(kdlib::TypedVar& typedVar, const std::wstring &name, python::object& object) +{ + kdlib::TypedValue value = NumVariantAdaptor::convertToVariant(object); + + try + { + AutoRestorePyState pystate; + typedVar.setElement(name, value); + return; + } + catch (kdlib::TypeException&) + {} + + std::wstringstream sstr; + sstr << L"typed var has no field " << L'\'' << name << L'\''; + throw KeyException(std::string(_bstr_t(sstr.str().c_str())).c_str()); +} + +/////////////////////////////////////////////////////////////////////////////// + } // namespace pykd diff --git a/pykd/pytypedvar.h b/pykd/pytypedvar.h index e9c6578..7c32ca0 100644 --- a/pykd/pytypedvar.h +++ b/pykd/pytypedvar.h @@ -146,6 +146,10 @@ struct TypedVarAdapter { static void setFieldAttr(kdlib::TypedVar& typedVar, const std::wstring &name, python::object& object); + static kdlib::TypedVarPtr getFieldByKey(kdlib::TypedVar& typedVar, const std::wstring &name); + + static void setFieldByKey(kdlib::TypedVar& typedVar, const std::wstring &name, python::object& object); + static size_t getElementCount( kdlib::TypedVar& typedVar ) { AutoRestorePyState pystate; diff --git a/pykd/pytypeinfo.cpp b/pykd/pytypeinfo.cpp index 632bd6d..3f22af5 100644 --- a/pykd/pytypeinfo.cpp +++ b/pykd/pytypeinfo.cpp @@ -130,8 +130,33 @@ kdlib::TypeInfoPtr TypeInfoAdapter::getElementAttr(kdlib::TypeInfo &typeInfo, co /////////////////////////////////////////////////////////////////////////////// -python::list TypeInfoAdapter::getElementDir(kdlib::TypeInfo &typeInfo) +kdlib::TypeInfoPtr TypeInfoAdapter::getElementByKey(kdlib::TypeInfo &typeInfo, const std::wstring &name) { + { + AutoRestorePyState pystate; + + try { + return typeInfo.getElement(name); + } + catch (kdlib::TypeException&) + {} + + try { + return typeInfo.getMethod(name); + } + catch (kdlib::TypeException&) + {} + } + + std::wstringstream sstr; + sstr << L'\'' << typeInfo.getName() << L'\'' << L" type has no field " << L'\'' << name << L'\''; + throw KeyException(std::string(_bstr_t(sstr.str().c_str())).c_str()); +} + +/////////////////////////////////////////////////////////////////////////////// + +python::list TypeInfoAdapter::getElementDir(kdlib::TypeInfo &typeInfo) +{ std::list lst; python::list pylst; diff --git a/pykd/pytypeinfo.h b/pykd/pytypeinfo.h index 8f2543f..2483bc3 100644 --- a/pykd/pytypeinfo.h +++ b/pykd/pytypeinfo.h @@ -146,6 +146,8 @@ struct TypeInfoAdapter : public kdlib::TypeInfo { static kdlib::TypeInfoPtr getElementAttr(kdlib::TypeInfo &typeInfo, const std::wstring &name); + static kdlib::TypeInfoPtr getElementByKey(kdlib::TypeInfo &typeInfo, const std::wstring &name); + static kdlib::TypeInfoPtr getElementByIndex( kdlib::TypeInfo &typeInfo, size_t index ) { AutoRestorePyState pystate; diff --git a/test/scripts/typedvar.py b/test/scripts/typedvar.py index 7c916fa..4b55c99 100644 --- a/test/scripts/typedvar.py +++ b/test/scripts/typedvar.py @@ -86,6 +86,9 @@ class TypedVarTest( unittest.TestCase ): self.assertEqual( 500, tv1.m_field1 ) self.assertEqual( True, tv1.m_field2 ) self.assertEqual( 1, tv1.m_field3 ) + self.assertEqual( 1, tv1["m_field3"] ) + self.assertRaises( AttributeError, lambda t: t.not_exists, tv1) # non-exsisting field + self.assertRaises( KeyError, lambda t: t["not_exists"], tv1) # non-exsisting field def testPtrField(self): tv = target.module.typedVar( "g_structTest" ) diff --git a/test/scripts/typeinfo.py b/test/scripts/typeinfo.py index ad20f58..e64108c 100644 --- a/test/scripts/typeinfo.py +++ b/test/scripts/typeinfo.py @@ -36,16 +36,18 @@ class TypeInfoTest( unittest.TestCase ): self.assertEqual( "Int4B(*[4])[2][3]", target.module.type("arrIntMatrixPtrs").name() ) self.assertEqual( "Int4B(*)[2][3]", target.module.type("ptrIntMatrix").name() ) - def testGetField( self ): """ 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" ) ) - try: hasattr(ti1, "m_field4" ) # non-exsisting field - except pykd.BaseException: pass + self.assertFalse( hasattr( ti1, "not_exists" ) ) + self.assertRaises( AttributeError, lambda t: t.not_exists, ti1) # non-exsisting field + self.assertRaises( KeyError, lambda t: t["not_exists"], ti1) # non-exsisting field + def testBaseTypes( self ): - self.assertEqual("Int1B", pykd.typeInfo( "Int1B" ).name() ) self.assertEqual("Int2B", pykd.typeInfo( "Int2B" ).name() ) self.assertEqual("Int4B", pykd.typeInfo( "Int4B" ).name() )