@@ 205-234 (lines=30) @@ | ||
202 | except OSError: |
|
203 | raise WriteFailedError(f"Failed to open {path} for read", filename=str(path)) |
|
204 | ||
205 | @classmethod |
|
206 | def verify_can_write_files( |
|
207 | cls: type[Self], |
|
208 | *paths: str | Path, |
|
209 | missing_ok: bool = False, |
|
210 | attempt: bool = False, |
|
211 | ) -> None: |
|
212 | """ |
|
213 | Checks that all files can be written to, to ensure atomicity before operations. |
|
214 | ||
215 | Args: |
|
216 | *paths: The files |
|
217 | missing_ok: Don't raise an error if a path doesn't exist |
|
218 | attempt: Actually try opening |
|
219 | ||
220 | Returns: |
|
221 | WriteFailedError: If a path is not a file (modulo existence) or doesn't have 'W' set |
|
222 | """ |
|
223 | paths = [Path(p) for p in paths] |
|
224 | for path in paths: |
|
225 | if path.exists() and not path.is_file(): |
|
226 | raise WriteFailedError(f"Path {path} is not a file", filename=str(path)) |
|
227 | if (not missing_ok or path.exists()) and not os.access(path, os.W_OK): |
|
228 | raise WriteFailedError(f"Cannot write to {path}", filename=str(path)) |
|
229 | if attempt: |
|
230 | try: |
|
231 | with open(path, "a"): # or w |
|
232 | pass |
|
233 | except OSError: |
|
234 | raise WriteFailedError(f"Failed to open {path} for write", filename=str(path)) |
|
235 | ||
236 | @classmethod |
|
237 | def verify_can_write_dirs( |
|
@@ 174-203 (lines=30) @@ | ||
171 | Some functions may be insecure. |
|
172 | """ |
|
173 | ||
174 | @classmethod |
|
175 | def verify_can_read_files( |
|
176 | cls: type[Self], |
|
177 | *paths: str | Path, |
|
178 | missing_ok: bool = False, |
|
179 | attempt: bool = False, |
|
180 | ) -> None: |
|
181 | """ |
|
182 | Checks that all files can be written to, to ensure atomicity before operations. |
|
183 | ||
184 | Args: |
|
185 | *paths: The files |
|
186 | missing_ok: Don't raise an error if a path doesn't exist |
|
187 | attempt: Actually try opening |
|
188 | ||
189 | Returns: |
|
190 | ReadFailedError: If a path is not a file (modulo existence) or doesn't have 'W' set |
|
191 | """ |
|
192 | paths = [Path(p) for p in paths] |
|
193 | for path in paths: |
|
194 | if path.exists() and not path.is_file(): |
|
195 | raise ReadFailedError(f"Path {path} is not a file", filename=str(path)) |
|
196 | if (not missing_ok or path.exists()) and not os.access(path, os.R_OK): |
|
197 | raise ReadFailedError(f"Cannot read from {path}", filename=str(path)) |
|
198 | if attempt: |
|
199 | try: |
|
200 | with open(path): |
|
201 | pass |
|
202 | except OSError: |
|
203 | raise WriteFailedError(f"Failed to open {path} for read", filename=str(path)) |
|
204 | ||
205 | @classmethod |
|
206 | def verify_can_write_files( |