mirror of
https://github.com/josegonzalez/python-github-backup.git
synced 2025-12-05 08:08:02 +01:00
Log a warning and the link to the DMCA notice. Continue backing up other repositories instead of crashing. Closes #163
144 lines
5.6 KiB
Python
144 lines
5.6 KiB
Python
"""Tests for HTTP 451 (DMCA takedown) handling."""
|
|
|
|
import json
|
|
from unittest.mock import Mock, patch
|
|
|
|
import pytest
|
|
|
|
from github_backup import github_backup
|
|
|
|
|
|
class TestHTTP451Exception:
|
|
"""Test suite for HTTP 451 DMCA takedown exception handling."""
|
|
|
|
def test_repository_unavailable_error_raised(self):
|
|
"""HTTP 451 should raise RepositoryUnavailableError with DMCA URL."""
|
|
# Create mock args
|
|
args = Mock()
|
|
args.as_app = False
|
|
args.token_fine = None
|
|
args.token_classic = None
|
|
args.username = None
|
|
args.password = None
|
|
args.osx_keychain_item_name = None
|
|
args.osx_keychain_item_account = None
|
|
args.throttle_limit = None
|
|
args.throttle_pause = 0
|
|
|
|
# Mock HTTPError 451 response
|
|
mock_response = Mock()
|
|
mock_response.getcode.return_value = 451
|
|
|
|
dmca_data = {
|
|
"message": "Repository access blocked",
|
|
"block": {
|
|
"reason": "dmca",
|
|
"created_at": "2024-11-12T14:38:04Z",
|
|
"html_url": "https://github.com/github/dmca/blob/master/2024/11/2024-11-04-source-code.md"
|
|
}
|
|
}
|
|
mock_response.read.return_value = json.dumps(dmca_data).encode("utf-8")
|
|
mock_response.headers = {"x-ratelimit-remaining": "5000"}
|
|
mock_response.reason = "Unavailable For Legal Reasons"
|
|
|
|
def mock_get_response(request, auth, template):
|
|
return mock_response, []
|
|
|
|
with patch("github_backup.github_backup._get_response", side_effect=mock_get_response):
|
|
with pytest.raises(github_backup.RepositoryUnavailableError) as exc_info:
|
|
list(github_backup.retrieve_data_gen(args, "https://api.github.com/repos/test/dmca/issues"))
|
|
|
|
# Check exception has DMCA URL
|
|
assert exc_info.value.dmca_url == "https://github.com/github/dmca/blob/master/2024/11/2024-11-04-source-code.md"
|
|
assert "451" in str(exc_info.value)
|
|
|
|
def test_repository_unavailable_error_without_dmca_url(self):
|
|
"""HTTP 451 without DMCA details should still raise exception."""
|
|
args = Mock()
|
|
args.as_app = False
|
|
args.token_fine = None
|
|
args.token_classic = None
|
|
args.username = None
|
|
args.password = None
|
|
args.osx_keychain_item_name = None
|
|
args.osx_keychain_item_account = None
|
|
args.throttle_limit = None
|
|
args.throttle_pause = 0
|
|
|
|
mock_response = Mock()
|
|
mock_response.getcode.return_value = 451
|
|
mock_response.read.return_value = b'{"message": "Blocked"}'
|
|
mock_response.headers = {"x-ratelimit-remaining": "5000"}
|
|
mock_response.reason = "Unavailable For Legal Reasons"
|
|
|
|
def mock_get_response(request, auth, template):
|
|
return mock_response, []
|
|
|
|
with patch("github_backup.github_backup._get_response", side_effect=mock_get_response):
|
|
with pytest.raises(github_backup.RepositoryUnavailableError) as exc_info:
|
|
list(github_backup.retrieve_data_gen(args, "https://api.github.com/repos/test/dmca/issues"))
|
|
|
|
# Exception raised even without DMCA URL
|
|
assert exc_info.value.dmca_url is None
|
|
assert "451" in str(exc_info.value)
|
|
|
|
def test_repository_unavailable_error_with_malformed_json(self):
|
|
"""HTTP 451 with malformed JSON should still raise exception."""
|
|
args = Mock()
|
|
args.as_app = False
|
|
args.token_fine = None
|
|
args.token_classic = None
|
|
args.username = None
|
|
args.password = None
|
|
args.osx_keychain_item_name = None
|
|
args.osx_keychain_item_account = None
|
|
args.throttle_limit = None
|
|
args.throttle_pause = 0
|
|
|
|
mock_response = Mock()
|
|
mock_response.getcode.return_value = 451
|
|
mock_response.read.return_value = b"invalid json {"
|
|
mock_response.headers = {"x-ratelimit-remaining": "5000"}
|
|
mock_response.reason = "Unavailable For Legal Reasons"
|
|
|
|
def mock_get_response(request, auth, template):
|
|
return mock_response, []
|
|
|
|
with patch("github_backup.github_backup._get_response", side_effect=mock_get_response):
|
|
with pytest.raises(github_backup.RepositoryUnavailableError):
|
|
list(github_backup.retrieve_data_gen(args, "https://api.github.com/repos/test/dmca/issues"))
|
|
|
|
def test_other_http_errors_unchanged(self):
|
|
"""Other HTTP errors should still raise generic Exception."""
|
|
args = Mock()
|
|
args.as_app = False
|
|
args.token_fine = None
|
|
args.token_classic = None
|
|
args.username = None
|
|
args.password = None
|
|
args.osx_keychain_item_name = None
|
|
args.osx_keychain_item_account = None
|
|
args.throttle_limit = None
|
|
args.throttle_pause = 0
|
|
|
|
mock_response = Mock()
|
|
mock_response.getcode.return_value = 404
|
|
mock_response.read.return_value = b'{"message": "Not Found"}'
|
|
mock_response.headers = {"x-ratelimit-remaining": "5000"}
|
|
mock_response.reason = "Not Found"
|
|
|
|
def mock_get_response(request, auth, template):
|
|
return mock_response, []
|
|
|
|
with patch("github_backup.github_backup._get_response", side_effect=mock_get_response):
|
|
# Should raise generic Exception, not RepositoryUnavailableError
|
|
with pytest.raises(Exception) as exc_info:
|
|
list(github_backup.retrieve_data_gen(args, "https://api.github.com/repos/test/notfound/issues"))
|
|
|
|
assert not isinstance(exc_info.value, github_backup.RepositoryUnavailableError)
|
|
assert "404" in str(exc_info.value)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
pytest.main([__file__, "-v"])
|