| """The wrapping code for providing natural ctypes-based OpenGL interface""" |
| import ctypes, logging |
| from OpenGL import platform, error |
| assert platform |
| from OpenGL._configflags import STORE_POINTERS, ERROR_ON_COPY, SIZE_1_ARRAY_UNPACK |
| from OpenGL import converters |
| from OpenGL.converters import DefaultCConverter |
| from OpenGL.converters import returnCArgument,returnPyArgument |
| from OpenGL.latebind import LateBind |
| from OpenGL.arrays import arrayhelpers, arraydatatype |
| from OpenGL._null import NULL |
| _log = logging.getLogger( 'OpenGL.wrapper' ) |
|
|
| from OpenGL import acceleratesupport |
| cWrapper = None |
| if acceleratesupport.ACCELERATE_AVAILABLE: |
| try: |
| from OpenGL_accelerate.latebind import LateBind |
| from OpenGL_accelerate.wrapper import ( |
| Wrapper as cWrapper, |
| CArgCalculator, |
| PyArgCalculator, |
| CArgumentCalculator, |
| MultiReturn, |
| ) |
| except ImportError as err: |
| _log.warning( """OpenGL_accelerate seems to be installed, but unable to import expected wrapper entry points!""" ) |
|
|
| if not STORE_POINTERS: |
| if not ERROR_ON_COPY: |
| _log.error( """You've specified (not STORE_POINTERS) yet ERROR_ON_COPY is False, this would cause segfaults, so (not STORE_POINTERS) is being ignored""" ) |
| STORE_POINTERS = True |
|
|
|
|
| def asList( o ): |
| """Convert to a list if not already one""" |
| if not isinstance( o, list ): |
| return list(o) |
| return o |
|
|
| def none_or_pass( incoming, function, arguments ): |
| return incoming |
| none_or_pass.optional=True |
|
|
| class Wrapper( LateBind ): |
| """Wrapper around a ctypes cFunction object providing SWIG-like hooks |
| |
| Attributes: |
| |
| wrappedOperation -- base operation, normally a ctypes function |
| with data-types and error-checking specified |
| pyConverters -- converters for incoming Python arguments, |
| provide 1:1 mapping to incoming Python arguments, can |
| suppress an argument from the argument-set as well |
| see setPyConverter |
| pyConverterNames -- caching/storage of the argument names |
| for the Python converters |
| cConverters -- converters for incoming C-level arguments |
| produce Python-level objects in 1:1 mapping to ctypes |
| arguments from pyConverters results |
| see setCConverter |
| cResolvers -- converters turning Python-level objects into |
| ctypes-compatible data-types |
| see setCResolver |
| |
| Generic Attributes: |
| |
| {ARG1}_LOOKUP_{ARG2} -- lookup dictionaries to provide sizes for |
| ARG1 output value from the value of ARG2, provided for |
| documentation/reference |
| {ARG1}_FROM_{ARG2} -- lookup functions to provide sizes for ARG1 |
| output value from the value of ARG2, provided for |
| documentation/reference |
| """ |
| localProperties = ( |
| 'wrappedOperation', |
| '__file__', |
| 'pyConverters', |
| 'pyConverterNames', |
| 'cConverters', |
| 'cResolvers', |
| 'storeValues', |
| 'returnValues', |
| '_finalCall', |
| ) |
| def __init__( self, wrappedOperation ): |
| """Initialise the wrapper, storing wrappedOperation""" |
| if isinstance( wrappedOperation, Wrapper ): |
| wrappedOperation = wrappedOperation.wrappedOperation |
| self.wrappedOperation = wrappedOperation |
| def __getattr__( self, key ): |
| """Delegate attribute lookup to our wrappedOperation""" |
| if key != 'wrappedOperation': |
| return getattr( self.wrappedOperation, key ) |
| raise AttributeError( key ) |
| def __nonzero__( self ): |
| """Is this function/wrapper available?""" |
| return bool( self.wrappedOperation ) |
| __bool__ = __nonzero__ |
| def __setattr__( self, key, value ): |
| """Forward attribute setting to our wrappedOperation""" |
| if key in self.localProperties: |
| super( Wrapper, self ).__setattr__( key, value ) |
| else: |
| return setattr( self.wrappedOperation, key, value ) |
| def pyArgIndex( self, argName ): |
| """Return the Python-argument index for the given argument name""" |
| argNames = getattr( self, 'pyConverterNames', None ) |
| if argNames is None: |
| argNames = self.wrappedOperation.argNames |
| try: |
| return asList( argNames ).index( argName ) |
| except (ValueError,IndexError): |
| raise KeyError( """No argument %r in argument list %r"""%( |
| argName, argNames |
| )) |
| def cArgIndex( self, argName ): |
| """Return the C-argument index for the given argument name""" |
| argNames = self.wrappedOperation.argNames |
| try: |
| return asList( argNames ).index( argName ) |
| except (ValueError,IndexError): |
| raise KeyError( """No argument %r in argument list %r"""%( |
| argName, argNames |
| )) |
| def setOutput( |
| self, outArg, size=(1,), pnameArg=None, |
| arrayType=None, oldStyleReturn=SIZE_1_ARRAY_UNPACK, |
| orPassIn = False, |
| ): |
| """Set the given argName to be an output array |
| |
| size -- either a tuple compatible with arrayType.zeros or |
| a function taking pname to produce such a value. |
| arrayType -- array data-type used to generate the output |
| array using the zeros class method... |
| pnameArg -- optional argument passed into size function, that |
| is, the name of the argument whose *value* will be passed |
| to the size function, often the name of an input argument |
| to be "sized" to match the output argument. |
| """ |
| if arrayType is None: |
| |
| index = self.cArgIndex( outArg ) |
| arrayType = self.wrappedOperation.argtypes[ index ] |
| if not hasattr( arrayType, 'asArray' ): |
| if arrayType == ctypes.c_void_p: |
| from OpenGL.arrays import GLubyteArray |
| arrayType = GLubyteArray |
| else: |
| raise TypeError( "Should only have array types for output parameters %s on %s is %r"%( |
| outArg, self.wrappedOperation.__name__, arrayType, |
| ) ) |
| if pnameArg is None: |
| assert not hasattr(size,'__call__' ) |
| if orPassIn: |
| cls = converters.OutputOrInput |
| else: |
| cls = converters.Output |
| conv = cls( |
| name=outArg, |
| size=size, |
| arrayType=arrayType, |
| ) |
| else: |
| if isinstance( size, dict ): |
| setattr( self, '%s_LOOKUP_%s'%(outArg,pnameArg), size ) |
| size = size.__getitem__ |
| else: |
| setattr( self, '%s_FROM_%s'%(outArg,pnameArg), size ) |
| assert hasattr( size, '__call__' ) |
| if orPassIn: |
| cls = converters.SizedOutputOrInput |
| else: |
| cls = converters.SizedOutput |
| conv = cls( |
| name=outArg, |
| specifier=pnameArg, |
| lookup=size, |
| arrayType=arrayType, |
| ) |
| if oldStyleReturn: |
| returnObject = conv.oldStyleReturn |
| else: |
| returnObject = converters.returnCArgument( outArg ) |
| if orPassIn: |
| self.setPyConverter( |
| outArg, none_or_pass |
| ) |
| else: |
| self.setPyConverter( outArg ) |
| return self.setCConverter( |
| outArg, conv, |
| ).setReturnValues( |
| returnObject |
| ) |
| def typeOfArg( self, outArg ): |
| """Retrieve the defined data-type for the given outArg (name)""" |
| index = self.cArgIndex( outArg ) |
| return self.wrappedOperation.argtypes[ index ] |
| |
| if not ERROR_ON_COPY: |
| def setInputArraySize( self, argName, size=None ): |
| """Decorate function with vector-handling code for a single argument |
| |
| if OpenGL.ERROR_ON_COPY is False, then we return the |
| named argument, converting to the passed array type, |
| optionally checking that the array matches size. |
| |
| if OpenGL.ERROR_ON_COPY is True, then we will dramatically |
| simplify this function, only wrapping if size is True, i.e. |
| only wrapping if we intend to do a size check on the array. |
| """ |
| arrayType = self.typeOfArg( argName ) |
| if not hasattr( arrayType, 'asArray' ): |
| if arrayType == ctypes.c_void_p: |
| |
| self.setPyConverter( |
| argName, |
| converters.CallFuncPyConverter( arraydatatype.ArrayDatatype.asArray ) |
| ) |
| self.setCConverter( argName, converters.getPyArgsName( argName ) ) |
| return self |
| elif hasattr( arrayType, '_type_' ) and hasattr(arrayType._type_, '_type_' ): |
| |
| |
| return self |
| else: |
| raise TypeError( "Should only have array types for output parameters: got %s"%(arrayType,) ) |
| if size is not None: |
| self.setPyConverter( argName, arrayhelpers.asArrayTypeSize(arrayType, size) ) |
| else: |
| self.setPyConverter( argName, arrayhelpers.asArrayType(arrayType) ) |
| self.setCConverter( argName, converters.getPyArgsName( argName ) ) |
| return self |
| else: |
| def setInputArraySize( self, argName, size=None ): |
| """Decorate function with vector-handling code for a single argument |
| |
| if OpenGL.ERROR_ON_COPY is False, then we return the |
| named argument, converting to the passed array type, |
| optionally checking that the array matches size. |
| |
| if OpenGL.ERROR_ON_COPY is True, then we will dramatically |
| simplify this function, only wrapping if size is True, i.e. |
| only wrapping if we intend to do a size check on the array. |
| """ |
| if size is not None: |
| arrayType = self.typeOfArg( argName ) |
| |
| if hasattr( arrayType, 'asArray' ): |
| self.setPyConverter( argName, arrayhelpers.asArrayTypeSize(arrayType, size) ) |
| self.setCConverter( argName, |
| converters.getPyArgsName( argName ) |
| ) |
| return self |
| |
| def setPyConverter( self, argName, function = NULL ): |
| """Set Python-argument converter for given argument |
| |
| argName -- the argument name which will be coerced to a usable internal |
| format using the function provided. |
| function -- None (indicating a simple copy), NULL (default) to eliminate |
| the argument from the Python argument-list, or a callable object with |
| the signature: |
| |
| converter(arg, wrappedOperation, args) |
| |
| where arg is the particular argument on which the convert is working, |
| wrappedOperation is the underlying wrapper, and args is the set of |
| original Python arguments to the function. |
| |
| Note that you need exactly the same number of pyConverters as Python |
| arguments. |
| """ |
| if not hasattr( self, 'pyConverters' ): |
| self.pyConverters = [None]*len( self.wrappedOperation.argNames ) |
| self.pyConverterNames = list(self.wrappedOperation.argNames) |
| try: |
| i = asList( self.pyConverterNames ).index( argName ) |
| except ValueError: |
| raise AttributeError( """No argument named %r left in pyConverters for %r: %s"""%( |
| argName, self.wrappedOperation.__name__, self.pyConverterNames, |
| )) |
| if function is NULL: |
| del self.pyConverters[i] |
| del self.pyConverterNames[i] |
| else: |
| self.pyConverters[i] = function |
| return self |
| def setCConverter( self, argName, function ): |
| """Set C-argument converter for a given argument |
| |
| argName -- the argument name whose C-compatible representation will |
| be calculated with the passed function. |
| function -- None (indicating a simple copy), a non-callable object to |
| be copied into the result-list itself, or a callable object with |
| the signature: |
| |
| converter( pyArgs, index, wrappedOperation ) |
| |
| where pyArgs is the set of passed Python arguments, with the |
| pyConverters already applied, index is the index of the C argument |
| and wrappedOperation is the underlying function. |
| |
| C-argument converters are your chance to expand/contract a Python |
| argument list (pyArgs) to match the number of arguments expected by |
| the ctypes baseOperation. You can't have a "null" C-argument converter, |
| as *something* has to be passed to the C-level function in the |
| parameter. |
| """ |
| if not hasattr( self, 'cConverters' ): |
| self.cConverters = [None]*len( self.wrappedOperation.argNames ) |
| try: |
| if not isinstance(self.wrappedOperation.argNames, list): |
| self.wrappedOperation.argNames = list( self.wrappedOperation.argNames ) |
| i = asList( self.wrappedOperation.argNames ).index( argName ) |
| except ValueError: |
| raise AttributeError( """No argument named %r left in cConverters: %s"""%( |
| argName, self.wrappedOperation.argNames, |
| )) |
| self.cConverters[i] = function |
| return self |
| def setCResolver( self, argName, function=NULL ): |
| """Set C-argument converter for a given argument""" |
| if not hasattr( self, 'cResolvers' ): |
| self.cResolvers = [None]*len( self.wrappedOperation.argNames ) |
| try: |
| if not isinstance(self.wrappedOperation.argNames, list): |
| self.wrappedOperation.argNames = list( self.wrappedOperation.argNames ) |
| i = asList( self.wrappedOperation.argNames).index( argName ) |
| except ValueError: |
| raise AttributeError( """No argument named %r left in cConverters: %s"""%( |
| argName, self.wrappedOperation.argNames, |
| )) |
| if function is NULL: |
| del self.cResolvers[i] |
| else: |
| self.cResolvers[i] = function |
| return self |
| def setStoreValues( self, function=NULL ): |
| """Set the storage-of-arguments function for the whole wrapper""" |
| if function is NULL or ERROR_ON_COPY and not STORE_POINTERS: |
| try: |
| del self.storeValues |
| except Exception: |
| pass |
| else: |
| self.storeValues = function |
| return self |
| def setReturnValues( self, function=NULL ): |
| """Set the return-of-results function for the whole wrapper""" |
| if function is NULL: |
| try: |
| del self.returnValues |
| except Exception: |
| pass |
| else: |
| if hasattr(self,'returnValues'): |
| if isinstance(self.returnValues,MultiReturn): |
| self.returnValues.append( function ) |
| else: |
| self.returnValues = MultiReturn( self.returnValues, function ) |
| else: |
| self.returnValues = function |
| return self |
| |
| def finalise( self ): |
| """Finalise our various elements into simple index-based operations""" |
| for attribute in ('pyConverters','cConverters','cResolvers' ): |
| value = getattr( self, attribute, None ) |
| if value is not None: |
| for i,item in enumerate(value): |
| if hasattr( item, 'finalise' ): |
| try: |
| item.finalise( self ) |
| except Exception as err: |
| raise error.Error( |
| """Error finalising item %s in %s for %s (%r): %s"""%( |
| i,attribute,self,item,err, |
| ) |
| ) |
| if hasattr( self, 'cConverters' ): |
| for i,converter in enumerate( self.cConverters ): |
| if isinstance( converter, (type(None),DefaultCConverter )): |
| self.cConverters[i] = DefaultCConverter( self.pyArgIndex( self.argNames[i]) ) |
| for attribute in ('storeValues','returnValues',): |
| item = getattr( self, attribute, None ) |
| if hasattr( item, 'finalise' ): |
| item.finalise( self ) |
| callFunction = self.finaliseCall() |
| if not callFunction: |
| raise RuntimeError( """Missing finalised call type for %s"""%( self, )) |
| else: |
| |
| |
| |
| |
| |
| |
| self.setFinalCall( callFunction ) |
| return callFunction |
| |
| def finaliseCall( self ): |
| """Produce specialised versions of call for finalised wrapper object |
| |
| This returns a version of __call__ that only does that work which is |
| required by the particular wrapper object |
| |
| This is essentially a huge set of expanded nested functions, very |
| inelegant... |
| """ |
| pyConverters = getattr( self, 'pyConverters', None ) |
| cConverters = getattr( self, 'cConverters', None ) |
| cResolvers = getattr( self, 'cResolvers', None ) |
| wrappedOperation = self.wrappedOperation |
| storeValues = getattr( self, 'storeValues', None ) |
| returnValues = getattr( self, 'returnValues', None ) |
| if pyConverters: |
| if cWrapper: |
| calculate_pyArgs = PyArgCalculator( |
| self,pyConverters, |
| ) |
| else: |
| pyConverters_mapped = [ |
| (i,converter,(converter is None)) |
| for (i,converter) in enumerate( pyConverters ) |
| ] |
| pyConverters_length = len([p for p in pyConverters if not getattr( p, 'optional', False)]) |
| def calculate_pyArgs( args ): |
| if pyConverters_length > len(args): |
| raise ValueError( |
| """%s requires %r arguments (%s), received %s: %r"""%( |
| wrappedOperation.__name__, |
| pyConverters_length, |
| ", ".join( self.pyConverterNames ), |
| len(args), |
| args |
| ) |
| ) |
| for index,converter,isNone in pyConverters_mapped: |
| if isNone: |
| yield args[index] |
| else: |
| try: |
| yield converter(args[index], self, args) |
| except IndexError as err: |
| yield NULL |
| except Exception as err: |
| if hasattr( err, 'args' ): |
| err.args += ( converter, ) |
| raise |
| else: |
| calculate_pyArgs = None |
| if cConverters: |
| if cWrapper: |
| calculate_cArgs = CArgCalculator( self, cConverters ) |
| else: |
| cConverters_mapped = [ |
| (i,converter,hasattr(converter,'__call__')) |
| for (i,converter) in enumerate( cConverters ) |
| ] |
| def calculate_cArgs( pyArgs ): |
| for index,converter,canCall in cConverters_mapped: |
| if canCall: |
| try: |
| yield converter( pyArgs, index, self ) |
| except Exception as err: |
| if hasattr( err, 'args' ): |
| err.args += ( |
| """Failure in cConverter %r"""%(converter), |
| pyArgs, index, self, |
| ) |
| raise |
| else: |
| yield converter |
| else: |
| calculate_cArgs = None |
| if cResolvers: |
| if cWrapper: |
| calculate_cArguments = CArgumentCalculator( cResolvers ) |
| else: |
| cResolvers_mapped = list(enumerate(cResolvers)) |
| def calculate_cArguments( cArgs ): |
| for i,converter in cResolvers_mapped: |
| if converter is None: |
| yield cArgs[i] |
| else: |
| try: |
| yield converter( cArgs[i] ) |
| except Exception as err: |
| err.args += (converter,) |
| raise |
| else: |
| calculate_cArguments = None |
| if cWrapper: |
| return cWrapper( |
| wrappedOperation, |
| calculate_pyArgs=calculate_pyArgs, |
| calculate_cArgs=calculate_cArgs, |
| calculate_cArguments=calculate_cArguments, |
| storeValues=storeValues, |
| returnValues=returnValues, |
| ) |
| if pyConverters: |
| if cConverters: |
| |
| if cResolvers: |
| if storeValues: |
| if returnValues: |
| def wrapperCall( *args ): |
| """Wrapper with all possible operations""" |
| pyArgs = tuple( calculate_pyArgs( args )) |
| cArgs = tuple(calculate_cArgs( pyArgs )) |
| cArguments = tuple(calculate_cArguments( cArgs )) |
| try: |
| result = wrappedOperation( *cArguments ) |
| except ctypes.ArgumentError as err: |
| err.args = err.args + (cArguments,) |
| raise err |
| except error.GLError as err: |
| err.cArgs = cArgs |
| err.pyArgs = pyArgs |
| raise err |
| |
| storeValues( |
| result, |
| self, |
| pyArgs, |
| cArgs, |
| ) |
| return returnValues( |
| result, |
| self, |
| pyArgs, |
| cArgs, |
| ) |
| return wrapperCall |
| else: |
| def wrapperCall( *args ): |
| """Wrapper with all save returnValues""" |
| pyArgs = tuple( calculate_pyArgs( args )) |
| cArgs = tuple(calculate_cArgs( pyArgs )) |
| cArguments = tuple(calculate_cArguments( cArgs )) |
| try: |
| result = wrappedOperation( *cArguments ) |
| except ctypes.ArgumentError as err: |
| err.args = err.args + (cArguments,) |
| raise err |
| except error.GLError as err: |
| err.cArgs = cArgs |
| err.pyArgs = pyArgs |
| raise err |
| |
| storeValues( |
| result, |
| self, |
| pyArgs, |
| cArgs, |
| ) |
| return result |
| return wrapperCall |
| else: |
| if returnValues: |
| def wrapperCall( *args ): |
| """Wrapper with all save storeValues""" |
| pyArgs = tuple( calculate_pyArgs( args )) |
| cArgs = tuple(calculate_cArgs( pyArgs )) |
| cArguments = tuple(calculate_cArguments( cArgs )) |
| try: |
| result = wrappedOperation( *cArguments ) |
| except ctypes.ArgumentError as err: |
| err.args = err.args + (cArguments,) |
| raise err |
| except error.GLError as err: |
| err.cArgs = cArgs |
| err.pyArgs = pyArgs |
| raise err |
| return returnValues( |
| result, |
| self, |
| pyArgs, |
| cArgs, |
| ) |
| return wrapperCall |
| else: |
| def wrapperCall( *args ): |
| """Wrapper with all save returnValues and storeValues""" |
| pyArgs = tuple( calculate_pyArgs( args )) |
| cArgs = tuple(calculate_cArgs( pyArgs )) |
| cArguments = tuple(calculate_cArguments( cArgs )) |
| try: |
| result = wrappedOperation( *cArguments ) |
| except ctypes.ArgumentError as err: |
| err.args = err.args + (cArguments,) |
| raise err |
| except error.GLError as err: |
| err.cArgs = cArgs |
| err.pyArgs = pyArgs |
| raise err |
| return result |
| return wrapperCall |
| else: |
| |
| if storeValues: |
| if returnValues: |
| def wrapperCall( *args ): |
| """Wrapper with all possible operations""" |
| pyArgs = tuple( calculate_pyArgs( args )) |
| cArgs = tuple(calculate_cArgs( pyArgs )) |
| cArguments = cArgs |
| try: |
| result = wrappedOperation( *cArguments ) |
| except ctypes.ArgumentError as err: |
| err.args = err.args + (cArguments,) |
| raise err |
| except error.GLError as err: |
| err.cArgs = cArgs |
| err.pyArgs = pyArgs |
| raise err |
| |
| storeValues( |
| result, |
| self, |
| pyArgs, |
| cArgs, |
| ) |
| return returnValues( |
| result, |
| self, |
| pyArgs, |
| cArgs, |
| ) |
| return wrapperCall |
| else: |
| def wrapperCall( *args ): |
| """Wrapper with all save returnValues""" |
| pyArgs = tuple( calculate_pyArgs( args )) |
| cArgs = tuple(calculate_cArgs( pyArgs )) |
| cArguments = cArgs |
| try: |
| result = wrappedOperation( *cArguments ) |
| except ctypes.ArgumentError as err: |
| err.args = err.args + (cArguments,) |
| raise err |
| except error.GLError as err: |
| err.cArgs = cArgs |
| err.pyArgs = pyArgs |
| raise err |
| |
| storeValues( |
| result, |
| self, |
| pyArgs, |
| cArgs, |
| ) |
| return result |
| return wrapperCall |
| else: |
| if returnValues: |
| def wrapperCall( *args ): |
| """Wrapper with all save storeValues""" |
| pyArgs = tuple( calculate_pyArgs( args )) |
| cArgs = tuple(calculate_cArgs( pyArgs )) |
| cArguments = cArgs |
| try: |
| result = wrappedOperation( *cArguments ) |
| except ctypes.ArgumentError as err: |
| err.args = err.args + (cArguments,) |
| raise |
| except error.GLError as err: |
| err.cArgs = cArgs |
| err.pyArgs = pyArgs |
| raise err |
| return returnValues( |
| result, |
| self, |
| pyArgs, |
| cArgs, |
| ) |
| return wrapperCall |
| else: |
| def wrapperCall( *args ): |
| """Wrapper with all save returnValues and storeValues""" |
| pyArgs = tuple( calculate_pyArgs( args )) |
| cArgs = tuple(calculate_cArgs( pyArgs )) |
| cArguments = cArgs |
| try: |
| result = wrappedOperation( *cArguments ) |
| except ctypes.ArgumentError as err: |
| err.args = err.args + (cArguments,) |
| raise |
| except error.GLError as err: |
| err.cArgs = cArgs |
| err.pyArgs = pyArgs |
| raise err |
| return result |
| return wrapperCall |
| else: |
| |
| if cResolvers: |
| if storeValues: |
| if returnValues: |
| def wrapperCall( *args ): |
| """Wrapper with all possible operations""" |
| pyArgs = tuple( calculate_pyArgs( args )) |
| cArgs = pyArgs |
| cArguments = tuple(calculate_cArguments( cArgs )) |
| try: |
| result = wrappedOperation( *cArguments ) |
| except ctypes.ArgumentError as err: |
| err.args = err.args + (cArguments,) |
| raise err |
| except error.GLError as err: |
| err.cArgs = cArgs |
| err.pyArgs = pyArgs |
| raise err |
| |
| storeValues( |
| result, |
| self, |
| pyArgs, |
| cArgs, |
| ) |
| return returnValues( |
| result, |
| self, |
| pyArgs, |
| cArgs, |
| ) |
| return wrapperCall |
| else: |
| def wrapperCall( *args ): |
| """Wrapper with all save returnValues""" |
| pyArgs = tuple( calculate_pyArgs( args )) |
| cArgs = pyArgs |
| cArguments = tuple(calculate_cArguments( cArgs )) |
| try: |
| result = wrappedOperation( *cArguments ) |
| except ctypes.ArgumentError as err: |
| err.args = err.args + (cArguments,) |
| raise err |
| except error.GLError as err: |
| err.cArgs = cArgs |
| err.pyArgs = pyArgs |
| raise err |
| |
| storeValues( |
| result, |
| self, |
| pyArgs, |
| cArgs, |
| ) |
| return result |
| return wrapperCall |
| else: |
| if returnValues: |
| def wrapperCall( *args ): |
| """Wrapper with all save storeValues""" |
| pyArgs = tuple( calculate_pyArgs( args )) |
| cArgs = pyArgs |
| cArguments = tuple(calculate_cArguments( cArgs )) |
| try: |
| result = wrappedOperation( *cArguments ) |
| except ctypes.ArgumentError as err: |
| err.args = err.args + (cArguments,) |
| raise err |
| except error.GLError as err: |
| err.cArgs = cArgs |
| err.pyArgs = pyArgs |
| raise err |
| return returnValues( |
| result, |
| self, |
| pyArgs, |
| cArgs, |
| ) |
| return wrapperCall |
| else: |
| def wrapperCall( *args ): |
| """Wrapper with all save returnValues and storeValues""" |
| pyArgs = tuple( calculate_pyArgs( args )) |
| cArgs = pyArgs |
| cArguments = tuple(calculate_cArguments( cArgs )) |
| try: |
| result = wrappedOperation( *cArguments ) |
| except ctypes.ArgumentError as err: |
| err.args = err.args + (cArguments,) |
| raise err |
| except error.GLError as err: |
| err.cArgs = cArgs |
| err.pyArgs = pyArgs |
| raise err |
| return result |
| return wrapperCall |
| else: |
| |
| if storeValues: |
| if returnValues: |
| def wrapperCall( *args ): |
| """Wrapper with all possible operations""" |
| pyArgs = tuple( calculate_pyArgs( args )) |
| cArguments = pyArgs |
| try: |
| result = wrappedOperation( *cArguments ) |
| except ctypes.ArgumentError as err: |
| err.args = err.args + (cArguments,) |
| raise err |
| except error.GLError as err: |
| err.cArgs = cArguments |
| err.pyArgs = pyArgs |
| raise err |
| |
| storeValues( |
| result, |
| self, |
| pyArgs, |
| cArguments, |
| ) |
| return returnValues( |
| result, |
| self, |
| pyArgs, |
| cArguments, |
| ) |
| return wrapperCall |
| else: |
| def wrapperCall( *args ): |
| """Wrapper with all save returnValues""" |
| pyArgs = tuple( calculate_pyArgs( args )) |
| cArguments = pyArgs |
| try: |
| result = wrappedOperation( *cArguments ) |
| except ctypes.ArgumentError as err: |
| err.args = err.args + (cArguments,) |
| raise err |
| except error.GLError as err: |
| err.cArgs = cArguments |
| err.pyArgs = pyArgs |
| raise err |
| |
| storeValues( |
| result, |
| self, |
| pyArgs, |
| cArguments, |
| ) |
| return result |
| return wrapperCall |
| else: |
| if returnValues: |
| def wrapperCall( *args ): |
| """Wrapper with all save storeValues""" |
| pyArgs = tuple( calculate_pyArgs( args )) |
| cArguments = pyArgs |
| try: |
| result = wrappedOperation( *cArguments ) |
| except ctypes.ArgumentError as err: |
| err.args = err.args + (cArguments,) |
| raise err |
| except error.GLError as err: |
| err.cArgs = cArguments |
| err.pyArgs = pyArgs |
| raise err |
| return returnValues( |
| result, |
| self, |
| pyArgs, |
| cArguments, |
| ) |
| return wrapperCall |
| else: |
| def wrapperCall( *args ): |
| """Wrapper with all save returnValues and storeValues""" |
| pyArgs = tuple( calculate_pyArgs( args )) |
| cArguments = pyArgs |
| try: |
| result = wrappedOperation( *cArguments ) |
| except ctypes.ArgumentError as err: |
| err.args = err.args + (cArguments,) |
| raise err |
| except error.GLError as err: |
| err.cArgs = cArguments |
| err.pyArgs = pyArgs |
| raise err |
| return result |
| return wrapperCall |
| else: |
| |
| if cConverters: |
| if cResolvers: |
| if storeValues: |
| if returnValues: |
| def wrapperCall( *args ): |
| """Wrapper with all possible operations""" |
| pyArgs = args |
| cArgs = [] |
| for (index,converter) in enumerate( cConverters ): |
| |
| if not hasattr(converter,'__call__'): |
| cArgs.append( converter ) |
| else: |
| try: |
| cArgs.append( |
| converter( pyArgs, index, self ) |
| ) |
| except Exception as err: |
| if hasattr( err, 'args' ): |
| err.args += ( |
| """Failure in cConverter %r"""%(converter), |
| pyArgs, index, |
| ) |
| raise |
| cArguments = tuple(calculate_cArguments( cArgs )) |
| try: |
| result = wrappedOperation( *cArguments ) |
| except ctypes.ArgumentError as err: |
| err.args = err.args + (cArguments,) |
| raise err |
| except error.GLError as err: |
| err.cArgs = cArgs |
| err.pyArgs = pyArgs |
| raise err |
| |
| storeValues( |
| result, |
| self, |
| pyArgs, |
| cArgs, |
| ) |
| return returnValues( |
| result, |
| self, |
| pyArgs, |
| cArgs, |
| ) |
| return wrapperCall |
| else: |
| def wrapperCall( *args ): |
| """Wrapper with all save returnValues""" |
| pyArgs = args |
| cArgs = [] |
| for (index,converter) in enumerate( cConverters ): |
| |
| if not hasattr(converter,'__call__'): |
| cArgs.append( converter ) |
| else: |
| try: |
| cArgs.append( |
| converter( pyArgs, index, self ) |
| ) |
| except Exception as err: |
| if hasattr( err, 'args' ): |
| err.args += ( |
| """Failure in cConverter %r"""%(converter), |
| pyArgs, index, |
| ) |
| raise |
| cArguments = tuple(calculate_cArguments( cArgs )) |
| try: |
| result = wrappedOperation( *cArguments ) |
| except ctypes.ArgumentError as err: |
| err.args = err.args + (cArguments,) |
| raise err |
| except error.GLError as err: |
| err.cArgs = cArgs |
| err.pyArgs = pyArgs |
| raise err |
| |
| storeValues( |
| result, |
| self, |
| pyArgs, |
| cArgs, |
| ) |
| return result |
| return wrapperCall |
| else: |
| if returnValues: |
| def wrapperCall( *args ): |
| """Wrapper with all save storeValues""" |
| pyArgs = args |
| cArgs = [] |
| for (index,converter) in enumerate( cConverters ): |
| |
| if not hasattr(converter,'__call__'): |
| cArgs.append( converter ) |
| else: |
| try: |
| cArgs.append( |
| converter( pyArgs, index, self ) |
| ) |
| except Exception as err: |
| if hasattr( err, 'args' ): |
| err.args += ( |
| """Failure in cConverter %r"""%(converter), |
| pyArgs, index, |
| ) |
| raise |
| cArguments = tuple(calculate_cArguments( cArgs )) |
| try: |
| result = wrappedOperation( *cArguments ) |
| except ctypes.ArgumentError as err: |
| err.args = err.args + (cArguments,) |
| raise err |
| except error.GLError as err: |
| err.cArgs = cArgs |
| err.pyArgs = pyArgs |
| raise err |
| return returnValues( |
| result, |
| self, |
| pyArgs, |
| cArgs, |
| ) |
| return wrapperCall |
| else: |
| def wrapperCall( *args ): |
| """Wrapper with all save returnValues and storeValues""" |
| pyArgs = args |
| cArgs = [] |
| for (index,converter) in enumerate( cConverters ): |
| |
| if not hasattr(converter,'__call__'): |
| cArgs.append( converter ) |
| else: |
| try: |
| cArgs.append( |
| converter( pyArgs, index, self ) |
| ) |
| except Exception as err: |
| if hasattr( err, 'args' ): |
| err.args += ( |
| """Failure in cConverter %r"""%(converter), |
| pyArgs, index, |
| ) |
| raise |
| cArguments = tuple(calculate_cArguments( cArgs )) |
| try: |
| result = wrappedOperation( *cArguments ) |
| except ctypes.ArgumentError as err: |
| err.args = err.args + (cArguments,) |
| raise err |
| except error.GLError as err: |
| err.cArgs = cArgs |
| err.pyArgs = pyArgs |
| raise err |
| return result |
| return wrapperCall |
| else: |
| |
| if storeValues: |
| if returnValues: |
| def wrapperCall( *args ): |
| """Wrapper with all possible operations""" |
| pyArgs = args |
| cArgs = [] |
| for (index,converter) in enumerate( cConverters ): |
| |
| if not hasattr(converter,'__call__'): |
| cArgs.append( converter ) |
| else: |
| try: |
| cArgs.append( |
| converter( pyArgs, index, self ) |
| ) |
| except Exception as err: |
| if hasattr( err, 'args' ): |
| err.args += ( |
| """Failure in cConverter %r"""%(converter), |
| pyArgs, index, |
| ) |
| raise |
| cArguments = cArgs |
| try: |
| result = wrappedOperation( *cArguments ) |
| except ctypes.ArgumentError as err: |
| err.args = err.args + (cArguments,) |
| raise err |
| except error.GLError as err: |
| err.cArgs = cArgs |
| err.pyArgs = pyArgs |
| raise err |
| |
| storeValues( |
| result, |
| self, |
| pyArgs, |
| cArgs, |
| ) |
| return returnValues( |
| result, |
| self, |
| pyArgs, |
| cArgs, |
| ) |
| return wrapperCall |
| else: |
| def wrapperCall( *args ): |
| """Wrapper with all save returnValues""" |
| pyArgs = args |
| cArgs = [] |
| for (index,converter) in enumerate( cConverters ): |
| |
| if not hasattr(converter,'__call__'): |
| cArgs.append( converter ) |
| else: |
| try: |
| cArgs.append( |
| converter( pyArgs, index, self ) |
| ) |
| except Exception as err: |
| if hasattr( err, 'args' ): |
| err.args += ( |
| """Failure in cConverter %r"""%(converter), |
| pyArgs, index, |
| ) |
| raise |
| cArguments = cArgs |
| try: |
| result = wrappedOperation( *cArguments ) |
| except ctypes.ArgumentError as err: |
| err.args = err.args + (cArguments,) |
| raise err |
| except error.GLError as err: |
| err.cArgs = cArgs |
| err.pyArgs = pyArgs |
| raise err |
| |
| storeValues( |
| result, |
| self, |
| pyArgs, |
| cArgs, |
| ) |
| return result |
| return wrapperCall |
| else: |
| if returnValues: |
| def wrapperCall( *args ): |
| """Wrapper with all save storeValues""" |
| pyArgs = args |
| cArgs = [] |
| for (index,converter) in enumerate( cConverters ): |
| |
| if not hasattr(converter,'__call__'): |
| cArgs.append( converter ) |
| else: |
| try: |
| cArgs.append( |
| converter( pyArgs, index, self ) |
| ) |
| except Exception as err: |
| if hasattr( err, 'args' ): |
| err.args += ( |
| """Failure in cConverter %r"""%(converter), |
| pyArgs, index, |
| ) |
| raise |
| cArguments = cArgs |
| try: |
| result = wrappedOperation( *cArguments ) |
| except ctypes.ArgumentError as err: |
| err.args = err.args + (cArguments,) |
| raise err |
| except error.GLError as err: |
| err.cArgs = cArgs |
| err.pyArgs = pyArgs |
| raise err |
| return returnValues( |
| result, |
| self, |
| pyArgs, |
| cArgs, |
| ) |
| return wrapperCall |
| else: |
| def wrapperCall( *args ): |
| """Wrapper with all save returnValues and storeValues""" |
| pyArgs = args |
| cArgs = [] |
| for (index,converter) in enumerate( cConverters ): |
| |
| if not hasattr(converter,'__call__'): |
| cArgs.append( converter ) |
| else: |
| try: |
| cArgs.append( |
| converter( pyArgs, index, self ) |
| ) |
| except Exception as err: |
| if hasattr( err, 'args' ): |
| err.args += ( |
| """Failure in cConverter %r"""%(converter), |
| pyArgs, index, |
| ) |
| raise |
| cArguments = cArgs |
| try: |
| result = wrappedOperation( *cArguments ) |
| except ctypes.ArgumentError as err: |
| err.args = err.args + (cArguments,) |
| raise err |
| except error.GLError as err: |
| err.cArgs = cArgs |
| err.pyArgs = pyArgs |
| raise err |
| return result |
| return wrapperCall |
| else: |
| |
| if cResolvers: |
| if storeValues: |
| if returnValues: |
| def wrapperCall( *args ): |
| """Wrapper with all possible operations""" |
| cArgs = args |
| cArguments = tuple(calculate_cArguments( cArgs )) |
| try: |
| result = wrappedOperation( *cArguments ) |
| except ctypes.ArgumentError as err: |
| err.args = err.args + (cArguments,) |
| raise err |
| except error.GLError as err: |
| err.cArgs = cArgs |
| err.pyArgs = args |
| raise err |
| |
| storeValues( |
| result, |
| self, |
| args, |
| cArgs, |
| ) |
| return returnValues( |
| result, |
| self, |
| args, |
| cArgs, |
| ) |
| return wrapperCall |
| else: |
| def wrapperCall( *args ): |
| """Wrapper with all save returnValues""" |
| cArgs = args |
| cArguments = tuple(calculate_cArguments( cArgs )) |
| try: |
| result = wrappedOperation( *cArguments ) |
| except ctypes.ArgumentError as err: |
| err.args = err.args + (cArguments,) |
| raise err |
| except error.GLError as err: |
| err.cArgs = cArgs |
| err.pyArgs = args |
| raise err |
| |
| storeValues( |
| result, |
| self, |
| args, |
| cArgs, |
| ) |
| return result |
| return wrapperCall |
| else: |
| if returnValues: |
| def wrapperCall( *args ): |
| """Wrapper with all save storeValues""" |
| cArgs = args |
| cArguments = tuple(calculate_cArguments( cArgs )) |
| try: |
| result = wrappedOperation( *cArguments ) |
| except ctypes.ArgumentError as err: |
| err.args = err.args + (cArguments,) |
| raise err |
| except error.GLError as err: |
| err.cArgs = cArgs |
| err.pyArgs = args |
| raise err |
| return returnValues( |
| result, |
| self, |
| args, |
| cArgs, |
| ) |
| return wrapperCall |
| else: |
| def wrapperCall( *args ): |
| """Wrapper with all save returnValues and storeValues""" |
| cArgs = args |
| cArguments = tuple(calculate_cArguments( cArgs )) |
| try: |
| result = wrappedOperation( *cArguments ) |
| except ctypes.ArgumentError as err: |
| err.args = err.args + (cArguments,) |
| raise err |
| except error.GLError as err: |
| err.cArgs = cArgs |
| err.pyArgs = args |
| raise err |
| return result |
| return wrapperCall |
| else: |
| |
| if storeValues: |
| if returnValues: |
| def wrapperCall( *args ): |
| """Wrapper with all possible operations""" |
| cArguments = args |
| try: |
| result = wrappedOperation( *cArguments ) |
| except ctypes.ArgumentError as err: |
| err.args = err.args + (cArguments,) |
| raise err |
| except error.GLError as err: |
| err.cArgs = cArguments |
| err.pyArgs = args |
| raise err |
| |
| storeValues( |
| result, |
| self, |
| args, |
| cArguments, |
| ) |
| return returnValues( |
| result, |
| self, |
| args, |
| cArguments, |
| ) |
| return wrapperCall |
| else: |
| def wrapperCall( *args ): |
| """Wrapper with all save returnValues""" |
| cArguments = args |
| try: |
| result = wrappedOperation( *cArguments ) |
| except ctypes.ArgumentError as err: |
| err.args = err.args + (cArguments,) |
| raise err |
| except error.GLError as err: |
| err.cArgs = cArguments |
| err.pyArgs = args |
| raise err |
| |
| storeValues( |
| result, |
| self, |
| args, |
| cArguments, |
| ) |
| return result |
| return wrapperCall |
| else: |
| if returnValues: |
| def wrapperCall( *args ): |
| """Wrapper with all save storeValues""" |
| cArguments = args |
| try: |
| result = wrappedOperation( *cArguments ) |
| except ctypes.ArgumentError as err: |
| err.args = err.args + (cArguments,) |
| raise err |
| except error.GLError as err: |
| err.cArgs = cArguments |
| err.pyArgs = args |
| raise err |
| return returnValues( |
| result, |
| self, |
| args, |
| cArguments, |
| ) |
| return wrapperCall |
| else: |
| def wrapperCall( *args ): |
| """Wrapper with all save returnValues and storeValues""" |
| cArguments = args |
| try: |
| result = wrappedOperation( *cArguments ) |
| except ctypes.ArgumentError as err: |
| err.args = err.args + (cArguments,) |
| raise err |
| except error.GLError as err: |
| err.cArgs = cArguments |
| err.pyArgs = args |
| raise err |
| return result |
| return wrapperCall |
| |
| |
| |
| |
| |
| |
|
|
| def _unspecialised__call__( self, *args ): |
| """Expand arguments, call the function, store values and check errors""" |
| pyConverters = getattr( self, 'pyConverters', None ) |
| if pyConverters: |
| if len(pyConverters) != len(args): |
| raise ValueError( |
| """%s requires %r arguments (%s), received %s: %r"""%( |
| self.wrappedOperation.__name__, |
| len(pyConverters), |
| ", ".join( self.pyConverterNames ), |
| len(args), |
| args |
| ) |
| ) |
| pyArgs = [] |
| for (converter,arg) in zip(pyConverters,args): |
| if converter is None: |
| pyArgs.append( arg ) |
| else: |
| pyArgs.append( converter(arg, self, args) ) |
| else: |
| pyArgs = args |
| cConverters = getattr( self, 'cConverters', None ) |
| if cConverters: |
| cArgs = [] |
| for (index,converter) in enumerate( cConverters ): |
| if not hasattr(converter,'__call__'): |
| cArgs.append( converter ) |
| else: |
| try: |
| cArgs.append( |
| converter( pyArgs, index, self ) |
| ) |
| except Exception as err: |
| if hasattr( err, 'args' ): |
| err.args += ( |
| """Failure in cConverter %r"""%(converter), |
| pyArgs, index, self, |
| ) |
| raise |
| else: |
| cArgs = pyArgs |
| cResolvers = getattr( self, 'cResolvers', None ) |
| if cResolvers: |
| cArguments = [] |
| for (converter, value) in zip( cResolvers, cArgs ): |
| if converter is None: |
| cArguments.append( value ) |
| else: |
| cArguments.append( converter( value ) ) |
| else: |
| cArguments = cArgs |
| try: |
| result = self.wrappedOperation( *cArguments ) |
| except ctypes.ArgumentError as err: |
| err.args = err.args + (cArguments,) |
| raise err |
| except error.GLError as err: |
| err.cArgs = cArgs |
| err.pyArgs = pyArgs |
| raise err |
| storeValues = getattr( self, 'storeValues', None ) |
| if storeValues is not None: |
| |
| storeValues( |
| result, |
| self, |
| pyArgs, |
| cArgs, |
| ) |
| returnValues = getattr( self, 'returnValues', None ) |
| if returnValues is not None: |
| return returnValues( |
| result, |
| self, |
| pyArgs, |
| cArgs, |
| ) |
| else: |
| return result |
|
|
| class MultiReturn(object): |
| def __init__(self,*children): |
| self.children = list(children) |
| def append(self, child ): |
| self.children.append( child ) |
| def __call__(self,*args,**named): |
| result = [] |
| for child in self.children: |
| try: |
| result.append( child(*args,**named) ) |
| except Exception as err: |
| err.args += ( child, args, named ) |
| raise |
| return result |
|
|
| def wrapper( wrappedOperation ): |
| """Create a Wrapper sub-class instance for the given wrappedOperation |
| |
| The purpose of this function is to create a subclass of Wrapper which |
| has the __doc__ and __name__ of the wrappedOperation so that the instance of |
| the wrapper will show up as <functionname instance @ address> by default, |
| and will have the docstring available naturally in pydoc and the like. |
| """ |
| if isinstance( wrappedOperation, Wrapper ): |
| return wrappedOperation |
| dict = { |
| '__doc__': wrappedOperation.__doc__, |
| '__slots__': ('wrappedOperation', ), |
| } |
| cls = type( wrappedOperation.__name__, (Wrapper,), dict ) |
| if hasattr( wrappedOperation, '__module__' ): |
| cls.__module__ = wrappedOperation.__module__ |
| instance = cls(wrappedOperation) |
| return instance |
|
|