Skip to content

feature: Design a better system to reference components of symbols #404

@pawamoy

Description

@pawamoy

Is your feature request related to a problem? Please describe.

More and more, we allow referencing things that aren't symbols (in the sense that you cannot / do not manipulate these things directly within the language / with the language constructs), such as parameters and type parameters. Currently, we allow referencing those with the following syntax:

  • parameters: path.to.symbol(parameter_name)
  • type parameters: path.to.symbol[type_parameter_name]

While these characters play well with the language constructs (parentheses for parameters, like function calls, and square brackets for type parameters, like how they're bound to functions/classes), they do not always play well with Markdown (parentheses are OK-ish, square brackets are just not supported within links), and our way of parsing them in identifiers is a bit messy (they were an after-thought).

Describe the solution you'd like

I would like to design a better system for referencing parameters, type parameters, and many more types of symbol components, with a clear, obvious syntax, and (less obvious) shortcuts for brevity. This system would be properly integrated in Griffe, with good, tested parsing of identifiers, and the whole API would be aware of it.

Symbol components I'd like the system to handle:

  • parameters
  • type parameters
  • returned values
  • exceptions raised
  • yielded values
  • received values
  • warnings emitted

The following ones could be interesting, though do not even have matching docstring sections yet:

  • logs emitted
  • messages written to stdout, stderr, and more file descriptors
  • inputs read from stdin, and more file descriptors
  • other I/O stuff? file read/writes? network read/writes? side-effects in general?

The syntax I imagine to reference each one of these symbol component types is:

Component type Clear syntax Shortcut
Parameters SYMBOL{param:ID} SYMBOL <- ID, and SYMBOL(ID) for backward-compatibility
Type parameters SYMBOL{type_param:ID} SYMBOL @ ID, and SYMBOL[ID] for backward-compatibility
Returned values SYMBOL{return:ID} SYMBOL -> ID
Exceptions raised SYMBOL{exception:ID} SYMBOL ! ID
Yielded values SYMBOL{yield:ID} SYMBOL ~> ID
Received values SYMBOL{receive:ID} SYMBOL <~ ID
Warnings emitted SYMBOL{warning:ID} SYMBOL ? ID
Logs emitted SYMBOL{log:ID} SYMBOL % ID
Standard output SYMBOL{output:ID} SYMBOL >1 ID
Standard error SYMBOL{error:ID} SYMBOL >2 ID
Standard input SYMBOL{input:ID} SYMBOL <0 ID
Generic file (descriptor) write SYMBOL{write:ID}, etc. SYMBOL > ID, etc.
Generic file (descriptor) read SYMBOL{read:ID}, etc. SYMBOL < ID, etc.
Other I/O stuff SYMBOL{io:ID} SYMBOL + ID

In the shorcut syntax, spaces around the "operator" would be irrelevant. SYMBOL is the path to a symbol like module.Class.function and ID is an identifier for a particular instance of this component type, for example RuntimeError for an instance of raised exception component.

Maybe standard output/error/input, generic file read/writes and I/O stuff in general could be merged in just read and write types, identifiers being file descriptors (0, 1, 2, etc.), file paths (/abs/path, rel/path, etc.), environment variables (SOME_THING, etc.), network interfaces, sockets or whatever (no ID idea yet), URLs (https://example.com/api/things, /api/things, etc.), or anything else, really. The point is just to document the inputs/reads and outputs/writes in a structured way.

Describe alternatives you've considered

/

Additional context

This will be needed to finish https://github.com/mkdocstrings/python/pull/221/files#r2296663095, as this PR brings the ability to reference type parameters, but the current supported syntax in Griffe (square brackets) cannot actually be used within Markdown links: [title][path.to.object[type_param_name]] is incorrect syntax and won't be parsed as expected.

As to "why do we want to reference emitted logs, emitted warnings, raised exceptions, etc?", we want this because users of an API might want to disable warnings, disable logs, catch exceptions, redirect outputs, block network requests, or whatever, so each of these instances should be able to be referenced for better docs, better discoverability and better exploitation.

Metadata

Metadata

Assignees

Labels

featureNew feature or request

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions