diff --git a/README.md b/README.md index dbfaa0f..54dd5ad 100644 --- a/README.md +++ b/README.md @@ -58,6 +58,9 @@ services: # https://immich.app/docs/features/command-line-interface#obtain-the-api-key API_KEY: xxxxxxxxxxxxxxxxx + # This is default. Can be omitted. When true, prints output but does not submit any changes + DRY_RUN: False + # Whether or not to modify photos that are already in stacks. Going over all assets takes a lot more time. SKIP_PREVIOUS: True diff --git a/immich_auto_stack.py b/immich_auto_stack.py index 25a24c4..ee20442 100644 --- a/immich_auto_stack.py +++ b/immich_auto_stack.py @@ -171,11 +171,16 @@ def main(): skip_previous = str2bool(os.environ.get("SKIP_PREVIOUS", True)) + dry_run = str2bool(os.environ.get("DRY_RUN", False)) + if not api_key: logger.warn("API key is required") return logger.info('============== INITIALIZING ==============') + + if dry_run: + logger.info('🔒 Dry run enabled, no changes will be applied') immich = Immich(api_url, api_key) @@ -213,8 +218,9 @@ def main(): "stackParentId": parent_id } - time.sleep(.1) - immich.modifyAssets(payload) + if not dry_run: + time.sleep(.1) + immich.modifyAssets(payload) if __name__ == '__main__': main() diff --git a/tests/test_dry_run.py b/tests/test_dry_run.py new file mode 100644 index 0000000..58df4f6 --- /dev/null +++ b/tests/test_dry_run.py @@ -0,0 +1,58 @@ +import os +import pytest +from unittest.mock import patch, Mock + +from immich_auto_stack import main + + +@pytest.mark.parametrize( + "dry_run_env_var,expected_call_count", + [ + ("True", 0), + ("true", 0), + ("yes", 0), + ("False", 1), + ("no", 1), + ("0", 1), + ("", 1), + (None, 1), + ], +) +@patch("immich_auto_stack.stratifyStack") +@patch("immich_auto_stack.stackBy") +@patch("immich_auto_stack.Immich") +def test_main_applies_dry_run_env_var_to_skip_modifyAssets( + mock_immich_class, + mock_stackBy, + mock_stratifyStack, + dry_run_env_var, + expected_call_count, +): + # Arrange + # mock the function calls within main() to create predictable scenarios + mock_stackBy.return_value = [ + ( + "dummy_key", + [ + {"id": "parent", "originalFileName": "foo.jpg"}, + { + "id": "child", + "originalFileName": "foo.png", + }, + ], + ) + ] + mock_stratifyStack.side_effect = lambda x: x # Return the same value passed in + test_environ = { + "API_KEY": "123", + "API_URL": "456", + } + if dry_run_env_var is not None: + test_environ["DRY_RUN"] = dry_run_env_var + + # Act + with patch.dict(os.environ, test_environ): + main() + + # Assert + assert mock_immich_class().modifyAssets.call_count == expected_call_count