c2pa-python 0.10.0__tar.gz → 0.11.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.
- c2pa_python-0.11.0/PKG-INFO +67 -0
- c2pa_python-0.11.0/README.md +44 -0
- {c2pa_python-0.10.0 → c2pa_python-0.11.0}/pyproject.toml +1 -1
- {c2pa_python-0.10.0 → c2pa_python-0.11.0}/scripts/download_artifacts.py +13 -2
- {c2pa_python-0.10.0 → c2pa_python-0.11.0}/setup.py +4 -0
- {c2pa_python-0.10.0 → c2pa_python-0.11.0}/src/c2pa/lib.py +6 -1
- c2pa_python-0.11.0/src/c2pa_python.egg-info/PKG-INFO +67 -0
- {c2pa_python-0.10.0 → c2pa_python-0.11.0}/tests/test_unit_tests.py +24 -0
- {c2pa_python-0.10.0 → c2pa_python-0.11.0}/tests/test_unit_tests_threaded.py +72 -52
- c2pa_python-0.10.0/PKG-INFO +0 -156
- c2pa_python-0.10.0/README.md +0 -133
- c2pa_python-0.10.0/src/c2pa_python.egg-info/PKG-INFO +0 -156
- {c2pa_python-0.10.0 → c2pa_python-0.11.0}/LICENSE-APACHE +0 -0
- {c2pa_python-0.10.0 → c2pa_python-0.11.0}/LICENSE-MIT +0 -0
- {c2pa_python-0.10.0 → c2pa_python-0.11.0}/MANIFEST.in +0 -0
- {c2pa_python-0.10.0 → c2pa_python-0.11.0}/requirements.txt +0 -0
- {c2pa_python-0.10.0 → c2pa_python-0.11.0}/setup.cfg +0 -0
- {c2pa_python-0.10.0 → c2pa_python-0.11.0}/src/c2pa/__init__.py +0 -0
- {c2pa_python-0.10.0 → c2pa_python-0.11.0}/src/c2pa/build.py +0 -0
- {c2pa_python-0.10.0 → c2pa_python-0.11.0}/src/c2pa/c2pa.py +0 -0
- {c2pa_python-0.10.0 → c2pa_python-0.11.0}/src/c2pa_python.egg-info/SOURCES.txt +0 -0
- {c2pa_python-0.10.0 → c2pa_python-0.11.0}/src/c2pa_python.egg-info/dependency_links.txt +0 -0
- {c2pa_python-0.10.0 → c2pa_python-0.11.0}/src/c2pa_python.egg-info/entry_points.txt +0 -0
- {c2pa_python-0.10.0 → c2pa_python-0.11.0}/src/c2pa_python.egg-info/requires.txt +0 -0
- {c2pa_python-0.10.0 → c2pa_python-0.11.0}/src/c2pa_python.egg-info/top_level.txt +0 -0
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: c2pa-python
|
|
3
|
+
Version: 0.11.0
|
|
4
|
+
Summary: Python bindings for the C2PA Content Authenticity Initiative (CAI) library
|
|
5
|
+
Author-email: Gavin Peacock <gvnpeacock@adobe.com>, Tania Mathern <mathern@adobe.com>
|
|
6
|
+
Maintainer-email: Gavin Peacock <gpeacock@adobe.com>
|
|
7
|
+
License: MIT OR Apache-2.0
|
|
8
|
+
Project-URL: homepage, https://contentauthenticity.org
|
|
9
|
+
Project-URL: repository, https://github.com/contentauth/c2pa-python
|
|
10
|
+
Classifier: Programming Language :: Python :: 3
|
|
11
|
+
Classifier: Operating System :: MacOS
|
|
12
|
+
Classifier: Operating System :: POSIX :: Linux
|
|
13
|
+
Classifier: Operating System :: Microsoft :: Windows
|
|
14
|
+
Requires-Python: >=3.10
|
|
15
|
+
Description-Content-Type: text/markdown
|
|
16
|
+
Requires-Dist: wheel>=0.41.2
|
|
17
|
+
Requires-Dist: setuptools>=68.0.0
|
|
18
|
+
Requires-Dist: toml>=0.10.2
|
|
19
|
+
Requires-Dist: pytest>=7.4.0
|
|
20
|
+
Requires-Dist: cryptography>=41.0.0
|
|
21
|
+
Requires-Dist: requests>=2.0.0
|
|
22
|
+
Dynamic: requires-python
|
|
23
|
+
|
|
24
|
+
# C2PA Python library
|
|
25
|
+
|
|
26
|
+
The [c2pa-python](https://github.com/contentauth/c2pa-python) repository provides a Python library that can:
|
|
27
|
+
- Read and validate C2PA manifest data from media files in supported formats.
|
|
28
|
+
- Create and sign manifest data, and attach it to media files in supported formats.
|
|
29
|
+
|
|
30
|
+
Features:
|
|
31
|
+
|
|
32
|
+
- Create and sign C2PA manifests using various signing algorithms.
|
|
33
|
+
- Verify C2PA manifests and extract metadata.
|
|
34
|
+
- Add assertions and ingredients to assets.
|
|
35
|
+
- Examples and unit tests to demonstrate usage.
|
|
36
|
+
|
|
37
|
+
## Prerequisites
|
|
38
|
+
|
|
39
|
+
This library requires Python version 3.10+.
|
|
40
|
+
|
|
41
|
+
## Package installation
|
|
42
|
+
|
|
43
|
+
Install the c2pa-python package from PyPI by running:
|
|
44
|
+
|
|
45
|
+
```bash
|
|
46
|
+
pip install c2pa-python
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
To use the module in Python code, import the module like this:
|
|
50
|
+
|
|
51
|
+
```python
|
|
52
|
+
import c2pa
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
## Examples
|
|
56
|
+
|
|
57
|
+
See the [`examples` directory](https://github.com/contentauth/c2pa-python/tree/main/examples) for some helpful examples:
|
|
58
|
+
- `examples/sign.py` shows how to sign and verify an asset with a C2PA manifest.
|
|
59
|
+
- `examples/training.py` demonstrates how to add a "Do Not Train" assertion to an asset and verify it.
|
|
60
|
+
|
|
61
|
+
## Contributing
|
|
62
|
+
|
|
63
|
+
Contributions are welcome! For more information, see [Contributing to the project](https://github.com/contentauth/c2pa-python/blob/main/docs/project-contributions.md).
|
|
64
|
+
|
|
65
|
+
## License
|
|
66
|
+
|
|
67
|
+
This project is licensed under the Apache License 2.0 and the MIT License. See the [LICENSE-MIT](https://github.com/contentauth/c2pa-python/blob/main/LICENSE-MIT) and [LICENSE-APACHE](https://github.com/contentauth/c2pa-python/blob/main/LICENSE-APACHE) files for details.
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
# C2PA Python library
|
|
2
|
+
|
|
3
|
+
The [c2pa-python](https://github.com/contentauth/c2pa-python) repository provides a Python library that can:
|
|
4
|
+
- Read and validate C2PA manifest data from media files in supported formats.
|
|
5
|
+
- Create and sign manifest data, and attach it to media files in supported formats.
|
|
6
|
+
|
|
7
|
+
Features:
|
|
8
|
+
|
|
9
|
+
- Create and sign C2PA manifests using various signing algorithms.
|
|
10
|
+
- Verify C2PA manifests and extract metadata.
|
|
11
|
+
- Add assertions and ingredients to assets.
|
|
12
|
+
- Examples and unit tests to demonstrate usage.
|
|
13
|
+
|
|
14
|
+
## Prerequisites
|
|
15
|
+
|
|
16
|
+
This library requires Python version 3.10+.
|
|
17
|
+
|
|
18
|
+
## Package installation
|
|
19
|
+
|
|
20
|
+
Install the c2pa-python package from PyPI by running:
|
|
21
|
+
|
|
22
|
+
```bash
|
|
23
|
+
pip install c2pa-python
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
To use the module in Python code, import the module like this:
|
|
27
|
+
|
|
28
|
+
```python
|
|
29
|
+
import c2pa
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
## Examples
|
|
33
|
+
|
|
34
|
+
See the [`examples` directory](https://github.com/contentauth/c2pa-python/tree/main/examples) for some helpful examples:
|
|
35
|
+
- `examples/sign.py` shows how to sign and verify an asset with a C2PA manifest.
|
|
36
|
+
- `examples/training.py` demonstrates how to add a "Do Not Train" assertion to an asset and verify it.
|
|
37
|
+
|
|
38
|
+
## Contributing
|
|
39
|
+
|
|
40
|
+
Contributions are welcome! For more information, see [Contributing to the project](https://github.com/contentauth/c2pa-python/blob/main/docs/project-contributions.md).
|
|
41
|
+
|
|
42
|
+
## License
|
|
43
|
+
|
|
44
|
+
This project is licensed under the Apache License 2.0 and the MIT License. See the [LICENSE-MIT](https://github.com/contentauth/c2pa-python/blob/main/LICENSE-MIT) and [LICENSE-APACHE](https://github.com/contentauth/c2pa-python/blob/main/LICENSE-APACHE) files for details.
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "c2pa-python"
|
|
7
|
-
version = "0.
|
|
7
|
+
version = "0.11.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" }
|
|
@@ -46,16 +46,21 @@ def get_platform_identifier():
|
|
|
46
46
|
Returns one of:
|
|
47
47
|
- universal-apple-darwin (for Mac)
|
|
48
48
|
- x86_64-pc-windows-msvc (for Windows 64-bit)
|
|
49
|
-
- x86_64-unknown-linux-gnu (for Linux
|
|
49
|
+
- x86_64-unknown-linux-gnu (for Linux x86_64)
|
|
50
|
+
- aarch64-unknown-linux-gnu (for Linux ARM64)
|
|
50
51
|
"""
|
|
51
52
|
system = platform.system().lower()
|
|
53
|
+
machine = platform.machine().lower()
|
|
52
54
|
|
|
53
55
|
if system == "darwin":
|
|
54
56
|
return "universal-apple-darwin"
|
|
55
57
|
elif system == "windows":
|
|
56
58
|
return "x86_64-pc-windows-msvc"
|
|
57
59
|
elif system == "linux":
|
|
58
|
-
|
|
60
|
+
if machine in ["arm64", "aarch64"]:
|
|
61
|
+
return "aarch64-unknown-linux-gnu"
|
|
62
|
+
else:
|
|
63
|
+
return "x86_64-unknown-linux-gnu"
|
|
59
64
|
else:
|
|
60
65
|
raise ValueError(f"Unsupported operating system: {system}")
|
|
61
66
|
|
|
@@ -105,8 +110,12 @@ def copy_artifacts_to_root():
|
|
|
105
110
|
print("Copying artifacts from scripts/artifacts to root...")
|
|
106
111
|
if ROOT_ARTIFACTS_DIR.exists():
|
|
107
112
|
shutil.rmtree(ROOT_ARTIFACTS_DIR)
|
|
113
|
+
print(f"Copying from {SCRIPTS_ARTIFACTS_DIR} to {ROOT_ARTIFACTS_DIR}")
|
|
108
114
|
shutil.copytree(SCRIPTS_ARTIFACTS_DIR, ROOT_ARTIFACTS_DIR)
|
|
109
115
|
print("Done copying artifacts")
|
|
116
|
+
print("\nFolder content of artifacts directory:")
|
|
117
|
+
for item in sorted(ROOT_ARTIFACTS_DIR.iterdir()):
|
|
118
|
+
print(f" {item.name}")
|
|
110
119
|
|
|
111
120
|
def main():
|
|
112
121
|
if len(sys.argv) < 2:
|
|
@@ -126,6 +135,8 @@ def main():
|
|
|
126
135
|
if env_platform:
|
|
127
136
|
print(f"Using platform from environment variable C2PA_LIBS_PLATFORM: {env_platform}")
|
|
128
137
|
platform_id = env_platform or get_platform_identifier()
|
|
138
|
+
print("Looking up releases for platform id: ", platform_id)
|
|
139
|
+
print("Environment variable set for lookup: ", env_platform)
|
|
129
140
|
platform_source = "environment variable" if env_platform else "auto-detection"
|
|
130
141
|
print(f"Target platform: {platform_id} (set through{platform_source})")
|
|
131
142
|
|
|
@@ -30,6 +30,7 @@ PLATFORM_FOLDERS = {
|
|
|
30
30
|
'x86_64-apple-darwin': 'dylib',
|
|
31
31
|
'x86_64-pc-windows-msvc': 'dll',
|
|
32
32
|
'x86_64-unknown-linux-gnu': 'so',
|
|
33
|
+
'aarch64-unknown-linux-gnu': 'so', # Add ARM Linux support
|
|
33
34
|
}
|
|
34
35
|
|
|
35
36
|
# Directory structure
|
|
@@ -51,6 +52,7 @@ def get_platform_identifier(cpu_arch = None) -> str:
|
|
|
51
52
|
- x86_64-apple-darwin (for Mac x86_64)
|
|
52
53
|
- x86_64-pc-windows-msvc (for Windows 64-bit)
|
|
53
54
|
- x86_64-unknown-linux-gnu (for Linux 64-bit)
|
|
55
|
+
- aarch64-unknown-linux-gnu (for Linux ARM64)
|
|
54
56
|
"""
|
|
55
57
|
system = platform.system().lower()
|
|
56
58
|
|
|
@@ -66,6 +68,8 @@ def get_platform_identifier(cpu_arch = None) -> str:
|
|
|
66
68
|
elif system == "windows":
|
|
67
69
|
return "x86_64-pc-windows-msvc"
|
|
68
70
|
elif system == "linux":
|
|
71
|
+
if platform.machine() == "aarch64":
|
|
72
|
+
return "aarch64-unknown-linux-gnu"
|
|
69
73
|
return "x86_64-unknown-linux-gnu"
|
|
70
74
|
else:
|
|
71
75
|
raise ValueError(f"Unsupported operating system: {system}")
|
|
@@ -62,6 +62,8 @@ def get_platform_identifier(cpu_arch: Optional[CPUArchitecture] = None) -> str:
|
|
|
62
62
|
elif system == "windows":
|
|
63
63
|
return "x86_64-pc-windows-msvc"
|
|
64
64
|
elif system == "linux":
|
|
65
|
+
if _get_architecture() in ['arm64', 'aarch64']:
|
|
66
|
+
return "aarch64-unknown-linux-gnu"
|
|
65
67
|
return "x86_64-unknown-linux-gnu"
|
|
66
68
|
else:
|
|
67
69
|
raise ValueError(f"Unsupported operating system: {system}")
|
|
@@ -245,8 +247,11 @@ def dynamically_load_library(
|
|
|
245
247
|
# If specific library name is provided, only load that one
|
|
246
248
|
lib = _load_single_library(lib_name, possible_paths)
|
|
247
249
|
if not lib:
|
|
250
|
+
platform_id = get_platform_identifier()
|
|
251
|
+
current_arch = _get_architecture()
|
|
248
252
|
logger.error(f"Could not find {lib_name} in any of the search paths: {[str(p) for p in possible_paths]}")
|
|
249
|
-
|
|
253
|
+
logger.error(f"Platform: {platform_id}, Architecture: {current_arch}")
|
|
254
|
+
raise RuntimeError(f"Could not find {lib_name} in any of the search paths (Platform: {platform_id}, Architecture: {current_arch})")
|
|
250
255
|
return lib
|
|
251
256
|
|
|
252
257
|
# Default path (no library name provided in the environment)
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: c2pa-python
|
|
3
|
+
Version: 0.11.0
|
|
4
|
+
Summary: Python bindings for the C2PA Content Authenticity Initiative (CAI) library
|
|
5
|
+
Author-email: Gavin Peacock <gvnpeacock@adobe.com>, Tania Mathern <mathern@adobe.com>
|
|
6
|
+
Maintainer-email: Gavin Peacock <gpeacock@adobe.com>
|
|
7
|
+
License: MIT OR Apache-2.0
|
|
8
|
+
Project-URL: homepage, https://contentauthenticity.org
|
|
9
|
+
Project-URL: repository, https://github.com/contentauth/c2pa-python
|
|
10
|
+
Classifier: Programming Language :: Python :: 3
|
|
11
|
+
Classifier: Operating System :: MacOS
|
|
12
|
+
Classifier: Operating System :: POSIX :: Linux
|
|
13
|
+
Classifier: Operating System :: Microsoft :: Windows
|
|
14
|
+
Requires-Python: >=3.10
|
|
15
|
+
Description-Content-Type: text/markdown
|
|
16
|
+
Requires-Dist: wheel>=0.41.2
|
|
17
|
+
Requires-Dist: setuptools>=68.0.0
|
|
18
|
+
Requires-Dist: toml>=0.10.2
|
|
19
|
+
Requires-Dist: pytest>=7.4.0
|
|
20
|
+
Requires-Dist: cryptography>=41.0.0
|
|
21
|
+
Requires-Dist: requests>=2.0.0
|
|
22
|
+
Dynamic: requires-python
|
|
23
|
+
|
|
24
|
+
# C2PA Python library
|
|
25
|
+
|
|
26
|
+
The [c2pa-python](https://github.com/contentauth/c2pa-python) repository provides a Python library that can:
|
|
27
|
+
- Read and validate C2PA manifest data from media files in supported formats.
|
|
28
|
+
- Create and sign manifest data, and attach it to media files in supported formats.
|
|
29
|
+
|
|
30
|
+
Features:
|
|
31
|
+
|
|
32
|
+
- Create and sign C2PA manifests using various signing algorithms.
|
|
33
|
+
- Verify C2PA manifests and extract metadata.
|
|
34
|
+
- Add assertions and ingredients to assets.
|
|
35
|
+
- Examples and unit tests to demonstrate usage.
|
|
36
|
+
|
|
37
|
+
## Prerequisites
|
|
38
|
+
|
|
39
|
+
This library requires Python version 3.10+.
|
|
40
|
+
|
|
41
|
+
## Package installation
|
|
42
|
+
|
|
43
|
+
Install the c2pa-python package from PyPI by running:
|
|
44
|
+
|
|
45
|
+
```bash
|
|
46
|
+
pip install c2pa-python
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
To use the module in Python code, import the module like this:
|
|
50
|
+
|
|
51
|
+
```python
|
|
52
|
+
import c2pa
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
## Examples
|
|
56
|
+
|
|
57
|
+
See the [`examples` directory](https://github.com/contentauth/c2pa-python/tree/main/examples) for some helpful examples:
|
|
58
|
+
- `examples/sign.py` shows how to sign and verify an asset with a C2PA manifest.
|
|
59
|
+
- `examples/training.py` demonstrates how to add a "Do Not Train" assertion to an asset and verify it.
|
|
60
|
+
|
|
61
|
+
## Contributing
|
|
62
|
+
|
|
63
|
+
Contributions are welcome! For more information, see [Contributing to the project](https://github.com/contentauth/c2pa-python/blob/main/docs/project-contributions.md).
|
|
64
|
+
|
|
65
|
+
## License
|
|
66
|
+
|
|
67
|
+
This project is licensed under the Apache License 2.0 and the MIT License. See the [LICENSE-MIT](https://github.com/contentauth/c2pa-python/blob/main/LICENSE-MIT) and [LICENSE-APACHE](https://github.com/contentauth/c2pa-python/blob/main/LICENSE-APACHE) files for details.
|
|
@@ -212,6 +212,30 @@ class TestReader(unittest.TestCase):
|
|
|
212
212
|
except Exception as e:
|
|
213
213
|
self.fail(f"Failed to read metadata from {filename}: {str(e)}")
|
|
214
214
|
|
|
215
|
+
def test_read_cawg_data_file(self):
|
|
216
|
+
"""Test reading C2PA metadata from C_with_CAWG_data.jpg file."""
|
|
217
|
+
file_path = os.path.join(self.data_dir, "files-for-reading-tests", "C_with_CAWG_data.jpg")
|
|
218
|
+
|
|
219
|
+
with open(file_path, "rb") as file:
|
|
220
|
+
reader = Reader("image/jpeg", file)
|
|
221
|
+
json_data = reader.json()
|
|
222
|
+
self.assertIsInstance(json_data, str)
|
|
223
|
+
|
|
224
|
+
# Parse the JSON and verify specific fields
|
|
225
|
+
manifest_data = json.loads(json_data)
|
|
226
|
+
|
|
227
|
+
# Verify basic manifest structure
|
|
228
|
+
self.assertIn("manifests", manifest_data)
|
|
229
|
+
self.assertIn("active_manifest", manifest_data)
|
|
230
|
+
|
|
231
|
+
# Get the active manifest
|
|
232
|
+
active_manifest_id = manifest_data["active_manifest"]
|
|
233
|
+
active_manifest = manifest_data["manifests"][active_manifest_id]
|
|
234
|
+
|
|
235
|
+
# Verify manifest is not null or empty
|
|
236
|
+
assert active_manifest is not None, "Active manifest should not be null"
|
|
237
|
+
assert len(active_manifest) > 0, "Active manifest should not be empty"
|
|
238
|
+
|
|
215
239
|
|
|
216
240
|
class TestBuilder(unittest.TestCase):
|
|
217
241
|
def setUp(self):
|
|
@@ -2096,32 +2096,22 @@ class TestBuilderWithThreads(unittest.TestCase):
|
|
|
2096
2096
|
builder.close()
|
|
2097
2097
|
|
|
2098
2098
|
def test_builder_sign_with_multiple_ingredient_random_many_threads(self):
|
|
2099
|
-
"""Test Builder class operations with
|
|
2099
|
+
"""Test Builder class operations with 12 threads, each adding 3 specific ingredients and signing a file."""
|
|
2100
2100
|
# Number of threads to use in the test
|
|
2101
|
-
# We are pushing it here, as we want to test with thread count one to two orders of magnitude
|
|
2102
|
-
# higher than "usual" max numbers of cores on (server) machines may be.
|
|
2103
|
-
|
|
2104
2101
|
TOTAL_THREADS_USED = 12
|
|
2105
2102
|
|
|
2106
|
-
#
|
|
2107
|
-
|
|
2108
|
-
|
|
2109
|
-
|
|
2110
|
-
|
|
2111
|
-
|
|
2112
|
-
if os.path.isfile(os.path.join(reading_dir, f))
|
|
2113
|
-
and os.path.splitext(f)[1].lower() in {'.jpg', '.jpeg', '.png'}
|
|
2103
|
+
# Define the specific files to use as ingredients
|
|
2104
|
+
# THose files should be valid to use as ingredient
|
|
2105
|
+
ingredient_files = [
|
|
2106
|
+
os.path.join(self.data_dir, "A_thumbnail.jpg"),
|
|
2107
|
+
os.path.join(self.data_dir, "C.jpg"),
|
|
2108
|
+
os.path.join(self.data_dir, "cloud.jpg")
|
|
2114
2109
|
]
|
|
2115
2110
|
|
|
2116
|
-
# Ensure we have enough files
|
|
2117
|
-
self.assertGreaterEqual(
|
|
2118
|
-
len(all_files),
|
|
2119
|
-
3,
|
|
2120
|
-
"Need at least 3 JPG/PNG files for testing")
|
|
2121
|
-
|
|
2122
2111
|
# Thread synchronization
|
|
2123
2112
|
thread_results = {}
|
|
2124
2113
|
completed_threads = 0
|
|
2114
|
+
thread_lock = threading.Lock() # Lock for thread-safe access to shared data
|
|
2125
2115
|
|
|
2126
2116
|
def thread_work(thread_id):
|
|
2127
2117
|
nonlocal completed_threads
|
|
@@ -2129,24 +2119,17 @@ class TestBuilderWithThreads(unittest.TestCase):
|
|
|
2129
2119
|
# Create a new builder for this thread
|
|
2130
2120
|
builder = Builder.from_json(self.manifestDefinition)
|
|
2131
2121
|
|
|
2132
|
-
# Select 3 random files for ingredients
|
|
2133
|
-
# Use thread_id as seed for reproducibility
|
|
2134
|
-
random.seed(thread_id)
|
|
2135
|
-
ingredient_files = random.sample(all_files, 3)
|
|
2136
|
-
|
|
2137
2122
|
# Add each ingredient
|
|
2138
|
-
for i,
|
|
2139
|
-
file_path = os.path.join(reading_dir, file_name)
|
|
2123
|
+
for i, file_path in enumerate(ingredient_files, 1):
|
|
2140
2124
|
ingredient_json = json.dumps({
|
|
2141
|
-
"title": f"Thread {thread_id} Ingredient {i} - {
|
|
2125
|
+
"title": f"Thread {thread_id} Ingredient {i} - {os.path.basename(file_path)}"
|
|
2142
2126
|
})
|
|
2143
2127
|
|
|
2144
2128
|
with open(file_path, 'rb') as f:
|
|
2145
2129
|
builder.add_ingredient(ingredient_json, "image/jpeg", f)
|
|
2146
2130
|
|
|
2147
|
-
#
|
|
2148
|
-
|
|
2149
|
-
sign_file_path = os.path.join(reading_dir, sign_file)
|
|
2131
|
+
# Use A.jpg as the file to sign
|
|
2132
|
+
sign_file_path = os.path.join(self.data_dir, "A.jpg")
|
|
2150
2133
|
|
|
2151
2134
|
# Sign the file
|
|
2152
2135
|
with open(sign_file_path, "rb") as file:
|
|
@@ -2168,11 +2151,13 @@ class TestBuilderWithThreads(unittest.TestCase):
|
|
|
2168
2151
|
manifest_data = json.loads(json_data)
|
|
2169
2152
|
|
|
2170
2153
|
# Store results for verification
|
|
2171
|
-
|
|
2172
|
-
|
|
2173
|
-
|
|
2174
|
-
|
|
2175
|
-
|
|
2154
|
+
with thread_lock:
|
|
2155
|
+
thread_results[thread_id] = {
|
|
2156
|
+
'manifest': manifest_data,
|
|
2157
|
+
'ingredient_files': [os.path.basename(f) for f in ingredient_files],
|
|
2158
|
+
'sign_file': os.path.basename(sign_file_path),
|
|
2159
|
+
'manifest_hash': hash(json.dumps(manifest_data, sort_keys=True)) # Add hash for comparison
|
|
2160
|
+
}
|
|
2176
2161
|
|
|
2177
2162
|
# Clean up streams
|
|
2178
2163
|
output.close()
|
|
@@ -2181,11 +2166,13 @@ class TestBuilderWithThreads(unittest.TestCase):
|
|
|
2181
2166
|
builder.close()
|
|
2182
2167
|
|
|
2183
2168
|
except Exception as e:
|
|
2184
|
-
|
|
2185
|
-
|
|
2186
|
-
|
|
2169
|
+
with thread_lock:
|
|
2170
|
+
thread_results[thread_id] = {
|
|
2171
|
+
'error': str(e)
|
|
2172
|
+
}
|
|
2187
2173
|
finally:
|
|
2188
|
-
|
|
2174
|
+
with thread_lock:
|
|
2175
|
+
completed_threads += 1
|
|
2189
2176
|
|
|
2190
2177
|
# Create and start threads
|
|
2191
2178
|
threads = []
|
|
@@ -2199,26 +2186,31 @@ class TestBuilderWithThreads(unittest.TestCase):
|
|
|
2199
2186
|
thread.join()
|
|
2200
2187
|
|
|
2201
2188
|
# Verify all threads completed
|
|
2202
|
-
self.assertEqual(completed_threads, TOTAL_THREADS_USED, f"All {
|
|
2203
|
-
TOTAL_THREADS_USED} threads should have completed")
|
|
2189
|
+
self.assertEqual(completed_threads, TOTAL_THREADS_USED, f"All {TOTAL_THREADS_USED} threads should have completed")
|
|
2204
2190
|
self.assertEqual(
|
|
2205
2191
|
len(thread_results),
|
|
2206
2192
|
TOTAL_THREADS_USED,
|
|
2207
2193
|
f"Should have results from all {TOTAL_THREADS_USED} threads")
|
|
2208
2194
|
|
|
2195
|
+
# Collect all manifest hashes for comparison
|
|
2196
|
+
manifest_hashes = set()
|
|
2197
|
+
thread_manifest_data = {}
|
|
2198
|
+
|
|
2209
2199
|
# Verify results for each thread
|
|
2210
2200
|
for thread_id in range(1, TOTAL_THREADS_USED + 1):
|
|
2211
2201
|
result = thread_results[thread_id]
|
|
2212
2202
|
|
|
2213
2203
|
# Check if thread encountered an error
|
|
2214
2204
|
if 'error' in result:
|
|
2215
|
-
self.fail(
|
|
2216
|
-
f"Thread {thread_id} failed with error: {
|
|
2217
|
-
result['error']}")
|
|
2205
|
+
self.fail(f"Thread {thread_id} failed with error: {result['error']}")
|
|
2218
2206
|
|
|
2219
2207
|
manifest_data = result['manifest']
|
|
2220
2208
|
ingredient_files = result['ingredient_files']
|
|
2221
|
-
|
|
2209
|
+
manifest_hash = result['manifest_hash']
|
|
2210
|
+
|
|
2211
|
+
# Store manifest data for cross-thread comparison
|
|
2212
|
+
thread_manifest_data[thread_id] = manifest_data
|
|
2213
|
+
manifest_hashes.add(manifest_hash)
|
|
2222
2214
|
|
|
2223
2215
|
# Verify active manifest exists
|
|
2224
2216
|
self.assertIn("active_manifest", manifest_data)
|
|
@@ -2234,16 +2226,44 @@ class TestBuilderWithThreads(unittest.TestCase):
|
|
|
2234
2226
|
self.assertIsInstance(active_manifest["ingredients"], list)
|
|
2235
2227
|
self.assertEqual(len(active_manifest["ingredients"]), 3)
|
|
2236
2228
|
|
|
2237
|
-
# Verify all ingredients exist with correct thread ID and file
|
|
2238
|
-
|
|
2239
|
-
ingredient_titles = [ing["title"]
|
|
2240
|
-
for ing in active_manifest["ingredients"]]
|
|
2229
|
+
# Verify all ingredients exist with correct thread ID and file names
|
|
2230
|
+
ingredient_titles = [ing["title"] for ing in active_manifest["ingredients"]]
|
|
2241
2231
|
for i, file_name in enumerate(ingredient_files, 1):
|
|
2242
|
-
expected_title = f"Thread {
|
|
2243
|
-
|
|
2244
|
-
|
|
2245
|
-
|
|
2232
|
+
expected_title = f"Thread {thread_id} Ingredient {i} - {file_name}"
|
|
2233
|
+
self.assertIn(expected_title, ingredient_titles, f"Thread {thread_id} should have ingredient with title {expected_title}")
|
|
2234
|
+
|
|
2235
|
+
# Verify no cross-thread contamination in ingredient titles
|
|
2236
|
+
for other_thread_id in range(1, TOTAL_THREADS_USED + 1):
|
|
2237
|
+
if other_thread_id != thread_id:
|
|
2238
|
+
for title in ingredient_titles:
|
|
2239
|
+
# Check for exact thread ID pattern to avoid false positives
|
|
2240
|
+
self.assertNotIn(
|
|
2241
|
+
f"Thread {other_thread_id} Ingredient",
|
|
2242
|
+
title,
|
|
2243
|
+
f"Thread {thread_id}'s manifest contains ingredient data from thread {other_thread_id}")
|
|
2244
|
+
|
|
2245
|
+
# Verify all manifests are unique (no data scrambling between threads)
|
|
2246
|
+
self.assertEqual(
|
|
2247
|
+
len(manifest_hashes),
|
|
2248
|
+
TOTAL_THREADS_USED,
|
|
2249
|
+
"Each thread should have a unique manifest (no data scrambling)")
|
|
2246
2250
|
|
|
2251
|
+
# Additional verification: Compare manifest structures between threads
|
|
2252
|
+
for thread_id in range(1, TOTAL_THREADS_USED + 1):
|
|
2253
|
+
current_manifest = thread_manifest_data[thread_id]
|
|
2254
|
+
|
|
2255
|
+
# Verify manifest structure is consistent
|
|
2256
|
+
self.assertIn("active_manifest", current_manifest)
|
|
2257
|
+
self.assertIn("manifests", current_manifest)
|
|
2258
|
+
|
|
2259
|
+
# Verify no cross-thread contamination in manifest data
|
|
2260
|
+
for other_thread_id in range(1, TOTAL_THREADS_USED + 1):
|
|
2261
|
+
if other_thread_id != thread_id:
|
|
2262
|
+
other_manifest = thread_manifest_data[other_thread_id]
|
|
2263
|
+
self.assertNotEqual(
|
|
2264
|
+
current_manifest["active_manifest"],
|
|
2265
|
+
other_manifest["active_manifest"],
|
|
2266
|
+
f"Thread {thread_id} and {other_thread_id} share the same active manifest ID")
|
|
2247
2267
|
|
|
2248
2268
|
if __name__ == '__main__':
|
|
2249
2269
|
unittest.main()
|
c2pa_python-0.10.0/PKG-INFO
DELETED
|
@@ -1,156 +0,0 @@
|
|
|
1
|
-
Metadata-Version: 2.4
|
|
2
|
-
Name: c2pa-python
|
|
3
|
-
Version: 0.10.0
|
|
4
|
-
Summary: Python bindings for the C2PA Content Authenticity Initiative (CAI) library
|
|
5
|
-
Author-email: Gavin Peacock <gvnpeacock@adobe.com>, Tania Mathern <mathern@adobe.com>
|
|
6
|
-
Maintainer-email: Gavin Peacock <gpeacock@adobe.com>
|
|
7
|
-
License: MIT OR Apache-2.0
|
|
8
|
-
Project-URL: homepage, https://contentauthenticity.org
|
|
9
|
-
Project-URL: repository, https://github.com/contentauth/c2pa-python
|
|
10
|
-
Classifier: Programming Language :: Python :: 3
|
|
11
|
-
Classifier: Operating System :: MacOS
|
|
12
|
-
Classifier: Operating System :: POSIX :: Linux
|
|
13
|
-
Classifier: Operating System :: Microsoft :: Windows
|
|
14
|
-
Requires-Python: >=3.10
|
|
15
|
-
Description-Content-Type: text/markdown
|
|
16
|
-
Requires-Dist: wheel>=0.41.2
|
|
17
|
-
Requires-Dist: setuptools>=68.0.0
|
|
18
|
-
Requires-Dist: toml>=0.10.2
|
|
19
|
-
Requires-Dist: pytest>=7.4.0
|
|
20
|
-
Requires-Dist: cryptography>=41.0.0
|
|
21
|
-
Requires-Dist: requests>=2.0.0
|
|
22
|
-
Dynamic: requires-python
|
|
23
|
-
|
|
24
|
-
# Python API for C2PA
|
|
25
|
-
|
|
26
|
-
This project provides a Python API for working with [C2PA](https://c2pa.org/) (Coalition for Content Provenance and Authenticity) manifests. It includes functionality for creating, signing, and verifying C2PA manifests, as well as working with assets and assertions.
|
|
27
|
-
|
|
28
|
-
## Features
|
|
29
|
-
|
|
30
|
-
- Create and sign C2PA manifests using various signing algorithms.
|
|
31
|
-
- Verify C2PA manifests and extract metadata.
|
|
32
|
-
- Add assertions and ingredients to assets.
|
|
33
|
-
- Examples and unit tests to demonstrate usage.
|
|
34
|
-
|
|
35
|
-
## Project Structure
|
|
36
|
-
|
|
37
|
-
```bash
|
|
38
|
-
.
|
|
39
|
-
├── .github/ # GitHub configuration files
|
|
40
|
-
├── artifacts/ # Platform-specific libraries for building (per subfolder)
|
|
41
|
-
│ └── your_target_platform/ # Platform-specific artifacts
|
|
42
|
-
├── docs/ # Project documentation
|
|
43
|
-
├── examples/ # Example scripts demonstrating usage
|
|
44
|
-
├── scripts/ # Utility scripts (eg. artifacts download)
|
|
45
|
-
├── src/ # Source code
|
|
46
|
-
│ └── c2pa/ # Main package directory
|
|
47
|
-
│ └── libs/ # Platform-specific libraries
|
|
48
|
-
├── tests/ # Unit tests and benchmarks
|
|
49
|
-
├── .gitignore # Git ignore rules
|
|
50
|
-
├── Makefile # Build and development commands
|
|
51
|
-
├── pyproject.toml # Python project configuration
|
|
52
|
-
├── requirements.txt # Python dependencies
|
|
53
|
-
├── requirements-dev.txt # Development dependencies
|
|
54
|
-
└── setup.py # Package setup script
|
|
55
|
-
```
|
|
56
|
-
|
|
57
|
-
## Package installation
|
|
58
|
-
|
|
59
|
-
The c2pa-python package is published to PyPI. You can install it from there by running:
|
|
60
|
-
|
|
61
|
-
```bash
|
|
62
|
-
pip install c2pa-python
|
|
63
|
-
```
|
|
64
|
-
|
|
65
|
-
To use the module in your Python code, import like this:
|
|
66
|
-
|
|
67
|
-
```python
|
|
68
|
-
import c2pa
|
|
69
|
-
```
|
|
70
|
-
|
|
71
|
-
## Examples
|
|
72
|
-
|
|
73
|
-
### Adding a "Do Not Train" Assertion
|
|
74
|
-
|
|
75
|
-
The `examples/training.py` script demonstrates how to add a "Do Not Train" assertion to an asset and verify it.
|
|
76
|
-
|
|
77
|
-
### Signing and Verifying Assets
|
|
78
|
-
|
|
79
|
-
The `examples/sign.py` script shows how to sign an asset with a C2PA manifest and verify it.
|
|
80
|
-
|
|
81
|
-
## Development Setup
|
|
82
|
-
|
|
83
|
-
1. Create and activate a virtual environment with native dependencies:
|
|
84
|
-
|
|
85
|
-
```bash
|
|
86
|
-
# Create virtual environment
|
|
87
|
-
python -m venv .venv
|
|
88
|
-
|
|
89
|
-
# Activate virtual environment
|
|
90
|
-
# On Windows:
|
|
91
|
-
.venv\Scripts\activate
|
|
92
|
-
# On macOS/Linux:
|
|
93
|
-
source .venv/bin/activate
|
|
94
|
-
|
|
95
|
-
# load project dependencies
|
|
96
|
-
pip install -r requirements.txt
|
|
97
|
-
pip install -r requirements-dev.txt
|
|
98
|
-
|
|
99
|
-
# download library artifacts for the current version you want, eg v0.55.0
|
|
100
|
-
python scripts/download_artifacts.py c2pa-v0.55.0
|
|
101
|
-
```
|
|
102
|
-
|
|
103
|
-
2. Install the package in development mode:
|
|
104
|
-
|
|
105
|
-
```bash
|
|
106
|
-
pip install -e .
|
|
107
|
-
```
|
|
108
|
-
|
|
109
|
-
This will:
|
|
110
|
-
|
|
111
|
-
- Copy the appropriate libraries for your platform from `artifacts/` to `src/c2pa/libs/`
|
|
112
|
-
- Install the package in development mode, allowing you to make changes to the Python code without reinstalling
|
|
113
|
-
|
|
114
|
-
## Building Wheels
|
|
115
|
-
|
|
116
|
-
To build wheels for all platforms that have libraries in the `artifacts/` directory:
|
|
117
|
-
|
|
118
|
-
```bash
|
|
119
|
-
python setup.py bdist_wheel
|
|
120
|
-
```
|
|
121
|
-
|
|
122
|
-
You can use `twine` to verify the wheels have correct metadata:
|
|
123
|
-
|
|
124
|
-
```bash
|
|
125
|
-
twine check dist/*
|
|
126
|
-
```
|
|
127
|
-
|
|
128
|
-
This will create platform-specific wheels in the `dist/` directory.
|
|
129
|
-
|
|
130
|
-
## Running Tests
|
|
131
|
-
|
|
132
|
-
Run the tests:
|
|
133
|
-
|
|
134
|
-
```bash
|
|
135
|
-
make test
|
|
136
|
-
```
|
|
137
|
-
|
|
138
|
-
Alternatively, install pytest (if not already installed):
|
|
139
|
-
|
|
140
|
-
```bash
|
|
141
|
-
pip install pytest
|
|
142
|
-
```
|
|
143
|
-
|
|
144
|
-
And run:
|
|
145
|
-
|
|
146
|
-
```bash
|
|
147
|
-
pytest
|
|
148
|
-
```
|
|
149
|
-
|
|
150
|
-
## Contributing
|
|
151
|
-
|
|
152
|
-
Contributions are welcome! Please fork the repository and submit a pull request.
|
|
153
|
-
|
|
154
|
-
## License
|
|
155
|
-
|
|
156
|
-
This project is licensed under the Apache License 2.0 or the MIT License. See the LICENSE-MIT and LICENSE-APACHE files for details.
|
c2pa_python-0.10.0/README.md
DELETED
|
@@ -1,133 +0,0 @@
|
|
|
1
|
-
# Python API for C2PA
|
|
2
|
-
|
|
3
|
-
This project provides a Python API for working with [C2PA](https://c2pa.org/) (Coalition for Content Provenance and Authenticity) manifests. It includes functionality for creating, signing, and verifying C2PA manifests, as well as working with assets and assertions.
|
|
4
|
-
|
|
5
|
-
## Features
|
|
6
|
-
|
|
7
|
-
- Create and sign C2PA manifests using various signing algorithms.
|
|
8
|
-
- Verify C2PA manifests and extract metadata.
|
|
9
|
-
- Add assertions and ingredients to assets.
|
|
10
|
-
- Examples and unit tests to demonstrate usage.
|
|
11
|
-
|
|
12
|
-
## Project Structure
|
|
13
|
-
|
|
14
|
-
```bash
|
|
15
|
-
.
|
|
16
|
-
├── .github/ # GitHub configuration files
|
|
17
|
-
├── artifacts/ # Platform-specific libraries for building (per subfolder)
|
|
18
|
-
│ └── your_target_platform/ # Platform-specific artifacts
|
|
19
|
-
├── docs/ # Project documentation
|
|
20
|
-
├── examples/ # Example scripts demonstrating usage
|
|
21
|
-
├── scripts/ # Utility scripts (eg. artifacts download)
|
|
22
|
-
├── src/ # Source code
|
|
23
|
-
│ └── c2pa/ # Main package directory
|
|
24
|
-
│ └── libs/ # Platform-specific libraries
|
|
25
|
-
├── tests/ # Unit tests and benchmarks
|
|
26
|
-
├── .gitignore # Git ignore rules
|
|
27
|
-
├── Makefile # Build and development commands
|
|
28
|
-
├── pyproject.toml # Python project configuration
|
|
29
|
-
├── requirements.txt # Python dependencies
|
|
30
|
-
├── requirements-dev.txt # Development dependencies
|
|
31
|
-
└── setup.py # Package setup script
|
|
32
|
-
```
|
|
33
|
-
|
|
34
|
-
## Package installation
|
|
35
|
-
|
|
36
|
-
The c2pa-python package is published to PyPI. You can install it from there by running:
|
|
37
|
-
|
|
38
|
-
```bash
|
|
39
|
-
pip install c2pa-python
|
|
40
|
-
```
|
|
41
|
-
|
|
42
|
-
To use the module in your Python code, import like this:
|
|
43
|
-
|
|
44
|
-
```python
|
|
45
|
-
import c2pa
|
|
46
|
-
```
|
|
47
|
-
|
|
48
|
-
## Examples
|
|
49
|
-
|
|
50
|
-
### Adding a "Do Not Train" Assertion
|
|
51
|
-
|
|
52
|
-
The `examples/training.py` script demonstrates how to add a "Do Not Train" assertion to an asset and verify it.
|
|
53
|
-
|
|
54
|
-
### Signing and Verifying Assets
|
|
55
|
-
|
|
56
|
-
The `examples/sign.py` script shows how to sign an asset with a C2PA manifest and verify it.
|
|
57
|
-
|
|
58
|
-
## Development Setup
|
|
59
|
-
|
|
60
|
-
1. Create and activate a virtual environment with native dependencies:
|
|
61
|
-
|
|
62
|
-
```bash
|
|
63
|
-
# Create virtual environment
|
|
64
|
-
python -m venv .venv
|
|
65
|
-
|
|
66
|
-
# Activate virtual environment
|
|
67
|
-
# On Windows:
|
|
68
|
-
.venv\Scripts\activate
|
|
69
|
-
# On macOS/Linux:
|
|
70
|
-
source .venv/bin/activate
|
|
71
|
-
|
|
72
|
-
# load project dependencies
|
|
73
|
-
pip install -r requirements.txt
|
|
74
|
-
pip install -r requirements-dev.txt
|
|
75
|
-
|
|
76
|
-
# download library artifacts for the current version you want, eg v0.55.0
|
|
77
|
-
python scripts/download_artifacts.py c2pa-v0.55.0
|
|
78
|
-
```
|
|
79
|
-
|
|
80
|
-
2. Install the package in development mode:
|
|
81
|
-
|
|
82
|
-
```bash
|
|
83
|
-
pip install -e .
|
|
84
|
-
```
|
|
85
|
-
|
|
86
|
-
This will:
|
|
87
|
-
|
|
88
|
-
- Copy the appropriate libraries for your platform from `artifacts/` to `src/c2pa/libs/`
|
|
89
|
-
- Install the package in development mode, allowing you to make changes to the Python code without reinstalling
|
|
90
|
-
|
|
91
|
-
## Building Wheels
|
|
92
|
-
|
|
93
|
-
To build wheels for all platforms that have libraries in the `artifacts/` directory:
|
|
94
|
-
|
|
95
|
-
```bash
|
|
96
|
-
python setup.py bdist_wheel
|
|
97
|
-
```
|
|
98
|
-
|
|
99
|
-
You can use `twine` to verify the wheels have correct metadata:
|
|
100
|
-
|
|
101
|
-
```bash
|
|
102
|
-
twine check dist/*
|
|
103
|
-
```
|
|
104
|
-
|
|
105
|
-
This will create platform-specific wheels in the `dist/` directory.
|
|
106
|
-
|
|
107
|
-
## Running Tests
|
|
108
|
-
|
|
109
|
-
Run the tests:
|
|
110
|
-
|
|
111
|
-
```bash
|
|
112
|
-
make test
|
|
113
|
-
```
|
|
114
|
-
|
|
115
|
-
Alternatively, install pytest (if not already installed):
|
|
116
|
-
|
|
117
|
-
```bash
|
|
118
|
-
pip install pytest
|
|
119
|
-
```
|
|
120
|
-
|
|
121
|
-
And run:
|
|
122
|
-
|
|
123
|
-
```bash
|
|
124
|
-
pytest
|
|
125
|
-
```
|
|
126
|
-
|
|
127
|
-
## Contributing
|
|
128
|
-
|
|
129
|
-
Contributions are welcome! Please fork the repository and submit a pull request.
|
|
130
|
-
|
|
131
|
-
## License
|
|
132
|
-
|
|
133
|
-
This project is licensed under the Apache License 2.0 or the MIT License. See the LICENSE-MIT and LICENSE-APACHE files for details.
|
|
@@ -1,156 +0,0 @@
|
|
|
1
|
-
Metadata-Version: 2.4
|
|
2
|
-
Name: c2pa-python
|
|
3
|
-
Version: 0.10.0
|
|
4
|
-
Summary: Python bindings for the C2PA Content Authenticity Initiative (CAI) library
|
|
5
|
-
Author-email: Gavin Peacock <gvnpeacock@adobe.com>, Tania Mathern <mathern@adobe.com>
|
|
6
|
-
Maintainer-email: Gavin Peacock <gpeacock@adobe.com>
|
|
7
|
-
License: MIT OR Apache-2.0
|
|
8
|
-
Project-URL: homepage, https://contentauthenticity.org
|
|
9
|
-
Project-URL: repository, https://github.com/contentauth/c2pa-python
|
|
10
|
-
Classifier: Programming Language :: Python :: 3
|
|
11
|
-
Classifier: Operating System :: MacOS
|
|
12
|
-
Classifier: Operating System :: POSIX :: Linux
|
|
13
|
-
Classifier: Operating System :: Microsoft :: Windows
|
|
14
|
-
Requires-Python: >=3.10
|
|
15
|
-
Description-Content-Type: text/markdown
|
|
16
|
-
Requires-Dist: wheel>=0.41.2
|
|
17
|
-
Requires-Dist: setuptools>=68.0.0
|
|
18
|
-
Requires-Dist: toml>=0.10.2
|
|
19
|
-
Requires-Dist: pytest>=7.4.0
|
|
20
|
-
Requires-Dist: cryptography>=41.0.0
|
|
21
|
-
Requires-Dist: requests>=2.0.0
|
|
22
|
-
Dynamic: requires-python
|
|
23
|
-
|
|
24
|
-
# Python API for C2PA
|
|
25
|
-
|
|
26
|
-
This project provides a Python API for working with [C2PA](https://c2pa.org/) (Coalition for Content Provenance and Authenticity) manifests. It includes functionality for creating, signing, and verifying C2PA manifests, as well as working with assets and assertions.
|
|
27
|
-
|
|
28
|
-
## Features
|
|
29
|
-
|
|
30
|
-
- Create and sign C2PA manifests using various signing algorithms.
|
|
31
|
-
- Verify C2PA manifests and extract metadata.
|
|
32
|
-
- Add assertions and ingredients to assets.
|
|
33
|
-
- Examples and unit tests to demonstrate usage.
|
|
34
|
-
|
|
35
|
-
## Project Structure
|
|
36
|
-
|
|
37
|
-
```bash
|
|
38
|
-
.
|
|
39
|
-
├── .github/ # GitHub configuration files
|
|
40
|
-
├── artifacts/ # Platform-specific libraries for building (per subfolder)
|
|
41
|
-
│ └── your_target_platform/ # Platform-specific artifacts
|
|
42
|
-
├── docs/ # Project documentation
|
|
43
|
-
├── examples/ # Example scripts demonstrating usage
|
|
44
|
-
├── scripts/ # Utility scripts (eg. artifacts download)
|
|
45
|
-
├── src/ # Source code
|
|
46
|
-
│ └── c2pa/ # Main package directory
|
|
47
|
-
│ └── libs/ # Platform-specific libraries
|
|
48
|
-
├── tests/ # Unit tests and benchmarks
|
|
49
|
-
├── .gitignore # Git ignore rules
|
|
50
|
-
├── Makefile # Build and development commands
|
|
51
|
-
├── pyproject.toml # Python project configuration
|
|
52
|
-
├── requirements.txt # Python dependencies
|
|
53
|
-
├── requirements-dev.txt # Development dependencies
|
|
54
|
-
└── setup.py # Package setup script
|
|
55
|
-
```
|
|
56
|
-
|
|
57
|
-
## Package installation
|
|
58
|
-
|
|
59
|
-
The c2pa-python package is published to PyPI. You can install it from there by running:
|
|
60
|
-
|
|
61
|
-
```bash
|
|
62
|
-
pip install c2pa-python
|
|
63
|
-
```
|
|
64
|
-
|
|
65
|
-
To use the module in your Python code, import like this:
|
|
66
|
-
|
|
67
|
-
```python
|
|
68
|
-
import c2pa
|
|
69
|
-
```
|
|
70
|
-
|
|
71
|
-
## Examples
|
|
72
|
-
|
|
73
|
-
### Adding a "Do Not Train" Assertion
|
|
74
|
-
|
|
75
|
-
The `examples/training.py` script demonstrates how to add a "Do Not Train" assertion to an asset and verify it.
|
|
76
|
-
|
|
77
|
-
### Signing and Verifying Assets
|
|
78
|
-
|
|
79
|
-
The `examples/sign.py` script shows how to sign an asset with a C2PA manifest and verify it.
|
|
80
|
-
|
|
81
|
-
## Development Setup
|
|
82
|
-
|
|
83
|
-
1. Create and activate a virtual environment with native dependencies:
|
|
84
|
-
|
|
85
|
-
```bash
|
|
86
|
-
# Create virtual environment
|
|
87
|
-
python -m venv .venv
|
|
88
|
-
|
|
89
|
-
# Activate virtual environment
|
|
90
|
-
# On Windows:
|
|
91
|
-
.venv\Scripts\activate
|
|
92
|
-
# On macOS/Linux:
|
|
93
|
-
source .venv/bin/activate
|
|
94
|
-
|
|
95
|
-
# load project dependencies
|
|
96
|
-
pip install -r requirements.txt
|
|
97
|
-
pip install -r requirements-dev.txt
|
|
98
|
-
|
|
99
|
-
# download library artifacts for the current version you want, eg v0.55.0
|
|
100
|
-
python scripts/download_artifacts.py c2pa-v0.55.0
|
|
101
|
-
```
|
|
102
|
-
|
|
103
|
-
2. Install the package in development mode:
|
|
104
|
-
|
|
105
|
-
```bash
|
|
106
|
-
pip install -e .
|
|
107
|
-
```
|
|
108
|
-
|
|
109
|
-
This will:
|
|
110
|
-
|
|
111
|
-
- Copy the appropriate libraries for your platform from `artifacts/` to `src/c2pa/libs/`
|
|
112
|
-
- Install the package in development mode, allowing you to make changes to the Python code without reinstalling
|
|
113
|
-
|
|
114
|
-
## Building Wheels
|
|
115
|
-
|
|
116
|
-
To build wheels for all platforms that have libraries in the `artifacts/` directory:
|
|
117
|
-
|
|
118
|
-
```bash
|
|
119
|
-
python setup.py bdist_wheel
|
|
120
|
-
```
|
|
121
|
-
|
|
122
|
-
You can use `twine` to verify the wheels have correct metadata:
|
|
123
|
-
|
|
124
|
-
```bash
|
|
125
|
-
twine check dist/*
|
|
126
|
-
```
|
|
127
|
-
|
|
128
|
-
This will create platform-specific wheels in the `dist/` directory.
|
|
129
|
-
|
|
130
|
-
## Running Tests
|
|
131
|
-
|
|
132
|
-
Run the tests:
|
|
133
|
-
|
|
134
|
-
```bash
|
|
135
|
-
make test
|
|
136
|
-
```
|
|
137
|
-
|
|
138
|
-
Alternatively, install pytest (if not already installed):
|
|
139
|
-
|
|
140
|
-
```bash
|
|
141
|
-
pip install pytest
|
|
142
|
-
```
|
|
143
|
-
|
|
144
|
-
And run:
|
|
145
|
-
|
|
146
|
-
```bash
|
|
147
|
-
pytest
|
|
148
|
-
```
|
|
149
|
-
|
|
150
|
-
## Contributing
|
|
151
|
-
|
|
152
|
-
Contributions are welcome! Please fork the repository and submit a pull request.
|
|
153
|
-
|
|
154
|
-
## License
|
|
155
|
-
|
|
156
|
-
This project is licensed under the Apache License 2.0 or the MIT License. See the LICENSE-MIT and LICENSE-APACHE files for details.
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|