Coretex
sample.py
1 # Copyright (C) 2023 Coretex LLC
2 
3 # This file is part of Coretex.ai
4 
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License as
7 # published by the Free Software Foundation, either version 3 of the
8 # License, or (at your option) any later version.
9 
10 # This program is distributed in the hope that it will be useful,
11 # but WITHOUT ANY WARRANTY; without even the implied warranty of
12 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 # GNU Affero General Public License for more details.
14 
15 # You should have received a copy of the GNU Affero General Public License
16 # along with this program. If not, see <https://www.gnu.org/licenses/>.
17 
18 from typing import TypeVar, Generic, Union
19 from abc import ABC, abstractmethod
20 from zipfile import BadZipFile, ZipFile
21 from pathlib import Path
22 
23 import shutil
24 
25 
26 SampleDataType = TypeVar("SampleDataType")
27 
28 
29 class Sample(ABC, Generic[SampleDataType]):
30 
31  """
32  Represents the generic class Sample
33  Includes methods that can be used by any instance of Sample
34  and abstract methods that must be implemented by any subclass
35  """
36 
37  name: str
38 
39  @property
40  @abstractmethod
41  def path(self) -> Path:
42  pass
43 
44  @property
45  @abstractmethod
46  def zipPath(self) -> Path:
47  pass
48 
49  @abstractmethod
50  def download(self, decrypt: bool = True, ignoreCache: bool = False) -> None:
51  """
52  Downloads the Sample if it is an instance or a subclass of NetworkSample
53  Ignored for instances and subclasses of LocalSample
54  """
55 
56  pass
57 
58  def __unzipSample(self) -> None:
59  if self.pathpath.exists():
60  shutil.rmtree(self.pathpath)
61 
62  with ZipFile(self.zipPathzipPath) as zipFile:
63  zipFile.extractall(self.pathpath)
64 
65  def unzip(self, ignoreCache: bool = False) -> None:
66  """
67  Unzip sample zip file
68 
69  Parameters
70  ----------
71  ignoreCache : bool
72  if set to false performs unzip action even if
73  sample is previously unzipped
74  """
75 
76  if not self.zipPathzipPath.exists():
77  raise FileNotFoundError(f"Sample \"{self.name}\" archive does not exist at path \"{self.zipPath}\"")
78 
79  if self.pathpath.exists() and not ignoreCache:
80  return
81 
82  try:
83  self.__unzipSample__unzipSample()
84  except BadZipFile:
85  # Delete invalid zip file
86  self.zipPathzipPath.unlink()
87 
88  # Re-download
89  self.downloaddownload()
90 
91  # Try to unzip - if it fails again it should crash
92  self.__unzipSample__unzipSample()
93 
94  @abstractmethod
95  def load(self) -> SampleDataType:
96  pass
97 
98  def joinPath(self, other: Union[Path, str]) -> Path:
99  """
100  Joins sample path and provided path
101 
102  Parameters
103  ----------
104  other : Union[Path, str]
105  path for join
106 
107  Returns
108  -------
109  Path -> path created from sample path and provided path
110 
111  Example
112  -------
113  >>> print(sampleObj.joinPath("dummy.zip"))
114  Path("path/to/sample/dummy.zip")
115  """
116 
117  if isinstance(other, str):
118  other = Path(other)
119 
120  return self.path / other
121 
122  def _updateArchive(self) -> None:
123  oldZipPath = self.zipPath.parent / f"{self.zipPath.stem}-old.zip"
124  self.zipPath.rename(oldZipPath)
125 
126  with ZipFile(self.zipPath, "w") as zipFile:
127  for value in self.path.rglob("*"):
128  if not value.is_file():
129  continue
130 
131  zipFile.write(value, value.relative_to(self.path))
132 
133  oldZipPath.unlink()
None download(self, bool decrypt=True, bool ignoreCache=False)
Definition: sample.py:50
Path joinPath(self, Union[Path, str] other)
Definition: sample.py:98
None unzip(self, bool ignoreCache=False)
Definition: sample.py:65