[Python-Dev] PEP 362 Third Revision

Yury Selivanov yselivanov.ml at gmail.com
Thu Jun 14 15:50:38 CEST 2012


On 2012-06-14, at 8:06 AM, Victor Stinner wrote:
> Sorry if I'm asking dummy questions, I didn't follow the discussion.
> 
>> * format(...) -> str
>>    Formats the Signature object to a string.  Optional arguments allow
>>    for custom render functions for parameter names,
>>    annotations and default values, along with custom separators.
> 
> Hum, what are these "custom render functions"? Can you give an example?

That's how the function looks right now (I'm not sure we should load
the PEP with this):

    def format(self, *, format_name=str,
                        format_default=repr,
                        format_annotation=formatannotation,
                        format_args=(lambda param: '*' + str(param)),
                        format_kwargs=(lambda param: '**' + str(param)),

                        token_params_separator=', ',
                        token_kwonly_separator='*',
                        token_left_paren='(',
                        token_right_paren=')',
                        token_colon=':',
                        token_eq='=',
                        token_return_annotation=' -> '):

        '''Format signature to a string.

        Arguments (all optional):

        * format_name : A function to format names of parameters.  Parameter
          won't be rendered if ``None`` is returned.
        * format_default : A function to format default values of parameters.
          Default value won't be rendered if ``None`` is returned.
        * format_annotation : A function to format parameter annotations.
          Annotation won't be rendered if ``None`` is returned.
        * format_args : A function to render ``*args`` like parameters.
          Parameter won't be rendered if ``None`` is returned.
        * format_kwargs : A function to render ``**kwargs`` like parameters.
          Parameter won't be rendered if ``None`` is returned.
        * token_params_separator : A separator for parameters.  Set to
          ', ' by default.
        * token_kwonly_separator : A separator for arguments and
          keyword-only arguments.  Defaults to '*'.
        * token_left_paren : Left signature parenthesis, defaults to '('.
        * token_right_paren : Left signature parenthesis, defaults to ')'.
        * token_colon : Separates parameter from its annotation,
          defaults to ':'.
        * token_eq : Separates parameter from its default value, set to
          '=' by default.
        * token_return_annotation : Function return annotation, defaults
          to ' -> '.
        '''

I've designed it in such a way, that everything is configurable, so you
can render functions to color-term, HTML, or whatever else.

>> * 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.
> 
> Hum, why not using a attribute with a string value instead of 3
> attribute? For example:
> * argtype: "index", "varargs", "keyword" or "keyword_only"
> 
> It would avoid a possible inconsitency (ex: is_args=True and
> is_kwargs=True). And it would help to implement something like a C
> switch/case using a dict: argtype => function for functions using
> signatures.

Originally, I thought the the line:

   if parameters.is_args

is better looking that:

   if parameters.kind == 'vararg'

But, I like your arguments regarding inconsistency and dispatch
through a dict (someone may find it useful).  Also, Larry gave
another one - who knows if we add another type of arguments in 
the future.

I guess if nobody really wants to keep 'is_args', we can alter the
PEP.

Let's consider replacement of 'Parameter.is_*' set of attributes with 
a single 'Parameter.kind' attribute, which will have the following 
possible values: 'positional', 'vararg', 'keyword-only', 'varkwarg'.

(I think 'positional' is more intuitive than 'index'?)

>> * is_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
>>    thoroughly documented.
> 
> I suppose that the value depends on the running platform? (For
> example, you may get a different value on Linux and Windows.)

Correct.

>> Implementation
>> ==============
>> 
>>    - If the object has a ``__signature__`` attribute and if it
>>      is not ``None`` - return a deepcopy of it
> 
> Oh, why copying the object? It may impact performances. If fhe caller
> knows that it will modify the signature, it can deepcopy the
> signature.

There was a discussion on this topic earlier on python-dev.  
In short - as we usually create new signatures with each 'signature()' 
call, users will expect that they can modify those freely.  But if we 
have one defined in __signature__, without copying it, all its 
modifications will be persistent across 'signature()' calls.  So the 
deepcopy here is required more for the consistency reasons.  Besides, 
I don't think that 'signature()' will be used extensively in 
performance-critical types of code.  And even if it is - you can just 
cache it manually.

>>        - If it is ``None`` and the object is an instance of
>>          ``BuiltinFunction``, raise a ``ValueError``
> 
> What about builtin functions (ex: len)? Do you plan to add a
> __signature__ attribute? If yes, something created on demand or
> created at startup?

Larry is going to add signatures to some 'os' module functions. But 
that would it for 3.3, I guess.

> It would be nice to have a C API to create Signature objects, maybe
> from the same format string than PyArg_Parse*() functions. But it can
> be implemented later.

Then parameters will lack the 'name' attribute.  I think we need another
approach here.

> Is it possible to build a Signature object from a string describing
> the prototype (ex: "def f(x, y): pass")? (I mean: do you plan to add
> such function?)


There are no plans to add it now (no good reasons to include such
functionality in 3.3 at least)

Thank you,

-
Yury


More information about the Python-Dev mailing list