| """Implementation of OpenGL errors/exceptions |
| |
| Note that OpenGL-ctypes will also throw standard errors, |
| such as TypeError or ValueError when appropriate. |
| |
| ErrorChecker is an _ErrorChecker instance that allows you |
| to register a new error-checking function for use |
| throughout the system. |
| """ |
| import logging |
| _log = logging.getLogger( 'OpenGL.error' ) |
| from OpenGL import platform, _configflags |
| from ctypes import ArgumentError |
| __all__ = ( |
| "Error",'GLError','GLUError','GLUTError', |
| 'GLerror','GLUerror','GLUTerror','ArgumentError', |
| ) |
|
|
| class Error( Exception ): |
| """Base class for all PyOpenGL-specific exception classes""" |
| class NoContext( Error ): |
| """Raised to indicate that there is no currently active context |
| |
| Technically almost *any* OpenGL call can segfault if there is |
| no active context. The OpenGL.CHECK_CONTEXT flag, if enabled |
| will cause this error to be raised whenever a GL or GLU call is |
| issued (via PyOpenGL) if there is no currently valid context. |
| """ |
| class CopyError( Error ): |
| """Raised to indicate that operation requires data-copying |
| |
| if you set: |
| OpenGL.ERROR_ON_COPY = True |
| |
| before importing OpenGL.GL, this error will be raised when |
| a passed argument would require a copy to be made. |
| """ |
|
|
| class NullFunctionError( Error ): |
| """Error raised when an undefined function is called""" |
|
|
| class GLError( Error ): |
| """OpenGL core error implementation class |
| |
| Primary purpose of this error class is to allow for |
| annotating an error with more details about the calling |
| environment so that it's easier to debug errors in the |
| wrapping process. |
| |
| Attributes: |
| |
| err -- the OpenGL error code for the error |
| result -- the OpenGL result code for the operation |
| baseOperation -- the "function" being called |
| pyArgs -- the translated set of Python arguments |
| cArgs -- the Python objects matching 1:1 the C arguments |
| cArguments -- ctypes-level arguments to the operation, |
| often raw integers for pointers and the like |
| description -- OpenGL description of the error (textual) |
| """ |
| def __init__( |
| self, |
| err=None, |
| result=None, |
| cArguments=None, |
| baseOperation=None, |
| pyArgs=None, |
| cArgs=None, |
| description=None, |
| ): |
| """Initialise the GLError, storing metadata for later display""" |
| ( |
| self.err, self.result, self.cArguments, |
| self.baseOperation, self.pyArgs, self.cArgs, |
| self.description |
| ) = ( |
| err, result, cArguments, |
| baseOperation, pyArgs, cArgs, |
| description |
| ) |
| DISPLAY_ORDER = ( |
| 'err', |
| 'description', |
| 'baseOperation', |
| 'pyArgs', |
| 'cArgs', |
| 'cArguments', |
| 'result', |
| ) |
| def __str__( self ): |
| """Create a fully formatted representation of the error""" |
| args = [] |
| for property in self.DISPLAY_ORDER: |
| value = getattr( self, property, None ) |
| if value is not None or property=='description': |
| formatFunction = 'format_%s'%(property) |
| if hasattr( self, formatFunction ): |
| args.append( getattr(self,formatFunction)( property, value )) |
| else: |
| args.append( '%s = %s'%( |
| property, |
| self.shortRepr( value ), |
| )) |
| return '%s(\n\t%s\n)'%(self.__class__.__name__, ',\n\t'.join( |
| [x for x in args if x] |
| )) |
| def __repr__( self ): |
| """Produce a much shorter version of the error as a string""" |
| return '%s( %s )'%( |
| self.__class__.__name__, |
| ", ".join([x for x in [ |
| 'err=%s'%(self.err), |
| self.format_description( 'description', self.description ) or '', |
| self.format_baseOperation( 'baseOperation', self.baseOperation ) or '', |
| ] if x]) |
| ) |
| def format_description( self, property, value ): |
| """Format description using GLU's gluErrorString""" |
| if value is None and self.err is not None: |
| try: |
| from OpenGL.GLU import gluErrorString |
| self.description = value = gluErrorString( self.err ) |
| except Exception as err: |
| return None |
| if value is None: |
| return None |
| return '%s = %s'%( |
| property, |
| self.shortRepr( value ), |
| ) |
| def shortRepr( self, value, firstLevel=True ): |
| """Retrieve short representation of the given value""" |
| if isinstance( value, (list,tuple) ) and value and len(repr(value))>=40: |
| if isinstance( value, list ): |
| template = '[\n\t\t%s\n\t]' |
| else: |
| template = '(\n\t\t%s,\n\t)' |
| return template%( ",\n\t\t".join( |
| [ |
| self.shortRepr(x,False) for x in value |
| ] |
| )) |
| r = repr( value ) |
| if len(r) < 120: |
| return r |
| else: |
| return r[:117] + '...' |
| def format_baseOperation( self, property, value ): |
| """Format a baseOperation reference for display""" |
| if hasattr( value, '__name__' ): |
| return '%s = %s'%( property, value.__name__ ) |
| else: |
| return '%s = %r'%( property, value ) |
|
|
| class GLUError( Error ): |
| """GLU error implementation class""" |
|
|
| class GLUTError( Error ): |
| """GLUT error implementation class""" |
|
|
|
|
| if _configflags.ERROR_CHECKING: |
| from OpenGL import acceleratesupport |
| _ErrorChecker = None |
| if acceleratesupport.ACCELERATE_AVAILABLE: |
| try: |
| from OpenGL_accelerate.errorchecker import _ErrorChecker |
| except ImportError as err: |
| _log.warning( """OpenGL_accelerate seems to be installed, but unable to import error checking entry point!""" ) |
| if _ErrorChecker is None: |
| class _ErrorChecker( object ): |
| """Per-API error-checking object |
| |
| Attributes: |
| _registeredChecker -- the checking function enabled when |
| not doing onBegin/onEnd processing |
| _currentChecker -- currently active checking function |
| """ |
| _getErrors = None |
| def __init__( self, platform, baseOperation=None, noErrorResult=0 ): |
| """Initialize from a platform module/reference""" |
| self._isValid = platform.CurrentContextIsValid |
| self._getErrors = baseOperation |
| self._noErrorResult = noErrorResult |
| if self._getErrors: |
| if _configflags.CONTEXT_CHECKING: |
| self._registeredChecker = self.safeGetError |
| else: |
| self._registeredChecker = self._getErrors |
| else: |
| self._registeredChecker = self.nullGetError |
| self._currentChecker = self._registeredChecker |
| def __bool__( self ): |
| """We are "true" if we actually do anything""" |
| if self._registeredChecker is self.nullGetError: |
| return False |
| return True |
| def safeGetError( self ): |
| """Check for error, testing for context before operation""" |
| if self._isValid(): |
| return self._getErrors() |
| return None |
| def nullGetError( self ): |
| """Used as error-checker when no error checking should be done""" |
| return self._noErrorResult |
| def glCheckError( |
| self, |
| result, |
| baseOperation=None, |
| cArguments=None, |
| *args |
| ): |
| """Base GL Error checker compatible with new ctypes errcheck protocol |
| |
| This function will raise a GLError with just the calling information |
| available at the C-calling level, i.e. the error code, cArguments, |
| baseOperation and result. Higher-level code is responsible for any |
| extra annotations. |
| |
| Note: |
| glCheckError relies on glBegin/glEnd interactions to |
| prevent glGetError being called during a glBegin/glEnd |
| sequence. If you are calling glBegin/glEnd in C you |
| should call onBegin and onEnd appropriately. |
| """ |
| err = self._currentChecker() |
| if err != self._noErrorResult: |
| raise GLError( |
| err, |
| result, |
| cArguments = cArguments, |
| baseOperation = baseOperation, |
| ) |
| return result |
| def onBegin( self ): |
| """Called by glBegin to record the fact that glGetError won't work""" |
| self._currentChecker = self.nullGetError |
| def onEnd( self ): |
| """Called by glEnd to record the fact that glGetError will work""" |
| self._currentChecker = self._registeredChecker |
| else: |
| _ErrorChecker = None |
| |
| GLUerror = GLUError |
| GLerror = GLError |
| GLUTerror = GLUTError |
|
|