On Thu, Dec 9, 2021 at 12:12 AM Paul Bryan <pbr...@anode.ca> wrote: > On Thu, 2021-12-09 at 12:32 +1100, Steven D'Aprano wrote: > > On Wed, Dec 08, 2021 at 09:45:35AM -0800, Paul Bryan wrote: > > I propose there is already a viable option in typing.Annotated. > Example: > > @dataclass > class InventoryItem: > """Class for keeping track of an item in inventory.""" > > name: Annotated[str, "Short name of the item."] > unit_price: Annotated[float, "Price per unit in dollar."] > ... > > > Oh nice! Guido's time machine strikes again. > > So dataclasses could recognise Annotated and populate `__attrdoc__`. > > > Indeed. > > Should all classes do the same? How about top level module variables? > > > If we started with dataclass, it could be performed in the dataclass > decorator and make_dataclass functions. I think this would be low-hanging > fruit compared to classes and modules. >
Again: better than nothing. But I'd really like to see this for all classes. I suggest that if a proposal like this is accepted, the help() output for classes and modules should have a new section added containing the member docstring information; it essentially would insert the member information to the end of the main docstring WHEN DISPLAYED (not suggested attaching it permanently as part of the docstring). This new section would appear directly beneath the module/class docstring when using help. Additionally, other help()-ilke tools (such as the ipython ? operator) should be encouraged to concatenate the member docstring information directly below the class/module docstring when printing out help-like information. To illustrate how things currently stand, here's a current, sort of minimally complicated class definition (class B) with some annotations: In [1]: from typing import Annotated In [2]: class B: ...: """Docstring for the B class.""" ...: ...: a: Annotated[int, "here is what i'd call a medium length docstring"] ...: b: Annotated[str, "short docstring"] ...: ....and here is the help(B) output that i get (Windows command line): In [3]: help(B) Help on class B in module __main__: class B(builtins.object) | Docstring for the B class. | | Data descriptors defined here: | | __dict__ | dictionary for instance variables (if defined) | | __weakref__ | list of weak references to the object (if defined) | | ---------------------------------------------------------------------- | Data and other attributes defined here: | | __annotations__ = {'a': typing.Annotated[int, "here is what i'd call a... The member annotations aren't very discoverable this way... you can't even see all of the first one. If it is agreed that Annotated should be The Blessed Way to annotate members, this needs to be improved. Here is the same thing for a dataclass (class C); here you CAN at least see the whole of each docstring, but they are on one line together and it's not all that great, and bits of the Annotated objects appear in this help output at least 5 times by my count (maybe this can't be helped since it's part of the Annotated object): In [4]: from dataclasses import dataclass In [5]: @dataclass ...: class C: ...: """Docstring for the C class.""" ...: ...: a: Annotated[int, "here is what i'd call a medium length docstring"] ...: b: Annotated[str, "short docstring"] ...: In [6]: help(C) Help on class C in module __main__: class C(builtins.object) | C(a: typing.Annotated[int, "here is what i'd call a medium length docstring"], b: typing.Annotated[str, 'short docstring']) -> None | | Docstring for the C class. | | Methods defined here: | | __eq__(self, other) | | __init__(self, a: typing.Annotated[int, "here is what i'd call a medium length docstring"], b: typing.Annotated[str, 'short docstring']) -> None | | __repr__(self) | | ---------------------------------------------------------------------- | Data descriptors defined here: | | __dict__ | dictionary for instance variables (if defined) | | __weakref__ | list of weak references to the object (if defined) | | ---------------------------------------------------------------------- | Data and other attributes defined here: | | __annotations__ = {'a': typing.Annotated[int, "here is what i'd call a... | | __dataclass_fields__ = {'a': Field(name='a',type=typing.Annotated[int,... | | __dataclass_params__ = _DataclassParams(init=True,repr=True,eq=True,or... | | __hash__ = None Here is the ipython ? output for the dataclass, by the way-- it is FAR better! But this is only so nice because dataclasses adds the typing information to the __init__ signature. For regular classes (like class B above), we would not get this nice output when using ?. In [7]: C? Init signature: C( a: typing.Annotated[int, "here is what i'd call a medium length docstring"], b: typing.Annotated[str, 'short docstring'], ) -> None Docstring: Docstring for the C class. Type: type Subclasses: --- Ricky. "I've never met a Kentucky man who wasn't either thinking about going home or actually going home." - Happy Chandler
_______________________________________________ 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/TXTZV6SQB3BV32QFIIQSUJKML3AQHC4K/ Code of Conduct: http://python.org/psf/codeofconduct/