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 _______________________________________________ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com