VirtualBox

Changeset 47981 in vbox for trunk/src/VBox


Ignore:
Timestamp:
Aug 22, 2013 12:47:00 AM (11 years ago)
Author:
vboxsync
Message:

vboxapi.py: Started on error abstrations (testsuite needs errIsDeadInterface).

Location:
trunk/src/VBox
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Frontends/VBoxShell/vboxshell.py

    r47979 r47981  
    205205
    206206def printErr(_ctx, e):
    207     print colored(str(e), 'red')
     207    oVBoxMgr = _ctx['global'];
     208    if oVBoxMgr.errIsOurXcptKind(e):
     209        print colored('%s: %s' % (oVBoxMgr.errToString(e), oVBoxMgr.errGetMessage(e)), 'red');
     210    else:
     211        print colored(str(e), 'red')
    208212
    209213def reportError(_ctx, progress):
  • trunk/src/VBox/Main/glue/vboxapi.py

    r47979 r47981  
    131131#
    132132def ComifyName(name):
    133     return name[0].capitalize()+name[1:]
     133    return name[0].capitalize() + name[1:]
    134134
    135135
     
    141141}
    142142
    143 def CustomGetAttr(self, attr):
    144     # fastpath
    145     if self.__class__.__dict__.get(attr) != None:
    146         return self.__class__.__dict__.get(attr)
    147 
    148     # try case-insensitivity workaround for class attributes (COM methods)
    149     for k in self.__class__.__dict__.keys():
    150         if k.lower() == attr.lower():
    151             self.__class__.__dict__[attr] = self.__class__.__dict__[k]
    152             return getattr(self, k)
     143def _CustomGetAttr(self, sAttr):
     144    """ Our getattr replacement for DispatchBaseClass. """
     145    # Fastpath.
     146    oRet = self.__class__.__dict__.get(sAttr);
     147    if oRet != None:
     148        return oRet;
     149
     150    # Try case-insensitivity workaround for class attributes (COM methods).
     151    sAttrLower = sAttr.lower();
     152    for sKey in self.__class__.__dict__.keys():
     153        if sKey.lower() == sAttrLower:
     154            self.__class__.__dict__[sAttr] = self.__class__.__dict__[sKey]
     155            return getattr(self, sKey)
     156
     157    # Slow path.
    153158    try:
    154         return _g_dCOMForward['getattr'](self, ComifyName(attr))
     159        return _g_dCOMForward['getattr'](self, ComifyName(sAttr))
    155160    except AttributeError:
    156         return _g_dCOMForward['getattr'](self, attr)
    157 
    158 def CustomSetAttr(self, attr, value):
     161        return _g_dCOMForward['getattr'](self, sAttr)
     162
     163def _CustomSetAttr(self, sAttr, oValue):
     164    """ Our setattr replacement for DispatchBaseClass. """
    159165    try:
    160         return _g_dCOMForward['setattr'](self, ComifyName(attr), value)
     166        return _g_dCOMForward['setattr'](self, ComifyName(sAttr), oValue)
    161167    except AttributeError:
    162         return _g_dCOMForward['setattr'](self, attr, value)
     168        return _g_dCOMForward['setattr'](self, sAttr, oValue)
    163169
    164170
     
    286292        """
    287293        return None;
     294
     295    #
     296    # Error (exception) access methods.
     297    #
     298
     299    def errGetStatus(self, oXcpt):
     300        """
     301        Returns the COM status code from the VBox API given exception.
     302        """
     303        return None;
     304
     305    def errIsDeadInterface(self, oXcpt):
     306        """
     307        Returns True if the exception indicates that the interface is dead, False if not.
     308        """
     309        return False;
     310
     311    def errIsEqual(oXcpt, hrStatus):
     312        """
     313        Checks if the exception oXcpt is equal to the COM/XPCOM status code
     314        hrStatus.
     315
     316        The oXcpt parameter can be any kind of object, we'll just return True
     317        if it doesn't behave like a our exception class.
     318
     319        Will not raise any exception as long as hrStatus and self are not bad.
     320        """
     321        try:
     322            hrXcpt = self.errGetStatus(oXcpt);
     323        except AttributeError:
     324            return False;
     325        return hrXcpt == hrStatus;
     326
     327    def errGetMessage(self, oXcpt):
     328        """
     329        Returns the best error message found in the COM-like exception.
     330        Returns None to fall back on errToString.
     331        Raises exception if oXcpt isn't our kind of exception object.
     332        """
     333        return None;
     334
     335    def errGetBaseXcpt(self):
     336        """
     337        Returns the base exception class.
     338        """
     339        return None;
     340
     341    def errSetupConstants(self, oDst):
     342        """
     343        Copy/whatever all error constants onto oDst.
     344        """
     345        return oDst;
     346
     347    @staticmethod
     348    def errCopyErrorConstants(oDst, oSrc):
     349        """
     350        Copy everything that looks like error constants from oDst to oSrc.
     351        """
     352        for sAttr in dir(oSrc):
     353            if sAttr[0].isupper() and (sAttr[1].isupper() or sAttr[1] == '_'):
     354                oAttr = getattr(oSrc, sAttr);
     355                if type(oAttr) is int:
     356                    setattr(oDst, sAttr, oAttr);
     357        return oDst;
     358
    288359
    289360
     
    377448        import pythoncom
    378449        import win32api
     450        import winerror
    379451        from win32con import DUPLICATE_SAME_ACCESS
    380452        from win32api import GetCurrentThread, GetCurrentThreadId, DuplicateHandle, GetCurrentProcess
    381453        import threading
     454
     455        self.winerror = winerror;
    382456
    383457        pid      = GetCurrentProcess()
     
    391465        if _g_dCOMForward['setattr'] is None:
    392466            _g_dCOMForward['getattr'] = DispatchBaseClass.__dict__['__getattr__']
    393             DispatchBaseClass.__dict__['__getattr__'] = CustomGetAttr
     467            DispatchBaseClass.__dict__['__getattr__'] = _CustomGetAttr
    394468            _g_dCOMForward['setattr'] = DispatchBaseClass.__dict__['__setattr__']
    395             DispatchBaseClass.__dict__['__setattr__'] = CustomSetAttr
     469            DispatchBaseClass.__dict__['__setattr__'] = _CustomSetAttr
    396470
    397471        # Hack the exception base class so the users doesn't need to check for
     
    538612        return CastTo(oIUnknown, sClassName)
    539613
     614    def errGetStatus(self, oXcpt):
     615        # The DISP_E_EXCEPTION + excptinfo fun needs checking up, only
     616        # empirical info on it so far.
     617        hrXcpt = oXcpt.hresult
     618        if hrXcpt == self.winerror.DISP_E_EXCEPTION:
     619            try:    hrXcpt = oXcpt.excepinfo[5];
     620            except: pass;
     621        return hrXcpt;
     622
     623    def errIsDeadInterface(self, oXcpt):
     624        return self.errGetStatus(oXcpt) in [
     625            0x800706ba, -2147023174, # RPC_S_SERVER_UNAVAILABLE.
     626            0x800706be, -2147023170, # RPC_S_CALL_FAILED.
     627            0x800706bf, -2147023169, # RPC_S_CALL_FAILED_DNE.
     628            0x80010108, -2147417848, # RPC_E_DISCONNECTED.
     629        ];
     630
     631
     632    def errGetMessage(self, oXcpt):
     633        if hasattr(oXcpt, 'excepinfo'):
     634            try:
     635                if len(oXcpt.excepinfo) >= 3:
     636                    sRet = oXcpt.excepinfo[2];
     637                    if len(sRet) > 0:
     638                        return sRet[0:];
     639            except:
     640                pass;
     641        if hasattr(oXcpt, 'strerror'):
     642            try:
     643                sRet = oXcpt.strerror;
     644                if len(sRet) > 0:
     645                    return sRet;
     646            except:
     647                pass;
     648        return None;
     649
     650    def errGetBaseXcpt(self):
     651        import pythoncom;
     652        return pythoncom.com_error;
     653
     654    def errSetupConstants(self, oDst):
     655        import winerror;
     656        oDst = self.errCopyErrorConstants(oDst, winerror);
     657
     658        # XPCOM compatability constants.
     659        oDst.NS_OK                    = oDst.S_OK;
     660        oDst.NS_ERROR_FAILURE         = oDst.E_FAIL;
     661        oDst.NS_ERROR_ABORT           = oDst.E_ABORT;
     662        oDst.NS_ERROR_NULL_POINTER    = oDst.E_POINTER;
     663        oDst.NS_ERROR_NO_INTERFACE    = oDst.E_NOINTERFACE;
     664        oDst.NS_ERROR_INVALID_ARG     = oDst.E_INVALIDARG;
     665        oDst.NS_ERROR_OUT_OF_MEMORY   = oDst.E_OUTOFMEMORY;
     666        oDst.NS_ERROR_NOT_IMPLEMENTED = oDst.E_NOTIMPL;
     667        oDst.NS_ERROR_UNEXPECTED      = oDst.E_UNEXPECTED;
     668        return oDst;
     669
    540670
    541671class PlatformXPCOM(PlatformBase):
     
    603733        import xpcom.components
    604734        return oIUnknown.queryInterface(getattr(xpcom.components.interfaces, sClassName))
     735
     736    def errGetStatus(self, oXcpt):
     737        return oXcpt.errno;
     738
     739    def errIsDeadInterface(self, oXcpt):
     740        import winerror;
     741        return self.errGetStatus(oXcpt) in [
     742            0x80004004, -2147467260, # NS_ERROR_ABORT
     743            0x800706be, -2147023170, # NS_ERROR_CALL_FAILED (RPC_S_CALL_FAILED)
     744        ];
     745
     746    def errGetMessage(self, oXcpt):
     747        if hasattr(oXcpt, 'msg'):
     748            try:
     749                sRet = oXcpt.msg;
     750                if len(sRet) > 0:
     751                    return sRet;
     752            except:
     753                pass;
     754        return None;
     755
     756    def errGetBaseXcpt(self):
     757        import xpcom;
     758        return xpcom.Exception;
     759
     760    def errSetupConstants(self, oDst):
     761        import winerror;
     762        oDst = self.errCopyErrorConstants(oDst, winerror);
     763
     764        # COM compatability constants.
     765        oDst.E_ACCESSDENIED           = -2147024891; # see VBox/com/defs.h
     766        oDst.S_OK                     = oDst.NS_OK;
     767        oDst.E_FAIL                   = oDst.NS_ERROR_FAILURE;
     768        oDst.E_ABORT                  = oDst.NS_ERROR_ABORT;
     769        oDst.E_POINTER                = oDst.NS_ERROR_NULL_POINTER;
     770        oDst.E_NOINTERFACE            = oDst.NS_ERROR_NO_INTERFACE;
     771        oDst.E_INVALIDARG             = oDst.NS_ERROR_INVALID_ARG;
     772        oDst.E_OUTOFMEMORY            = oDst.NS_ERROR_OUT_OF_MEMORY;
     773        oDst.E_NOTIMPL                = oDst.NS_ERROR_NOT_IMPLEMENTED;
     774        oDst.E_UNEXPECTED             = oDst.NS_ERROR_UNEXPECTED;
     775        oDst.DISP_E_EXCEPTION         = -2147352567; # For COM compatability only.
     776        return oDst;
    605777
    606778
     
    705877
    706878
     879## The current (last) exception class.
     880# This is reinitalized whenever VirtualBoxManager is called, so it will hold
     881# the reference to the error exception class for the last platform/style that
     882# was used.  Most clients does talk to multiple VBox instance on different
     883# platforms at the same time, so this should be sufficent for most uses and
     884# be way simpler to use than VirtualBoxManager::oXcptClass.
     885CurXctpClass = None;
     886
    707887
    708888class VirtualBoxManager(object):
     
    718898    WEBSERVICE backend.
    719899    """
     900
     901    class Statuses(object):
     902        def __init__(self):
     903            pass;
    720904
    721905    def __init__(self, sStyle = None, dPlatformParams = None):
     
    736920        self.type      = self.platform.getType()
    737921        self.remote    = self.platform.isRemote()
    738         # for webservices, enums are symbolic
     922        ## VirtualBox API constants (for webservices, enums are symbolic).
    739923        self.constants = VirtualBoxReflectionInfo(sStyle == "WEBSERVICE")
    740924
     925        ## Status constants.
     926        self.statuses  = self.platform.errSetupConstants(VirtualBoxManager.Statuses());
     927        ## @todo Add VBOX_E_XXX to statuses? They're already in constants...
     928        ## Dictionary for errToString, built on demand.
     929        self._dErrorValToName = None;
     930
     931        ## The exception class for the selected platform.
     932        self.oXcptClass = self.platform.errGetBaseXcpt();
     933        global CurXcptClass;
     934        CurXcptClass = self.oXcptClass;
     935
     936        # Get the virtualbox singleton.
    741937        try:
    742938            self.vbox = self.platform.getVirtualBox()
     
    760956        self.deinit()
    761957
     958    def getPythonApiRevision(self):
     959        """
     960        Returns a Python API revision number.
     961        This will be incremented when features are added to this file.
     962        """
     963        return 2;
     964
    762965
    763966    #
     
    8681071        return VBoxSdkDir
    8691072
     1073
     1074    #
     1075    # Error code utilities.
     1076    #
     1077
     1078    ## @todo port to webservices!
     1079
     1080    def errGetStatus(self, oXcpt):
     1081        """
     1082        Gets the status code from an exception.
     1083        """
     1084        return self.platform.errGetStatus(oXcpt);
     1085
     1086    def errIsDeadInterface(self, oXcpt):
     1087        """
     1088        Returns True if the exception indicates that the interface is dead, False if not.
     1089        """
     1090        return self.platform.errIsDeadInterface(oXcpt);
     1091
     1092    def errIsOurXcptKind(self, oXcpt):
     1093        """
     1094        Checks if the exception is one that could come from the VBox API.
     1095        """
     1096        if self.oXcptClass is None: ## @todo find the exception class for web services!
     1097            return False;
     1098        return isinstance(oXcpt, self.oXcptClass);
     1099
     1100    def errIsEqual(self, oXcpt, hrStatus):
     1101        """ See PlatformBase::errIsEqual(). """
     1102        return self.platform.errIsEqual(oXcpt, hrStatus);
     1103
     1104    def errIsNotEqual(self, oXcpt, hrStatus):
     1105        """
     1106        Negated errIsEqual.
     1107        """
     1108        return self.errIsEqual(oXcpt, hrStatus);
     1109
     1110    def errToString(self, hrStatusOrXcpt):
     1111        """
     1112        Converts the specified COM status code, or the status code of the
     1113        specified exception, to a C constant string.
     1114        """
     1115
     1116        # Deal with exceptions.
     1117        if self.errIsOurXcptKind(hrStatusOrXcpt):
     1118            hrStatus = self.errGetStatus(hrStatusOrXcpt);
     1119        else:
     1120            hrStatus = hrStatusOrXcpt;
     1121
     1122        # Build the dictionary on demand.
     1123        if self._dErrorValToName is None:
     1124            dErrorValToName = dict();
     1125            for sKey in dir(self.statuses):
     1126                if sKey[0].isupper():
     1127                    oValue = getattr(self.statuses, sKey);
     1128                    if type(oValue) is int:
     1129                        dErrorValToName[oValue] = sKey;
     1130            self._dErrorValToName = dErrorValToName;
     1131
     1132        # Do the lookup, falling back on formatting the status number.
     1133        try:
     1134            sStr = self._dErrorValToName[int(hrStatus)];
     1135        except KeyError:
     1136            hrLong = long(hrStatus);
     1137            sStr = '%#x (%d)' % (hrLong, hrLong);
     1138        return sStr;
     1139
     1140    def errGetMessage(self, oXcpt):
     1141        """
     1142        Returns the best error message found in the COM-like exception.
     1143        """
     1144        sRet = self.platform.errGetMessage(oXcpt);
     1145        if sRet is None:
     1146            sRet = self.errToString(oXcpt);
     1147        return sRet;
     1148
Note: See TracChangeset for help on using the changeset viewer.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette