Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow bare typing.ClassVar qualifiers #1931

Open
wants to merge 3 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion docs/spec/annotations.rst
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@ The following grammar describes the allowed elements of type and annotation expr
annotation_expression: <Required> '[' `annotation_expression` ']'
: | <NotRequired> '[' `annotation_expression` ']'
: | <ReadOnly> '[' `annotation_expression`']'
: | <ClassVar> '[' `annotation_expression`']'
: | <ClassVar> ('[' `annotation_expression`']')?
: | <Final> ('[' `annotation_expression`']')?
: | <InitVar> '[' `annotation_expression` ']'
: | <Annotated> '[' `annotation_expression` ','
Expand Down
34 changes: 29 additions & 5 deletions docs/spec/class-compat.rst
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,35 @@ Class type assignability

(Originally specified in :pep:`526`.)

A :term:`type qualifier` ``ClassVar[T]`` exists in the :py:mod:`typing`
module. It accepts only a single argument that should be a valid type,
and is used to annotate class variables that should not be set on class
instances. This restriction is enforced by static checkers,
but not at runtime.
The :py:data:`typing.ClassVar` :term:`type qualifier` is used to annotate
class variables that should not be set on class instances. This restriction
is enforced by static checkers, but not at runtime.

Syntax
^^^^^^

:py:data:`~typing.ClassVar` may be used in one of several forms:

* With an explicit type, using the syntax ``ClassVar[<type>]``. Example::

class C:
x: ClassVar[float] = 1

* With no type annotation. Example::

class C:
y: ClassVar = 2
z: ClassVar

If an assigned value is available (e.g. with ``y``), the type should be
inferred as some type to which this value is :term:`assignable` (in this
case, either ``int``, ``Literal[2]``, or ``Any``).
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The listed options are not the only choices here, I'd prefer not to imply that they are. (I think a strong case can be made that inferring Any | Literal[2] is the most correct option, from a gradual-typing perspective.) I'm fine with just listing the simpler options that you have here, but we shouldn't imply that it's an exhaustive list.

Suggested change
inferred as some type to which this value is :term:`assignable` (in this
case, either ``int``, ``Literal[2]``, or ``Any``).
inferred as some type to which this value is :term:`assignable` (for example,
``int``, ``Literal[2]``, or ``Any``).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is what I wanted to write out to begin with, but I realize my wording is wrong indeed :)


If the ``ClassVar`` qualifier is used without any assigned value, the type
should be inferred to an unknown static type (such as :ref:`Any`).
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The only dynamic type discussed in the typing spec is Any, so it's a bit odd to imply here that there would be others. Most type checkers do distinguish between different "origins" of Any, and some do so with a variant of Any named Unknown, but as far as the spec is concerned these are all just Any.

Suggested change
should be inferred to an unknown static type (such as :ref:`Any`).
should be inferred as :ref:`Any`.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was wondering if such a concept of an unknown static type, as written in the referenced any section:

.. _`any`:
``Any``
-------
``Any`` represents an unknown static type.
Every type is :term:`assignable` to ``Any``, and ``Any`` is assignable to every
type.

would be worth specifying, and that's why I chose the same phrasing. But let's not complicate things, I'll go with Any.


Semantics and examples
^^^^^^^^^^^^^^^^^^^^^^

Type annotations can be used to annotate class and instance variables
in class bodies and methods. In particular, the value-less notation ``a: int``
Expand Down