Skip to content

Newbie question about how to deal with builtins. #7931

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

Closed
YangTianz opened this issue Nov 12, 2019 · 6 comments
Closed

Newbie question about how to deal with builtins. #7931

YangTianz opened this issue Nov 12, 2019 · 6 comments

Comments

@YangTianz
Copy link

  • Are you reporting a bug, or opening a feature request?
    It's a newbie question.

  • Please insert below the code you are checking with mypy

foo.py

class Person(object):
    def __init__(self, name, age, is_male):
        # type: (str, int, bool) -> None
        self.name = name
        self.age = age
        self.is_male = is_male

    def greeting(self):
        # type: () -> None
        print "Hello, " + self.name

def init():
    __builtins__["Person"] = Person
bar.py

from foo import init

init()
alice = Person("Alice", 99, False)
alice.greeting()
  • What is the actual behavior/output?
$ mypy --py2 bar.py foo.py
bar.py:7: error: Name 'Person' is not defined
Found 1 error in 1 file (checked 2 source files)

I defined a class named Person and added it into __builtins__, but mypy could not recognize it. I wonder what I can do to make it work. Thank you.

@JelleZijlstra
Copy link
Member

Mypy doesn't support this sort of highly dynamic pattern. Ideally you should just import foo directly instead of injecting it into builtins. If you really want it to be a builtin and have mypy understand it, I suppose you could manually edit the typeshed stubs mypy is using to add the Person class to builtins.

@msullivan
Copy link
Collaborator

I'm curious what your use-case for this is, but in any case I don't think mypy would support it.

(Discouraging such things is essentially a feature of mypy ;) )

@nicoddemus
Copy link

Just came across this after googling it. 😁

While I agree Person is an odd choice to be installed in builtins, one use case that makes sense is to install a translation function, like gettext.install() does (this is also reported separately: #8727). I'm considering mypy for a large code base, and unfortunately we do install a tr function in the builtins module so it is easily accessible anywhere.

Of course it is rather easy to programatically add an import to the thousand of files of that code base, but this generates a bit attrition with people who are not so convinced of mypy's benefits.

@gvanrossum
Copy link
Member

So how do you imagine this could be supported? The simplest thing I can think of is to build your own copy of mypy with one line added to buildings.pyi.

@JelleZijlstra
Copy link
Member

Actually the easiest way is to fork typeshed to add your change, then use mypy's --custom-typeshed-dir to point mypy to your enhanced typeshed. Mypy doesn't special-case the builtins module too much, so that should be enough. Maybe a plugin could also do it by performing some manipulation of mypy's internal data structures.

@nicoddemus
Copy link

So how do you imagine this could be supported?

I see two possibilities:

  1. a new option that allows to suppress name-defined errors for certain names, possibly as a list of regex patterns where names that match against one of the patterns don't trigger the error. This just serves to suppress the errors of course, with mypy not being able to point out usage errors (passing wrong number of arguments for example), it would be equivalent to add # type: ignore[name-defined] to every line that has that name.

The simplest thing I can think of is to build your own copy of mypy with one line added to buildings.pyi.
Actually the easiest way is to fork typeshed to add your change, then use mypy's --custom-typeshed-dir to point mypy to your enhanced typeshed.

Indeed that's what I did and it works great, with the benefit that now mypy can help catching errors with that name now. Unfortunately that is not as convenient, but doable and worth the effort for large code bases.

Maybe a plugin could also do it by performing some manipulation of mypy's internal data structures.

A plugin to explicitly add new typesheds to existing modules and/or builtins would work even better, if that's possible.

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

5 participants