Let’s say I have the following structure:

my_module/
  __init__.py
  utilities.py

and __init__.py contains

from .utilities import SomeUtilityFunction

Is there a way to prevent or alert developers when they do

from my_module.utilities import SomeUtilityFunction

instead of

from my_module import SomeUtilityFunction

The problem arose when a few modules started using a function that was imported inside a module in which it wasn’t used, while also being available on the module’s __init__.py, so after linting the file and removing the unused import my tests started failing.

any other advice for situations like this?

  • Chais@sh.itjust.works
    link
    fedilink
    arrow-up
    2
    arrow-down
    1
    ·
    7 months ago

    That’s not correct. __all__ is not a whitelist. It is only the list used for

    from module import *
    

    If you have a module with submodules foo, bar and baz and __all__ = ["foo", "bar"] it will not prevent you from importing baz manually. It just won’t do it automatically.

    • sebsch@discuss.tchncs.de
      link
      fedilink
      arrow-up
      1
      arrow-down
      1
      ·
      edit-2
      7 months ago

      It works exactly like one. You get a warning if you try to import something not defined in it. The docs are just very confusing here ;)

      • Chais@sh.itjust.works
        link
        fedilink
        English
        arrow-up
        1
        arrow-down
        1
        ·
        edit-2
        7 months ago

        Bullshit!

        module/__init__.py:

        __all__ = ["foo", "bar"]
        

        module/foo.py:

        def foo():
            print("foo")
        

        module/bar.py:

        def bar():
            print("bar")
        

        module/baz.py:

        def baz():
            print("baz")
        

        main.py:

        from module import *
        from module import baz
        
        if __name__ == "__main__":
            print("main")
            foo.foo()
            bar.bar()
            baz.baz()
        

        Output:

        $ python main.py 
        main
        foo
        bar
        baz
        

        No errors, warnings or anything.