66
77from __future__ import annotations
88
9- import abc
10- from typing import Any , ClassVar , MutableMapping
9+ from typing import Any , MutableMapping , runtime_checkable
1110
12- from typing_extensions import LiteralString , Self
11+ from typing_extensions import Protocol , Self
1312
1413from . import options
1514from . import types
1615
1716
18- class SOMAObject (metaclass = abc .ABCMeta ):
17+ @runtime_checkable
18+ class SOMAObject (Protocol ):
1919 """The base type for all SOMA objects, containing common behaviors."""
2020
21- __slots__ = ("__weakref__" ,)
22-
2321 @classmethod
24- @abc .abstractmethod
2522 def open (
2623 cls ,
2724 uri : str ,
@@ -41,10 +38,9 @@ def open(
4138 Returns: The SOMA object, opened for reading.
4239 Lifecycle: maturing
4340 """
44- raise NotImplementedError ()
41+ ...
4542
4643 @classmethod
47- @abc .abstractmethod
4844 def exists (cls , uri : str , * , context : Any | None = None ) -> bool :
4945 """Checks whether a SOMA object of this type is stored at the URI.
5046
@@ -56,16 +52,15 @@ def exists(cls, uri: str, *, context: Any | None = None) -> bool:
5652 False if the object does not exist, or is of a different type.
5753 Lifecycle: maturing
5854 """
59- raise NotImplementedError ()
55+ ...
6056
6157 @property
62- @abc .abstractmethod
6358 def uri (self ) -> str :
6459 """The URI of this SOMA object.
6560
6661 Lifecycle: maturing
6762 """
68- raise NotImplementedError ()
63+ ...
6964
7065 @property
7166 def context (self ) -> types .ContextBase | None :
@@ -81,10 +76,9 @@ def context(self) -> types.ContextBase | None:
8176
8277 Lifecycle: maturing
8378 """
84- return None
79+ ...
8580
8681 @property
87- @abc .abstractmethod
8882 def metadata (self ) -> MutableMapping [str , Any ]:
8983 """The metadata of this SOMA object.
9084
@@ -94,35 +88,23 @@ def metadata(self) -> MutableMapping[str, Any]:
9488
9589 Lifecycle: maturing
9690 """
97- raise NotImplementedError ()
91+ ...
9892
9993 @property
100- @abc .abstractmethod
10194 def mode (self ) -> options .OpenMode :
10295 """Returns the mode this object was opened in, either ``r`` or ``w``.
10396
10497 Lifecycle: maturing
10598 """
106- raise NotImplementedError ()
99+ ...
107100
108101 @property
109- @abc .abstractmethod
110102 def closed (self ) -> bool :
111103 """True if this object has been closed; False if still open.
112104
113105 Lifecycle: maturing
114106 """
115- raise NotImplementedError ()
116-
117- soma_type : ClassVar [LiteralString ]
118- """A string describing the SOMA type of this object. This is constant.
119-
120- This uses ClassVar since you can't do abstract class properties.
121- This is the equivalent, just without abc-based automatic verification.
122- Overrides are marked Final with an ignore[misc] because mypy by default
123- wants this to be mutable, and doesn't like overriding the mutable member
124- with a Final member.
125- """
107+ ...
126108
127109 # Context management
128110
@@ -138,28 +120,8 @@ def close(self) -> None:
138120
139121 Lifecycle: maturing
140122 """
141- # Default implementation does nothing.
142-
143- def __enter__ (self ) -> Self :
144- return self
145-
146- def __exit__ (self , * _ : Any ) -> None :
147- self .close ()
148-
149- def __del__ (self ) -> None :
150- self .close ()
151- super_del = getattr (super (), "__del__" , lambda : None )
152- super_del ()
153-
154- # Explicitly use Python's identity-based equality/hash checks.
155- # These will show up in the `__mro__` before any other classes
156- # provided a SOMAObject base is put first:
157- #
158- # class SubType(SomeSOMAObject, MutableMapping):
159- # ...
160- #
161- # # sub_type_inst.__eq__ uses object.__eq__ rather than
162- # # MutableMapping.__eq__.
163-
164- __eq__ = object .__eq__
165- __hash__ = object .__hash__
123+ ...
124+
125+ def __enter__ (self ) -> Self : ...
126+
127+ def __exit__ (self , * _ : Any ) -> None : ...
0 commit comments