From c9716566252715c7a88a57d6c159584677823aee Mon Sep 17 00:00:00 2001
From: "SND\\kernelnet_cp"
 <SND\kernelnet_cp@9b283d60-5439-405e-af05-b73fd8c4d996>
Date: Tue, 22 Mar 2016 08:12:37 +0000
Subject: [PATCH] [0.3.x] fixed : hasattr for python 3

git-svn-id: https://pykd.svn.codeplex.com/svn@90967 9b283d60-5439-405e-af05-b73fd8c4d996
---
 pykd/dbgexcept.h  | 16 ++++++++++++++++
 pykd/pymod.cpp    |  6 +++---
 pykd/pymodule.h   | 19 +++++++++++++++++++
 pykd/pytypedvar.h | 17 +++++++++++++++++
 pykd/pytypeinfo.h | 18 ++++++++++++++++++
 5 files changed, 73 insertions(+), 3 deletions(-)

diff --git a/pykd/dbgexcept.h b/pykd/dbgexcept.h
index 66bd439..ed69942 100644
--- a/pykd/dbgexcept.h
+++ b/pykd/dbgexcept.h
@@ -17,6 +17,15 @@ public:
     {}
 };
 
+class AttributeException : public std::exception
+{
+public:
+
+    AttributeException(const char* desc) : std::exception(desc)
+    {}
+};
+
+
 template< class TExcept >
 struct exceptPyType{
     static python::handle<>     pyExceptType;
@@ -96,6 +105,12 @@ inline void pykdExceptionTranslate(const std::exception &e)
         return;
     }
 
+    if (typeid(e).hash_code() == typeid(AttributeException).hash_code())
+    {
+        PyErr_SetString(PyExc_AttributeError, e.what());
+        return;
+    }
+
 }
 
 inline void registerExceptions()
@@ -107,6 +122,7 @@ inline void registerExceptions()
 
     python::register_exception_translator<kdlib::DbgException>( &dbgExceptionTranslate );
     python::register_exception_translator<OverflowException>( &pykdExceptionTranslate );
+    python::register_exception_translator<AttributeException>(&pykdExceptionTranslate);
 }
 
 /////////////////////////////////////////////////////////////////////////////////////
diff --git a/pykd/pymod.cpp b/pykd/pymod.cpp
index f9b64c2..6191413 100644
--- a/pykd/pymod.cpp
+++ b/pykd/pymod.cpp
@@ -717,7 +717,7 @@ BOOST_PYTHON_MODULE( pykd )
             "Return tuple of the module's file version")
         .def("getFixedFileInfo", ModuleAdapter::getFixedFileInfo,
             "Return FixedFileInfo" )
-        .def("__getattr__", ModuleAdapter::getSymbolVa,
+        .def("__getattr__", ModuleAdapter::getSymbolVaAttr,
             "Return address of the symbol" )
         .def( "__str__", &ModuleAdapter::print );
 
@@ -783,7 +783,7 @@ BOOST_PYTHON_MODULE( pykd )
             "Return class parent" )
         .def( "__str__", TypeInfoAdapter::str,
             "Return type as a printable string" )
-        .def( "__getattr__", TypeInfoAdapter::getElementByName )
+        .def( "__getattr__", TypeInfoAdapter::getElementAttr )
         .def( "__len__", TypeInfoAdapter::getElementCount )
         .def( "__getitem__", TypeInfoAdapter::getElementByIndex )
         .def( "__dir__", TypeInfoAdapter::getElementDir )
@@ -825,7 +825,7 @@ BOOST_PYTHON_MODULE( pykd )
             "Return value by pointer" )
         .def("type", TypedVarAdapter::getType,
             "Return typeInfo instance" )
-        .def("__getattr__", TypedVarAdapter::getField,
+        .def("__getattr__", TypedVarAdapter::getFieldAttr,
             "Return field of structure as an object attribute" )
         .def( "__str__", TypedVarAdapter::print )
         .def("__len__", TypedVarAdapter::getElementCount )
diff --git a/pykd/pymodule.h b/pykd/pymodule.h
index 03507bc..b4277c8 100644
--- a/pykd/pymodule.h
+++ b/pykd/pymodule.h
@@ -2,10 +2,15 @@
 
 #include <sstream>
 
+#include <comutil.h>
+
+
 #include "kdlib/module.h"
+#include "kdlib/exceptions.h"
 
 #include "stladaptor.h"
 #include "pythreadstate.h"
+#include "dbgexcept.h"
 
 namespace pykd {
 
@@ -74,6 +79,20 @@ struct ModuleAdapter : public kdlib::Module
         return module.getSymbolVa(symbolName);
     }
 
+    static kdlib::MEMOFFSET_64 getSymbolVaAttr(kdlib::Module& module, const std::wstring &symbolName)
+    {
+        AutoRestorePyState  pystate;
+        try {
+            return module.getSymbolVa(symbolName);
+        }
+        catch (kdlib::DbgException&)
+        {
+            std::wstringstream sstr;
+            sstr << L'\'' << module.getName() << L'\'' << L" module has no symbol " << L'\'' << symbolName << L'\'';
+            throw AttributeException(std::string(_bstr_t(sstr.str().c_str())).c_str());
+        }
+    }
+
     static kdlib::MEMOFFSET_32 getSymbolRva( kdlib::Module& module, const std::wstring &symbolName )
     {
         AutoRestorePyState  pystate;
diff --git a/pykd/pytypedvar.h b/pykd/pytypedvar.h
index 86f1c72..4f7caf0 100644
--- a/pykd/pytypedvar.h
+++ b/pykd/pytypedvar.h
@@ -1,5 +1,7 @@
 #pragma once
 
+#include <comutil.h>
+
 #include <boost/python/list.hpp>
 #include <boost/python/tuple.hpp>
 namespace python = boost::python;
@@ -8,6 +10,7 @@ namespace python = boost::python;
 
 #include "stladaptor.h"
 #include "pythreadstate.h"
+#include "dbgexcept.h"
 
 namespace pykd {
 
@@ -106,6 +109,20 @@ struct TypedVarAdapter {
         return typedVar.getElement( name );
     }
 
+    static kdlib::TypedVarPtr getFieldAttr(kdlib::TypedVar& typedVar, const std::wstring &name)
+    {
+        try
+        {
+            return getField(typedVar, name);
+        }
+        catch (kdlib::DbgException&)
+        {
+            std::wstringstream sstr;
+            sstr << L"typed var has no field " << L'\'' << name << L'\'';
+            throw AttributeException(std::string(_bstr_t(sstr.str().c_str())).c_str());
+        }
+    }
+
     static size_t getElementCount( kdlib::TypedVar& typedVar ) 
     {
         AutoRestorePyState  pystate;
diff --git a/pykd/pytypeinfo.h b/pykd/pytypeinfo.h
index 33d82dd..1bf8de6 100644
--- a/pykd/pytypeinfo.h
+++ b/pykd/pytypeinfo.h
@@ -1,7 +1,11 @@
 #pragma  once
 
+#include <comutil.h>
+
 #include "kdlib/typeinfo.h"
+
 #include "pythreadstate.h"
+#include "dbgexcept.h"
 
 namespace pykd {
 
@@ -109,6 +113,20 @@ struct TypeInfoAdapter : public kdlib::TypeInfo {
         return typeInfo.getElement(name);
     }
 
+    static kdlib::TypeInfoPtr getElementAttr(kdlib::TypeInfo &typeInfo, const std::wstring &name)
+    {
+        try
+        {
+            return getElementByName(typeInfo, name);
+        }
+        catch (kdlib::DbgException&)
+        {
+            std::wstringstream sstr;
+            sstr << L'\'' << typeInfo.getName() << L'\'' << L" type has no field " << L'\'' << name << L'\'';
+            throw AttributeException(std::string(_bstr_t(sstr.str().c_str())).c_str());
+        }
+    }
+
 
     static kdlib::TypeInfoPtr getElementByIndex( kdlib::TypeInfo &typeInfo, size_t index )
     {