mirror of
https://github.com/freedomofpress/dangerzone.git
synced 2025-04-28 18:02:38 +02:00
Specialize DocumentFilenameException() for disambiguation
All filename-related exceptions were of class DocumentFilenameException. This made it difficult to disambiguate them. Specializing them makes it it easier for tests to detect which exception in particular we want to verify.
This commit is contained in:
parent
1bdbb1959c
commit
93f17b3166
3 changed files with 57 additions and 23 deletions
|
@ -9,7 +9,7 @@ from typing import Optional
|
|||
|
||||
import appdirs
|
||||
|
||||
from .errors import DocumentFilenameException
|
||||
from . import errors
|
||||
|
||||
SAFE_EXTENSION = "-safe.pdf"
|
||||
|
||||
|
@ -54,28 +54,24 @@ class Document:
|
|||
try:
|
||||
open(filename, "rb")
|
||||
except FileNotFoundError as e:
|
||||
raise DocumentFilenameException(
|
||||
"Input file not found: make sure you typed it correctly."
|
||||
) from e
|
||||
raise errors.InputFileNotFoundException() from e
|
||||
except PermissionError as e:
|
||||
raise DocumentFilenameException(
|
||||
"You don't have permission to open the input file."
|
||||
) from e
|
||||
raise errors.InputFileNotReadableException() from e
|
||||
|
||||
@staticmethod
|
||||
def validate_output_filename(filename: str) -> None:
|
||||
if not filename.endswith(".pdf"):
|
||||
raise DocumentFilenameException("Safe PDF filename must end in '.pdf'")
|
||||
raise errors.NonPDFOutputFileException()
|
||||
try:
|
||||
with open(filename, "wb"):
|
||||
pass
|
||||
except PermissionError as e:
|
||||
raise DocumentFilenameException("Safe PDF filename is not writable") from e
|
||||
raise errors.UnwriteableOutputFileException() from e
|
||||
|
||||
@property
|
||||
def input_filename(self) -> str:
|
||||
if self._input_filename is None:
|
||||
raise DocumentFilenameException("Input filename has not been set yet.")
|
||||
raise errors.NotSetInputFilenameException()
|
||||
else:
|
||||
return self._input_filename
|
||||
|
||||
|
@ -92,7 +88,7 @@ class Document:
|
|||
if self._input_filename is not None:
|
||||
return self.default_output_filename
|
||||
else:
|
||||
raise DocumentFilenameException("Output filename has not been set yet.")
|
||||
raise errors.NotSetOutputFilenameException()
|
||||
else:
|
||||
return self._output_filename
|
||||
|
||||
|
|
|
@ -14,6 +14,49 @@ class DocumentFilenameException(Exception):
|
|||
"""Exception for document-related filename errors."""
|
||||
|
||||
|
||||
class InputFileNotFoundException(DocumentFilenameException):
|
||||
"""Exception for when an input file does not exist."""
|
||||
|
||||
def __init__(self) -> None:
|
||||
super().__init__("Input file not found: make sure you typed it correctly.")
|
||||
|
||||
|
||||
class InputFileNotReadableException(DocumentFilenameException):
|
||||
"""Exception for when an input file exists but is not readable."""
|
||||
|
||||
def __init__(self) -> None:
|
||||
super().__init__("You don't have permission to open the input file.")
|
||||
|
||||
|
||||
class NonPDFOutputFileException(DocumentFilenameException):
|
||||
"""Exception for when the output file is not a PDF."""
|
||||
|
||||
def __init__(self) -> None:
|
||||
super().__init__("Safe PDF filename must end in '.pdf'")
|
||||
|
||||
|
||||
class UnwriteableOutputFileException(DocumentFilenameException):
|
||||
"""Exception for when the output file is not writeable."""
|
||||
|
||||
def __init__(self) -> None:
|
||||
super().__init__("Safe PDF filename is not writable")
|
||||
|
||||
|
||||
class NotSetInputFilenameException(DocumentFilenameException):
|
||||
"""Exception for when the output filename is set before having an
|
||||
associated input file."""
|
||||
|
||||
def __init__(self) -> None:
|
||||
super().__init__("Input filename has not been set yet.")
|
||||
|
||||
|
||||
class NotSetOutputFilenameException(DocumentFilenameException):
|
||||
"""Exception for when the output filename is read before it has been set."""
|
||||
|
||||
def __init__(self) -> None:
|
||||
super().__init__("Output filename has not been set yet.")
|
||||
|
||||
|
||||
def handle_document_errors(func: F) -> F:
|
||||
"""Log document-related errors and exit gracefully."""
|
||||
|
||||
|
|
|
@ -5,8 +5,8 @@ from pathlib import Path
|
|||
|
||||
import pytest
|
||||
|
||||
from dangerzone import errors
|
||||
from dangerzone.document import Document
|
||||
from dangerzone.errors import DocumentFilenameException
|
||||
|
||||
from . import sample_doc, unreadable_pdf, unwriteable_pdf
|
||||
|
||||
|
@ -25,15 +25,13 @@ def test_input_file_none() -> None:
|
|||
Attempts to read a document's filename when no doc has been set
|
||||
"""
|
||||
d = Document()
|
||||
with pytest.raises(DocumentFilenameException) as e:
|
||||
with pytest.raises(errors.NotSetInputFilenameException) as e:
|
||||
d.input_filename
|
||||
assert "Input filename has not been set yet" in str(e.value)
|
||||
|
||||
|
||||
def test_input_file_non_existing() -> None:
|
||||
with pytest.raises(DocumentFilenameException) as e:
|
||||
with pytest.raises(errors.InputFileNotFoundException) as e:
|
||||
Document("non-existing-file.pdf")
|
||||
assert "Input file not found" in str(e.value)
|
||||
|
||||
|
||||
# XXX: This is not easy to test on Windows, as the file owner can always read it.
|
||||
|
@ -41,14 +39,13 @@ def test_input_file_non_existing() -> None:
|
|||
# https://stackoverflow.com/questions/72528318/what-file-permissions-make-a-file-unreadable-by-owner-in-windows
|
||||
@pytest.mark.skipif(platform.system() == "Windows", reason="Unix-specific")
|
||||
def test_input_file_unreadable(unreadable_pdf: str) -> None:
|
||||
with pytest.raises(DocumentFilenameException) as e:
|
||||
with pytest.raises(errors.InputFileNotReadableException) as e:
|
||||
Document(unreadable_pdf)
|
||||
assert "don't have permission to open the input file" in str(e.value)
|
||||
|
||||
|
||||
def test_output_file_unwriteable(unwriteable_pdf: str) -> None:
|
||||
d = Document()
|
||||
with pytest.raises(DocumentFilenameException) as e:
|
||||
with pytest.raises(errors.UnwriteableOutputFileException) as e:
|
||||
d.output_filename = unwriteable_pdf
|
||||
assert "Safe PDF filename is not writable" in str(e.value)
|
||||
|
||||
|
@ -64,18 +61,16 @@ def test_output_file_none() -> None:
|
|||
Attempts to read a document's filename when no doc has been set
|
||||
"""
|
||||
d = Document()
|
||||
with pytest.raises(DocumentFilenameException) as e:
|
||||
with pytest.raises(errors.NotSetOutputFilenameException) as e:
|
||||
d.output_filename
|
||||
assert "Output filename has not been set yet" in str(e.value)
|
||||
|
||||
|
||||
def test_output_file_not_pdf(tmp_path: Path) -> None:
|
||||
docx_file = str(tmp_path.joinpath("document.docx"))
|
||||
d = Document()
|
||||
|
||||
with pytest.raises(DocumentFilenameException) as e:
|
||||
with pytest.raises(errors.NonPDFOutputFileException) as e:
|
||||
d.output_filename = docx_file
|
||||
assert "Safe PDF filename must end in '.pdf'" in str(e.value)
|
||||
|
||||
assert not os.path.exists(docx_file)
|
||||
|
||||
|
|
Loading…
Reference in a new issue