Skip to main content

Automatically update `__all__` statements.

Project description

allways

Automatically update __all__ statements.

Installation

pip install allways

Command line interface

allways <file1.py> <file2.py> ...

As a pre-commit hook

See pre-commit for instructions.

Sample .pre-commit-config.yaml

-   repo: https://github.com/tjsmart/allways
    rev: v0.0.2
    hooks:
    -   id: allways

Note: by default the pre-commit hook will run only against __init__.py files.

What does it do?

Add __all__ statements to your python files

from ._foo import bar
from ._x import y as z

def foo():
    ...

becomes

from ._foo import bar
from ._x import y as z

def foo():
    ...


# allways: start
__all__ = [
    "bar",
    "foo",
    "z",
]
# allways: end

Ignore private variables

from . import _foo
from . import bar

becomes

from . import _foo
from . import bar


# allways: start
__all__ = [
    "bar",
]
# allways: end

Update pre-existing __all__ statements

from . import bar
from . import baz


# allways: start
__all__ = [
    "bar",
    "foo",
]
# allways: end

becomes

from . import bar
from . import baz


# allways: start
__all__ = [
    "bar",
    "baz",
]
# allways: end

Why?

the problem

I choose to organize python libraries with:

  • PEP 561 compliance
  • private module files, public (sub-)package folders
  • using __init__.py to define the public interface of a (sub-)package

For example, I might layout my project as such:

pkg/
├── bar/
│   ├── _bar.py
│   └── __init__.py
├── _foo.py
├── __init__.py
└── py.typed

Contained in the files pkg/_foo.py and pkg/bar/_bar.py there will be some portion that I would like to expose publicly via pkg/__init__.py and pkg/bar/__init__.py, respectively.

For example, perhaps I would like to expose a function do_something from the module file pkg/_foo.py by adding the following line to pkg/__init__.py:

from ._foo import do_something

And here is where the problem arises! (I know... a lot of setup...)

When a user of our package turns to use do_something they will be slapped on the wrist by the type-checker.

  • pyright output:
t.py:1:18 - error: "do_something" is not exported from module "pkg"
Import from "pkg._foo" instead (reportPrivateImportUsage)
  • mypy --strict output:
t.py:1: error: Module "pkg" does not explicitly export attribute "do_something"  [attr-defined] 

And if you aren't concerned that users will have to ignore this type error, know that it get's worse! Language servers will not display any hint that the object pkg.do_something exists. 😱

For small projects maintaining this by hand is no big deal. But for large projects with several contributors this becomes a complete wast of time! 😠

the solution

According to pyright documentation, a typed library can choose to explicitly re-export symbols by adding it to the __all__ of the corresponding module.

allways mission is to automate the process of updating __all__ statements in __init__.py files. 🤗

but also

My personal goal here is to contribute something to open source and write some more rust! 🦀

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distributions

No source distribution files available for this release.See tutorial on generating distribution archives.

Built Distributions

allways-0.0.2-py3-none-win_amd64.whl (1.2 MB view hashes)

Uploaded Python 3 Windows x86-64

allways-0.0.2-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (2.2 MB view hashes)

Uploaded Python 3 manylinux: glibc 2.17+ x86-64

allways-0.0.2-py3-none-macosx_10_7_x86_64.whl (1.3 MB view hashes)

Uploaded Python 3 macOS 10.7+ x86-64

Supported by

AWS AWS Cloud computing and Security Sponsor Datadog Datadog Monitoring Fastly Fastly CDN Google Google Download Analytics Microsoft Microsoft PSF Sponsor Pingdom Pingdom Monitoring Sentry Sentry Error logging StatusPage StatusPage Status page