On Sat, Dec 11, 2021 at 05:02:39PM -0800, Christopher Barker wrote: > On Sat, Dec 11, 2021 at 3:03 PM Steven D'Aprano <st...@pearwood.info> wrote:
> > Didn't we decide there was an existing feature for this, no need for > > new syntax? > Well, no. In fact, you could always put anything you wanted into an > annotation: Right, and we want to put a documentation string in it! :-) > Anyway, take a look at the docs for Annotated: > > https://docs.python.org/3/library/typing.html#typing.Annotated > > It has a number of possible unspecified uses, but fundamentally, it's about > the adding information to the type, not to the attribute -- e.g. not really > intended for docstrings. I don't think that the docs argue against this. Annotated is documented as the way to put arbitrary metadata into an annotation. What you do with it is up to the consumer of the metadata. The docs talk about this associating the metadata with the type, but that's because this is the *typing* module and *type* hints are still the primary use-case for annotations. And despite what the docs say, the metadata is actually, literally, associated with the variable (or its name at least). The annotation that gets stored in __annotations__ is **not** {T: "metadata"} as a naive reading of the docs might trick you into believing, but {"var": Annotated[T, "metadata"]} In any case, we can still use annotations for anything we like, and while typing is definitely and certainly the primary use for them, there will always be a way to opt-out. (Just don't run mypy!) Don't need type hints at all? Great, put your doc string as the annotation. μ: 'Number of steps from x0 to the start of the cycle.' λ: 'Length (period) of the cycle.' y: 'Value of f at the start of the cycle.' = None You might want to annotate the class with `no_type_check` if there is any chance the user might want to run mypy over your module, but that's entirely up to you. You do want type hints? Great, use Annotated. If there's an attribute that you don't want to give a type hint to, just use Any. (A small price to pay for using an existing feature, instead of waiting until Python 3.11 or 3.27 when it gets added to the core language.) μ: Annotated[int, 'Number of steps from x0 to the start of the cycle.'] λ: Annotated[int, 'Length (period) of the cycle.'] y: Annotated[Any, 'Value of f at the start of the cycle.' ] = None No new syntax required. No bare strings floating around. You can generate the doc strings dynamically, they don't have to be literals. lunch: Annotated[Meal, ' '.join(['spam']*SPAM_COUNT)] > Sure, typing.Annotated *could* be used that way, but I don't think we can > say that the problem is solved. I think that from a language standpoint, we absolutely can say that the problem is solved. We don't need new syntax. We *might* want to standardise on a decorator or other tool to extract those docstrings, possibly sticking them in a new __attrdoc__ dunder. Being a dunder, we should get the core dev's approval for this, even if it is a third-party tool that uses it. (I assume we don't already use __attrdoc__ for something?) If the first use of this is dataclasses, then that would be de facto core dev approval. So we have a tool that takes an annotation: var: Annotated[T, docstring, *args] extracts out the docstring to an __attrdoc__ dunder: # Class.__attrdoc__ {'var': docstring} and removes the annotation from the annotation: # Class.__annotation__ {'var': Annotated[T, *args]} # or just T if *args is empty? Dataclasses can automatically apply this tool (subject to backwards compatibility constraints), or we can apply it as a decorator to any other class we want. So we've gone from the *hard* problem of making a language change (new syntax, build the functionality into the interpreter) to the *easy* problem of writing a decorator. > Heck you could just as easily provide a tuple for the annotation: > > In [17]: class C: > ...: x: ("Doc string", int) = 123 > ...: Sure, annotations can be anything you like. But external static typing tools may not support this, and will be confused or break. Same for third-party runtime tools. Best practice is to stick as closely to the standard type-hinting behaviour as you can, or to completely opt-out with no_type_hints. > The use cases for annotations are a bit up in the air at the moment -- see > the ongoing discussion on python-dev. But I don't think there's any doubt > that any future endorsed use of them will be compatible with static typing > (if not restricted to it), so extending the use of annotations for > docstrings would take a bit of work to define and accept that use. Annotated is explicitly documented as *arbitrary* metadata that is entirely up to the application to interpret. There's no reason to think that will change. > Perhaps a better way to do that than to use Annotated would be to introduce > new "thing", maybe in teh typoing module, like "Documented": > > class C: > x: Documented(doc_string="this is the doc string", type=int) = 123 Now you're just arguing about the colour of the bike-shed :-) Fine, if we want to increase the complexity of *every* tool that operates on annotations, to specially recognise this new pseudo-type, we could make them recognise Documented["docstring", T] where T is optional and to be interpreted as Any if missing. But I suspect that the type checkers will say "Just use Annotated" but what do I know? Having introduced that special Documented type-hint, we still need to modify dataclasses to extract the docstring from it, and we still need to make it available to other classes via a decorator. So apart from the spelling, which I don't think is a win, we gain nothing. -- Steve _______________________________________________ Python-ideas mailing list -- python-ideas@python.org To unsubscribe send an email to python-ideas-le...@python.org https://mail.python.org/mailman3/lists/python-ideas.python.org/ Message archived at https://mail.python.org/archives/list/python-ideas@python.org/message/7K3ZCICFMQEJHI3KQCNB2E3P7V3MKSBZ/ Code of Conduct: http://python.org/psf/codeofconduct/