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

A problem with bool subclassing int and JSON; excluding subclasses using "exactly()" notation? #52

Closed
gvanrossum opened this issue Jan 21, 2015 · 8 comments
Labels
resolution: out of scope The idea or discussion was out of scope for this repository topic: feature Discussions about new features for Python's type annotations

Comments

@gvanrossum
Copy link
Member

This came up in python-idea under the subject "Should bool continue to inherit from int?" by Michael Mitchell.

Suppose I have a function that takes an integer argument and then JSON-encodes it and sends it to some server that requires a JSON int. Now suppose you are adding type hints to your code, and you add ": int" to the parameter under discussion. And now suppose you have a faulty caller which calls this function with the argument set to True. This program will type-check correctly, because True is a bool which is a subclass of int, but it will run incorrectly, because (under this assumption) True will be converted to a JSON true value, which the server rejects.

My hunch is that we shouldn't try to address this but instead recommend using a schema-based way of generating JSON. But it's an interesting concern nevertheless. Maybe it should be possible to tell the typechecker that exactly an int is required, and a subclass won't do? I think this came up in some other contexts too.

[TBD: cross-links]

@gvanrossum gvanrossum changed the title A problem with bool subclassing int and JSON; subclasses in general A problem with bool subclassing int and JSON; excluding subclasses using "exactly()" notation? Jan 21, 2015
@gvanrossum
Copy link
Member Author

This also came up in the context of Cython. Stefan Behnel's proposal is a function typing.exactly(), which can be used as for example

from typing import List, exactly
def foo(a: exactly(List[int])): ...
def bar(b: List[exactly(int)]): ...

@Rosuav
Copy link

Rosuav commented Jan 21, 2015

If there is such a facility, it should be used VERY sparingly. It's normally safe to subclass something to add functionality and have your class still work like the parent (imagine a self-sorting subclass of list - it should JSON-encode like any other list). Too much use of exactly() would disrupt that - and often in cases where it wouldn't even matter, which would just give type hinting a bad name.

+1 on the concept, but with very clear documentation that this is for the unusual cases. +1 on the name, too - it parallels PyLong_Check vs PyLong_CheckExact.

@gvanrossum
Copy link
Member Author

I'm wondering if the spelling should be Exactly[t] rather than exactly(t). We don't seem to have a great rule for deciding when to use [] vs. (), but in general when something is composable as part of the type system, takes a type (or more) as arguments, and could support issubclass() or isinstance() checks, I have proposed []. Thus Callable[...], Tuple[...], Union[...], and even Optional[...], but TypeVar('T') (the upper case because it's a class instantiation). I think Exactly[...] fits in this pattern, since the run time representation must retain the information that [Ee]xactly was used, and it would make sense at run time to use e.g. isinstance(x, Exactly[int]).

@gcewing
Copy link

gcewing commented Jan 21, 2015

Exactly[T] looks good to me.

I think the fact that it's rather verbose is probably enough to discourage unnecesary use.

@vlasovskikh
Copy link
Member

It's a rare case, it might be better not to address it.

@gvanrossum
Copy link
Member Author

Another use case (if we decide it's worth it) might be for @overload. Pickling is (conceptually) defined by a function that is overloaded for many types. Several such overloads are for exactly the builtin types (e.g. int, str) and their pickled representation is different from that of subclasses. Still, there are other ways to do this, so if we decide not to include it I won't be upset.

@gvanrossum gvanrossum added the resolution: out of scope The idea or discussion was out of scope for this repository label Jan 29, 2015
@srittau
Copy link
Collaborator

srittau commented Nov 4, 2021

@gvanrossum You tagged this "out of scope" an eternity ago. Do you think this is a feasible idea (in which case I would remove the "out of scope" label) or should we close this issue?

@srittau srittau added the topic: feature Discussions about new features for Python's type annotations label Nov 4, 2021
@gvanrossum
Copy link
Member Author

Just close it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
resolution: out of scope The idea or discussion was out of scope for this repository topic: feature Discussions about new features for Python's type annotations
Projects
None yet
Development

No branches or pull requests

5 participants