Skip to content

Commit 0d369fa

Browse files
authored
fix: Builder and Reader initialized checks (#155)
* fix: Builder state * fix: reader state * fix: Clean up states * fix: Comment clean up
1 parent 5aae02c commit 0d369fa

File tree

1 file changed

+26
-16
lines changed

1 file changed

+26
-16
lines changed

src/c2pa/c2pa.py

Lines changed: 26 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1344,6 +1344,7 @@ def __init__(self,
13441344
"""
13451345

13461346
self._closed = False
1347+
self._initialized = False
13471348

13481349
self._reader = None
13491350
self._own_stream = None
@@ -1399,6 +1400,8 @@ def __init__(self,
13991400
# Store the file to close it later
14001401
self._backing_file = file
14011402

1403+
self._initialized = True
1404+
14021405
except Exception as e:
14031406
if self._own_stream:
14041407
self._own_stream.close()
@@ -1458,6 +1461,8 @@ def __init__(self,
14581461
)
14591462

14601463
self._backing_file = file
1464+
1465+
self._initialized = True
14611466
except Exception as e:
14621467
if self._own_stream:
14631468
self._own_stream.close()
@@ -1509,12 +1514,10 @@ def __init__(self,
15091514
)
15101515
)
15111516

1517+
self._initialized = True
1518+
15121519
def __enter__(self):
15131520
self._ensure_valid_state()
1514-
1515-
if not self._reader:
1516-
raise C2paError("Invalid Reader when entering context")
1517-
15181521
return self
15191522

15201523
def __exit__(self, exc_type, exc_val, exc_tb):
@@ -1532,10 +1535,12 @@ def _ensure_valid_state(self):
15321535
"""Ensure the reader is in a valid state for operations.
15331536
15341537
Raises:
1535-
C2paError: If the reader is closed or invalid
1538+
C2paError: If the reader is closed, not initialized, or invalid
15361539
"""
15371540
if self._closed:
15381541
raise C2paError(Reader._ERROR_MESSAGES['closed_error'])
1542+
if not self._initialized:
1543+
raise C2paError("Reader is not properly initialized")
15391544
if not self._reader:
15401545
raise C2paError(Reader._ERROR_MESSAGES['closed_error'])
15411546

@@ -1585,6 +1590,9 @@ def _cleanup_resources(self):
15851590
finally:
15861591
self._backing_file = None
15871592

1593+
# Reset initialized state after cleanup
1594+
self._initialized = False
1595+
15881596
except Exception:
15891597
# Ensure we don't raise exceptions during cleanup
15901598
pass
@@ -2079,6 +2087,7 @@ def __init__(self, manifest_json: Any):
20792087
C2paError.Json: If the manifest JSON cannot be serialized
20802088
"""
20812089
self._closed = False
2090+
self._initialized = False
20822091
self._builder = None
20832092

20842093
if not isinstance(manifest_json, str):
@@ -2108,6 +2117,8 @@ def __init__(self, manifest_json: Any):
21082117
)
21092118
)
21102119

2120+
self._initialized = True
2121+
21112122
@classmethod
21122123
def from_json(cls, manifest_json: Any) -> 'Builder':
21132124
"""Create a new Builder from a JSON manifest.
@@ -2150,16 +2161,19 @@ def from_archive(cls, stream: Any) -> 'Builder':
21502161
raise C2paError(error)
21512162
raise C2paError("Failed to create builder from archive")
21522163

2164+
builder._initialized = True
21532165
return builder
21542166

21552167
def _ensure_valid_state(self):
21562168
"""Ensure the builder is in a valid state for operations.
21572169
21582170
Raises:
2159-
C2paError: If the builder is closed or invalid
2171+
C2paError: If the builder is closed, not initialized, or invalid
21602172
"""
21612173
if self._closed:
21622174
raise C2paError(Builder._ERROR_MESSAGES['closed_error'])
2175+
if not self._initialized:
2176+
raise C2paError("Builder is not properly initialized")
21632177
if not self._builder:
21642178
raise C2paError(Builder._ERROR_MESSAGES['closed_error'])
21652179

@@ -2187,6 +2201,9 @@ def _cleanup_resources(self):
21872201
pass
21882202
finally:
21892203
self._builder = None
2204+
2205+
# Reset initialized state after cleanup
2206+
self._initialized = False
21902207
except Exception:
21912208
# Ensure we don't raise exceptions during cleanup
21922209
pass
@@ -2219,10 +2236,6 @@ def close(self):
22192236

22202237
def __enter__(self):
22212238
self._ensure_valid_state()
2222-
2223-
if not self._builder:
2224-
raise C2paError("Invalid Builder when entering context")
2225-
22262239
return self
22272240

22282241
def __exit__(self, exc_type, exc_val, exc_tb):
@@ -2327,8 +2340,7 @@ def add_ingredient_from_stream(
23272340
C2paError.Encoding: If the ingredient JSON or format
23282341
contains invalid UTF-8 characters
23292342
"""
2330-
if not self._builder:
2331-
raise C2paError(Builder._ERROR_MESSAGES['closed_error'])
2343+
self._ensure_valid_state()
23322344

23332345
try:
23342346
ingredient_str = ingredient_json.encode('utf-8')
@@ -2413,8 +2425,7 @@ def to_archive(self, stream: Any) -> None:
24132425
Raises:
24142426
C2paError: If there was an error writing the archive
24152427
"""
2416-
if not self._builder:
2417-
raise C2paError(Builder._ERROR_MESSAGES['closed_error'])
2428+
self._ensure_valid_state()
24182429

24192430
with Stream(stream) as stream_obj:
24202431
result = _lib.c2pa_builder_to_archive(
@@ -2452,8 +2463,7 @@ def _sign_internal(
24522463
Raises:
24532464
C2paError: If there was an error during signing
24542465
"""
2455-
if not self._builder:
2456-
raise C2paError(Builder._ERROR_MESSAGES['closed_error'])
2466+
self._ensure_valid_state()
24572467

24582468
# Validate signer pointer before use
24592469
if not signer or not hasattr(signer, '_signer') or not signer._signer:

0 commit comments

Comments
 (0)