From 2902074dc1d9e4f4c9cc712e7dc49fc946018ee6 Mon Sep 17 00:00:00 2001 From: Hagen Wierstorf Date: Sun, 15 Dec 2024 11:18:36 +0100 Subject: [PATCH 1/4] Ensure audb.Repository is hashable --- audb/core/repository.py | 9 +++++++++ tests/test_repository.py | 11 +++++++++++ 2 files changed, 20 insertions(+) diff --git a/audb/core/repository.py b/audb/core/repository.py index 8e1497f2..0419eee8 100644 --- a/audb/core/repository.py +++ b/audb/core/repository.py @@ -71,6 +71,15 @@ def __eq__(self, other) -> bool: """ return str(self) == str(other) + def __hash__(self): + """Hash of repository. + + Returns: + hash of repository + + """ + return hash(str(self)) + def __repr__(self): # noqa: D105 return ( f"Repository(" diff --git a/tests/test_repository.py b/tests/test_repository.py index a78c0ad2..77a21c51 100644 --- a/tests/test_repository.py +++ b/tests/test_repository.py @@ -43,6 +43,17 @@ def test_repository_eq(repository1, repository2, expected): assert (repository1 == repository2) == expected +@pytest.mark.parametrize( + "repository", + [audb.Repository("repo", "host", "file-system")], +) +def test_repository_hash(repository): + """Test Repository object is hashable.""" + assert isinstance(hash(repository), int) + # set needs `__hash__` to exist to work + assert set([repository]) == set([str(repository)]) + + @pytest.mark.parametrize( "backend, host, repo, expected", [ From a8e0ca5c71f0f8daddb34540bbc7b6f0b912dc51 Mon Sep 17 00:00:00 2001 From: Hagen Wierstorf Date: Sun, 15 Dec 2024 11:22:38 +0100 Subject: [PATCH 2/4] Update tests/test_repository.py Co-authored-by: sourcery-ai[bot] <58596630+sourcery-ai[bot]@users.noreply.github.com> --- tests/test_repository.py | 56 +++++++++++++++++++++++++++++++++++----- 1 file changed, 49 insertions(+), 7 deletions(-) diff --git a/tests/test_repository.py b/tests/test_repository.py index 77a21c51..5827163e 100644 --- a/tests/test_repository.py +++ b/tests/test_repository.py @@ -44,14 +44,56 @@ def test_repository_eq(repository1, repository2, expected): @pytest.mark.parametrize( - "repository", - [audb.Repository("repo", "host", "file-system")], + "repo1, repo2, should_have_same_hash", + [ + # Same repositories should have same hash + ( + audb.Repository("repo", "host", "file-system"), + audb.Repository("repo", "host", "file-system"), + True, + ), + # Different attributes should have different hashes + ( + audb.Repository("repo1", "host", "file-system"), + audb.Repository("repo2", "host", "file-system"), + False, + ), + ( + audb.Repository("repo", "host1", "file-system"), + audb.Repository("repo", "host2", "file-system"), + False, + ), + ( + audb.Repository("repo", "host", "file-system"), + audb.Repository("repo", "host", "s3"), + False, + ), + ], ) -def test_repository_hash(repository): - """Test Repository object is hashable.""" - assert isinstance(hash(repository), int) - # set needs `__hash__` to exist to work - assert set([repository]) == set([str(repository)]) +def test_repository_hash(repo1, repo2, should_have_same_hash): + """Test Repository object hash behavior. + + Tests that: + - Repository objects are hashable + - Equal repositories have same hash + - Different repositories have different hashes + """ + # Verify objects are hashable + assert isinstance(hash(repo1), int) + assert isinstance(hash(repo2), int) + + # Test hash equality matches object equality + if should_have_same_hash: + assert hash(repo1) == hash(repo2) + assert repo1 == repo2 + else: + assert hash(repo1) != hash(repo2) + assert repo1 != repo2 + + # Verify can be used in sets + test_set = {repo1, repo2} + expected_len = 1 if should_have_same_hash else 2 + assert len(test_set) == expected_len @pytest.mark.parametrize( From 2245949f4bc6d2b915e40dce8812e854af883ec8 Mon Sep 17 00:00:00 2001 From: Hagen Wierstorf Date: Sun, 15 Dec 2024 11:21:10 +0100 Subject: [PATCH 3/4] Add missing return type --- audb/core/repository.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/audb/core/repository.py b/audb/core/repository.py index 0419eee8..a312f53e 100644 --- a/audb/core/repository.py +++ b/audb/core/repository.py @@ -71,7 +71,7 @@ def __eq__(self, other) -> bool: """ return str(self) == str(other) - def __hash__(self): + def __hash__(self) -> int: """Hash of repository. Returns: From cd8e7804d8679bf593a5b6eb5824181f6e94bf35 Mon Sep 17 00:00:00 2001 From: Hagen Wierstorf Date: Sun, 15 Dec 2024 11:24:34 +0100 Subject: [PATCH 4/4] Extend test docstring --- tests/test_repository.py | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/tests/test_repository.py b/tests/test_repository.py index 5827163e..98e138ea 100644 --- a/tests/test_repository.py +++ b/tests/test_repository.py @@ -77,6 +77,14 @@ def test_repository_hash(repo1, repo2, should_have_same_hash): - Repository objects are hashable - Equal repositories have same hash - Different repositories have different hashes + + Args: + repo1: repository object + repo2: repository object + should_have_same_hash: if ``True``, + expects ``repo1`` and ``repo2`` + to be the same object + """ # Verify objects are hashable assert isinstance(hash(repo1), int)