mirror of
https://github.com/wiltodelta/remove-ai-watermarks.git
synced 2026-10-14 13:30:55 +02:00
Collect provider samples from Higgsfield, Runway and Dreamina plus Google Photos, Gemini, Grok and YouTube re-encodes into data/captures/2026-09 with a hash-checked manifest, and use them to fix attribution and false positives: - Attribute aggregator outputs: Higgsfield job metadata, Dreamina's re-signed manifests, Runway's own C2PA signer, TC260 video producers. - Veto any visible video mark when a valid C2PA claim names another vendor (a Gemini Omni clip read as Sora on steam), and gate Kling and Hailuo matches on edge, anchor and white-label evidence. - Veto the Gemini sparkle when trusted provenance names another vendor. - Report SynthID as present for Google Photos AI edits: Google's checker found it on all four measured edits, though manifests record no action. - Add Vidu video and Wan image marks, TC260 audio placements, and record the AIGC key in metadata records. - Document the research sweep, the Dreamina badge decision, and verified Google statements on SynthID in Photos. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
106 lines
3.3 KiB
Python
106 lines
3.3 KiB
Python
"""Published dependency boundaries."""
|
|
|
|
from __future__ import annotations
|
|
|
|
from importlib.metadata import metadata, requires
|
|
|
|
from packaging.requirements import Requirement
|
|
from packaging.specifiers import SpecifierSet
|
|
from packaging.utils import canonicalize_name
|
|
|
|
|
|
def _requirement_names(extra: str | None = None, *, python_version: str | None = None) -> set[str]:
|
|
selected_extra = extra or ""
|
|
environment = {"extra": selected_extra}
|
|
if python_version is not None:
|
|
environment["python_version"] = python_version
|
|
parsed = (Requirement(value) for value in requires("remove-ai-watermarks") or [])
|
|
return {
|
|
canonicalize_name(requirement.name)
|
|
for requirement in parsed
|
|
if requirement.marker is None or requirement.marker.evaluate(environment)
|
|
}
|
|
|
|
|
|
def test_supported_python_floor_is_published():
|
|
assert SpecifierSet(metadata("remove-ai-watermarks")["Requires-Python"]) == SpecifierSet(">=3.11,<3.15")
|
|
|
|
|
|
def test_default_install_is_metadata_focused():
|
|
default = _requirement_names()
|
|
|
|
assert {
|
|
"c2pa-python",
|
|
"click",
|
|
"piexif",
|
|
"pillow",
|
|
"python-dotenv",
|
|
} <= default
|
|
assert {
|
|
"av",
|
|
"invisible-watermark",
|
|
"numpy",
|
|
"opencv-python-headless",
|
|
"pillow-heif",
|
|
"torch",
|
|
"trustmark",
|
|
}.isdisjoint(default)
|
|
|
|
|
|
def test_pixels_extra_owns_shared_numeric_dependencies():
|
|
assert {
|
|
"numpy",
|
|
"opencv-python-headless",
|
|
} <= _requirement_names("pixels")
|
|
|
|
|
|
def test_video_extra_owns_timestamp_dependency():
|
|
assert "av" in _requirement_names("video")
|
|
|
|
|
|
def test_file_format_and_detector_dependencies_are_independent():
|
|
assert "pillow-heif" in _requirement_names("heif")
|
|
assert "pywavelets" in _requirement_names("detect")
|
|
|
|
|
|
def test_openai_sdk_is_development_only():
|
|
assert "openai" in _requirement_names("dev")
|
|
assert "openai" not in _requirement_names("all")
|
|
|
|
|
|
def test_trustmark_covers_every_supported_python():
|
|
# trustmark 0.9.2 dropped its NumPy <2 pin, so the extra is no longer capped at 3.12.
|
|
for python_version in ("3.12", "3.13", "3.14"):
|
|
assert "trustmark" in _requirement_names("trustmark", python_version=python_version)
|
|
|
|
|
|
def test_extras_use_capability_names_without_legacy_aliases():
|
|
extras = set(metadata("remove-ai-watermarks").get_all("Provides-Extra") or [])
|
|
|
|
assert {"pixels", "heif", "visible", "video", "detect", "diffusion", "classify", "classify-onnx"} <= extras
|
|
assert {"gpu", "remove", "detect-pywavelets", "verify"}.isdisjoint(extras)
|
|
|
|
|
|
def test_classify_extra_owns_the_photo_heads() -> None:
|
|
names = _requirement_names("classify")
|
|
assert {"torch", "transformers", "huggingface-hub", "tokenizers"} <= names
|
|
|
|
|
|
def test_classify_onnx_extra_extends_the_default_classifier() -> None:
|
|
names = _requirement_names("classify-onnx")
|
|
assert {"torch", "transformers", "huggingface-hub", "tokenizers", "onnxruntime"} <= names
|
|
|
|
|
|
def test_qwen_zimage_extra_owns_every_profile_tokenizer_backend() -> None:
|
|
assert "sentencepiece" in _requirement_names("qwen-zimage")
|
|
|
|
|
|
def test_production_all_does_not_include_development_tools():
|
|
assert {
|
|
"pyright",
|
|
"pytest",
|
|
"pytest-cov",
|
|
"pytest-xdist",
|
|
"ruff",
|
|
}.isdisjoint(_requirement_names("all"))
|