From ddbf52449b69959b389c9c5e64caa383c0de3109 Mon Sep 17 00:00:00 2001 From: Uchechukwu Orji Date: Mon, 4 Nov 2024 15:10:13 +0100 Subject: [PATCH 1/3] 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..333bd284 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..1539a7ae 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_creatable` 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") From cdb82f0b7c204b58db0f3f093e141fd56182bb59 Mon Sep 17 00:00:00 2001 From: Uchechukwu Orji Date: Tue, 5 Nov 2024 22:16:57 +0100 Subject: [PATCH 2/3] remove ZIM reference in filesystem exceptions --- CHANGELOG.md | 5 +-- src/zimscraperlib/__about__.py | 2 +- src/zimscraperlib/zim/filesystem.py | 50 ++++++++++++++--------------- tests/zim/test_fs.py | 24 +++++++------- 4 files changed, 41 insertions(+), 40 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 333bd284..4b1aaf05 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,9 +7,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] -### Changed +### Breaking Changes -- **BREAKING** Renamed `filesystem.validate_zimfile_creatable` to `filesystem.file_creatable` to reflect general applicability to check file creation beyond ZIM files #200 +- Renamed `filesystem.validate_zimfile_creatable` to `filesystem.file_creatable` to reflect general applicability to check file creation beyond ZIM files #200 +- Remove any "ZIM" reference in exceptions while working with files. ### Added diff --git a/src/zimscraperlib/__about__.py b/src/zimscraperlib/__about__.py index 0de2e0c2..5bd32610 100644 --- a/src/zimscraperlib/__about__.py +++ b/src/zimscraperlib/__about__.py @@ -1 +1 @@ -__version__ = "4.0.1-dev0" +__version__ = "5.0.0-dev0" diff --git a/src/zimscraperlib/zim/filesystem.py b/src/zimscraperlib/zim/filesystem.py index 1539a7ae..ae1f5836 100644 --- a/src/zimscraperlib/zim/filesystem.py +++ b/src/zimscraperlib/zim/filesystem.py @@ -220,33 +220,33 @@ def make_zim_file( zim_file.finish() -class IncorrectZIMPathError(Exception): - """A generic exception for any problem encountered in validate_zimfile_creatable""" +class IncorrectPathError(Exception): + """A generic exception for any problem encountered while working with filepaths""" pass -class MissingZIMFolderError(IncorrectZIMPathError): - """Exception raised in validate_zimfile_creatable when folder does not exists""" +class MissingFolderError(IncorrectPathError): + """Exception raised when folder does not exist""" pass -class NotADirectoryZIMFolderError(IncorrectZIMPathError): - """Exception raised in validate_zimfile_creatable when folder is not a directory""" +class NotADirectoryFolderError(IncorrectPathError): + """Exception raised when folder is not a directory""" pass -class NotWritableZIMFolderError(IncorrectZIMPathError): - """Exception raised in validate_zimfile_creatable when folder is not writable""" +class NotWritableFolderError(IncorrectPathError): + """Exception raised when folder is not writable""" pass -class IncorrectZIMFilenameError(IncorrectZIMPathError): +class IncorrectFilenameError(IncorrectPathError): """ - Exception raised in validate_zimfile_creatable when filename is not creatable + Exception raised when filename is not creatable This usually occurs when bad characters are present in filename (typically characters not supported on current filesystem). @@ -258,21 +258,21 @@ class IncorrectZIMFilenameError(IncorrectZIMPathError): 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 + Any problem encountered raises an exception inheriting from IncorrectPathError Checks that: - - folder passed exists (or raise MissingZIMFolderError exception) - - folder passed is a directory (or raise NotADirectoryZIMFolderError exception) + - folder passed exists (or raise MissingFolderError exception) + - folder passed is a directory (or raise NotADirectoryFolderError exception) - folder is writable, i.e. it is possible to create a file in folder (or raise - NotWritableZIMFolderError exception with inner exception details) + NotWritableFolderError exception with inner exception details) """ # ensure folder exists if not folder.exists(): - raise MissingZIMFolderError(f"Folder does not exist: {folder}") + raise MissingFolderError(f"Folder does not exist: {folder}") # ensure folder is a directory if not folder.is_dir(): - raise NotADirectoryZIMFolderError(f"Folder is not a directory: {folder}") + raise NotADirectoryFolderError(f"Folder is not a directory: {folder}") logger.debug(f"Attempting to confirm output is writable in directory {folder}") @@ -281,17 +281,17 @@ def validate_folder_writable(folder: pathlib.Path): 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 is not writable: {folder}") from exc + raise NotWritableFolderError(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 - Any problem encountered raises an exception inheriting from IncorrectZIMPathError + Any problem encountered raises an exception inheriting from IncorrectPathError Checks that: - folder is writable (or raise exception from `validate_folder_writable`) - - file can be created (or raise IncorrectZIMFilenameError exception with + - file can be created (or raise IncorrectFilenameError exception with inner exception details) """ folder = pathlib.Path(folder) @@ -305,21 +305,21 @@ def validate_file_creatable(folder: str | pathlib.Path, filename: str): fpath.touch() fpath.unlink() except Exception as exc: - raise IncorrectZIMFilenameError(f"File is not creatable: {fpath}") from exc + raise IncorrectFilenameError(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 + Any problem encountered raises an exception inheriting from IncorrectPathError Checks that: - - folder passed exists (or raise MissingZIMFolderError exception) - - folder passed is a directory (or raise NotADirectoryZIMFolderError exception) + - folder passed exists (or raise MissingFolderError exception) + - folder passed is a directory (or raise NotADirectoryFolderError exception) - folder is writable, i.e. it is possible to create a file in folder (or raise - NotWritableZIMFolderError exception with inner exception details) + NotWritableFolderError 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) + IncorrectFilenameError exception with inner exception details) """ warnings.warn( "'validate_zimfile_creatable' is deprecated and will be removed. " diff --git a/tests/zim/test_fs.py b/tests/zim/test_fs.py index 8484eff6..deb12593 100644 --- a/tests/zim/test_fs.py +++ b/tests/zim/test_fs.py @@ -11,10 +11,10 @@ from zimscraperlib.zim.archive import Archive from zimscraperlib.zim.filesystem import ( FileItem, - IncorrectZIMFilenameError, - MissingZIMFolderError, - NotADirectoryZIMFolderError, - NotWritableZIMFolderError, + IncorrectFilenameError, + MissingFolderError, + NotADirectoryFolderError, + NotWritableFolderError, make_zim_file, validate_file_creatable, validate_folder_writable, @@ -180,46 +180,46 @@ def test_validate_zimfile_creatable_ok(tmp_path, valid_zim_filename): def test_validate_zimfile_creatable_folder_not_exists(tmp_path, valid_zim_filename): - with pytest.raises(MissingZIMFolderError): + with pytest.raises(MissingFolderError): validate_zimfile_creatable(tmp_path / "foo", valid_zim_filename) def test_validate_zimfile_creatable_bad_folder(tmp_path, valid_zim_filename): - with pytest.raises(NotADirectoryZIMFolderError): + with pytest.raises(NotADirectoryFolderError): (tmp_path / "foo.txt").touch() validate_zimfile_creatable(tmp_path / "foo.txt", valid_zim_filename) def test_validate_zimfile_creatable_folder_not_writable(tmp_path, valid_zim_filename): - with pytest.raises(NotWritableZIMFolderError): + with pytest.raises(NotWritableFolderError): (tmp_path / "foo").mkdir(mode=111) validate_zimfile_creatable(tmp_path / "foo", valid_zim_filename) def test_validate_zimfile_creatable_bad_name(tmp_path): - with pytest.raises(IncorrectZIMFilenameError): + with pytest.raises(IncorrectFilenameError): validate_zimfile_creatable(tmp_path, "t\0t\0.zim") def test_validate_folder_writable_not_exists(tmp_path): - with pytest.raises(MissingZIMFolderError): + with pytest.raises(MissingFolderError): validate_folder_writable(tmp_path / "foo") def test_validate_folder_writable_not_dir(tmp_path): - with pytest.raises(NotADirectoryZIMFolderError): + with pytest.raises(NotADirectoryFolderError): (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): + with pytest.raises(NotWritableFolderError): (tmp_path / "foo").mkdir(mode=111) validate_folder_writable(tmp_path / "foo") @@ -235,5 +235,5 @@ def test_validate_file_creatable_ok(tmp_path, valid_zim_filename): def test_validate_file_creatable_bad_name(tmp_path): - with pytest.raises(IncorrectZIMFilenameError): + with pytest.raises(IncorrectFilenameError): validate_file_creatable(tmp_path, "t\0t\0.zim") From baa3e9d48f03ebac5908cc0a885161df6e1e15ce Mon Sep 17 00:00:00 2001 From: Uchechukwu Orji Date: Tue, 5 Nov 2024 22:17:58 +0100 Subject: [PATCH 3/3] completely remove validate_zimfile_creatable function --- CHANGELOG.md | 2 +- src/zimscraperlib/zim/filesystem.py | 23 --------------------- tests/zim/test_fs.py | 32 ----------------------------- 3 files changed, 1 insertion(+), 56 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4b1aaf05..f94c5a0f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,7 +10,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Breaking Changes - Renamed `filesystem.validate_zimfile_creatable` to `filesystem.file_creatable` to reflect general applicability to check file creation beyond ZIM files #200 -- Remove any "ZIM" reference in exceptions while working with files. +- Remove any "ZIM" reference in exceptions while working with files #200 ### Added diff --git a/src/zimscraperlib/zim/filesystem.py b/src/zimscraperlib/zim/filesystem.py index ae1f5836..bdf0125a 100644 --- a/src/zimscraperlib/zim/filesystem.py +++ b/src/zimscraperlib/zim/filesystem.py @@ -32,7 +32,6 @@ import pathlib import re import tempfile -import warnings from collections.abc import Sequence from zimscraperlib import logger @@ -306,25 +305,3 @@ def validate_file_creatable(folder: str | pathlib.Path, filename: str): fpath.unlink() except Exception as exc: raise IncorrectFilenameError(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 IncorrectPathError - - Checks that: - - folder passed exists (or raise MissingFolderError exception) - - folder passed is a directory (or raise NotADirectoryFolderError exception) - - folder is writable, i.e. it is possible to create a file in folder (or raise - NotWritableFolderError exception with inner exception details) - - filename is creatable, i.e. there is no bad characters in filename (or raise - IncorrectFilenameError exception with inner exception details) - """ - warnings.warn( - "'validate_zimfile_creatable' is deprecated and will be removed. " - "Use 'validate_file_creatable` 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 deb12593..3eec120c 100644 --- a/tests/zim/test_fs.py +++ b/tests/zim/test_fs.py @@ -18,7 +18,6 @@ make_zim_file, validate_file_creatable, validate_folder_writable, - validate_zimfile_creatable, ) @@ -173,37 +172,6 @@ def valid_zim_filename(): return "myfile.zim" -def test_validate_zimfile_creatable_ok(tmp_path, valid_zim_filename): - - validate_zimfile_creatable(tmp_path, valid_zim_filename) - - -def test_validate_zimfile_creatable_folder_not_exists(tmp_path, valid_zim_filename): - - with pytest.raises(MissingFolderError): - validate_zimfile_creatable(tmp_path / "foo", valid_zim_filename) - - -def test_validate_zimfile_creatable_bad_folder(tmp_path, valid_zim_filename): - - with pytest.raises(NotADirectoryFolderError): - (tmp_path / "foo.txt").touch() - validate_zimfile_creatable(tmp_path / "foo.txt", valid_zim_filename) - - -def test_validate_zimfile_creatable_folder_not_writable(tmp_path, valid_zim_filename): - - with pytest.raises(NotWritableFolderError): - (tmp_path / "foo").mkdir(mode=111) - validate_zimfile_creatable(tmp_path / "foo", valid_zim_filename) - - -def test_validate_zimfile_creatable_bad_name(tmp_path): - - with pytest.raises(IncorrectFilenameError): - validate_zimfile_creatable(tmp_path, "t\0t\0.zim") - - def test_validate_folder_writable_not_exists(tmp_path): with pytest.raises(MissingFolderError):