mirror of
https://github.com/jbranchaud/til
synced 2026-07-02 23:58:25 +00:00
Add Define Typed Class Interface With Protocol as a Python TIL
This commit is contained in:
@@ -10,7 +10,7 @@ working across different projects via [VisualMode](https://www.visualmode.dev/).
|
|||||||
|
|
||||||
For a steady stream of TILs, [sign up for my newsletter](https://visualmode.kit.com/newsletter).
|
For a steady stream of TILs, [sign up for my newsletter](https://visualmode.kit.com/newsletter).
|
||||||
|
|
||||||
_1804 TILs and counting..._
|
_1805 TILs and counting..._
|
||||||
|
|
||||||
See some of the other learning resources I work on:
|
See some of the other learning resources I work on:
|
||||||
|
|
||||||
@@ -1069,6 +1069,7 @@ If you've learned something here, support my efforts writing daily TILs by
|
|||||||
- [Create A Range Of Descending Values](python/create-a-range-of-descending-values.md)
|
- [Create A Range Of Descending Values](python/create-a-range-of-descending-values.md)
|
||||||
- [Deduplicate A List Into A Tuple](python/deduplicate-a-list-into-a-tuple.md)
|
- [Deduplicate A List Into A Tuple](python/deduplicate-a-list-into-a-tuple.md)
|
||||||
- [Define Sequence Of Tests With Parametrize Decorator](python/define-sequence-of-tests-with-parametrize-decorator.md)
|
- [Define Sequence Of Tests With Parametrize Decorator](python/define-sequence-of-tests-with-parametrize-decorator.md)
|
||||||
|
- [Define Typed Class Interface With Protocol](python/define-typed-class-interface-with-protocol.md)
|
||||||
- [Dunder Methods](python/dunder-methods.md)
|
- [Dunder Methods](python/dunder-methods.md)
|
||||||
- [Easy Key-Value Aggregates With defaultdict](python/easy-key-value-aggregates-with-defaultdict.md)
|
- [Easy Key-Value Aggregates With defaultdict](python/easy-key-value-aggregates-with-defaultdict.md)
|
||||||
- [Get Absolute Seconds From `timedelta` Object](python/get-absolute-seconds-from-timedelta-object.md)
|
- [Get Absolute Seconds From `timedelta` Object](python/get-absolute-seconds-from-timedelta-object.md)
|
||||||
|
|||||||
@@ -0,0 +1,42 @@
|
|||||||
|
# Define Typed Class Interface With Protocol
|
||||||
|
|
||||||
|
In [`py-vmt`](https://github.com/jbranchaud/py-vmt) I am defining different
|
||||||
|
storage access layers for the CLI to use. I want a consistent interface that the
|
||||||
|
core CLI logic can depend on regardless of whether it is a JSON file or a SQLite
|
||||||
|
database. To achieve that I can define a class of unimplemented functions that
|
||||||
|
inherits from
|
||||||
|
[`typing.Protocol`](https://typing.python.org/en/latest/spec/protocol.html).
|
||||||
|
|
||||||
|
```python
|
||||||
|
from typing import Protocol
|
||||||
|
|
||||||
|
class SessionRepository(Protocol):
|
||||||
|
def active_session(self) -> Session | None: ...
|
||||||
|
def write_active_session(self, session) -> None: ...
|
||||||
|
def append_session(self, session) -> None: ...
|
||||||
|
def all_sessions(self) -> list[Session]: ...
|
||||||
|
def clear_active_session(self) -> None: ...
|
||||||
|
```
|
||||||
|
|
||||||
|
Notice that none of these have default implementations. The `...` indicates that
|
||||||
|
class implementing this protocol will define the implementation of those
|
||||||
|
functions.
|
||||||
|
|
||||||
|
Now, my `CliContext` class, which needs some kind of `SessionRepository` to
|
||||||
|
function can indicate as much in `__init__`.
|
||||||
|
|
||||||
|
```python
|
||||||
|
class CliContext:
|
||||||
|
def __init__(self, verbose: bool, repo: SessionRepository | None = None) -> None:
|
||||||
|
self.verbose: bool = verbose
|
||||||
|
self.active_session: Session | None = None
|
||||||
|
self.repo: SessionRepository = repo or JsonRepository()
|
||||||
|
self.active_session = self.repo.active_session()
|
||||||
|
```
|
||||||
|
|
||||||
|
If `JsonRepository` doesn't define all of the methods specified in the protocol,
|
||||||
|
then a type error will occur wherever it clashes with `SessionRepository`. Now
|
||||||
|
as I implement `SqliteRepository` I have a standard interface to build against
|
||||||
|
that I know I can seamlessly swap in.
|
||||||
|
|
||||||
|
[source](https://typing.python.org/en/latest/reference/protocols.html#simple-user-defined-protocols)
|
||||||
Reference in New Issue
Block a user