c2pa-python 0.17.0__tar.gz → 0.19.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.17.0/src/c2pa_python.egg-info → c2pa_python-0.19.0}/PKG-INFO +1 -1
- {c2pa_python-0.17.0 → c2pa_python-0.19.0}/pyproject.toml +1 -1
- {c2pa_python-0.17.0 → c2pa_python-0.19.0}/scripts/download_artifacts.py +68 -21
- {c2pa_python-0.17.0 → c2pa_python-0.19.0}/setup.py +63 -48
- {c2pa_python-0.17.0 → c2pa_python-0.19.0}/src/c2pa/c2pa.py +508 -237
- {c2pa_python-0.17.0 → c2pa_python-0.19.0}/src/c2pa/lib.py +30 -20
- {c2pa_python-0.17.0 → c2pa_python-0.19.0/src/c2pa_python.egg-info}/PKG-INFO +1 -1
- {c2pa_python-0.17.0 → c2pa_python-0.19.0}/tests/test_unit_tests.py +11 -2
- {c2pa_python-0.17.0 → c2pa_python-0.19.0}/LICENSE-APACHE +0 -0
- {c2pa_python-0.17.0 → c2pa_python-0.19.0}/LICENSE-MIT +0 -0
- {c2pa_python-0.17.0 → c2pa_python-0.19.0}/MANIFEST.in +0 -0
- {c2pa_python-0.17.0 → c2pa_python-0.19.0}/README.md +0 -0
- {c2pa_python-0.17.0 → c2pa_python-0.19.0}/requirements.txt +0 -0
- {c2pa_python-0.17.0 → c2pa_python-0.19.0}/setup.cfg +0 -0
- {c2pa_python-0.17.0 → c2pa_python-0.19.0}/src/c2pa/__init__.py +0 -0
- {c2pa_python-0.17.0 → c2pa_python-0.19.0}/src/c2pa/build.py +0 -0
- {c2pa_python-0.17.0 → c2pa_python-0.19.0}/src/c2pa_python.egg-info/SOURCES.txt +0 -0
- {c2pa_python-0.17.0 → c2pa_python-0.19.0}/src/c2pa_python.egg-info/dependency_links.txt +0 -0
- {c2pa_python-0.17.0 → c2pa_python-0.19.0}/src/c2pa_python.egg-info/entry_points.txt +0 -0
- {c2pa_python-0.17.0 → c2pa_python-0.19.0}/src/c2pa_python.egg-info/requires.txt +0 -0
- {c2pa_python-0.17.0 → c2pa_python-0.19.0}/src/c2pa_python.egg-info/top_level.txt +0 -0
- {c2pa_python-0.17.0 → c2pa_python-0.19.0}/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.
|
|
3
|
+
Version: 0.19.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.
|
|
7
|
+
version = "0.19.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" }
|
|
@@ -54,11 +54,20 @@ def detect_arch():
|
|
|
54
54
|
else:
|
|
55
55
|
raise ValueError(f"Unsupported CPU architecture: {machine}")
|
|
56
56
|
|
|
57
|
-
def get_platform_identifier():
|
|
58
|
-
"""Get the full platform identifier (arch-os) for the current system
|
|
59
|
-
|
|
57
|
+
def get_platform_identifier(target_arch=None):
|
|
58
|
+
"""Get the full platform identifier (arch-os) for the current system or target.
|
|
59
|
+
|
|
60
|
+
Args:
|
|
61
|
+
target_arch: Optional target architecture.
|
|
62
|
+
If provided, overrides auto-detection.
|
|
63
|
+
For macOS: 'universal2', 'arm64', or 'x86_64'
|
|
64
|
+
For Linux: 'aarch64' or 'x86_64'
|
|
65
|
+
For Windows: 'arm64' or 'x64'
|
|
66
|
+
|
|
60
67
|
Returns one of:
|
|
61
|
-
- universal-apple-darwin (for
|
|
68
|
+
- universal-apple-darwin (for macOS universal)
|
|
69
|
+
- aarch64-apple-darwin (for macOS ARM64)
|
|
70
|
+
- x86_64-apple-darwin (for macOS x86_64)
|
|
62
71
|
- x86_64-pc-windows-msvc (for Windows 64-bit)
|
|
63
72
|
- x86_64-unknown-linux-gnu (for Linux x86_64)
|
|
64
73
|
- aarch64-unknown-linux-gnu (for Linux ARM64)
|
|
@@ -67,11 +76,27 @@ def get_platform_identifier():
|
|
|
67
76
|
machine = platform.machine().lower()
|
|
68
77
|
|
|
69
78
|
if system == "darwin":
|
|
70
|
-
|
|
79
|
+
if target_arch == "arm64":
|
|
80
|
+
return "aarch64-apple-darwin"
|
|
81
|
+
elif target_arch == "x86_64":
|
|
82
|
+
return "x86_64-apple-darwin"
|
|
83
|
+
elif target_arch == "universal2":
|
|
84
|
+
return "universal-apple-darwin"
|
|
85
|
+
else:
|
|
86
|
+
# Auto-detect: prefer specific architecture over universal
|
|
87
|
+
if machine == "arm64":
|
|
88
|
+
return "aarch64-apple-darwin"
|
|
89
|
+
elif machine == "x86_64":
|
|
90
|
+
return "x86_64-apple-darwin"
|
|
91
|
+
else:
|
|
92
|
+
return "universal-apple-darwin"
|
|
71
93
|
elif system == "windows":
|
|
72
|
-
|
|
94
|
+
if target_arch == "arm64":
|
|
95
|
+
return "aarch64-pc-windows-msvc"
|
|
96
|
+
else:
|
|
97
|
+
return "x86_64-pc-windows-msvc"
|
|
73
98
|
elif system == "linux":
|
|
74
|
-
if machine in ["arm64", "aarch64"]:
|
|
99
|
+
if target_arch == "aarch64" or machine in ["arm64", "aarch64"]:
|
|
75
100
|
return "aarch64-unknown-linux-gnu"
|
|
76
101
|
else:
|
|
77
102
|
return "x86_64-unknown-linux-gnu"
|
|
@@ -101,19 +126,20 @@ def download_and_extract_libs(url, platform_name):
|
|
|
101
126
|
response = requests.get(url, headers=headers)
|
|
102
127
|
response.raise_for_status()
|
|
103
128
|
|
|
129
|
+
print(f"Downloaded zip file, extracting lib files...")
|
|
104
130
|
with zipfile.ZipFile(io.BytesIO(response.content)) as zip_ref:
|
|
105
131
|
# Extract only files inside the libs/ directory
|
|
132
|
+
extracted_count = 0
|
|
106
133
|
for member in zip_ref.namelist():
|
|
107
|
-
print(f" Processing zip member: {member}")
|
|
108
134
|
if member.startswith("lib/") and not member.endswith("/"):
|
|
109
|
-
print(f" Processing lib file from downloadedzip: {member}")
|
|
110
135
|
target_path = platform_dir / os.path.relpath(member, "lib")
|
|
111
|
-
print(f" Moving file to target path: {target_path}")
|
|
112
136
|
target_path.parent.mkdir(parents=True, exist_ok=True)
|
|
113
137
|
with zip_ref.open(member) as source, open(target_path, "wb") as target:
|
|
114
138
|
target.write(source.read())
|
|
139
|
+
extracted_count += 1
|
|
140
|
+
print(f" Extracted: {member} -> {target_path}")
|
|
115
141
|
|
|
116
|
-
print(f"Done downloading and extracting
|
|
142
|
+
print(f"Done downloading and extracting {extracted_count} library files for {platform_name}")
|
|
117
143
|
|
|
118
144
|
def copy_artifacts_to_root():
|
|
119
145
|
"""Copy the artifacts folder from scripts/artifacts to the root of the repository."""
|
|
@@ -122,37 +148,53 @@ def copy_artifacts_to_root():
|
|
|
122
148
|
return
|
|
123
149
|
|
|
124
150
|
print("Copying artifacts from scripts/artifacts to root...")
|
|
151
|
+
print("Contents of scripts/artifacts before copying:")
|
|
152
|
+
for item in sorted(SCRIPTS_ARTIFACTS_DIR.iterdir()):
|
|
153
|
+
print(f" {item.name}")
|
|
154
|
+
|
|
125
155
|
if ROOT_ARTIFACTS_DIR.exists():
|
|
126
156
|
shutil.rmtree(ROOT_ARTIFACTS_DIR)
|
|
127
157
|
print(f"Copying from {SCRIPTS_ARTIFACTS_DIR} to {ROOT_ARTIFACTS_DIR}")
|
|
128
158
|
shutil.copytree(SCRIPTS_ARTIFACTS_DIR, ROOT_ARTIFACTS_DIR)
|
|
129
159
|
print("Done copying artifacts")
|
|
130
|
-
print("\nFolder content of artifacts directory:")
|
|
160
|
+
print("\nFolder content of root artifacts directory:")
|
|
131
161
|
for item in sorted(ROOT_ARTIFACTS_DIR.iterdir()):
|
|
132
162
|
print(f" {item.name}")
|
|
133
163
|
|
|
134
164
|
def main():
|
|
135
165
|
if len(sys.argv) < 2:
|
|
136
|
-
print("Usage: python download_artifacts.py <release_tag>")
|
|
166
|
+
print("Usage: python download_artifacts.py <release_tag> [target_architecture]")
|
|
137
167
|
print("Example: python download_artifacts.py c2pa-v0.49.5")
|
|
168
|
+
print("Example: python download_artifacts.py c2pa-v0.49.5 arm64")
|
|
138
169
|
sys.exit(1)
|
|
139
170
|
|
|
140
171
|
release_tag = sys.argv[1]
|
|
172
|
+
target_arch = sys.argv[2] if len(sys.argv) > 2 else None
|
|
173
|
+
|
|
141
174
|
try:
|
|
175
|
+
# Clean up any existing artifacts before starting
|
|
176
|
+
print("Cleaning up existing artifacts...")
|
|
177
|
+
if SCRIPTS_ARTIFACTS_DIR.exists():
|
|
178
|
+
shutil.rmtree(SCRIPTS_ARTIFACTS_DIR)
|
|
142
179
|
SCRIPTS_ARTIFACTS_DIR.mkdir(exist_ok=True)
|
|
143
180
|
print(f"Fetching release information for tag {release_tag}...")
|
|
144
181
|
release = get_release_by_tag(release_tag)
|
|
145
182
|
print(f"Found release: {release['tag_name']} \n")
|
|
146
183
|
|
|
147
|
-
# Get the platform identifier for the
|
|
184
|
+
# Get the platform identifier for the target architecture
|
|
148
185
|
env_platform = os.environ.get("C2PA_LIBS_PLATFORM")
|
|
149
186
|
if env_platform:
|
|
150
187
|
print(f"Using platform from environment variable C2PA_LIBS_PLATFORM: {env_platform}")
|
|
151
|
-
|
|
188
|
+
platform_id = env_platform
|
|
189
|
+
else:
|
|
190
|
+
platform_id = get_platform_identifier(target_arch)
|
|
191
|
+
print(f"Using target architecture: {target_arch or 'auto-detected'}")
|
|
192
|
+
print(f"Detected machine architecture: {platform.machine()}")
|
|
193
|
+
print(f"Detected system: {platform.system()}")
|
|
194
|
+
|
|
152
195
|
print("Looking up releases for platform id: ", platform_id)
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
print(f"Target platform: {platform_id} (set through{platform_source})")
|
|
196
|
+
platform_source = "environment variable" if env_platform else "target architecture" if target_arch else "auto-detection"
|
|
197
|
+
print(f"Target platform: {platform_id} (set through {platform_source})")
|
|
156
198
|
|
|
157
199
|
# Construct the expected asset name
|
|
158
200
|
expected_asset_name = f"{release_tag}-{platform_id}.zip"
|
|
@@ -160,18 +202,23 @@ def main():
|
|
|
160
202
|
|
|
161
203
|
# Find the matching asset in the release
|
|
162
204
|
matching_asset = None
|
|
205
|
+
print(f"Looking for asset: {expected_asset_name}")
|
|
206
|
+
print("Available assets in release:")
|
|
163
207
|
for asset in release['assets']:
|
|
208
|
+
print(f" - {asset['name']}")
|
|
164
209
|
if asset['name'] == expected_asset_name:
|
|
165
210
|
matching_asset = asset
|
|
166
|
-
|
|
211
|
+
print(f"Using native library: {matching_asset['name']}")
|
|
167
212
|
|
|
168
213
|
if matching_asset:
|
|
169
|
-
print(f"
|
|
214
|
+
print(f"\nDownloading asset: {matching_asset['name']}")
|
|
170
215
|
download_and_extract_libs(matching_asset['browser_download_url'], platform_id)
|
|
171
216
|
print("\nArtifacts have been downloaded and extracted successfully!")
|
|
172
217
|
copy_artifacts_to_root()
|
|
173
218
|
else:
|
|
174
|
-
print(f"\nNo matching asset found: {
|
|
219
|
+
print(f"\nNo matching asset found for platform: {platform_id}")
|
|
220
|
+
print(f"Expected asset name: {expected_asset_name}")
|
|
221
|
+
print("Please check if the asset exists in the release or if the platform identifier is correct.")
|
|
175
222
|
|
|
176
223
|
except requests.exceptions.RequestException as e:
|
|
177
224
|
print(f"Error: {e}")
|
|
@@ -38,6 +38,8 @@ PLATFORM_EXTENSIONS = {
|
|
|
38
38
|
# Based on what c2pa-rs repo publishes
|
|
39
39
|
PLATFORM_FOLDERS = {
|
|
40
40
|
'universal-apple-darwin': 'dylib',
|
|
41
|
+
'aarch64-apple-darwin': 'dylib',
|
|
42
|
+
'x86_64-apple-darwin': 'dylib',
|
|
41
43
|
'x86_64-pc-windows-msvc': 'dll',
|
|
42
44
|
'x86_64-unknown-linux-gnu': 'so',
|
|
43
45
|
'aarch64-unknown-linux-gnu': 'so',
|
|
@@ -48,16 +50,20 @@ ARTIFACTS_DIR = Path('artifacts') # Where downloaded libraries are stored
|
|
|
48
50
|
PACKAGE_LIBS_DIR = Path('src/c2pa/libs') # Where libraries will be copied for the wheel
|
|
49
51
|
|
|
50
52
|
|
|
51
|
-
def get_platform_identifier() -> str:
|
|
52
|
-
"""Get a platform identifier (arch-os) for the current system
|
|
53
|
-
matching downloaded identifiers used by the Github publisher.
|
|
53
|
+
def get_platform_identifier(target_arch=None) -> str:
|
|
54
|
+
"""Get a platform identifier (arch-os) for the current system or target architecture.
|
|
54
55
|
|
|
55
56
|
Args:
|
|
56
|
-
|
|
57
|
-
|
|
57
|
+
target_arch: Optional target architecture.
|
|
58
|
+
If provided, overrides auto-detection.
|
|
59
|
+
For macOS: 'universal2', 'arm64', or 'x86_64'
|
|
60
|
+
For Linux: 'aarch64' or 'x86_64'
|
|
61
|
+
For Windows: 'arm64' or 'x64'
|
|
58
62
|
|
|
59
63
|
Returns one of:
|
|
60
|
-
- universal-apple-darwin (for macOS)
|
|
64
|
+
- universal-apple-darwin (for macOS universal)
|
|
65
|
+
- aarch64-apple-darwin (for macOS ARM64)
|
|
66
|
+
- x86_64-apple-darwin (for macOS x86_64)
|
|
61
67
|
- x86_64-pc-windows-msvc (for Windows 64-bit)
|
|
62
68
|
- x86_64-unknown-linux-gnu (for Linux 64-bit)
|
|
63
69
|
- aarch64-unknown-linux-gnu (for Linux ARM64)
|
|
@@ -65,13 +71,22 @@ def get_platform_identifier() -> str:
|
|
|
65
71
|
system = platform.system().lower()
|
|
66
72
|
|
|
67
73
|
if system == "darwin":
|
|
68
|
-
|
|
74
|
+
if target_arch == "arm64":
|
|
75
|
+
return "aarch64-apple-darwin"
|
|
76
|
+
elif target_arch == "x86_64":
|
|
77
|
+
return "x86_64-apple-darwin"
|
|
78
|
+
else:
|
|
79
|
+
return "universal-apple-darwin"
|
|
69
80
|
elif system == "windows":
|
|
70
|
-
|
|
81
|
+
if target_arch == "arm64":
|
|
82
|
+
return "aarch64-pc-windows-msvc"
|
|
83
|
+
else:
|
|
84
|
+
return "x86_64-pc-windows-msvc"
|
|
71
85
|
elif system == "linux":
|
|
72
|
-
if platform.machine() == "aarch64":
|
|
86
|
+
if target_arch == "aarch64" or platform.machine() == "aarch64":
|
|
73
87
|
return "aarch64-unknown-linux-gnu"
|
|
74
|
-
|
|
88
|
+
else:
|
|
89
|
+
return "x86_64-unknown-linux-gnu"
|
|
75
90
|
else:
|
|
76
91
|
raise ValueError(f"Unsupported operating system: {system}")
|
|
77
92
|
|
|
@@ -157,9 +172,38 @@ if 'develop' in sys.argv or 'install' in sys.argv:
|
|
|
157
172
|
|
|
158
173
|
# For wheel building (both bdist_wheel and build)
|
|
159
174
|
if 'bdist_wheel' in sys.argv or 'build' in sys.argv:
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
175
|
+
# Check if we're building for a specific architecture
|
|
176
|
+
# This is mostly to support macOS wheel builds
|
|
177
|
+
target_arch = None
|
|
178
|
+
for i, arg in enumerate(sys.argv):
|
|
179
|
+
if arg == '--plat-name':
|
|
180
|
+
if i + 1 < len(sys.argv):
|
|
181
|
+
plat_name = sys.argv[i + 1]
|
|
182
|
+
if 'arm64' in plat_name:
|
|
183
|
+
target_arch = 'arm64'
|
|
184
|
+
elif 'x86_64' in plat_name:
|
|
185
|
+
target_arch = 'x86_64'
|
|
186
|
+
elif 'universal2' in plat_name:
|
|
187
|
+
target_arch = 'universal2'
|
|
188
|
+
break
|
|
189
|
+
|
|
190
|
+
# Get the platform identifier for the target architecture
|
|
191
|
+
target_platform = get_platform_identifier(target_arch)
|
|
192
|
+
print(f"Building wheel for target platform: {target_platform}")
|
|
193
|
+
|
|
194
|
+
# Check if we have libraries for this platform
|
|
195
|
+
platform_dir = ARTIFACTS_DIR / target_platform
|
|
196
|
+
if not platform_dir.exists() or not any(platform_dir.iterdir()):
|
|
197
|
+
print(f"Warning: No libraries found for platform {target_platform}")
|
|
198
|
+
print("Available platforms:")
|
|
199
|
+
for platform_name in find_available_platforms():
|
|
200
|
+
print(f" - {platform_name}")
|
|
201
|
+
|
|
202
|
+
# Copy libraries for the target platform
|
|
203
|
+
try:
|
|
204
|
+
copy_platform_libraries(target_platform, clean_first=True)
|
|
205
|
+
|
|
206
|
+
# Build the wheel
|
|
163
207
|
setup(
|
|
164
208
|
name=PACKAGE_NAME,
|
|
165
209
|
version=VERSION,
|
|
@@ -167,50 +211,21 @@ if 'bdist_wheel' in sys.argv or 'build' in sys.argv:
|
|
|
167
211
|
packages=find_namespace_packages(where="src"),
|
|
168
212
|
include_package_data=True,
|
|
169
213
|
package_data={
|
|
170
|
-
"c2pa": ["libs/*"],
|
|
214
|
+
"c2pa": ["libs/*"],
|
|
171
215
|
},
|
|
172
216
|
classifiers=[
|
|
173
217
|
"Programming Language :: Python :: 3",
|
|
174
|
-
get_platform_classifier(
|
|
218
|
+
get_platform_classifier(target_platform),
|
|
175
219
|
],
|
|
176
220
|
python_requires=">=3.10",
|
|
177
221
|
long_description=open("README.md").read(),
|
|
178
222
|
long_description_content_type="text/markdown",
|
|
179
223
|
license="MIT OR Apache-2.0",
|
|
180
224
|
)
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
for platform_name in available_platforms:
|
|
186
|
-
print(f"\nBuilding wheel for {platform_name}...")
|
|
187
|
-
try:
|
|
188
|
-
# Copy libraries for this platform (cleaning first)
|
|
189
|
-
copy_platform_libraries(platform_name, clean_first=True)
|
|
190
|
-
|
|
191
|
-
# Build the wheel
|
|
192
|
-
setup(
|
|
193
|
-
name=PACKAGE_NAME,
|
|
194
|
-
version=VERSION,
|
|
195
|
-
package_dir={"": "src"},
|
|
196
|
-
packages=find_namespace_packages(where="src"),
|
|
197
|
-
include_package_data=True,
|
|
198
|
-
package_data={
|
|
199
|
-
"c2pa": ["libs/*"], # Include all files in libs directory
|
|
200
|
-
},
|
|
201
|
-
classifiers=[
|
|
202
|
-
"Programming Language :: Python :: 3",
|
|
203
|
-
get_platform_classifier(platform_name),
|
|
204
|
-
],
|
|
205
|
-
python_requires=">=3.10",
|
|
206
|
-
long_description=open("README.md").read(),
|
|
207
|
-
long_description_content_type="text/markdown",
|
|
208
|
-
license="MIT OR Apache-2.0",
|
|
209
|
-
)
|
|
210
|
-
finally:
|
|
211
|
-
# Clean up by removing the package libs directory
|
|
212
|
-
if PACKAGE_LIBS_DIR.exists():
|
|
213
|
-
shutil.rmtree(PACKAGE_LIBS_DIR)
|
|
225
|
+
finally:
|
|
226
|
+
# Clean up
|
|
227
|
+
if PACKAGE_LIBS_DIR.exists():
|
|
228
|
+
shutil.rmtree(PACKAGE_LIBS_DIR)
|
|
214
229
|
sys.exit(0)
|
|
215
230
|
|
|
216
231
|
# For sdist and development installation
|