From 632d5067b7094d4be98431e21cdc5909a9b9f05b Mon Sep 17 00:00:00 2001 From: Uchechukwu Orji Date: Mon, 4 Nov 2024 15:10:13 +0100 Subject: [PATCH] rename validate_zimfile_creatable to validate_file_creatable --- CHANGELOG.md | 9 ++++ src/zimscraperlib/zim/filesystem.py | 66 ++++++++++++++++++++--------- tests/zim/test_fs.py | 37 ++++++++++++++++ 3 files changed, 92 insertions(+), 20 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 20c71d4a..15d499a9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,14 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +### Changed + +- **BREAKING** Renamed `filesystem.validate_zimfile_creatable` to `filesystem.file_creatable` to reflect general applicability to check file creation beyond ZIM files #200 + +### Added + +- Add `filesystem.validate_folder_writable` to check if a folder can be written to # 200 + ## [4.0.0] - 2024-08-05 ### Added @@ -38,6 +46,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - **BREAKING** Rename `i18.NotFound` to `i18n.NotFoundError` ### Removed + - **BREAKING** Remove translation features in `i18n`: `Locale` class + `_` and `setlocale` functions #134 ### Fixed diff --git a/src/zimscraperlib/zim/filesystem.py b/src/zimscraperlib/zim/filesystem.py index ecd677d0..78b4af5c 100644 --- a/src/zimscraperlib/zim/filesystem.py +++ b/src/zimscraperlib/zim/filesystem.py @@ -32,6 +32,7 @@ import pathlib import re import tempfile +import warnings from collections.abc import Sequence from zimscraperlib import logger @@ -254,8 +255,8 @@ class IncorrectZIMFilenameError(IncorrectZIMPathError): pass -def validate_zimfile_creatable(folder: str | pathlib.Path, filename: str): - """Validate that a ZIM can be created in given folder with given filename +def validate_folder_writable(folder: pathlib.Path): + """Validate that a file can be created in a given folder. Any problem encountered raises an exception inheriting from IncorrectZIMPathError @@ -264,22 +265,14 @@ def validate_zimfile_creatable(folder: str | pathlib.Path, filename: str): - folder passed is a directory (or raise NotADirectoryZIMFolderError exception) - folder is writable, i.e. it is possible to create a file in folder (or raise NotWritableZIMFolderError exception with inner exception details) - - filename is creatable, i.e. there is no bad characters in filename (or raise - IncorrectZIMFilenameError exception with inner exception details) """ - folder = pathlib.Path(folder) - # ensure folder exists if not folder.exists(): - raise MissingZIMFolderError( - f"Folder to create the ZIM does not exist: {folder}" - ) + raise MissingZIMFolderError(f"Folder does not exist: {folder}") # ensure folder is a directory if not folder.is_dir(): - raise NotADirectoryZIMFolderError( - f"Folder to create the ZIM is not a directory: {folder}" - ) + raise NotADirectoryZIMFolderError(f"Folder is not a directory: {folder}") logger.debug(f"Attempting to confirm output is writable in directory {folder}") @@ -288,17 +281,50 @@ def validate_zimfile_creatable(folder: str | pathlib.Path, filename: str): with tempfile.NamedTemporaryFile(dir=folder, delete=True) as fh: logger.debug(f"Output is writable. Temporary file used for test: {fh.name}") except Exception as exc: - raise NotWritableZIMFolderError( - f"Folder to create the ZIM is not writable: {folder}" - ) from exc + raise NotWritableZIMFolderError(f"Folder is not writable: {folder}") from exc + + +def validate_file_creatable(folder: str | pathlib.Path, filename: str): + """Validate that a file can be created in given folder with given filename - # ensure ZIM file is creatable with the given name + Any problem encountered raises an exception inheriting from IncorrectZIMPathError + + Checks that: + - folder is writable (or raise exception from `validate_folder_writable`) + - file can be created (or raise IncorrectZIMFilenameError exception with + inner exception details) + """ + folder = pathlib.Path(folder) + + validate_folder_writable(folder) + + # ensure file is creatable with the given name fpath = folder / filename try: - logger.debug(f"Confirming ZIM file can be created at {fpath}") + logger.debug(f"Confirming file can be created at {fpath}") fpath.touch() fpath.unlink() except Exception as exc: - raise IncorrectZIMFilenameError( - f"ZIM filename is not creatable: {fpath}" - ) from exc + raise IncorrectZIMFilenameError(f"File is not creatable: {fpath}") from exc + + +def validate_zimfile_creatable(folder: str | pathlib.Path, filename: str): + """Validate that a ZIM can be created in given folder with given filename + + Any problem encountered raises an exception inheriting from IncorrectZIMPathError + + Checks that: + - folder passed exists (or raise MissingZIMFolderError exception) + - folder passed is a directory (or raise NotADirectoryZIMFolderError exception) + - folder is writable, i.e. it is possible to create a file in folder (or raise + NotWritableZIMFolderError exception with inner exception details) + - filename is creatable, i.e. there is no bad characters in filename (or raise + IncorrectZIMFilenameError exception with inner exception details) + """ + warnings.warn( + "'validate_zimfile_creatable' is deprecated and will be removed. " + "Use 'validate_file_createable` to ensure future compatibility.", + DeprecationWarning, + stacklevel=2, + ) + validate_file_creatable(folder, filename) diff --git a/tests/zim/test_fs.py b/tests/zim/test_fs.py index 41ad1367..8484eff6 100644 --- a/tests/zim/test_fs.py +++ b/tests/zim/test_fs.py @@ -16,6 +16,8 @@ NotADirectoryZIMFolderError, NotWritableZIMFolderError, make_zim_file, + validate_file_creatable, + validate_folder_writable, validate_zimfile_creatable, ) @@ -200,3 +202,38 @@ def test_validate_zimfile_creatable_bad_name(tmp_path): with pytest.raises(IncorrectZIMFilenameError): validate_zimfile_creatable(tmp_path, "t\0t\0.zim") + + +def test_validate_folder_writable_not_exists(tmp_path): + + with pytest.raises(MissingZIMFolderError): + validate_folder_writable(tmp_path / "foo") + + +def test_validate_folder_writable_not_dir(tmp_path): + + with pytest.raises(NotADirectoryZIMFolderError): + (tmp_path / "foo.txt").touch() + validate_folder_writable(tmp_path / "foo.txt") + + +def test_validate_folder_writable_not_writable(tmp_path): + + with pytest.raises(NotWritableZIMFolderError): + (tmp_path / "foo").mkdir(mode=111) + validate_folder_writable(tmp_path / "foo") + + +def test_validate_folder_writable_ok(tmp_path): + validate_folder_writable(tmp_path) + + +def test_validate_file_creatable_ok(tmp_path, valid_zim_filename): + + validate_file_creatable(tmp_path, valid_zim_filename) + + +def test_validate_file_creatable_bad_name(tmp_path): + + with pytest.raises(IncorrectZIMFilenameError): + validate_file_creatable(tmp_path, "t\0t\0.zim")