c2pa-python 0.37.3__tar.gz → 0.37.4__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.37.3/src/c2pa_python.egg-info → c2pa_python-0.37.4}/PKG-INFO +4 -4
  2. {c2pa_python-0.37.3 → c2pa_python-0.37.4}/README.md +3 -3
  3. {c2pa_python-0.37.3 → c2pa_python-0.37.4}/pyproject.toml +1 -1
  4. {c2pa_python-0.37.3 → c2pa_python-0.37.4}/src/c2pa/c2pa.py +42 -42
  5. {c2pa_python-0.37.3 → c2pa_python-0.37.4/src/c2pa_python.egg-info}/PKG-INFO +4 -4
  6. {c2pa_python-0.37.3 → c2pa_python-0.37.4}/tests/test_unit_tests.py +12 -12
  7. {c2pa_python-0.37.3 → c2pa_python-0.37.4}/LICENSE-APACHE +0 -0
  8. {c2pa_python-0.37.3 → c2pa_python-0.37.4}/LICENSE-MIT +0 -0
  9. {c2pa_python-0.37.3 → c2pa_python-0.37.4}/MANIFEST.in +0 -0
  10. {c2pa_python-0.37.3 → c2pa_python-0.37.4}/requirements.txt +0 -0
  11. {c2pa_python-0.37.3 → c2pa_python-0.37.4}/scripts/download_artifacts.py +0 -0
  12. {c2pa_python-0.37.3 → c2pa_python-0.37.4}/setup.cfg +0 -0
  13. {c2pa_python-0.37.3 → c2pa_python-0.37.4}/setup.py +0 -0
  14. {c2pa_python-0.37.3 → c2pa_python-0.37.4}/src/c2pa/__init__.py +0 -0
  15. {c2pa_python-0.37.3 → c2pa_python-0.37.4}/src/c2pa/build.py +0 -0
  16. {c2pa_python-0.37.3 → c2pa_python-0.37.4}/src/c2pa/lib.py +0 -0
  17. {c2pa_python-0.37.3 → c2pa_python-0.37.4}/src/c2pa_python.egg-info/SOURCES.txt +0 -0
  18. {c2pa_python-0.37.3 → c2pa_python-0.37.4}/src/c2pa_python.egg-info/dependency_links.txt +0 -0
  19. {c2pa_python-0.37.3 → c2pa_python-0.37.4}/src/c2pa_python.egg-info/entry_points.txt +0 -0
  20. {c2pa_python-0.37.3 → c2pa_python-0.37.4}/src/c2pa_python.egg-info/requires.txt +0 -0
  21. {c2pa_python-0.37.3 → c2pa_python-0.37.4}/src/c2pa_python.egg-info/top_level.txt +0 -0
  22. {c2pa_python-0.37.3 → c2pa_python-0.37.4}/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.37.3
3
+ Version: 0.37.4
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>
@@ -35,7 +35,7 @@ Features:
35
35
  - Add assertions and ingredients to assets.
36
36
  - Examples and unit tests to demonstrate usage.
37
37
 
38
- <div style={{display: 'none'}}>
38
+ <div class="github-only">
39
39
 
40
40
  For the best experience, read the docs on the [CAI Open Source SDK documentation website](https://opensource.contentauthenticity.org/docs/c2pa-c).
41
41
 
@@ -44,7 +44,7 @@ If you want to view the documentation in GitHub, see:
44
44
  - [Supported formats](https://github.com/contentauth/c2pa-rs/blob/main/docs/supported-formats.md)
45
45
  - [Configuring the SDK using `Context` and `Settings`](docs/context-settings.md)
46
46
  - [Using Builder intents](docs/intents.md) to ensure spec-compliant manifests
47
- - Using [working stores and archvies](docs/working-stores.md)
47
+ - Using [working stores and archives](docs/working-stores.md)
48
48
  - Selectively constructing manifests by [filtering actions and ingredients](docs/selective-manifests.md)
49
49
  - [Diagram of public classes in the Python library and their relationships](docs/class-diagram.md)
50
50
  - [Release notes](docs/release-notes.md)
@@ -95,7 +95,7 @@ export C2PA_RS_PATH=/path/to/c2pa-rs
95
95
  make build-from-source C2PA_RS_PATH=$C2PA_RS_PATH
96
96
  ```
97
97
 
98
- This does a clean build of the `c2pa-c-ffi` crate (with the `file_io` feature, which the Python wrapper requires), stages the resulting library under both `artifacts/` and `src/c2pa/libs/`, and installs the package in editable mode, replacing any prebuilt artifacts from `make download-native-artifacts`. The release profile is used by default; to build the debug profile instead, pass `EXTRA_BUILD_ARGS="--debug"`:
98
+ This does a clean build of the `c2pa-c-ffi` crate (with the `file_io` feature, which the Python wrapper requires), stages the resulting library under both `artifacts/` and `src/c2pa/libs/`, and installs the package in editable mode, replacing any prebuilt artifacts from `make download-native-artifacts`. By default, the build uses the release profile; to build the debug profile instead, pass `EXTRA_BUILD_ARGS="--debug"`:
99
99
 
100
100
  ```sh
101
101
  make build-from-source C2PA_RS_PATH=$C2PA_RS_PATH EXTRA_BUILD_ARGS="--debug"
@@ -12,7 +12,7 @@ Features:
12
12
  - Add assertions and ingredients to assets.
13
13
  - Examples and unit tests to demonstrate usage.
14
14
 
15
- <div style={{display: 'none'}}>
15
+ <div class="github-only">
16
16
 
17
17
  For the best experience, read the docs on the [CAI Open Source SDK documentation website](https://opensource.contentauthenticity.org/docs/c2pa-c).
18
18
 
@@ -21,7 +21,7 @@ If you want to view the documentation in GitHub, see:
21
21
  - [Supported formats](https://github.com/contentauth/c2pa-rs/blob/main/docs/supported-formats.md)
22
22
  - [Configuring the SDK using `Context` and `Settings`](docs/context-settings.md)
23
23
  - [Using Builder intents](docs/intents.md) to ensure spec-compliant manifests
24
- - Using [working stores and archvies](docs/working-stores.md)
24
+ - Using [working stores and archives](docs/working-stores.md)
25
25
  - Selectively constructing manifests by [filtering actions and ingredients](docs/selective-manifests.md)
26
26
  - [Diagram of public classes in the Python library and their relationships](docs/class-diagram.md)
27
27
  - [Release notes](docs/release-notes.md)
@@ -72,7 +72,7 @@ export C2PA_RS_PATH=/path/to/c2pa-rs
72
72
  make build-from-source C2PA_RS_PATH=$C2PA_RS_PATH
73
73
  ```
74
74
 
75
- This does a clean build of the `c2pa-c-ffi` crate (with the `file_io` feature, which the Python wrapper requires), stages the resulting library under both `artifacts/` and `src/c2pa/libs/`, and installs the package in editable mode, replacing any prebuilt artifacts from `make download-native-artifacts`. The release profile is used by default; to build the debug profile instead, pass `EXTRA_BUILD_ARGS="--debug"`:
75
+ This does a clean build of the `c2pa-c-ffi` crate (with the `file_io` feature, which the Python wrapper requires), stages the resulting library under both `artifacts/` and `src/c2pa/libs/`, and installs the package in editable mode, replacing any prebuilt artifacts from `make download-native-artifacts`. By default, the build uses the release profile; to build the debug profile instead, pass `EXTRA_BUILD_ARGS="--debug"`:
76
76
 
77
77
  ```sh
78
78
  make build-from-source C2PA_RS_PATH=$C2PA_RS_PATH EXTRA_BUILD_ARGS="--debug"
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "c2pa-python"
7
- version = "0.37.3"
7
+ version = "0.37.4"
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" }
@@ -11,7 +11,7 @@
11
11
  # specific language governing permissions and limitations under
12
12
  # each license.
13
13
 
14
- # Version: 0.37.3
14
+ # Version: 0.37.4
15
15
 
16
16
  import ctypes
17
17
  import enum
@@ -1464,36 +1464,6 @@ def load_settings(settings: Union[str, dict], format: str = "json") -> None:
1464
1464
  check=lambda r: r != 0)
1465
1465
 
1466
1466
 
1467
- def _get_mime_type_from_path(path: Union[str, Path]) -> str:
1468
- """Attempt to guess the MIME type from a file path's extension.
1469
- When the extension is missing or unrecognized, this returns an empty
1470
- string so the caller hands it to the lib for auto-detection.
1471
- A recognized-but-wrong extension still returns a mimetype:
1472
- the native layer will attempt to correct it from the bytes when
1473
- reading (the real type still needs to be supported by the lib),
1474
- and if it can't, an error will happen then.
1475
-
1476
- Args:
1477
- path: File path as string or Path object
1478
-
1479
- Returns:
1480
- MIME type string, or an empty string
1481
- (when it cannot be determined from the extension).
1482
- An empty string here means the native lib should attempt auto-detect.
1483
- """
1484
- path_obj = Path(path)
1485
- file_extension = path_obj.suffix.lower() if path_obj.suffix else ""
1486
-
1487
- if file_extension == ".dng":
1488
- # mimetypes guesses the wrong type for dng,
1489
- # so we bypass it and set the correct type
1490
- return "image/dng"
1491
- else:
1492
- # Fall back to an empty string for extensionless or unknown files.
1493
- # Empty string flags this as a guess-type attempt.
1494
- return mimetypes.guess_type(str(path))[0] or ""
1495
-
1496
-
1497
1467
  class ContextProvider(ABC):
1498
1468
  """Abstract base class for types that provide a C2PA context.
1499
1469
 
@@ -2154,6 +2124,46 @@ class Stream:
2154
2124
  """
2155
2125
  return self._initialized
2156
2126
 
2127
+ @staticmethod
2128
+ def is_read_stream(obj) -> bool:
2129
+ """Return True if obj is a stream-like object this SDK can use.
2130
+ Note: only method presence to identify streams are checked,
2131
+ not that they work (a broken stream can fail later).
2132
+ """
2133
+ if obj is None or isinstance(obj, (str, Path)):
2134
+ return False
2135
+ return all(hasattr(obj, method) for method in Stream._REQUIRED_STREAM_METHODS)
2136
+
2137
+
2138
+ def _get_mime_type_from_path(path: Union[str, Path]) -> str:
2139
+ """Attempt to guess the MIME type from a file path's extension.
2140
+ When the extension is missing or unrecognized, this returns an empty
2141
+ string so the caller hands it to the lib for auto-detection.
2142
+ A recognized-but-wrong extension still returns a mimetype:
2143
+ the native layer will attempt to correct it from the bytes when
2144
+ reading (the real type still needs to be supported by the lib),
2145
+ and if it can't, an error will happen then.
2146
+
2147
+ Args:
2148
+ path: File path as string or Path object
2149
+
2150
+ Returns:
2151
+ MIME type string, or an empty string
2152
+ (when it cannot be determined from the extension).
2153
+ An empty string here means the native lib should attempt auto-detect.
2154
+ """
2155
+ path_obj = Path(path)
2156
+ file_extension = path_obj.suffix.lower() if path_obj.suffix else ""
2157
+
2158
+ if file_extension == ".dng":
2159
+ # mimetypes guesses the wrong type for dng,
2160
+ # so we bypass it and set the correct type
2161
+ return "image/dng"
2162
+ else:
2163
+ # Fall back to an empty string for extensionless or unknown files.
2164
+ # Empty string flags this as a guess-type attempt.
2165
+ return mimetypes.guess_type(str(path))[0] or ""
2166
+
2157
2167
 
2158
2168
  def _get_supported_mime_types(ffi_func, cache):
2159
2169
  """Shared helper to retrieve supported MIME types from the native library.
@@ -2269,16 +2279,6 @@ def _format_ffi_arg(fmt: Optional[bytes]) -> bytes:
2269
2279
  return fmt if fmt is not None else b""
2270
2280
 
2271
2281
 
2272
- def _is_read_stream(obj) -> bool:
2273
- """Return True if obj is a stream-like object this SDK can use.
2274
- Note: only method presence to identify streams are checked,
2275
- not that they work (a broken stream can fail later).
2276
- """
2277
- if obj is None or isinstance(obj, (str, Path)):
2278
- return False
2279
- return all(hasattr(obj, method) for method in Stream._REQUIRED_STREAM_METHODS)
2280
-
2281
-
2282
2282
  class Reader(ManagedResource):
2283
2283
  """High-level wrapper for C2PA Reader operations.
2284
2284
 
@@ -2478,7 +2478,7 @@ class Reader(ManagedResource):
2478
2478
  self._context = context
2479
2479
 
2480
2480
  # Only stream, no format: Reader(fh) must auto-detect on the stream.
2481
- if stream is None and _is_read_stream(format_or_path):
2481
+ if stream is None and Stream.is_read_stream(format_or_path):
2482
2482
  stream = format_or_path
2483
2483
  format_or_path = None
2484
2484
  # A context supplies settings, not the asset, so a path or stream is
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: c2pa-python
3
- Version: 0.37.3
3
+ Version: 0.37.4
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>
@@ -35,7 +35,7 @@ Features:
35
35
  - Add assertions and ingredients to assets.
36
36
  - Examples and unit tests to demonstrate usage.
37
37
 
38
- <div style={{display: 'none'}}>
38
+ <div class="github-only">
39
39
 
40
40
  For the best experience, read the docs on the [CAI Open Source SDK documentation website](https://opensource.contentauthenticity.org/docs/c2pa-c).
41
41
 
@@ -44,7 +44,7 @@ If you want to view the documentation in GitHub, see:
44
44
  - [Supported formats](https://github.com/contentauth/c2pa-rs/blob/main/docs/supported-formats.md)
45
45
  - [Configuring the SDK using `Context` and `Settings`](docs/context-settings.md)
46
46
  - [Using Builder intents](docs/intents.md) to ensure spec-compliant manifests
47
- - Using [working stores and archvies](docs/working-stores.md)
47
+ - Using [working stores and archives](docs/working-stores.md)
48
48
  - Selectively constructing manifests by [filtering actions and ingredients](docs/selective-manifests.md)
49
49
  - [Diagram of public classes in the Python library and their relationships](docs/class-diagram.md)
50
50
  - [Release notes](docs/release-notes.md)
@@ -95,7 +95,7 @@ export C2PA_RS_PATH=/path/to/c2pa-rs
95
95
  make build-from-source C2PA_RS_PATH=$C2PA_RS_PATH
96
96
  ```
97
97
 
98
- This does a clean build of the `c2pa-c-ffi` crate (with the `file_io` feature, which the Python wrapper requires), stages the resulting library under both `artifacts/` and `src/c2pa/libs/`, and installs the package in editable mode, replacing any prebuilt artifacts from `make download-native-artifacts`. The release profile is used by default; to build the debug profile instead, pass `EXTRA_BUILD_ARGS="--debug"`:
98
+ This does a clean build of the `c2pa-c-ffi` crate (with the `file_io` feature, which the Python wrapper requires), stages the resulting library under both `artifacts/` and `src/c2pa/libs/`, and installs the package in editable mode, replacing any prebuilt artifacts from `make download-native-artifacts`. By default, the build uses the release profile; to build the debug profile instead, pass `EXTRA_BUILD_ARGS="--debug"`:
99
99
 
100
100
  ```sh
101
101
  make build-from-source C2PA_RS_PATH=$C2PA_RS_PATH EXTRA_BUILD_ARGS="--debug"
@@ -36,7 +36,7 @@ warnings.simplefilter("ignore", category=DeprecationWarning)
36
36
 
37
37
  from c2pa import Builder, C2paError as Error, Reader, C2paSigningAlg as SigningAlg, C2paSignerInfo, Signer, sdk_version, C2paBuilderIntent, C2paDigitalSourceType
38
38
  from c2pa import Settings, Context, ContextBuilder, ContextProvider
39
- from c2pa.c2pa import Stream, LifecycleState, ManagedResource, load_settings, create_signer, create_signer_from_info, ed25519_sign, format_embeddable, _get_mime_type_from_path, _encode_format, _format_ffi_arg, _is_read_stream
39
+ from c2pa.c2pa import Stream, LifecycleState, ManagedResource, load_settings, create_signer, create_signer_from_info, ed25519_sign, format_embeddable, _get_mime_type_from_path, _encode_format, _format_ffi_arg
40
40
  import c2pa.c2pa as c2pa_module
41
41
  from pathlib import Path
42
42
 
@@ -105,17 +105,17 @@ class TestIsReadableStream(unittest.TestCase):
105
105
  def test_paths_and_formats_are_not_streams(self):
106
106
  for value in (None, "", "image/jpeg", "path/to/file.jpg",
107
107
  Path("x.jpg")):
108
- self.assertFalse(_is_read_stream(value), repr(value))
108
+ self.assertFalse(Stream.is_read_stream(value), repr(value))
109
109
 
110
110
  def test_non_stream_objects_are_not_streams(self):
111
111
  for value in (b"bytes", bytearray(b"x"), 42, object()):
112
- self.assertFalse(_is_read_stream(value), repr(value))
112
+ self.assertFalse(Stream.is_read_stream(value), repr(value))
113
113
 
114
114
  def test_object_missing_methods_is_not_a_stream(self):
115
115
  class OnlyRead:
116
116
  def read(self):
117
117
  return b""
118
- self.assertFalse(_is_read_stream(OnlyRead()))
118
+ self.assertFalse(Stream.is_read_stream(OnlyRead()))
119
119
 
120
120
  def test_read_only_object_is_not_a_stream(self):
121
121
  # Has read/seek/tell but no write/flush, so not a Stream for us.
@@ -128,11 +128,11 @@ class TestIsReadableStream(unittest.TestCase):
128
128
 
129
129
  def tell(self):
130
130
  return 0
131
- self.assertFalse(_is_read_stream(ReadOnly()))
131
+ self.assertFalse(Stream.is_read_stream(ReadOnly()))
132
132
 
133
133
  def test_in_memory_streams_are_streams(self):
134
- self.assertTrue(_is_read_stream(io.BytesIO(b"x")))
135
- self.assertTrue(_is_read_stream(io.StringIO("x")))
134
+ self.assertTrue(Stream.is_read_stream(io.BytesIO(b"x")))
135
+ self.assertTrue(Stream.is_read_stream(io.StringIO("x")))
136
136
 
137
137
  def test_file_handles_are_streams(self):
138
138
  path = self._tmp_path()
@@ -145,13 +145,13 @@ class TestIsReadableStream(unittest.TestCase):
145
145
  ):
146
146
  fh = opener()
147
147
  try:
148
- self.assertTrue(_is_read_stream(fh), type(fh).__name__)
148
+ self.assertTrue(Stream.is_read_stream(fh), type(fh).__name__)
149
149
  finally:
150
150
  fh.close()
151
151
 
152
152
  def test_spooled_temporary_file_is_a_stream(self):
153
153
  with tempfile.SpooledTemporaryFile() as fh:
154
- self.assertTrue(_is_read_stream(fh))
154
+ self.assertTrue(Stream.is_read_stream(fh))
155
155
 
156
156
  def test_compressed_file_objects_are_streams(self):
157
157
  with tempfile.TemporaryDirectory() as tmp:
@@ -164,7 +164,7 @@ class TestIsReadableStream(unittest.TestCase):
164
164
  with opener(p, "wb") as fh:
165
165
  fh.write(b"data")
166
166
  with opener(p, "rb") as fh:
167
- self.assertTrue(_is_read_stream(fh), ext)
167
+ self.assertTrue(Stream.is_read_stream(fh), ext)
168
168
 
169
169
  def test_placeholder_typed_object_with_all_methods_is_a_stream(self):
170
170
  class Duck:
@@ -182,7 +182,7 @@ class TestIsReadableStream(unittest.TestCase):
182
182
 
183
183
  def flush(self):
184
184
  pass
185
- self.assertTrue(_is_read_stream(Duck()))
185
+ self.assertTrue(Stream.is_read_stream(Duck()))
186
186
 
187
187
 
188
188
  class TestFormatValidation(unittest.TestCase):
@@ -562,7 +562,7 @@ class TestReader(unittest.TestCase):
562
562
  reader.close()
563
563
 
564
564
  def test_bare_stream_closed_handle_raises(self):
565
- # _is_read_stream only checks method presence
565
+ # Stream.is_read_stream only checks method presence
566
566
  # so a closed handle is accepted as a stream and fails at read time.
567
567
  file = open(self.testPath, "rb")
568
568
  file.close()
File without changes
File without changes
File without changes
File without changes