[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
This commit is contained in:
SND\ussrhero_cp 2017-10-03 20:38:08 +00:00 committed by Mikhail I. Izmestev
parent 61bab00356
commit af129a9a00
8 changed files with 106 additions and 5 deletions

View File

@ -25,6 +25,14 @@ public:
{} {}
}; };
class KeyException : public std::exception
{
public:
KeyException(const char* desc) : std::exception(desc)
{}
};
class StopIteration : public std::exception class StopIteration : public std::exception
{ {
public: public:
@ -124,6 +132,11 @@ inline void pykdExceptionTranslate(const std::exception &e)
return; return;
} }
if (typeid(e).hash_code() == typeid(KeyException).hash_code())
{
PyErr_SetString(PyExc_KeyError, e.what());
return;
}
} }
inline void registerExceptions() inline void registerExceptions()
@ -139,6 +152,7 @@ inline void registerExceptions()
python::register_exception_translator<OverflowException>( &pykdExceptionTranslate ); python::register_exception_translator<OverflowException>( &pykdExceptionTranslate );
python::register_exception_translator<AttributeException>(&pykdExceptionTranslate); python::register_exception_translator<AttributeException>(&pykdExceptionTranslate);
python::register_exception_translator<StopIteration>(&pykdExceptionTranslate); python::register_exception_translator<StopIteration>(&pykdExceptionTranslate);
python::register_exception_translator<KeyException>(&pykdExceptionTranslate);
} }
///////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////

View File

@ -937,6 +937,7 @@ BOOST_PYTHON_MODULE( pykd )
.def( "__getattr__", TypeInfoAdapter::getElementAttr ) .def( "__getattr__", TypeInfoAdapter::getElementAttr )
.def( "__len__", TypeInfoAdapter::getElementCount ) .def( "__len__", TypeInfoAdapter::getElementCount )
.def( "__getitem__", TypeInfoAdapter::getElementByIndex ) .def( "__getitem__", TypeInfoAdapter::getElementByIndex )
.def( "__getitem__", TypeInfoAdapter::getElementByKey )
.def( "__dir__", TypeInfoAdapter::getElementDir ) .def( "__dir__", TypeInfoAdapter::getElementDir )
#if PY_VERSION_HEX >= 0x03000000 #if PY_VERSION_HEX >= 0x03000000
.def("__bool__", TypeInfoAdapter::isZero ) .def("__bool__", TypeInfoAdapter::isZero )
@ -1002,6 +1003,8 @@ BOOST_PYTHON_MODULE( pykd )
.def("__len__", TypedVarAdapter::getElementCount ) .def("__len__", TypedVarAdapter::getElementCount )
.def("__getitem__", TypedVarAdapter::getElementByIndex ) .def("__getitem__", TypedVarAdapter::getElementByIndex )
.def("__setitem__", TypedVarAdapter::setElementByIndex ) .def("__setitem__", TypedVarAdapter::setElementByIndex )
.def( "__getitem__", TypedVarAdapter::getFieldByKey )
.def( "__setitem__", TypedVarAdapter::setFieldByKey )
.def("__dir__", TypedVarAdapter::getElementsDir) .def("__dir__", TypedVarAdapter::getElementsDir)
.def("__call__", python::raw_function(pykd::callFunctionByVar, 0) ) .def("__call__", python::raw_function(pykd::callFunctionByVar, 0) )
.def("__iter__", TypedVarAdapter::getArrayIter, python::return_value_policy<python::manage_new_object>()) .def("__iter__", TypedVarAdapter::getArrayIter, python::return_value_policy<python::manage_new_object>())

View File

@ -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 } // namespace pykd

View File

@ -146,6 +146,10 @@ struct TypedVarAdapter {
static void setFieldAttr(kdlib::TypedVar& typedVar, const std::wstring &name, python::object& object); 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 ) static size_t getElementCount( kdlib::TypedVar& typedVar )
{ {
AutoRestorePyState pystate; AutoRestorePyState pystate;

View File

@ -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<std::wstring> lst; std::list<std::wstring> lst;
python::list pylst; python::list pylst;

View File

@ -146,6 +146,8 @@ struct TypeInfoAdapter : public kdlib::TypeInfo {
static kdlib::TypeInfoPtr getElementAttr(kdlib::TypeInfo &typeInfo, const std::wstring &name); 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 ) static kdlib::TypeInfoPtr getElementByIndex( kdlib::TypeInfo &typeInfo, size_t index )
{ {
AutoRestorePyState pystate; AutoRestorePyState pystate;

View File

@ -86,6 +86,9 @@ class TypedVarTest( unittest.TestCase ):
self.assertEqual( 500, tv1.m_field1 ) self.assertEqual( 500, tv1.m_field1 )
self.assertEqual( True, tv1.m_field2 ) self.assertEqual( True, tv1.m_field2 )
self.assertEqual( 1, tv1.m_field3 ) 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): def testPtrField(self):
tv = target.module.typedVar( "g_structTest" ) tv = target.module.typedVar( "g_structTest" )

View File

@ -36,16 +36,18 @@ class TypeInfoTest( unittest.TestCase ):
self.assertEqual( "Int4B(*[4])[2][3]", target.module.type("arrIntMatrixPtrs").name() ) self.assertEqual( "Int4B(*[4])[2][3]", target.module.type("arrIntMatrixPtrs").name() )
self.assertEqual( "Int4B(*)[2][3]", target.module.type("ptrIntMatrix").name() ) self.assertEqual( "Int4B(*)[2][3]", target.module.type("ptrIntMatrix").name() )
def testGetField( self ): def testGetField( self ):
""" get field of the complex type """ """ get field of the complex type """
ti1 = target.module.type( "structTest" ) 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.assertTrue( hasattr( ti1, "m_field0" ) )
try: hasattr(ti1, "m_field4" ) # non-exsisting field self.assertFalse( hasattr( ti1, "not_exists" ) )
except pykd.BaseException: pass 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 ): def testBaseTypes( self ):
self.assertEqual("Int1B", pykd.typeInfo( "Int1B" ).name() ) self.assertEqual("Int1B", pykd.typeInfo( "Int1B" ).name() )
self.assertEqual("Int2B", pykd.typeInfo( "Int2B" ).name() ) self.assertEqual("Int2B", pykd.typeInfo( "Int2B" ).name() )
self.assertEqual("Int4B", pykd.typeInfo( "Int4B" ).name() ) self.assertEqual("Int4B", pykd.typeInfo( "Int4B" ).name() )