# ***** BEGIN LICENSE BLOCK *****
# Version: MPL 1.1/GPL 2.0/LGPL 2.1
#
# The contents of this file are subject to the Mozilla Public License Version
# 1.1 (the "License"); you may not use this file except in compliance with
# the License. You may obtain a copy of the License at
# http://www.mozilla.org/MPL/
#
# Software distributed under the License is distributed on an "AS IS" basis,
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
# for the specific language governing rights and limitations under the
# License.
#
# The Original Code is the Python Computer Graphics Kit.
#
# The Initial Developer of the Original Code is Matthias Baas.
# Portions created by the Initial Developer are Copyright (C) 2004
# the Initial Developer. All Rights Reserved.
#
# Contributor(s):
#
# Alternatively, the contents of this file may be used under the terms of
# either the GNU General Public License Version 2 or later (the "GPL"), or
# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
# in which case the provisions of the GPL or the LGPL are applicable instead
# of those above. If you wish to allow use of your version of this file only
# under the terms of either the GPL or the LGPL, and not to allow others to
# use your version of this file under the terms of the MPL, indicate your
# decision by deleting the provisions above and replace them with the notice
# and other provisions required by the GPL or the LGPL. If you do not delete
# the provisions above, a recipient may use your version of this file under
# the terms of any one of the MPL, the GPL or the LGPL.
#
# ***** END LICENSE BLOCK *****
# $Id: call.py,v 1.1.1.1 2004/12/12 14:31:33 mbaas Exp $
## \file call.py
## Contains the Call class.
import string, types
# Call
class Call:
"""Call adapter.
This class can either be used to wrap a string or a callable
object with a fixed set of arguments (positional and keyword
arguments). When the %Call object is called (without any
arguments) it executes the string or calls the wrapped function
with the stored arguments.
Objects of this class can be compared using == or != and they're
hashable (so can be used in dictionaries, etc.)
The purpose of this class is to provide an adapter for GUI commands
which take no arguments.
Example:
\code
def foo(a, b, c=0):
print "a:%s b:%s c:%s"%(a,b,c)
>>> f = Call(foo, 1, 2, c=3)
# Call foo with the specified arguments
>>> f()
a:1 b:2 c:3
# Print a readable description of the command object
>>> print f
foo(1, 2, c=3)
\endcode
"""
def __init__(self, func, *args, **keyargs):
"""Constructor.
You must provide the callable object as first argument. All
additional arguments will be passed to the callable object
when its called.
If \a func is a string then there may be one additional argument
that specifies a dictionary which should be used as global
(and local) namespace. The dictionary may be specified as positional
argument following the string or as keyword argument "globals".
The constructor sets the variable __doc__ to a reasonable value.
It'll be either the function doc string if there is one or the
command string itself.
\param func (\c callable or \c str) The function that should be called
\param *args The positional arguments (default = no args)
\param **keyargs The keyword arguments (default = no keyword args)
"""
if isinstance(func, types.StringTypes):
self._func = func
self._args = None
self._keyargs = None
compilestr = func
if "globals" in keyargs:
self._globals = keyargs["globals"]
elif len(args)==1:
self._globals = args[0]
self.__doc__ = None
elif callable(func):
self._func = func
self._args = args
self._keyargs = keyargs
compilestr = "apply(self._func, self._args, self._keyargs)"
self.__doc__ = getattr(func, "__doc__", None)
else:
raise TypeError, "The 'func' argument must be a string or a callable object."
self._code = compile(compilestr, "<command: '%s'>"%str(self), "exec")
if self.__doc__==None or self.__doc__=="":
self.__doc__ = str(self)
def __str__(self):
if callable(self._func):
res = getattr(self._func, "__name__", "<unknown>")
args = map(lambda x: str(x), self._args)
args += map(lambda x: "%s=%s"%(x,self._keyargs[x]), self._keyargs)
res = "%s(%s)"%(res,string.join(args,", "))
else:
res = self._func
return res
def __repr__(self):
return "<Call cmd='%s'>"%str(self)
def __call__(self):
if hasattr(self, "_globals"):
exec self._code in self._globals
else:
exec self._code
def __eq__(self, other):
if not isinstance(other, Call):
return False
return (self._func==other._func and
self._args==other._args and
self._keyargs==other._keyargs)
def __ne__(self, other):
if not isinstance(other, Call):
return True
return (self._func!=other._func or
self._args!=other._args or
self._keyargs!=other._keyargs)
def __hash__(self):
return hash(self._code)
# return hash(self._func) ^ hash(self._args)
|