コード例 #1
0
def test_safe_path_long_file_name_invalid(tmp_path):
    """Test that SafePath raises ValueError if path is too long but cannot be trimmed"""
    test_dir = tmp_path / "test"
    bad_file_name = "X" + "." + "x" * MAX_FILE_NAME_LEN

    safe_path = SafePath(test_dir)
    with pytest.raises(ValueError):
        safe_path.get_file("test1", bad_file_name)
コード例 #2
0
def test_safe_path_file(tmp_path):
    test_dir = tmp_path / "test"
    expected_file = tmp_path / "test" / "test1" / "test2" / "test3.txt"

    safe_path = SafePath(test_dir)
    result_file_path = safe_path.get_file("test1", "test2", "test3.txt")

    assert expected_file.parent.is_dir()
    assert not expected_file.exists()
    assert result_file_path == expected_file
コード例 #3
0
def test_safe_path_file(tmp_path):
    test_dir = tmp_path / "test"
    expected_file = tmp_path / "test" / "test1" / "test2" / "test3.txt"

    safe_path = SafePath(str(test_dir))
    result_file_path = safe_path.get_file("test1", "test2", "test3.txt")

    expected_file.touch()

    assert expected_file.is_file()
    assert result_file_path == str(expected_file)
コード例 #4
0
def test_safe_path_file_existing_overwrite(tmp_path):
    test_dir = tmp_path / "test"

    existing_file = tmp_path / "test" / "test1" / "test2" / "test3.txt"
    existing_file.parent.mkdir(parents=True)
    existing_file.touch()

    safe_path = SafePath(test_dir, overwrite=True)
    result_file_path = safe_path.get_file("test1", "test2", "test3.txt")

    assert result_file_path == existing_file
コード例 #5
0
def test_safe_path_no_trim(tmp_path):
    """Test that the SafePath does not trim the path if the path is not too long"""
    test_dir = tmp_path / "test"
    max_file_name = "X" * 251 + ".ext"
    expected_file_name = max_file_name
    expected_file = tmp_path / "test" / "test1" / expected_file_name

    safe_path = SafePath(test_dir)
    result_file_path = safe_path.get_file("test1", max_file_name)

    expected_file.touch()

    assert expected_file.is_file()
    assert result_file_path == expected_file
コード例 #6
0
def test_safe_path_file_existing(tmp_path):
    test_dir = tmp_path / "test"

    existing_file = tmp_path / "test" / "test1" / "test2" / "test3.txt"
    existing_file.parent.mkdir(parents=True)
    existing_file.touch()

    expected_file = tmp_path / "test" / "test1" / "test2" / "test3 (1).txt"

    safe_path = SafePath(test_dir)
    result_file_path = safe_path.get_file("test1", "test2", "test3.txt")

    assert expected_file.parent.is_dir()
    assert not expected_file.exists()
    assert result_file_path == expected_file
コード例 #7
0
def test_safe_path_long_file_name(tmp_path):
    """Test that SafePath trims a long file name with extension"""
    test_dir = tmp_path / "test"

    test_ext = ".ext"
    long_file_name = "X" * MAX_FILE_NAME_LEN + test_ext
    expected_file_name = "X" * (MAX_FILE_NAME_LEN - len(test_ext)) + test_ext
    expected_file = tmp_path / "test" / "test1" / expected_file_name

    safe_path = SafePath(test_dir)
    result_file_path = safe_path.get_file("test1", long_file_name)

    expected_file.touch()

    assert expected_file.is_file()
    assert result_file_path == expected_file
コード例 #8
0
def test_safe_path_long_file_name_no_ext(tmp_path):
    """Test that SafePath trims a long file name with no extension"""
    test_dir = tmp_path / "test"

    slightly_longer_than_supported = MAX_FILE_NAME_LEN + 10

    long_file_name = "X" * slightly_longer_than_supported
    expected_file_name = "X" * MAX_FILE_NAME_LEN
    expected_file = tmp_path / "test" / "test1" / expected_file_name

    safe_path = SafePath(test_dir)
    result_file_path = safe_path.get_file("test1", long_file_name)

    expected_file.touch()

    assert expected_file.is_file()
    assert result_file_path == expected_file
コード例 #9
0
def test_safe_path_long_file_name_existing(tmp_path):
    """Test that SafePath trims an existing long file name with extension"""
    test_dir = tmp_path / "test"

    test_ext = ".ext"
    long_file_name = "X" * (MAX_FILE_NAME_LEN - len(test_ext)) + test_ext
    long_file = tmp_path / "test" / long_file_name

    expected_file_name = (
        "X" * (MAX_FILE_NAME_LEN - len(test_ext) - 4) + " (1)" + test_ext
    )
    expected_file = tmp_path / "test" / expected_file_name

    long_file.parent.mkdir(parents=True)
    long_file.touch()

    safe_path = SafePath(test_dir)
    result_file_path = safe_path.get_file(long_file_name)

    expected_file.touch()

    assert expected_file.is_file()
    assert result_file_path == expected_file
コード例 #10
0
class NoteExporter(object):
    def __init__(self, storage: SqliteStorage, target_dir: str) -> None:
        self.storage = storage
        self.safe_paths = SafePath(target_dir)

    def export_notebooks(self, single_notes: bool, export_trash: bool) -> None:
        count_notes = self.storage.notes.get_notes_count()
        count_trash = self.storage.notes.get_notes_count(is_active=False)

        if logger.getEffectiveLevel() == logging.DEBUG:  # pragma: no cover
            logger.debug(f"Notes to export: {count_notes}")
            logger.debug(f"Trashed notes: {count_trash}")
            if single_notes:
                logger.debug("Export mode: single notes")
            else:
                logger.debug("Export mode: notebooks")

        if count_notes == 0 and count_trash == 0:
            raise NothingToExportError

        if count_notes > 0:
            logger.info("Exporting notes...")

            self._export_active(single_notes)

        if count_trash > 0 and export_trash:
            logger.info("Exporting trash...")

            self._export_trash(single_notes)

    def _export_active(self, single_notes: bool) -> None:
        notebooks = tuple(self.storage.notebooks.iter_notebooks())

        with progressbar(
                notebooks,
                item_show_func=lambda x: str(x.name) if x else "",
                show_pos=True,
                file=get_progress_output(),
        ) as notebooks_bar:
            for nb in notebooks_bar:
                if logger.getEffectiveLevel(
                ) == logging.DEBUG:  # pragma: no cover
                    nb_info = log_format_notebook(nb)
                    logger.debug(f"Exporting notebook {nb_info}")

                if self.storage.notebooks.get_notebook_notes_count(
                        nb.guid) == 0:
                    logger.debug("Notebook is empty, skip")
                    continue

                self._export_notes(nb, single_notes)

    def _export_notes(self, notebook: Notebook, single_notes: bool) -> None:
        parent_dir = [notebook.stack] if notebook.stack else []

        notes_source = self.storage.notes.iter_notes(notebook.guid)

        if single_notes:
            parent_dir.append(notebook.name)
            self._output_single_notes(parent_dir, notes_source)
        else:
            self._output_notebook(parent_dir, notebook.name, notes_source)

    def _export_trash(self, single_notes: bool) -> None:
        notes_source = self.storage.notes.iter_notes_trash()

        if single_notes:
            self._output_single_notes(["Trash"], notes_source)
        else:
            self._output_notebook([], "Trash", notes_source)

    def _output_single_notes(
        self,
        parent_dir: List[str],
        notes_source: Iterable[Note],
    ) -> None:
        for note in notes_source:
            note_path = self.safe_paths.get_file(*parent_dir,
                                                 f"{note.title}.enex")

            _write_export_file(note_path, note)

    def _output_notebook(
        self,
        parent_dir: List[str],
        notebook_name: str,
        notes_source: Iterable[Note],
    ) -> None:
        notebook_path = self.safe_paths.get_file(*parent_dir,
                                                 f"{notebook_name}.enex")

        _write_export_file(notebook_path, notes_source)