On 8/14/06, Paul Prescod <[EMAIL PROTECTED]> wrote: > Third, we absolutely need a standard for > multiple independent annotations on a parameter. Using lists is a > no-brainer. So let's do that.
The problem with using lists is that its impossible for non-decorator annotation consumers to know which element "belongs" to them. Way back in http://mail.python.org/pipermail/python-3000/2006-August/002865.html, Nick Coghlan said: > However, what we're really talking about here is a scenario where you're > defining your *own* custom annotation processor: you want the first part of > the tuple in the expression handled by the type processing library, and the > second part handled by the docstring processing library. > > Which says to me that the right solution is for the annotation to be split up > into its constituent parts before the libraries ever see it. > > This could be done as Collin suggests by tampering with > __signature__.annotations before calling each decorator, but I think it is > cleaner to do it by defining a particular signature for decorators that are > intended to process annotations. > > Specifically, such decorators should accept a separate dictionary to use in > preference to the annotations on the function itself: > > process_function_annotations(f, annotations=None): > # Process the function f > # If annotations is not None, use it > # otherwise, get the annotations from f.__signature__ I've come to like this idea more and more. Here's my stab at a dict-based convention for specifying annotations for decorator-style consumers: There are several annotation consumers, docstring, typecheck and constrain_values. Respectively, these treat annotations as documentation; as restrictions on the type of an argument; as restrictions on the values of an argument. Each of these is defined something like def consumer(annotated_function, annotations=sentinel): ... If the consumer isn't given an `annotations` parameter, it is free to assume it is the only consumer for the annotations on that function and is free to treat the annotation expressions however it sees fit. However, if it is given an `annotations` argument, it should observe those annotations and only those annotations. The more complete example: @multiple_annotations(docstring, typecheck, constrain_values) def foo(a: {'docstring': "Frobnication count", 'typecheck': Number, 'constrain_values': range(3, 9)}, b: {'typecheck': Number, # This can be only 4, 8 or 12 'constrain_values': [4, 8, 12]}) -> {'typecheck': Number} Here, multiple_annotations assumes that the annotation dicts are keyed on consumer.__name__; the test "if consumer.__name__ in per_parameter_annotations" should do nicely for figuring out whether a given consumer should be provided an `annotations` argument. (It is up to multiple_annotations() to decide whether "consumer.__name__ in per_parameter_annotations == False" should raise an exception.) Collin Winter _______________________________________________ Python-3000 mailing list Python-3000@python.org http://mail.python.org/mailman/listinfo/python-3000 Unsubscribe: http://mail.python.org/mailman/options/python-3000/archive%40mail-archive.com