Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions CHANGES
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
1.27.8
-------
- Return None instead of raising when fetching a deleted analysis (410 Gone) by id, matching the documented from_analysis_id contract

1.27.7
-------
- Include the server's error message in the HTTPError raised by raise_for_status for all error statuses
Expand Down
2 changes: 1 addition & 1 deletion intezer_sdk/__init__.py
Original file line number Diff line number Diff line change
@@ -1 +1 @@
__version__ = '1.27.7'
__version__ = '1.27.8'
3 changes: 2 additions & 1 deletion intezer_sdk/_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -911,7 +911,8 @@ def get_case_ttps(self, case_id: str) -> dict:

@staticmethod
def _assert_result_response(ignore_not_found: bool, response: Response):
statuses_to_ignore = [HTTPStatus.NOT_FOUND] if ignore_not_found else None
# A deleted, expired or deprecated analysis is returned as GONE, which callers treat as a missing analysis
statuses_to_ignore = [HTTPStatus.NOT_FOUND, HTTPStatus.GONE] if ignore_not_found else None
raise_for_status(response, statuses_to_ignore=statuses_to_ignore)

@staticmethod
Expand Down
2 changes: 1 addition & 1 deletion intezer_sdk/base_analysis.py
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,7 @@ def _assert_analysis_finished(self):

@classmethod
def _create_analysis_from_response(cls, response: Response, api: IntezerApiClient, analysis_id: str):
if response.status_code == HTTPStatus.NOT_FOUND:
if response.status_code in (HTTPStatus.NOT_FOUND, HTTPStatus.GONE):
return None

response_json = response.json()
Expand Down
18 changes: 10 additions & 8 deletions tests/unit/test_endpoint_analysis.py
Original file line number Diff line number Diff line change
Expand Up @@ -93,18 +93,20 @@ def test_analysis_failed(self):
with self.assertRaises(errors.AnalysisFailedError):
EndpointAnalysis.from_analysis_id(analysis_id)

def test_analysis_not_found(self):
# Arrange
def test_analysis_missing_or_deleted(self):
analysis_id = str(uuid.uuid4())

with responses.RequestsMock() as mock:
mock.add('GET', url=f'{self.full_url}/endpoint-analyses/{analysis_id}', status=HTTPStatus.NOT_FOUND)
for status in (HTTPStatus.NOT_FOUND, HTTPStatus.GONE):
with self.subTest(status=status):
# Arrange
with responses.RequestsMock() as mock:
mock.add('GET', url=f'{self.full_url}/endpoint-analyses/{analysis_id}', status=status)

# Act
analysis = EndpointAnalysis.from_analysis_id(analysis_id)
# Act
analysis = EndpointAnalysis.from_analysis_id(analysis_id)

# Assert
self.assertIsNone(analysis)
# Assert
self.assertIsNone(analysis)

def test_get_sub_analyses(self):
# Arrange
Expand Down
27 changes: 27 additions & 0 deletions tests/unit/test_file_analysis.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@

from intezer_sdk import consts
from intezer_sdk import errors
from intezer_sdk._api import IntezerApi
from intezer_sdk.analysis import FileAnalysis
from intezer_sdk.api import get_global_api
from intezer_sdk.consts import OnPremiseVersion
Expand Down Expand Up @@ -1101,6 +1102,32 @@ def test_get_analysis_by_id_in_progress(self):
self.assertEqual(consts.AnalysisStatusCode.IN_PROGRESS, analysis.status)
self.assertEqual(analysis_id, analysis.analysis_id)

def test_get_analysis_by_id_returns_none_when_analysis_is_missing_or_deleted(self):
analysis_id = 'analysis_id'

for status in (HTTPStatus.NOT_FOUND, HTTPStatus.GONE):
with self.subTest(status=status):
# Arrange
with responses.RequestsMock() as mock:
mock.add('GET', url=f'{self.full_url}/analyses/{analysis_id}', status=status)

# Act
analysis = FileAnalysis.from_analysis_id(analysis_id)

# Assert
self.assertIsNone(analysis)

def test_get_file_analysis_response_raises_when_analysis_is_deleted_and_not_found_is_not_ignored(self):
# Arrange
analysis_id = 'analysis_id'

with responses.RequestsMock() as mock:
mock.add('GET', url=f'{self.full_url}/analyses/{analysis_id}', status=HTTPStatus.GONE)

# Act & Assert
with self.assertRaises(requests.HTTPError):
IntezerApi(get_global_api()).get_file_analysis_response(analysis_id, False)

def test_download_file_path_uses_content_disposition(self):
# Arrange
file_hash = 'hash'
Expand Down
15 changes: 15 additions & 0 deletions tests/unit/test_url_analysis.py
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,21 @@ def test_get_analysis_by_id_raises_when_analysis_failed(self):
with self.assertRaises(errors.AnalysisFailedError):
UrlAnalysis.from_analysis_id(analysis_id)

def test_get_analysis_by_id_returns_none_when_analysis_is_missing_or_deleted(self):
analysis_id = 'analysis_id'

for status in (HTTPStatus.NOT_FOUND, HTTPStatus.GONE):
with self.subTest(status=status):
# Arrange
with responses.RequestsMock() as mock:
mock.add('GET', url=f'{self.full_url}/url/{analysis_id}', status=status)

# Act
analysis = UrlAnalysis.from_analysis_id(analysis_id)

# Assert
self.assertIsNone(analysis)

def test_send_perform_request_and_sets_analysis_status(self):
# Arrange
analysis_id = str(uuid.uuid4())
Expand Down
Loading