Skip to content

Quickstart

A five-minute tour of every feature.

Decorate the class

from strictaccess import strict_access_control, private, protected, public

@strict_access_control()
class Counter:
    def __init__(self) -> None:
        self._value = 0          # protected by convention

    @public
    def increment(self) -> None:
        self._step()             # internal call to protected: OK

    @protected
    def _step(self) -> None:
        self._value += 1

    @private
    def _reset(self) -> None:
        self._value = 0

Use it

c = Counter()
c.increment()        # OK
c._value             # raises ProtectedAccessError
c._step()            # raises ProtectedAccessError
c._reset()           # raises PrivateAccessError

Catch the violations

from strictaccess import PrivateAccessError, ProtectedAccessError

try:
    c._reset()
except PrivateAccessError as e:
    print(e)
    # Access to private member '_reset' of class 'Counter'
    # from 'caller_qualname' is forbidden.

Subclass it

class FastCounter(Counter):
    def jump(self) -> None:
        self._step()             # OK: protected reachable from subclass
        # self._reset()          # would still raise PrivateAccessError

Run in debug mode

import logging
logging.basicConfig(level=logging.WARNING)

@strict_access_control(debug=True)
class Soft(Counter):
    pass

s = Soft()
s._reset()      # logs a WARNING via the 'strictaccess' logger
                # returns the result; does NOT raise

See Debug mode for how to use this during refactors.

Next

  • @private — strict same-class restriction.
  • @protected — class + subclasses.
  • @public — explicit opt-out of the underscore convention.
  • Limitations — what strictaccess cannot do.