Observed since 20 Oct, 17:57 UTC
No superseded metadata states collected. Unchanged observations do not create new revisions.
Runtime final guard for methods/properties across projects
A super lightweight runtime guard that provides a @final decorator, final_class, and an Access metaclass. It prevents methods/properties (optionally magic methods) marked as final from being overridden in subclasses, and blocks dynamic overriding after a class is created.
@staticmethod, @classmethod, and @property (including getter / setter / deleter).@final_class(include_magic=True).RuntimeError (fail fast).py.typed, friendly to type checkers.Supports Python 3.10+.
Using uv:
uv add access-guard
Or using pip:
pip install access-guard
final
from access_guard import Access, final
class Base(metaclass=Access):
@final
def stable(self):
return "v1"
@property
@final
def value(self):
return 42
class Child(Base):
pass
Child().stable() # OK
# Any of the following will raise RuntimeError:
# class Bad(Base):
# def stable(self): # overriding a final method
# return "v2"
# Bad.stable = lambda self: "hack" # dynamic override after class creation
final_class
Mark all currently defined non-magic members in the class as final in one go:
from access_guard import Access, final_class
@final_class
class Service(metaclass=Access):
def create(self):
return "created"
def delete(self):
return "deleted"
class Child(Service):
pass # OK
# The following will fail:
# class Bad(Service):
# def create(self): # RuntimeError
# return "x"
Note: Members added dynamically after the class is created will not be final automatically; it’s recommended to use @final on those members individually when you define them.
from access_guard import Access, final_class
# Exclude some methods from being locked
@final_class(exclude={"debug", "open"})
class Service(metaclass=Access):
def create(self): ... # final
def debug(self): ... # not final
def open(self): ... # not final
# Lock including magic methods
@final_class(include_magic=True)
class Model(metaclass=Access):
def __repr__(self):
return "Model()" # final
def run(self):
return 1 # final
# Use both together
@final_class(exclude=["__repr__"], include_magic=True)
class Partial(metaclass=Access):
def __repr__(self): # not final
return "P()"
def calc(self): # final
return 42
Parameter details:
exclude: iterable[str]. Names that should NOT be marked final; can be list / set / tuple.include_magic: when True, magic methods like __repr__ are also marked (builtin low-level __dict__ and __weakref__ are always ignored).@final marks a special attribute on the actual function/property/descriptor object; for properties it also marks their accessors.final_class collects all members in the class at decoration time and marks them; exclude and include_magic control the scope.Access metaclass in __new__:
__setattr__.final_class(include_magic=True), its magic methods are locked and propagated to all subclasses.types.FunctionType (e.g., some dynamic __getattr__ patterns).__dict__ manipulation (deliberate attack scenarios).After installing dev dependencies:
uv sync --extra dev
uv run pytest -q
Or using pip:
pip install -e .[dev]
pytest -q
Semantic Versioning. In the early phase (<1.0.0), breaking changes may occur.
Current version: 0.1.3.
@allow_override (in design).MIT License. See LICENSE.
Issues and PRs are welcome:
For performance topics, please include a simple benchmark (timeit or pyperf).
Download counts and popularity will appear here as the collector receives them.
| Version | Published | Direct dependencies | Open version |
|---|---|---|---|
| 0.1.6 | 17 Sept 2025 | 3 |
This describes our collected data; it is not a security assessment.
Observed since 20 Oct, 17:57 UTC
No superseded metadata states collected. Unchanged observations do not create new revisions.
package:bf8dd526b5f1be03272a7705982d23031f6688dcfb675d22f2d971a82d6ad514