Skip to content
Merged
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
42 changes: 26 additions & 16 deletions src/c2pa/c2pa.py
Original file line number Diff line number Diff line change
Expand Up @@ -1344,6 +1344,7 @@ def __init__(self,
"""

self._closed = False
self._initialized = False

self._reader = None
self._own_stream = None
Expand Down Expand Up @@ -1399,6 +1400,8 @@ def __init__(self,
# Store the file to close it later
self._backing_file = file

self._initialized = True

except Exception as e:
if self._own_stream:
self._own_stream.close()
Expand Down Expand Up @@ -1458,6 +1461,8 @@ def __init__(self,
)

self._backing_file = file

self._initialized = True
except Exception as e:
if self._own_stream:
self._own_stream.close()
Expand Down Expand Up @@ -1509,12 +1514,10 @@ def __init__(self,
)
)

self._initialized = True

def __enter__(self):
self._ensure_valid_state()

if not self._reader:
raise C2paError("Invalid Reader when entering context")

return self

def __exit__(self, exc_type, exc_val, exc_tb):
Expand All @@ -1532,10 +1535,12 @@ def _ensure_valid_state(self):
"""Ensure the reader is in a valid state for operations.

Raises:
C2paError: If the reader is closed or invalid
C2paError: If the reader is closed, not initialized, or invalid
"""
if self._closed:
raise C2paError(Reader._ERROR_MESSAGES['closed_error'])
if not self._initialized:
raise C2paError("Reader is not properly initialized")
if not self._reader:
raise C2paError(Reader._ERROR_MESSAGES['closed_error'])

Expand Down Expand Up @@ -1585,6 +1590,9 @@ def _cleanup_resources(self):
finally:
self._backing_file = None

# Reset initialized state after cleanup
self._initialized = False

except Exception:
# Ensure we don't raise exceptions during cleanup
pass
Expand Down Expand Up @@ -2079,6 +2087,7 @@ def __init__(self, manifest_json: Any):
C2paError.Json: If the manifest JSON cannot be serialized
"""
self._closed = False
self._initialized = False
self._builder = None

if not isinstance(manifest_json, str):
Expand Down Expand Up @@ -2108,6 +2117,8 @@ def __init__(self, manifest_json: Any):
)
)

self._initialized = True

@classmethod
def from_json(cls, manifest_json: Any) -> 'Builder':
"""Create a new Builder from a JSON manifest.
Expand Down Expand Up @@ -2150,16 +2161,19 @@ def from_archive(cls, stream: Any) -> 'Builder':
raise C2paError(error)
raise C2paError("Failed to create builder from archive")

builder._initialized = True
return builder

def _ensure_valid_state(self):
"""Ensure the builder is in a valid state for operations.

Raises:
C2paError: If the builder is closed or invalid
C2paError: If the builder is closed, not initialized, or invalid
"""
if self._closed:
raise C2paError(Builder._ERROR_MESSAGES['closed_error'])
if not self._initialized:
raise C2paError("Builder is not properly initialized")
if not self._builder:
raise C2paError(Builder._ERROR_MESSAGES['closed_error'])

Expand Down Expand Up @@ -2187,6 +2201,9 @@ def _cleanup_resources(self):
pass
finally:
self._builder = None

# Reset initialized state after cleanup
self._initialized = False
except Exception:
# Ensure we don't raise exceptions during cleanup
pass
Expand Down Expand Up @@ -2219,10 +2236,6 @@ def close(self):

def __enter__(self):
self._ensure_valid_state()

if not self._builder:
raise C2paError("Invalid Builder when entering context")

return self

def __exit__(self, exc_type, exc_val, exc_tb):
Expand Down Expand Up @@ -2327,8 +2340,7 @@ def add_ingredient_from_stream(
C2paError.Encoding: If the ingredient JSON or format
contains invalid UTF-8 characters
"""
if not self._builder:
raise C2paError(Builder._ERROR_MESSAGES['closed_error'])
self._ensure_valid_state()

try:
ingredient_str = ingredient_json.encode('utf-8')
Expand Down Expand Up @@ -2413,8 +2425,7 @@ def to_archive(self, stream: Any) -> None:
Raises:
C2paError: If there was an error writing the archive
"""
if not self._builder:
raise C2paError(Builder._ERROR_MESSAGES['closed_error'])
self._ensure_valid_state()

with Stream(stream) as stream_obj:
result = _lib.c2pa_builder_to_archive(
Expand Down Expand Up @@ -2452,8 +2463,7 @@ def _sign_internal(
Raises:
C2paError: If there was an error during signing
"""
if not self._builder:
raise C2paError(Builder._ERROR_MESSAGES['closed_error'])
self._ensure_valid_state()

# Validate signer pointer before use
if not signer or not hasattr(signer, '_signer') or not signer._signer:
Expand Down
Loading