[Zope-Checkins] CVS: Zope3/lib/python/Zope/Publisher - mapply.py:1.1.2.2

Shane Hathaway shane@digicool.com
Thu, 15 Nov 2001 10:01:39 -0500


Update of /cvs-repository/Zope3/lib/python/Zope/Publisher
In directory cvs.zope.org:/tmp/cvs-serv30113

Modified Files:
      Tag: Zope-3x-branch
	mapply.py 
Log Message:
Simplified the contract of mapply().  It doesn't need extensible behavior,
just good exceptions.


=== Zope3/lib/python/Zope/Publisher/mapply.py 1.1.2.1 => 1.1.2.2 ===
 """
 
-def default_call_object(object, args, context):
-    result=apply(object,args) # Type s<cr> to step into published object.
-    return result
-
-def default_missing_name(name, context):
-    raise TypeError, 'argument %s was ommitted' % name
-
-def default_handle_class(klass, context):
-    if hasattr(klass,'__init__'): 
-        f=klass.__init__.im_func
-        c=f.func_code
-        names=c.co_varnames[1:c.co_argcount]
-        return klass, names, f.func_defaults
-    else:
-        return klass, (), ()
+_marker = []  # Create a new marker object.
 
-def mapply(object, positional=(), keyword={},
-           debug=None, maybe=None,
-           missing_name=default_missing_name,
-           handle_class=default_handle_class,
-           context=None, bind=0,
-           ):
+def mapply(object, positional=(), keyword={}, call=apply):
 
     if hasattr(object,'__bases__'):
-        f, names, defaults = handle_class(object, context)
+        # Calling class constructors might be dangerous.
+        raise TypeError, "mapply() can not call class constructors"
     else:
         f=object
         im=0
         if hasattr(f, 'im_func'):
+            # It's a method.
             im=1
         elif not hasattr(f,'func_defaults'):
+            # It's not a function.  Maybe it's an instance.
             if hasattr(f, '__call__'):
                 f=f.__call__
                 if hasattr(f, 'im_func'):
+                    # It is an instance with a __call__() method.
                     im=1
-                elif not hasattr(f,'func_defaults') and maybe: return object
-            elif maybe: return object
-    
+                elif not hasattr(f, 'func_defaults'):
+                    # The __call__ attribute is not a method.
+                    raise TypeError, "mapply() can not call %s" % `object`
+            else:
+                # We don't know what it is.
+                raise TypeError, "mapply() can not call %s" % `object`
+        # else it's a function.
+
         if im:
-            f=f.im_func
-            c=f.func_code
-            defaults=f.func_defaults
-            names=c.co_varnames[1:c.co_argcount]
+            f = f.im_func
+            c = f.func_code
+            defaults = f.func_defaults
+            names = c.co_varnames[1:c.co_argcount]
         else:
-            defaults=f.func_defaults
-            c=f.func_code
-            names=c.co_varnames[:c.co_argcount]
+            defaults = f.func_defaults
+            c = f.func_code
+            names = c.co_varnames[:c.co_argcount]
 
-    nargs=len(names)
+    nargs = len(names)
     if positional:
-        positional=list(positional)
-        if bind and nargs and names[0]=='self':
-            positional.insert(0, missing_name('self', context))
-        if len(positional) > nargs: raise TypeError, 'too many arguments'
-        args=positional
+        args = list(positional)
+        if len(args) > nargs:
+            given = len(args)
+            if im:
+                given = given + 1
+            raise TypeError, (
+                '%s() takes at most %d argument%s(%d given)' % (
+                getattr(f, '__name__', repr(object)), c.co_argcount,
+                (c.co_argcount > 1 and 's ' or ' '), given))
     else:
-        if bind and nargs and names[0]=='self':
-            args=[missing_name('self', context)]
-        else:
-            args=[]
+        args = []
 
-    get=keyword.get
-    nrequired=len(names) - (len(defaults or ()))
-    for index in range(len(args), len(names)):
-        name=names[index]
-        v=get(name, args)
-        if v is args:
-            if index < nrequired: v=missing_name(name, context)
-            else: v=defaults[index-nrequired]
+    get = keyword.get
+    if defaults:
+        nrequired = len(names) - (len(defaults))
+    else:
+        nrequired = len(names)
+    for index in range(len(args), nargs):
+        name = names[index]
+        v = get(name, _marker)
+        if v is _marker:
+            if index < nrequired:
+                raise TypeError, 'Missing argument to %s(): %s' % (
+                    getattr(f, '__name__', repr(object)), name)
+            else: v = defaults[index-nrequired]
         args.append(v)
 
-    args=tuple(args)
-    if debug is not None: return debug(object,args,context)
-    else: return apply(object,args)
+    args = tuple(args)
+    return call(object, args)