c2pa-python 0.15.0__tar.gz → 0.17.0__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 (23) hide show
  1. {c2pa_python-0.15.0/src/c2pa_python.egg-info → c2pa_python-0.17.0}/PKG-INFO +1 -1
  2. {c2pa_python-0.15.0 → c2pa_python-0.17.0}/pyproject.toml +1 -1
  3. {c2pa_python-0.15.0 → c2pa_python-0.17.0}/requirements.txt +1 -1
  4. {c2pa_python-0.15.0 → c2pa_python-0.17.0}/scripts/download_artifacts.py +14 -0
  5. {c2pa_python-0.15.0 → c2pa_python-0.17.0}/setup.py +13 -0
  6. c2pa_python-0.17.0/src/c2pa/__init__.py +43 -0
  7. {c2pa_python-0.15.0 → c2pa_python-0.17.0}/src/c2pa/build.py +13 -0
  8. {c2pa_python-0.15.0 → c2pa_python-0.17.0}/src/c2pa/c2pa.py +51 -12
  9. {c2pa_python-0.15.0 → c2pa_python-0.17.0/src/c2pa_python.egg-info}/PKG-INFO +1 -1
  10. {c2pa_python-0.15.0 → c2pa_python-0.17.0}/tests/test_unit_tests.py +18 -4
  11. {c2pa_python-0.15.0 → c2pa_python-0.17.0}/tests/test_unit_tests_threaded.py +1 -1
  12. c2pa_python-0.15.0/src/c2pa/__init__.py +0 -30
  13. {c2pa_python-0.15.0 → c2pa_python-0.17.0}/LICENSE-APACHE +0 -0
  14. {c2pa_python-0.15.0 → c2pa_python-0.17.0}/LICENSE-MIT +0 -0
  15. {c2pa_python-0.15.0 → c2pa_python-0.17.0}/MANIFEST.in +0 -0
  16. {c2pa_python-0.15.0 → c2pa_python-0.17.0}/README.md +0 -0
  17. {c2pa_python-0.15.0 → c2pa_python-0.17.0}/setup.cfg +0 -0
  18. {c2pa_python-0.15.0 → c2pa_python-0.17.0}/src/c2pa/lib.py +0 -0
  19. {c2pa_python-0.15.0 → c2pa_python-0.17.0}/src/c2pa_python.egg-info/SOURCES.txt +0 -0
  20. {c2pa_python-0.15.0 → c2pa_python-0.17.0}/src/c2pa_python.egg-info/dependency_links.txt +0 -0
  21. {c2pa_python-0.15.0 → c2pa_python-0.17.0}/src/c2pa_python.egg-info/entry_points.txt +0 -0
  22. {c2pa_python-0.15.0 → c2pa_python-0.17.0}/src/c2pa_python.egg-info/requires.txt +0 -0
  23. {c2pa_python-0.15.0 → c2pa_python-0.17.0}/src/c2pa_python.egg-info/top_level.txt +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: c2pa-python
3
- Version: 0.15.0
3
+ Version: 0.17.0
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>
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "c2pa-python"
7
- version = "0.15.0"
7
+ version = "0.17.0"
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" }
@@ -1,2 +1,2 @@
1
1
  # only used in the training example
2
- cryptography>=45.0.3
2
+ cryptography>=45.0.6
@@ -1,4 +1,18 @@
1
1
  #!/usr/bin/env python3
2
+
3
+ # Copyright 2025 Adobe. All rights reserved.
4
+ # This file is licensed to you under the Apache License,
5
+ # Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0)
6
+ # or the MIT license (http://opensource.org/licenses/MIT),
7
+ # at your option.
8
+
9
+ # Unless required by applicable law or agreed to in writing,
10
+ # this software is distributed on an "AS IS" BASIS, WITHOUT
11
+ # WARRANTIES OR REPRESENTATIONS OF ANY KIND, either express or
12
+ # implied. See the LICENSE-MIT and LICENSE-APACHE files for the
13
+ # specific language governing permissions and limitations under
14
+ # each license.
15
+
2
16
  import os
3
17
  import sys
4
18
  import requests
@@ -1,3 +1,16 @@
1
+ # Copyright 2025 Adobe. All rights reserved.
2
+ # This file is licensed to you under the Apache License,
3
+ # Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0)
4
+ # or the MIT license (http://opensource.org/licenses/MIT),
5
+ # at your option.
6
+
7
+ # Unless required by applicable law or agreed to in writing,
8
+ # this software is distributed on an "AS IS" BASIS, WITHOUT
9
+ # WARRANTIES OR REPRESENTATIONS OF ANY KIND, either express or
10
+ # implied. See the LICENSE-MIT and LICENSE-APACHE files for the
11
+ # specific language governing permissions and limitations under
12
+ # each license.
13
+
1
14
  from setuptools import setup, find_namespace_packages
2
15
  import sys
3
16
  import platform
@@ -0,0 +1,43 @@
1
+ # Copyright 2025 Adobe. All rights reserved.
2
+ # This file is licensed to you under the Apache License,
3
+ # Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0)
4
+ # or the MIT license (http://opensource.org/licenses/MIT),
5
+ # at your option.
6
+
7
+ # Unless required by applicable law or agreed to in writing,
8
+ # this software is distributed on an "AS IS" BASIS, WITHOUT
9
+ # WARRANTIES OR REPRESENTATIONS OF ANY KIND, either express or
10
+ # implied. See the LICENSE-MIT and LICENSE-APACHE files for the
11
+ # specific language governing permissions and limitations under
12
+ # each license.
13
+
14
+ try:
15
+ from importlib.metadata import version
16
+ __version__ = version("c2pa-python")
17
+ except ImportError: # pragma: no cover
18
+ __version__ = "unknown"
19
+
20
+ from .c2pa import (
21
+ Builder,
22
+ C2paError,
23
+ Reader,
24
+ C2paSigningAlg,
25
+ C2paSignerInfo,
26
+ Signer,
27
+ Stream,
28
+ sdk_version,
29
+ read_ingredient_file
30
+ ) # NOQA
31
+
32
+ # Re-export C2paError and its subclasses
33
+ __all__ = [
34
+ 'Builder',
35
+ 'C2paError',
36
+ 'Reader',
37
+ 'C2paSigningAlg',
38
+ 'C2paSignerInfo',
39
+ 'Signer',
40
+ 'Stream',
41
+ 'sdk_version',
42
+ 'read_ingredient_file'
43
+ ]
@@ -1,3 +1,16 @@
1
+ # Copyright 2025 Adobe. All rights reserved.
2
+ # This file is licensed to you under the Apache License,
3
+ # Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0)
4
+ # or the MIT license (http://opensource.org/licenses/MIT),
5
+ # at your option.
6
+
7
+ # Unless required by applicable law or agreed to in writing,
8
+ # this software is distributed on an "AS IS" BASIS, WITHOUT
9
+ # WARRANTIES OR REPRESENTATIONS OF ANY KIND, either express or
10
+ # implied. See the LICENSE-MIT and LICENSE-APACHE files for the
11
+ # specific language governing permissions and limitations under
12
+ # each license.
13
+
1
14
  import os
2
15
  import sys
3
16
  import requests
@@ -1,3 +1,16 @@
1
+ # Copyright 2025 Adobe. All rights reserved.
2
+ # This file is licensed to you under the Apache License,
3
+ # Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0)
4
+ # or the MIT license (http://opensource.org/licenses/MIT),
5
+ # at your option.
6
+
7
+ # Unless required by applicable law or agreed to in writing,
8
+ # this software is distributed on an "AS IS" BASIS, WITHOUT
9
+ # WARRANTIES OR REPRESENTATIONS OF ANY KIND, either express or
10
+ # implied. See the LICENSE-MIT and LICENSE-APACHE files for the
11
+ # specific language governing permissions and limitations under
12
+ # each license.
13
+
1
14
  import ctypes
2
15
  import enum
3
16
  import json
@@ -641,6 +654,33 @@ def load_settings(settings: str, format: str = "json") -> None:
641
654
  return result
642
655
 
643
656
 
657
+ def _get_mime_type_from_path(path: Union[str, Path]) -> str:
658
+ """Attempt to guess the MIME type from a file path (with extension).
659
+
660
+ Args:
661
+ path: File path as string or Path object
662
+
663
+ Returns:
664
+ MIME type string
665
+
666
+ Raises:
667
+ C2paError.NotSupported: If MIME type cannot be determined
668
+ """
669
+ path_obj = Path(path)
670
+ file_extension = path_obj.suffix.lower() if path_obj.suffix else ""
671
+
672
+ if file_extension == ".dng":
673
+ # mimetypes guesses the wrong type for dng,
674
+ # so we bypass it and set the correct type
675
+ return "image/dng"
676
+ else:
677
+ mime_type = mimetypes.guess_type(str(path))[0]
678
+ if not mime_type:
679
+ raise C2paError.NotSupported(
680
+ f"Could not determine MIME type for file: {path}")
681
+ return mime_type
682
+
683
+
644
684
  def read_ingredient_file(
645
685
  path: Union[str, Path], data_dir: Union[str, Path]) -> str:
646
686
  """Read a file as C2PA ingredient.
@@ -1201,7 +1241,11 @@ class Reader:
1201
1241
  """Create a new Reader.
1202
1242
 
1203
1243
  Args:
1204
- format_or_path: The format or path to read from
1244
+ format_or_path: The format or path to read from.
1245
+ The stream API (params format and an open stream) is
1246
+ the recommended way to use the Reader. For paths, we
1247
+ will attempt to guess the mimetype of the source
1248
+ file based on the extension.
1205
1249
  stream: Optional stream to read from (Python stream-like object)
1206
1250
  manifest_data: Optional manifest data in bytes
1207
1251
 
@@ -1218,12 +1262,8 @@ class Reader:
1218
1262
  # If we don't get a stream as param:
1219
1263
  # Create a stream from the file path in format_or_path
1220
1264
  path = str(format_or_path)
1221
- mime_type = mimetypes.guess_type(
1222
- path)[0]
1223
1265
 
1224
- if not mime_type:
1225
- raise C2paError.NotSupported(
1226
- f"Could not determine MIME type for file: {path}")
1266
+ mime_type = _get_mime_type_from_path(path)
1227
1267
 
1228
1268
  if mime_type not in Reader.get_supported_mime_types():
1229
1269
  raise C2paError.NotSupported(
@@ -2256,7 +2296,9 @@ class Builder:
2256
2296
  """Sign a file and write the signed data to an output file.
2257
2297
 
2258
2298
  Args:
2259
- source_path: Path to the source file
2299
+ source_path: Path to the source file. We will attempt
2300
+ to guess the mimetype of the source file based on
2301
+ the extension.
2260
2302
  dest_path: Path to write the signed file to
2261
2303
  signer: The signer to use
2262
2304
 
@@ -2266,11 +2308,8 @@ class Builder:
2266
2308
  Raises:
2267
2309
  C2paError: If there was an error during signing
2268
2310
  """
2269
- # Get the MIME type from the file extension
2270
- mime_type = mimetypes.guess_type(str(source_path))[0]
2271
- if not mime_type:
2272
- raise C2paError.NotSupported(
2273
- f"Could not determine MIME type for file: {source_path}")
2311
+
2312
+ mime_type = _get_mime_type_from_path(source_path)
2274
2313
 
2275
2314
  try:
2276
2315
  # Open source file and destination file, then use the sign method
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: c2pa-python
3
- Version: 0.15.0
3
+ Version: 0.17.0
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>
@@ -9,7 +9,7 @@
9
9
  # WARRANTIES OR REPRESENTATIONS OF ANY KIND, either express or
10
10
  # implied. See the LICENSE-MIT and LICENSE-APACHE files for the
11
11
  # specific language governing permissions and limitations under
12
- # each license.import unittest
12
+ # each license.
13
13
 
14
14
  import os
15
15
  import io
@@ -126,9 +126,6 @@ class TestReader(unittest.TestCase):
126
126
  def test_reader_close_cleanup(self):
127
127
  with open(self.testPath, "rb") as file:
128
128
  reader = Reader("image/jpeg", file)
129
- # Store references to internal objects
130
- reader_ref = reader._reader
131
- stream_ref = reader._own_stream
132
129
  # Close the reader
133
130
  reader.close()
134
131
  # Verify all resources are cleaned up
@@ -144,6 +141,23 @@ class TestReader(unittest.TestCase):
144
141
  with self.assertRaises(Error):
145
142
  reader.resource_to_stream("", io.BytesIO(bytearray()))
146
143
 
144
+ def test_read_dng_from_stream(self):
145
+ test_path = os.path.join(self.data_dir, "C.dng")
146
+ with open(test_path, "rb") as file:
147
+ file_content = file.read()
148
+
149
+ with Reader("dng", io.BytesIO(file_content)) as reader:
150
+ # Just run and verify there is no crash
151
+ json.loads(reader.json())
152
+
153
+ def test_read_dng_file_from_path(self):
154
+ test_path = os.path.join(self.data_dir, "C.dng")
155
+
156
+ # Create reader with the file content
157
+ with Reader(test_path) as reader:
158
+ # Just run and verify there is no crash
159
+ json.loads(reader.json())
160
+
147
161
  def test_read_all_files(self):
148
162
  """Test reading C2PA metadata from all files in the fixtures/files-for-reading-tests directory"""
149
163
  reading_dir = os.path.join(self.data_dir, "files-for-reading-tests")
@@ -9,7 +9,7 @@
9
9
  # WARRANTIES OR REPRESENTATIONS OF ANY KIND, either express or
10
10
  # implied. See the LICENSE-MIT and LICENSE-APACHE files for the
11
11
  # specific language governing permissions and limitations under
12
- # each license.import unittest
12
+ # each license.
13
13
 
14
14
  import os
15
15
  import io
@@ -1,30 +0,0 @@
1
- try:
2
- from importlib.metadata import version
3
- __version__ = version("c2pa-python")
4
- except ImportError: # pragma: no cover
5
- __version__ = "unknown"
6
-
7
- from .c2pa import (
8
- Builder,
9
- C2paError,
10
- Reader,
11
- C2paSigningAlg,
12
- C2paSignerInfo,
13
- Signer,
14
- Stream,
15
- sdk_version,
16
- read_ingredient_file
17
- ) # NOQA
18
-
19
- # Re-export C2paError and its subclasses
20
- __all__ = [
21
- 'Builder',
22
- 'C2paError',
23
- 'Reader',
24
- 'C2paSigningAlg',
25
- 'C2paSignerInfo',
26
- 'Signer',
27
- 'Stream',
28
- 'sdk_version',
29
- 'read_ingredient_file'
30
- ]
File without changes
File without changes
File without changes
File without changes