c2pa-python 0.35.1__tar.gz → 0.35.2__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (22) hide show
  1. {c2pa_python-0.35.1/src/c2pa_python.egg-info → c2pa_python-0.35.2}/PKG-INFO +1 -1
  2. {c2pa_python-0.35.1 → c2pa_python-0.35.2}/pyproject.toml +1 -1
  3. {c2pa_python-0.35.1 → c2pa_python-0.35.2}/src/c2pa/c2pa.py +6 -6
  4. {c2pa_python-0.35.1 → c2pa_python-0.35.2/src/c2pa_python.egg-info}/PKG-INFO +1 -1
  5. {c2pa_python-0.35.1 → c2pa_python-0.35.2}/tests/test_unit_tests.py +113 -0
  6. {c2pa_python-0.35.1 → c2pa_python-0.35.2}/LICENSE-APACHE +0 -0
  7. {c2pa_python-0.35.1 → c2pa_python-0.35.2}/LICENSE-MIT +0 -0
  8. {c2pa_python-0.35.1 → c2pa_python-0.35.2}/MANIFEST.in +0 -0
  9. {c2pa_python-0.35.1 → c2pa_python-0.35.2}/README.md +0 -0
  10. {c2pa_python-0.35.1 → c2pa_python-0.35.2}/requirements.txt +0 -0
  11. {c2pa_python-0.35.1 → c2pa_python-0.35.2}/scripts/download_artifacts.py +0 -0
  12. {c2pa_python-0.35.1 → c2pa_python-0.35.2}/setup.cfg +0 -0
  13. {c2pa_python-0.35.1 → c2pa_python-0.35.2}/setup.py +0 -0
  14. {c2pa_python-0.35.1 → c2pa_python-0.35.2}/src/c2pa/__init__.py +0 -0
  15. {c2pa_python-0.35.1 → c2pa_python-0.35.2}/src/c2pa/build.py +0 -0
  16. {c2pa_python-0.35.1 → c2pa_python-0.35.2}/src/c2pa/lib.py +0 -0
  17. {c2pa_python-0.35.1 → c2pa_python-0.35.2}/src/c2pa_python.egg-info/SOURCES.txt +0 -0
  18. {c2pa_python-0.35.1 → c2pa_python-0.35.2}/src/c2pa_python.egg-info/dependency_links.txt +0 -0
  19. {c2pa_python-0.35.1 → c2pa_python-0.35.2}/src/c2pa_python.egg-info/entry_points.txt +0 -0
  20. {c2pa_python-0.35.1 → c2pa_python-0.35.2}/src/c2pa_python.egg-info/requires.txt +0 -0
  21. {c2pa_python-0.35.1 → c2pa_python-0.35.2}/src/c2pa_python.egg-info/top_level.txt +0 -0
  22. {c2pa_python-0.35.1 → c2pa_python-0.35.2}/tests/test_unit_tests_threaded.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: c2pa-python
3
- Version: 0.35.1
3
+ Version: 0.35.2
4
4
  Summary: Python bindings for the C2PA Content Authenticity Initiative (CAI) library
5
5
  Author-email: Gavin Peacock <gvnpeacock@adobe.com>, Tania Mathern <mathern@adobe.com>
6
6
  Maintainer-email: Gavin Peacock <gpeacock@adobe.com>, Tania Mathern <mathern@adobe.com>
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "c2pa-python"
7
- version = "0.35.1"
7
+ version = "0.35.2"
8
8
  requires-python = ">=3.10"
9
9
  description = "Python bindings for the C2PA Content Authenticity Initiative (CAI) library"
10
10
  readme = { file = "README.md", content-type = "text/markdown" }
@@ -2263,6 +2263,9 @@ class Reader(ManagedResource):
2263
2263
  if not context.is_valid:
2264
2264
  raise C2paError("Context is not valid")
2265
2265
 
2266
+ if manifest_data is not None and not isinstance(manifest_data, bytes):
2267
+ raise TypeError(Reader._ERROR_MESSAGES['manifest_error'])
2268
+
2266
2269
  # Determine format and open stream
2267
2270
  supported = Reader.get_supported_mime_types()
2268
2271
 
@@ -2303,10 +2306,6 @@ class Reader(ManagedResource):
2303
2306
  raise
2304
2307
 
2305
2308
  if manifest_data is not None:
2306
- if not isinstance(manifest_data, bytes):
2307
- raise TypeError(
2308
- Reader._ERROR_MESSAGES[
2309
- 'manifest_error'])
2310
2309
  manifest_array = (
2311
2310
  ctypes.c_ubyte *
2312
2311
  len(manifest_data)).from_buffer_copy(manifest_data)
@@ -2322,14 +2321,15 @@ class Reader(ManagedResource):
2322
2321
  len(manifest_data),
2323
2322
  )
2324
2323
  )
2325
- # reader_ptr has been invalidated(consumed)
2326
2324
  else:
2327
2325
  # Consume reader with stream
2328
2326
  new_ptr = _lib.c2pa_reader_with_stream(
2329
2327
  reader_ptr, format_bytes,
2330
2328
  self._own_stream._stream,
2331
2329
  )
2332
- # reader_ptr has been invalidated(consumed)
2330
+
2331
+ # reader_ptr has been consumed by the FFI call.
2332
+ reader_ptr = None
2333
2333
 
2334
2334
  self._handle = new_ptr
2335
2335
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: c2pa-python
3
- Version: 0.35.1
3
+ Version: 0.35.2
4
4
  Summary: Python bindings for the C2PA Content Authenticity Initiative (CAI) library
5
5
  Author-email: Gavin Peacock <gvnpeacock@adobe.com>, Tania Mathern <mathern@adobe.com>
6
6
  Maintainer-email: Gavin Peacock <gpeacock@adobe.com>, Tania Mathern <mathern@adobe.com>
@@ -6041,6 +6041,119 @@ class TestReaderWithContext(TestContextAPIs):
6041
6041
  context.close()
6042
6042
 
6043
6043
 
6044
+ class TestSidecarReader(TestContextAPIs):
6045
+ """Reader over a detached (sidecar) manifest with a Context"""
6046
+
6047
+ def _make_detached_manifest(self):
6048
+ """Sign DEFAULT_TEST_FILE with no-embed, return (asset_bytes,
6049
+ manifest_bytes) where manifest_bytes is the "detached" sidecar
6050
+ C2PA manifest."""
6051
+
6052
+ signer = self._ctx_make_signer()
6053
+ with open(DEFAULT_TEST_FILE, "rb") as f:
6054
+ asset_bytes = f.read()
6055
+ builder = Builder(self.test_manifest)
6056
+ builder.set_no_embed()
6057
+ # Output is discarded: with no-embed the asset is unchanged and the
6058
+ # manifest is returned by sign().
6059
+ manifest_bytes = builder.sign(
6060
+ signer, "image/jpeg", io.BytesIO(asset_bytes), io.BytesIO())
6061
+ builder.close()
6062
+ signer.close()
6063
+ self.assertIsInstance(manifest_bytes, bytes)
6064
+ self.assertGreater(len(manifest_bytes), 0)
6065
+ return asset_bytes, manifest_bytes
6066
+
6067
+ def test_reader_with_manifest_data_and_context(self):
6068
+ asset_bytes, manifest_bytes = self._make_detached_manifest()
6069
+ context = Context()
6070
+ reader = Reader(
6071
+ "image/jpeg",
6072
+ io.BytesIO(asset_bytes),
6073
+ manifest_bytes,
6074
+ context=context,
6075
+ )
6076
+ try:
6077
+ data = reader.json()
6078
+ self.assertTrue(data)
6079
+ self.assertFalse(reader.is_embedded())
6080
+ self.assertIn("manifests", json.loads(data))
6081
+ finally:
6082
+ reader.close()
6083
+ context.close()
6084
+
6085
+ def test_reader_manifest_data_context_invalid_manifest_raises(self):
6086
+ with open(DEFAULT_TEST_FILE, "rb") as f:
6087
+ asset_bytes = f.read()
6088
+ context = Context()
6089
+ reader = None
6090
+ try:
6091
+ with self.assertRaises(Error):
6092
+ reader = Reader(
6093
+ "image/jpeg",
6094
+ io.BytesIO(asset_bytes),
6095
+ b"not a real manifest",
6096
+ context=context,
6097
+ )
6098
+ # The consumed-pointer error branch must leave no usable handle.
6099
+ if reader is not None:
6100
+ self.assertEqual(
6101
+ reader._lifecycle_state, LifecycleState.CLOSED)
6102
+ self.assertIsNone(reader._handle)
6103
+ finally:
6104
+ if reader is not None:
6105
+ reader.close()
6106
+ context.close()
6107
+
6108
+ def test_reader_manifest_data_context_wrong_type_raises(self):
6109
+ with open(DEFAULT_TEST_FILE, "rb") as f:
6110
+ asset_bytes = f.read()
6111
+ context = Context()
6112
+ try:
6113
+ # Non-bytes manifest_data must raise TypeError before any native
6114
+ # reader handle is allocated (no leak on this path).
6115
+ with self.assertRaises(TypeError):
6116
+ Reader(
6117
+ "image/jpeg",
6118
+ io.BytesIO(asset_bytes),
6119
+ "manifest as str, not bytes",
6120
+ context=context,
6121
+ )
6122
+ finally:
6123
+ context.close()
6124
+
6125
+ def test_reader_manifest_data_context_use_after_close_raises(self):
6126
+ asset_bytes, manifest_bytes = self._make_detached_manifest()
6127
+ context = Context()
6128
+ reader = Reader(
6129
+ "image/jpeg",
6130
+ io.BytesIO(asset_bytes),
6131
+ manifest_bytes,
6132
+ context=context,
6133
+ )
6134
+ reader.close()
6135
+ self.assertEqual(reader._lifecycle_state, LifecycleState.CLOSED)
6136
+ with self.assertRaises(Error):
6137
+ reader.json()
6138
+ # Idempotent close after use-after-close attempt.
6139
+ reader.close()
6140
+ context.close()
6141
+
6142
+ def test_reader_manifest_data_context_as_context_manager(self):
6143
+ asset_bytes, manifest_bytes = self._make_detached_manifest()
6144
+ context = Context()
6145
+ with Reader(
6146
+ "image/jpeg",
6147
+ io.BytesIO(asset_bytes),
6148
+ manifest_bytes,
6149
+ context=context,
6150
+ ) as reader:
6151
+ self.assertEqual(reader._lifecycle_state, LifecycleState.ACTIVE)
6152
+ self.assertTrue(reader.json())
6153
+ self.assertEqual(reader._lifecycle_state, LifecycleState.CLOSED)
6154
+ context.close()
6155
+
6156
+
6044
6157
  class TestBuilderWithContext(TestContextAPIs):
6045
6158
 
6046
6159
  def test_contextual_builder_with_default_context(self):
File without changes
File without changes
File without changes
File without changes
File without changes