Skip to content

Commit ae04e35

Browse files
committed
fix: None
1 parent fddc183 commit ae04e35

File tree

2 files changed

+62
-10
lines changed

2 files changed

+62
-10
lines changed

src/c2pa/c2pa.py

Lines changed: 47 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1264,7 +1264,9 @@ class Reader:
12641264
'file_error': "Error cleaning up file: {}",
12651265
'reader_cleanup_error': "Error cleaning up reader: {}",
12661266
'encoding_error': "Invalid UTF-8 characters in input: {}",
1267-
'closed_error': "Reader is closed"
1267+
'closed_error': "Reader is closed",
1268+
'not_initialized_error': "Reader is not properly initialized",
1269+
'no_manifest_error': "No manifest store to read"
12681270
}
12691271

12701272
@classmethod
@@ -1350,6 +1352,7 @@ def __init__(self,
13501352

13511353
self._closed = False
13521354
self._initialized = False
1355+
self._no_manifest_to_read = False
13531356

13541357
self._reader = None
13551358
self._own_stream = None
@@ -1397,6 +1400,12 @@ def __init__(self,
13971400
error = _parse_operation_result_for_error(
13981401
_lib.c2pa_error())
13991402
if error:
1403+
# Check if this is a ManifestNotFound error
1404+
if error.startswith("ManifestNotFound"):
1405+
# Set reader to no manifest state
1406+
self._no_manifest_to_read = True
1407+
self._initialized = True
1408+
return
14001409
raise C2paError(error)
14011410
raise C2paError(
14021411
Reader._ERROR_MESSAGES['reader_error'].format(
@@ -1460,6 +1469,12 @@ def __init__(self,
14601469
error = _parse_operation_result_for_error(
14611470
_lib.c2pa_error())
14621471
if error:
1472+
# Check if this is a ManifestNotFound error
1473+
if error.startswith("ManifestNotFound"):
1474+
# Set reader to no manifest state
1475+
self._no_manifest_to_read = True
1476+
self._initialized = True
1477+
return
14631478
raise C2paError(error)
14641479
raise C2paError(
14651480
Reader._ERROR_MESSAGES['reader_error'].format(
@@ -1514,6 +1529,12 @@ def __init__(self,
15141529
error = _parse_operation_result_for_error(
15151530
_lib.c2pa_error())
15161531
if error:
1532+
# Check if this is a ManifestNotFound error
1533+
if error.startswith("ManifestNotFound"):
1534+
# Set reader to no manifest state
1535+
self._no_manifest_to_read = True
1536+
self._initialized = True
1537+
return
15171538
raise C2paError(error)
15181539
raise C2paError(
15191540
Reader._ERROR_MESSAGES['reader_error'].format(
@@ -1542,12 +1563,15 @@ def _ensure_valid_state(self):
15421563
"""Ensure the reader is in a valid state for operations.
15431564
15441565
Raises:
1545-
C2paError: If the reader is closed, not initialized, or invalid
1566+
C2paError: If the reader is closed, not initialized, invalid, or
1567+
has no manifest to read
15461568
"""
15471569
if self._closed:
15481570
raise C2paError(Reader._ERROR_MESSAGES['closed_error'])
15491571
if not self._initialized:
1550-
raise C2paError("Reader is not properly initialized")
1572+
raise C2paError(Reader._ERROR_MESSAGES['not_initialized_error'])
1573+
if self._no_manifest_to_read:
1574+
raise C2paError(Reader._ERROR_MESSAGES['no_manifest_error'])
15511575
if not self._reader:
15521576
raise C2paError(Reader._ERROR_MESSAGES['closed_error'])
15531577

@@ -1609,14 +1633,19 @@ def _get_cached_manifest_data(self) -> Optional[dict]:
16091633
16101634
Returns:
16111635
A dictionary containing the parsed manifest data, or None if
1612-
JSON parsing fails
1636+
JSON parsing fails or reader has no manifest to read
16131637
16141638
Raises:
16151639
C2paError: If there was an error getting the JSON
16161640
"""
1641+
if self._no_manifest_to_read:
1642+
return None
16171643
if self._manifest_data_cache is None:
16181644
if self._manifest_json_str_cache is None:
1619-
self._manifest_json_str_cache = self.json()
1645+
manifest_json = self.json()
1646+
if manifest_json is None:
1647+
return None
1648+
self._manifest_json_str_cache = manifest_json
16201649

16211650
try:
16221651
self._manifest_data_cache = json.loads(
@@ -1656,15 +1685,20 @@ def close(self):
16561685
self._manifest_data_cache = None
16571686
self._closed = True
16581687

1659-
def json(self) -> str:
1688+
def json(self) -> Optional[str]:
16601689
"""Get the manifest store as a JSON string.
16611690
16621691
Returns:
1663-
The manifest store as a JSON string
1692+
The manifest store as a JSON string, or None if no manifest is
1693+
found
16641694
16651695
Raises:
1666-
C2paError: If there was an error getting the JSON
1696+
C2paError: If there was an error getting the JSON (other than
1697+
ManifestNotFound)
16671698
"""
1699+
# Check if reader is in no-manifest state first
1700+
if self._no_manifest_to_read:
1701+
return None
16681702

16691703
self._ensure_valid_state()
16701704

@@ -1677,6 +1711,11 @@ def json(self) -> str:
16771711
if result is None:
16781712
error = _parse_operation_result_for_error(_lib.c2pa_error())
16791713
if error:
1714+
# Check if this is a ManifestNotFound error
1715+
if error.startswith("ManifestNotFound"):
1716+
# Set reader to no manifest state and return None
1717+
self._no_manifest_to_read = True
1718+
return None
16801719
raise C2paError(error)
16811720
raise C2paError("Error during manifest parsing in Reader")
16821721

tests/test_unit_tests.py

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,18 @@ def test_stream_read(self):
6464
json_data = reader.json()
6565
self.assertIn(DEFAULT_TEST_FILE_NAME, json_data)
6666

67+
def test_stream_read_no_manifest(self):
68+
# INGREDIENT_TEST_FILE does not have a manifest
69+
with open(INGREDIENT_TEST_FILE, "rb") as file:
70+
reader = Reader("image/jpeg", file)
71+
# Reader should be created but in no-manifest state
72+
self.assertIsNotNone(reader)
73+
# Check that json() raises appropriate error for no-manifest files
74+
self.assertIsNone(reader.json())
75+
76+
# Check that get_active_manifest() returns None for no-manifest files
77+
self.assertIsNone(reader.get_active_manifest())
78+
6779
def test_get_active_manifest(self):
6880
with open(self.testPath, "rb") as file:
6981
reader = Reader("image/jpeg", file)
@@ -475,6 +487,7 @@ def test_reader_partial_initialization_states(self):
475487
reader._reader = None
476488
reader._own_stream = None
477489
reader._backing_file = None
490+
reader._no_manifest_to_read = False
478491

479492
with self.assertRaises(Error):
480493
reader._ensure_valid_state()
@@ -1169,8 +1182,8 @@ def test_remote_sign(self):
11691182
output.seek(0)
11701183
# When set_no_embed() is used, no manifest should be embedded in the file
11711184
# So reading from the file should fail
1172-
with self.assertRaises(Error):
1173-
Reader("image/jpeg", output)
1185+
reader = Reader("image/jpeg", output)
1186+
self.assertIsNone(reader.json())
11741187
output.close()
11751188

11761189
def test_remote_sign_using_returned_bytes(self):

0 commit comments

Comments
 (0)