• 
      

    Add a common mixin class for handling invalidation.

    Review Request #15170 — Created July 15, 2026 and submitted

    Information

    cryptozoology
    master

    Reviewers

    Sensitive data (keys, secrets) are intended to be invalidated early,
    keeping the data safe and out of memory as best as possible.

    This class implements this as a mixin class. It handles invalidation
    when the instance falls out of scope, and allows the object to be used
    as a context manager, invalidating on exit.

    Unit tests pass.

    Summary ID
    Add a common mixin class for handling invalidation.
    Sensitive data (keys, secrets) are intended to be invalidated early, keeping the data safe and out of memory as best as possible. This class implements this as a mixin class. It handles invalidation when the instance falls out of scope, and allows the object to be used as a context manager, invalidating on exit.
    e8a39a80860703921eb6272749efef0bdf94ff88
    Description From Last Updated

    Instead of methods that raise NotImplementedError, how about subclassing abc.ABC and marking those with @abstractmethod?

    david david

    Should probably change this to say self?

    david david

    __exit__ never gets called with kwargs. Can we use the standard signature? def __exit( self, exc_type: type[BaseException] | None, exc_value: …

    david david

    If a subclass raises an exception from __init__, __del__ could get called on a partially-constructed instance. If the implementation of …

    david david

    It's harmless here, but just to model goot behavior, can we call super().__init__()?

    david david

    Since this is greenfield, can we use pytest test cases and real docstrings instead of a UnitTest subclass?

    david david

    typo: exceptio -> exception

    david david

    This was copy/pasted without updating to match the test.

    david david
    chipx86
    david
    1. 
        
    2. cryptozoology/utils/invalidation.py (Diff revision 2)
       
       
      Show all issues

      Instead of methods that raise NotImplementedError, how about subclassing abc.ABC and marking those with @abstractmethod?

      1. abc.ABC provides a hard-interface that makes it difficult to maintain forward-compatibility. If you use it in 1.0 and you add a new method using it in 1.1, you break interface compatibility because any subclass not implementing that method will break. It's great within an isolated codebase but bad for an extensible library.

    3. cryptozoology/utils/invalidation.py (Diff revision 2)
       
       
      Show all issues

      Should probably change this to say self?

      1. We don't do that anywhere else in our Python code.

    4. cryptozoology/utils/invalidation.py (Diff revision 2)
       
       
      Show all issues

      __exit__ never gets called with kwargs. Can we use the standard signature?

      def __exit(
          self,
          exc_type: type[BaseException] | None,
          exc_value: BaseException | None,
          traceback: TracebackType | None,
      ) -> None:
      
    5. cryptozoology/utils/invalidation.py (Diff revision 2)
       
       
       
       
       
       
       
      Show all issues

      If a subclass raises an exception from __init__, __del__ could get called on a partially-constructed instance. If the implementation of invalidate() then assumes an attribute it set, it will AttributeError, and python will silently swallow it (I think it prints to stderr, but that's not the best for a library). This could leave the object not fully invalidated.

      Can we document in here that the implementation must be able to handle partially-constructed instances, and cannot assume that all attributes have been set?

      We also should document that this method needs to be idempotent, since it can get called first from __exit__ and then again from __del__

    6. cryptozoology/utils/tests/test_invalidatable_mixin.py (Diff revision 2)
       
       
       
       
       
       
      Show all issues

      It's harmless here, but just to model goot behavior, can we call super().__init__()?

      1. Sure. The mixin doesn't define __init__ and likely won't.

    7. Show all issues

      Since this is greenfield, can we use pytest test cases and real docstrings instead of a UnitTest subclass?

      1. I don't want to use pytest alone for this package. I have a reply in another review somewhere, but there's benefits to unittest.TestCase that I'm employing, and I want consistency across test. I'd really like consistency across packages so we're not using different approaches everywhere. TestCase offers far better test organization and a lot of benefits around state management.

    8. Show all issues

      typo: exceptio -> exception

    9. Show all issues

      This was copy/pasted without updating to match the test.

    10. 
        
    chipx86
    david
    1. Ship It!
    2. 
        
    chipx86
    Review request changed
    Status:
    Completed
    Change Summary:
    Pushed to master (282d3e7)