diff --git a/bulkredditdownloader/file_name_formatter.py b/bulkredditdownloader/file_name_formatter.py index 5be0213..ecd71be 100644 --- a/bulkredditdownloader/file_name_formatter.py +++ b/bulkredditdownloader/file_name_formatter.py @@ -46,13 +46,24 @@ class FileNameFormatter: def _format_path(self, resource: Resource, destination_directory: Path, index: Optional[int] = None) -> Path: subfolder = destination_directory / self._format_name(resource.source_submission, self.directory_format_string) index = f'_{str(index)}' if index else '' + if not resource.extension: + raise BulkDownloaderException(f'Resource from {resource.url} has no extension') + ending = index + resource.extension + file_name = str(self._format_name(resource.source_submission, self.file_format_string)) + file_name = self._limit_file_name_length(file_name, ending) try: - file_path = subfolder / (str(self._format_name(resource.source_submission, - self.file_format_string)) + index + resource.extension) + file_path = Path(subfolder, file_name) 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) -> str: + max_length = 255 - len(ending) + if len(filename) > max_length: + filename = filename[:max_length] + return filename + ending + def format_resource_paths(self, resources: list[Resource], destination_directory: Path) -> list[tuple[Path, Resource]]: out = [] diff --git a/bulkredditdownloader/tests/test_file_name_formatter.py b/bulkredditdownloader/tests/test_file_name_formatter.py index 533d570..2e9d7bc 100644 --- a/bulkredditdownloader/tests/test_file_name_formatter.py +++ b/bulkredditdownloader/tests/test_file_name_formatter.py @@ -125,3 +125,28 @@ def test_format_multiple_resources(): results = test_formatter.format_resource_paths(mocks, Path('.')) results = set([str(res[0]) for res in results]) assert results == {'test_1.png', 'test_2.png', 'test_3.png', 'test_4.png'} + + +@pytest.mark.parametrize(('test_filename', 'test_ending'), ( + ('A' * 300, '.png'), + ('A' * 300, '_1.png'), + ('a' * 300, '_1000.jpeg'), +)) +def test_limit_filename_length(test_filename: str, test_ending: str): + result = FileNameFormatter._limit_file_name_length(test_filename, test_ending) + assert len(result) <= 255 + + +@pytest.mark.online +@pytest.mark.reddit +def test_shorten_filenames(reddit_instance: praw.Reddit, tmp_path: Path): + test_submission = MagicMock() + test_submission.title = 'A' * 300 + test_submission.author.name = 'test' + test_submission.subreddit.display_name = 'test' + test_submission.id = 'BBBBBB' + test_resource = Resource(test_submission, 'www.example.com/empty', '.jpeg') + test_formatter = FileNameFormatter('{REDDITOR}_{TITLE}_{POSTID}', '{SUBREDDIT}') + result = test_formatter._format_path(test_resource, tmp_path) + result.parent.mkdir(parents=True) + result.touch() diff --git a/bulkredditdownloader/tests/test_integration.py b/bulkredditdownloader/tests/test_integration.py index 17067a1..1cc7a63 100644 --- a/bulkredditdownloader/tests/test_integration.py +++ b/bulkredditdownloader/tests/test_integration.py @@ -43,6 +43,7 @@ def test_cli_download_subreddits(test_args: list[str], tmp_path: Path): @pytest.mark.parametrize('test_args', ( ['-l', 'm2601g'], ['-l', 'https://www.reddit.com/r/TrollXChromosomes/comments/m2601g/its_a_step_in_the_right_direction/'], + ['-l', 'm3hxzd'], # Really long title used to overflow filename limit )) def test_cli_download_links(test_args: list[str], tmp_path: Path): runner = CliRunner()