SLD9xx - Privacy¶
The checker enforces Python’s underscore-prefix convention across class
attributes, module attributes, and submodule imports. Dunder names
(__init__, __class__, __future__) are not flagged. Only the
current package exposes a private surface you may reach: from . import
_x binds an own private submodule, and from ._sub import public reads
its public surface. Reaching up into an ancestor (from .. import _x,
from .._sub import y) or sideways into a sibling’s private name
(from .sub import _x) is flagged just like an absolute private import.
SLD901: External read of a private attribute. obj._attr is only
permitted on the privileged first argument (self, cls, or whatever
the method’s first parameter is named) of an instance or class method.
# Bad
def render(thing):
return thing._cached_html
# Good
class Renderer:
def render(self):
return self._cached_html
SLD902: External write of a private attribute. Same predicate as SLD901
but for assignment, augmented assignment, and del. Tracked as a separate
code so codebases can adopt different policies for reads and writes.
# Bad
session._token = new_token
del session._cache
SLD903: A private name imported across a package boundary. The only
permitted way to import a private name is from . import _name, which
binds the current package’s own private submodule. Any module part
(from .sub import _x), any ancestor level (from .. import _x), and
every absolute import (from pkg import _x) is flagged. To consume a
private submodule’s contents, import its public names instead.
# Bad
from pkg import _internal_helper # absolute
from .sub import _internal_helper # sibling's private name
from .. import _internal_helper # ancestor's private name
# Good
from . import _internal_helper # own private submodule
from ._submodule import public # own submodule's public surface
SLD904: An import reaches into a private submodule across a package
boundary. A private segment (one starting with _, other than a dunder)
in the dotted path is permitted only for the current package’s own private
submodule — a single-dot relative import. Absolute paths and ancestor
(.. or deeper) paths are flagged.
# Bad
from numpy._core import multiarray # absolute
import numpy._core.umath # absolute
from .._engine import compile # ancestor's private submodule
# Good
from ._core import multiarray # own private submodule
SLD905: Private attribute access on an imported name. The post-import counterpart to SLD903 and SLD904.
import numpy as np
# Bad
np._core.something
# Good
np.array(...)