[Python-checkins] peps: Update from Yury.

brett.cannon python-checkins at python.org
Fri Jun 15 19:56:27 CEST 2012


http://hg.python.org/peps/rev/c1f693b39292
changeset:   4461:c1f693b39292
user:        Brett Cannon <brett at python.org>
date:        Fri Jun 15 13:56:20 2012 -0400
summary:
  Update from Yury.

files:
  pep-0362.txt |  164 +++++++++++++++++++++++++++++---------
  1 files changed, 126 insertions(+), 38 deletions(-)


diff --git a/pep-0362.txt b/pep-0362.txt
--- a/pep-0362.txt
+++ b/pep-0362.txt
@@ -51,12 +51,13 @@
     as listed in ``code.co_varnames``).
 * bind(\*args, \*\*kwargs) -> BoundArguments
     Creates a mapping from positional and keyword arguments to
-    parameters.  Raises a ``BindError`` (subclass of ``TypeError``)
-    if the passed arguments do not match the signature.
+    parameters.  Raises a ``TypeError`` if the passed arguments do
+    not match the signature.
 * bind_partial(\*args, \*\*kwargs) -> BoundArguments
     Works the same way as ``bind()``, but allows the omission
     of some required arguments (mimics ``functools.partial``
-    behavior.)
+    behavior.)  Raises a ``TypeError`` if the passed arguments do
+    not match the signature.
 * format(...) -> str
     Formats the Signature object to a string.  Optional arguments allow
     for custom render functions for parameter names,
@@ -84,27 +85,53 @@
 
 * name : str
     The name of the parameter as a string.
+
 * default : object
     The default value for the parameter, if specified.  If the
     parameter has no default value, this attribute is not set.
+
 * annotation : object
     The annotation for the parameter if specified.  If the
     parameter has no annotation, this attribute is not set.
-* is_keyword_only : bool
-    True if the parameter is keyword-only, else False.
-* is_args : bool
-    True if the parameter accepts variable number of arguments
-    (``*args``-like), else False.
-* is_kwargs : bool
-    True if the parameter accepts variable number of keyword
-    arguments (``**kwargs``-like), else False.
-* is_implemented : bool
+
+* kind : str
+    Describes how argument values are bound to the parameter.
+    Possible values:
+
+       * ``Parameter.POSITIONAL_ONLY`` - value must be supplied
+         as a positional argument.
+
+         Python has no explicit syntax for defining positional-only
+         parameters, but many builtin and extension module functions
+         (especially those that accept only one or two parameters)
+         accept them.
+
+       * ``Parameter.POSITIONAL_OR_KEYWORD`` - value may be
+         supplied as either a keyword or positional argument
+         (this is the standard binding behaviour for functions
+         implemented in Python.)
+
+       * ``Parameter.KEYWORD_ONLY`` - value must be supplied
+         as a keyword argument.  Keyword only parameters are those
+         which appear after a "*" or "\*args" entry in a Python
+         function definition.
+
+       * ``Parameter.VAR_POSITIONAL`` - a tuple of positional
+         arguments that aren't bound to any other parameter.
+         This corresponds to a "\*args" parameter in a Python
+         function definition.
+
+       * ``Parameter.VAR_KEYWORD`` - a dict of keyword arguments
+         that aren't bound to any other parameter. This corresponds
+         to a "\*\*kwds" parameter in a Python function definition.
+
+* implemented : bool
     True if the parameter is implemented for use.  Some platforms
     implement functions but can't support specific parameters
     (e.g. "mode" for ``os.mkdir``).  Passing in an unimplemented
     parameter may result in the parameter being ignored,
     or in NotImplementedError being raised.  It is intended that
-    all conditions where ``is_implemented`` may be False be
+    all conditions where ``implemented`` may be False be
     thoroughly documented.
 
 Two parameters are equal when all their attributes are equal.
@@ -159,12 +186,11 @@
         - If it is ``None`` and the object is an instance of
           ``BuiltinFunction``, raise a ``ValueError``
 
-    - If the object is a an instance of ``FunctionType``:
+    - If it has a ``__wrapped__`` attribute, return
+      ``signature(object.__wrapped__)``
 
-        - If it has a ``__wrapped__`` attribute, return
-          ``signature(object.__wrapped__)``
-
-        - Or else construct a new ``Signature`` object and return it
+    - If the object is a an instance of ``FunctionType`` construct
+      and return a new ``Signature`` for it
 
     - If the object is a method or a classmethod, construct and return
       a new ``Signature`` object, with its first parameter (usually
@@ -223,6 +249,9 @@
 
 Visualizing Callable Objects' Signature
 ---------------------------------------
+
+Let's define some classes and functions:
+
 ::
 
     from inspect import signature
@@ -245,25 +274,62 @@
             return a, b, c
 
 
-    print('FooMeta >', str(signature(FooMeta)))
-    print('Foo >', str(signature(Foo)))
-    print('Foo.__call__ >', str(signature(Foo.__call__)))
-    print('Foo().__call__ >', str(signature(Foo().__call__)))
-    print('partial(Foo().__call__, 1, c=3) >',
-          str(signature(partial(Foo().__call__, 1, c=3))))
-    print('partial(partial(Foo().__call__, 1, c=3), 2, c=20) >',
-          str(signature(partial(partial(Foo().__call__, 1, c=3), 2, c=20))))
+    def shared_vars(*shared_args):
+        """Decorator factory that defines shared variables that are
+           passed to every invocation of the function"""
 
+        def decorator(f):
+            @wraps(f)
+            def wrapper(*args, **kwds):
+                full_args = shared_args + args
+                return f(*full_args, **kwds)
+            # Override signature
+            sig = wrapper.__signature__ = signature(f)
+            for __ in shared_args:
+                sig.parameters.popitem(last=False)
+            return wrapper
+        return decorator
 
-The script will output:
+
+    @shared_vars({})
+    def example(_state, a, b, c):
+        return _state, a, b, c
+
+
+    def format_signature(obj):
+        return str(signature(obj))
+
+
+Now, in the python REPL:
+
 ::
 
-    FooMeta > (name, bases, dct, *, bar:bool=False)
-    Foo > (spam:int=42)
-    Foo.__call__ > (self, a, b, *, c) -> tuple
-    Foo().__call__ > (a, b, *, c) -> tuple
-    partial(Foo().__call__, 1, c=3) > (b, *, c=3) -> tuple
-    partial(partial(Foo().__call__, 1, c=3), 2, c=20) > (*, c=20) -> tuple
+    >>> format_signature(FooMeta)
+    '(name, bases, dct, *, bar:bool=False)'
+
+    >>> format_signature(Foo)
+    '(spam:int=42)'
+
+    >>> format_signature(Foo.__call__)
+    '(self, a, b, *, c) -> tuple'
+
+    >>> format_signature(Foo().__call__)
+    '(a, b, *, c) -> tuple'
+
+    >>> format_signature(partial(Foo().__call__, 1, c=3))
+    '(b, *, c=3) -> tuple'
+
+    >>> format_signature(partial(partial(Foo().__call__, 1, c=3), 2, c=20))
+    '(*, c=20) -> tuple'
+
+    >>> format_signature(example)
+    '(a, b, c)'
+
+    >>> format_signature(partial(example, 1, 2))
+    '(c)'
+
+    >>> format_signature(partial(partial(example, 1, b=2), c=3))
+    '(b=2, c=3)'
 
 
 Annotation Checker
@@ -317,14 +383,14 @@
                 else:
                     if not isinstance(default, type_):
                         raise ValueError("{func}: wrong type of a default value for {arg!r}". \
-                                         format(func=sig.qualname, arg=param.name))
+                                         format(func=func.__qualname__, arg=param.name))
 
         def check_type(sig, arg_name, arg_type, arg_value):
             # Internal function that encapsulates arguments type checking
             if not isinstance(arg_value, arg_type):
                 raise ValueError("{func}: wrong type of {arg!r} argument, " \
                                  "{exp!r} expected, got {got!r}". \
-                                 format(func=sig.qualname, arg=arg_name,
+                                 format(func=func.__qualname__, arg=arg_name,
                                         exp=arg_type.__name__, got=type(arg_value).__name__))
 
         @functools.wraps(func)
@@ -341,12 +407,12 @@
                     # OK, we have a type for the argument, lets get the corresponding
                     # parameter description from the signature object
                     param = sig.parameters[arg_name]
-                    if param.is_args:
+                    if param.kind == param.VAR_POSITIONAL:
                         # If this parameter is a variable-argument parameter,
                         # then we need to check each of its values
                         for value in arg:
                             check_type(sig, arg_name, type_, value)
-                    elif param.is_kwargs:
+                    elif param.kind == param.VAR_KEYWORD:
                         # If this parameter is a variable-keyword-argument parameter:
                         for subname, value in arg.items():
                             check_type(sig, arg_name + ':' + subname, type_, value)
@@ -364,13 +430,35 @@
             else:
                 if isinstance(return_type, type) and not isinstance(result, return_type):
                     raise ValueError('{func}: wrong return type, {exp} expected, got {got}'. \
-                                     format(func=sig.qualname, exp=return_type.__name__,
+                                     format(func=func.__qualname__, exp=return_type.__name__,
                                             got=type(result).__name__))
             return result
 
         return wrapper
 
 
+Render Function Signature to HTML
+---------------------------------
+
+::
+
+    import inspect
+
+    def format_to_html(func):
+        sig = inspect.signature(func)
+
+        html = sig.format(token_params_separator='<span class="t-comma">,</span>',
+                          token_colon='<span class="t-colon">:</span>',
+                          token_eq='<span class="t-eq">=</span>',
+                          token_return_annotation='<span class="t-ra">-&gt;</span>',
+                          token_left_paren='<span class="t-lp">(</span>',
+                          token_right_paren='<span class="t-lp">)</span>',
+                          token_kwonly_separator='<span class="t-ast">*</span>',
+                          format_name=lambda name: '<span class="name">'+name+'</span>')
+
+        return '<span class="py-func">{}</span>'.format(html)
+
+
 References
 ==========
 

-- 
Repository URL: http://hg.python.org/peps


More information about the Python-checkins mailing list