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

is_member_of_type #2

Closed
lucaswiman opened this issue Jun 25, 2017 · 6 comments
Closed

is_member_of_type #2

lucaswiman opened this issue Jun 25, 2017 · 6 comments

Comments

@lucaswiman
Copy link

The most useful introspection methods I'd like to use from the typing module are basically the functions that were removed in python/typing#283: checking whether a concrete object is compatible with a given type. This would be useful for simple runtime type assertions, for exploring the implications of PEP484 in the REPL, and annotations-based dispatch.

Please let me know what you think; I'd be very interested in helping to implement this. I can also submit a PR if that makes discussion easier.

Objections

Should this be in external tools?

@1st1 objected to this on the grounds that it should be left to external tools, but it seems like implementing a reference for cases which are unambiguous according to PEP484 would be quite useful, and even helpful to building external tools of that kind.

For cases where something other than recursive isinstance calls are required (e.g. type variables), a helpful error can be raised at runtime.

Mutable values

There was an objection to __instancecheck__ and __subclasscheck__ by BDFL-delegate @markshannon here:

For example,
List[int] and List[str] and mutually incompatible types, yet
isinstance([], List[int]) and isinstance([], List[str))
both return true.

This is a bit tricky for mutable types, since [] is a member of List[X] for all X, but the same list object might cease to be in List[X] when elements are added to it. For immutable types, the answer is unambiguous, so Tuple[*] could always deliver an unambiguous answer.

For List[], Dict[] and other mutable types, my preference would be to check the types of the elements right now, when the method is called, and not at some future time when it may have been mutated. This would be a distinction between mypy and the runtime type checking, but this behavior seems more in keeping with the principle of least surprise, and would accord with the main intended use cases (REPL-based exploration of the type system, and simple runtime type assertions).

Implementation

I think the implementation would be roughly like the following:

def is_member_of_type(obj, tp):
    if has_type_variables(tp):
        raise ValueError('Type variables cannot be determined at runtime')
    if is_union(tp):
        return any(is_member_of_type(obj, s) for s in tp.__args__)
    elif is_tuple(tp):
        ...
    elif ...:
        ...
    else:
        return isinstance(obj, tp)

Include issubtype to match issubclass?

issubtype could make sense as an addition, but it would involve introducing much more of the sorts of logic a typechecker should implement, e.g. the following:

>>> from typing import *
>>> class MyTuple(NamedTuple):
...     foo: int
...     bar: str
... 
>>> issubtype(MyTuple, Tuple[int, str])
True

For this reason, I think it would make more sense to leave issubtype out of typing_inspect.

@Stewori
Copy link

Stewori commented Jun 25, 2017

@lucaswiman Before you start with this approach, please note that I already did exactly this work. Including support for type variables. Including issubtype. Already supporting older versions of typing module, at least from 3.5.2.2 onwards. Tested with Python 2.7, 3.5, 3.6, 3.6.1 and even Jython.

Implementing this was much more involved than one might expect (e.g. getting things like issubtype(Tuple[int, int, int], Iterable[int]) right.) Honestly NamedTuple is not yet supported, but it is on the agenda. Maybe you could at first try, if the existing approach might be already sufficient (see https://github.com/Stewori/pytypes#is_of_typeobj-cls). If it's not, maybe we can combine our efforts and improve it...?

@lucaswiman
Copy link
Author

No, that looks fantastic! I searched for something which implements that collection of functionality, and could only find runtime typecheckers.

In the abstract, I think much of your pytypes library would be better in the standard library (or at least linked from the typing documentation), but for my particular interests, your library looks great!

@lucaswiman
Copy link
Author

In the abstract, I think much of your pytypes library would be better in the standard library

Having read through the documentation in more detail, I guess only a small subset of it makes sense for the standard library, though several of the "Utilities" functions would be good candidates.

@ilevkivskyi
Copy link
Owner

After some thinking, it seems to me this should not be in typing_inspect, mainly because it is hard to draw a line between "simple" and "non-simple" runtime checks. Plus there are excellent existing tools mentioned above.

Anyway, thanks for a nice write-up!

@lucaswiman
Copy link
Author

That's disappointing; I do hope you'll reconsider after the typing library matures. Obviously missing functionality in the standard library leads to a proliferation of incompatible third party libraries of varying quality (c.f. the history of urllib2, requests, etc. where "simple" functionality has a complicated answer as to what you should use.) Python has always advertised itself as "batteries included", and this seems like a glaringly missing battery.

From the perspective of an end user of typing it feels like isinstance is broken, and there's no functionality to replace it. Once pytypes is released on pypi, linking to it in the typing docs would help fill this gap.

Plus there are excellent existing tools mentioned above.

pytypes hasn't been released on pypi and the other tools I could find did not implement this functionality in a simple form, so I disagree with you there. It may be the case in the future, but I don't think it is the case now.

@ilevkivskyi
Copy link
Owner

pytypes hasn't been released on pypi and the other tools I could find did not implement this functionality in a simple form, so I disagree with you there. It may be the case in the future, but I don't think it is the case now.

I would say that this is a perfect reason for you to contribute to and improve these projects, so that they will suit your needs. The goal they declare seems to be what you need, while the main goal of typing_inspect is mostly runtime introspection of types themselves.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants