2525
2626from __future__ import annotations
2727
28+ from abc import ABCMeta , abstractmethod
2829from io import BytesIO
2930from types import TracebackType
3031from typing import Iterator , Literal , Mapping , TypeVar
6263_T = TypeVar ('_T' )
6364
6465
65- class AbstractSlide :
66+ class AbstractSlide ( metaclass = ABCMeta ) :
6667 """The base class of a slide object."""
6768
6869 def __init__ (self ) -> None :
@@ -81,22 +82,26 @@ def __exit__(
8182 return False
8283
8384 @classmethod
85+ @abstractmethod
8486 def detect_format (cls , filename : lowlevel .Filename ) -> str | None :
8587 """Return a string describing the format of the specified file.
8688
8789 If the file format is not recognized, return None."""
8890 raise NotImplementedError
8991
92+ @abstractmethod
9093 def close (self ) -> None :
9194 """Close the slide."""
9295 raise NotImplementedError
9396
9497 @property
98+ @abstractmethod
9599 def level_count (self ) -> int :
96100 """The number of levels in the image."""
97101 raise NotImplementedError
98102
99103 @property
104+ @abstractmethod
100105 def level_dimensions (self ) -> tuple [tuple [int , int ], ...]:
101106 """A tuple of (width, height) tuples, one for each level of the image.
102107
@@ -109,20 +114,23 @@ def dimensions(self) -> tuple[int, int]:
109114 return self .level_dimensions [0 ]
110115
111116 @property
117+ @abstractmethod
112118 def level_downsamples (self ) -> tuple [float , ...]:
113119 """A tuple of downsampling factors for each level of the image.
114120
115121 level_downsample[n] contains the downsample factor of level n."""
116122 raise NotImplementedError
117123
118124 @property
125+ @abstractmethod
119126 def properties (self ) -> Mapping [str , str ]:
120127 """Metadata about the image.
121128
122129 This is a map: property name -> property value."""
123130 raise NotImplementedError
124131
125132 @property
133+ @abstractmethod
126134 def associated_images (self ) -> Mapping [str , Image .Image ]:
127135 """Images associated with this whole-slide image.
128136
@@ -136,10 +144,12 @@ def color_profile(self) -> ImageCms.ImageCmsProfile | None:
136144 return None
137145 return ImageCms .getOpenProfile (BytesIO (self ._profile ))
138146
147+ @abstractmethod
139148 def get_best_level_for_downsample (self , downsample : float ) -> int :
140149 """Return the best level for displaying the given downsample."""
141150 raise NotImplementedError
142151
152+ @abstractmethod
143153 def read_region (
144154 self , location : tuple [int , int ], level : int , size : tuple [int , int ]
145155 ) -> Image .Image :
@@ -151,6 +161,7 @@ def read_region(
151161 size: (width, height) tuple giving the region size."""
152162 raise NotImplementedError
153163
164+ @abstractmethod
154165 def set_cache (self , cache : OpenSlideCache ) -> None :
155166 """Use the specified cache to store recently decoded slide tiles.
156167
@@ -299,6 +310,7 @@ def __len__(self) -> int:
299310 def __iter__ (self ) -> Iterator [str ]:
300311 return iter (self ._keys ())
301312
313+ @abstractmethod
302314 def _keys (self ) -> list [str ]:
303315 # Private method; always returns list.
304316 raise NotImplementedError ()
0 commit comments