diff --git a/bdfr/file_name_formatter.py b/bdfr/file_name_formatter.py index e81fe7f..542a722 100644 --- a/bdfr/file_name_formatter.py +++ b/bdfr/file_name_formatter.py @@ -111,19 +111,19 @@ class FileNameFormatter: if not resource.extension: raise BulkDownloaderException(f'Resource from {resource.url} has no extension') file_name = str(self._format_name(resource.source_submission, self.file_format_string)) - if not re.match(r'.*\.$',file_name) and not re.match(r'^\..*',resource.extension): + if not re.match(r'.*\.$', file_name) and not re.match(r'^\..*', resource.extension): ending = index + '.' + resource.extension else: ending = index + resource.extension try: - file_path = self._limit_file_name_length(file_name, ending, subfolder) + file_path = self.limit_file_name_length(file_name, ending, subfolder) except TypeError: raise BulkDownloaderException(f'Could not determine path name: {subfolder}, {index}, {resource.extension}') return file_path @staticmethod - def _limit_file_name_length(filename: str, ending: str, root: Path) -> Path: + def limit_file_name_length(filename: str, ending: str, root: Path) -> Path: root = root.resolve().expanduser() possible_id = re.search(r'((?:_\w{6})?$)', filename) if possible_id: @@ -133,9 +133,9 @@ class FileNameFormatter: max_length_chars = 255 - len(ending) max_length_bytes = 255 - len(ending.encode('utf-8')) max_path_length = max_path - len(ending) - len(str(root)) - 1 - while len(filename) > max_length_chars or \ - len(filename.encode('utf-8')) > max_length_bytes or \ - len(filename) > max_path_length: + while any([len(filename) > max_length_chars, + len(filename.encode('utf-8')) > max_length_bytes, + len(filename) > max_path_length]): filename = filename[:-1] return Path(root, filename + ending) diff --git a/tests/test_file_name_formatter.py b/tests/test_file_name_formatter.py index f9bb2ad..97fd851 100644 --- a/tests/test_file_name_formatter.py +++ b/tests/test_file_name_formatter.py @@ -188,7 +188,7 @@ def test_format_multiple_resources(): ('πŸ˜πŸ’•βœ¨' * 100, '_1.png'), )) def test_limit_filename_length(test_filename: str, test_ending: str): - result = FileNameFormatter._limit_file_name_length(test_filename, test_ending, Path('.')) + result = FileNameFormatter.limit_file_name_length(test_filename, test_ending, Path('.')) assert len(result.name) <= 255 assert len(result.name.encode('utf-8')) <= 255 assert len(str(result)) <= FileNameFormatter.find_max_path_length() @@ -207,15 +207,15 @@ def test_limit_filename_length(test_filename: str, test_ending: str): ('πŸ˜πŸ’•βœ¨' * 100 + '_aaa1aa', '_1.png', '_aaa1aa_1.png'), )) def test_preserve_id_append_when_shortening(test_filename: str, test_ending: str, expected_end: str): - result = FileNameFormatter._limit_file_name_length(test_filename, test_ending, Path('.')) + result = FileNameFormatter.limit_file_name_length(test_filename, test_ending, Path('.')) assert len(result.name) <= 255 assert len(result.name.encode('utf-8')) <= 255 assert result.name.endswith(expected_end) assert len(str(result)) <= FileNameFormatter.find_max_path_length() -def test_shorten_filenames(submission: MagicMock, tmp_path: Path): - submission.title = 'A' * 300 +def test_shorten_filename_real(submission: MagicMock, tmp_path: Path): + submission.title = 'A' * 500 submission.author.name = 'test' submission.subreddit.display_name = 'test' submission.id = 'BBBBBB' @@ -226,6 +226,21 @@ def test_shorten_filenames(submission: MagicMock, tmp_path: Path): result.touch() +@pytest.mark.parametrize(('test_name', 'test_ending'), ( + ('a', 'b'), + ('a', '_bbbbbb.jpg'), + ('a' * 20, '_bbbbbb.jpg'), + ('a' * 50, '_bbbbbb.jpg'), + ('a' * 500, '_bbbbbb.jpg'), +)) +def test_shorten_path(test_name: str, test_ending: str, tmp_path: Path): + result = FileNameFormatter.limit_file_name_length(test_name, test_ending, tmp_path) + assert len(str(result.name)) <= 255 + assert len(str(result.name).encode('UTF-8')) <= 255 + assert len(str(result.name).encode('cp1252')) <= 255 + assert len(str(result)) <= FileNameFormatter.find_max_path_length() + + @pytest.mark.parametrize(('test_string', 'expected'), ( ('test', 'test'), ('test😍', 'test'), @@ -380,7 +395,7 @@ def test_get_max_path_length(): def test_windows_max_path(tmp_path: Path): with unittest.mock.patch('platform.system', return_value='Windows'): with unittest.mock.patch('bdfr.file_name_formatter.FileNameFormatter.find_max_path_length', return_value=260): - result = FileNameFormatter._limit_file_name_length('test' * 100, '_1.png', tmp_path) + result = FileNameFormatter.limit_file_name_length('test' * 100, '_1.png', tmp_path) assert len(str(result)) <= 260 assert len(result.name) <= (260 - len(str(tmp_path)))