Metadata-Version: 2.4
Name: EmbedXMP
Version: 0.1.5.dev1
Summary: Dynamic XMP embed/read/remove orchestration for Swarmauri handlers.
License-Expression: Apache-2.0
License-File: LICENSE
Keywords: swarmauri,xmp,metadata,embedding,plugin,digital-asset-management,digital-asset-workflows,metadata-pipelines,media-workflows,metadata-extraction,metadata-synchronization,asyncio,media-metadata,python-library,async-discovery,plugin-discovery,png,gif,jpeg,svg,webp,tiff,pdf,mp4
Author: Jacob Stewart
Author-email: jacob@swarmauri.com
Requires-Python: >=3.10,<3.15
Classifier: Development Status :: 1 - Planning
Classifier: License :: OSI Approved :: Apache Software License
Classifier: Natural Language :: English
Classifier: Intended Audience :: Developers
Classifier: Framework :: AsyncIO
Classifier: Operating System :: OS Independent
Classifier: Topic :: Multimedia :: Graphics
Classifier: Topic :: Multimedia :: Video
Classifier: Topic :: Software Development :: Libraries
Classifier: Programming Language :: Python
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3 :: Only
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Programming Language :: Python :: 3.14
Provides-Extra: all
Provides-Extra: gif
Provides-Extra: jpeg
Provides-Extra: mp4
Provides-Extra: pdf
Provides-Extra: png
Provides-Extra: svg
Provides-Extra: tiff
Provides-Extra: webp
Requires-Dist: swarmauri_base
Requires-Dist: swarmauri_core
Requires-Dist: swarmauri_xmp_gif ; extra == "all"
Requires-Dist: swarmauri_xmp_gif ; extra == "gif"
Requires-Dist: swarmauri_xmp_jpeg ; extra == "all"
Requires-Dist: swarmauri_xmp_jpeg ; extra == "jpeg"
Requires-Dist: swarmauri_xmp_mp4 ; extra == "all"
Requires-Dist: swarmauri_xmp_mp4 ; extra == "mp4"
Requires-Dist: swarmauri_xmp_pdf ; extra == "all"
Requires-Dist: swarmauri_xmp_pdf ; extra == "pdf"
Requires-Dist: swarmauri_xmp_png
Requires-Dist: swarmauri_xmp_png ; extra == "all"
Requires-Dist: swarmauri_xmp_png ; extra == "png"
Requires-Dist: swarmauri_xmp_svg ; extra == "all"
Requires-Dist: swarmauri_xmp_svg ; extra == "svg"
Requires-Dist: swarmauri_xmp_tiff ; extra == "all"
Requires-Dist: swarmauri_xmp_tiff ; extra == "tiff"
Requires-Dist: swarmauri_xmp_webp ; extra == "all"
Requires-Dist: swarmauri_xmp_webp ; extra == "webp"
Project-URL: Changelog, https://github.com/swarmauri/swarmauri-sdk/releases
Project-URL: Documentation, https://github.com/swarmauri/swarmauri-sdk/tree/main/pkgs/plugins/EmbedXMP#readme
Project-URL: Discussions, https://github.com/orgs/swarmauri/discussions
Project-URL: Homepage, https://github.com/swarmauri/swarmauri-sdk
Project-URL: Issues, https://github.com/swarmauri/swarmauri-sdk/issues
Project-URL: Source, https://github.com/swarmauri/swarmauri-sdk/tree/main/pkgs/plugins/EmbedXMP
Description-Content-Type: text/markdown

![Swarmauri Logo](https://raw.githubusercontent.com/swarmauri/swarmauri-sdk/master/assets/swarmauri_sdk_brand.png)

<p align="center">
    <a href="https://pepy.tech/project/EmbedXMP/">
        <img src="https://static.pepy.tech/badge/EmbedXMP/month" alt="PyPI - Downloads"/></a>
    <a href="https://hits.sh/github.com/swarmauri/swarmauri-sdk/tree/master/pkgs/plugins/EmbedXMP/">
        <img alt="Hits" src="https://hits.sh/github.com/swarmauri/swarmauri-sdk/tree/master/pkgs/plugins/EmbedXMP.svg"/></a>
    <a href="https://pypi.org/project/EmbedXMP/">
        <img src="https://img.shields.io/badge/python-3.10%20%7C%203.11%20%7C%203.12%20%7C%203.13%20%7C%203.14-blue" alt="PyPI - Python Version"/></a>
    <a href="https://pypi.org/project/EmbedXMP/">
        <img src="https://img.shields.io/pypi/l/EmbedXMP" alt="PyPI - License"/></a>
    <a href="https://pypi.org/project/EmbedXMP/">
        <img src="https://img.shields.io/pypi/v/EmbedXMP?label=EmbedXMP&color=green" alt="PyPI - EmbedXMP"/></a>
</p>

EmbedXMP collects every installed `EmbedXmpBase` implementation, discovers them via Swarmauri's dynamic registry, and exposes a unified manager that can embed, read, or remove XMP packets without worrying about container formats.

## Features

- **Dynamic discovery** - lazily imports modules named `swarmauri_xmp_*` and collects subclasses registered under `EmbedXmpBase`.
- **Unified interface** - delegates to the first handler whose `supports` method confirms compatibility with the payload.
- **Convenience wrappers** - module-level helpers (`embed`, `read`, `remove`) keep high-level workflows succinct.
- **Async-friendly APIs** - integrate inside event loops without blocking when calling out to plugin hooks.
- **Media-format coverage** - load handlers for PNG, GIF, JPEG, SVG, WEBP, TIFF, PDF, and MP4 assets through extras.

## Installation

### Using `uv`

```bash
uv add EmbedXMP
```

### Using `pip`

```bash
pip install EmbedXMP
```

## Usage

```python
from pathlib import Path

from EmbedXMP import EmbedXMP, embed, embed_file, read, read_file_xmp

manager = EmbedXMP()
image = Path("example.png")
packet = """<x:xmpmeta xmlns:x='adobe:ns:meta/'><rdf:RDF>...</rdf:RDF></x:xmpmeta>"""

# Embed into the file in place.
embed_file(image, packet)

# Inspect metadata via the manager API.
xmp_text = manager.read(image.read_bytes(), str(image))
print(xmp_text)

# Remove metadata from the file when it is no longer required.
manager.remove(image.read_bytes(), str(image))
```

> **Note**
> You can provide either a `path` or a `hint` keyword argument when calling
> `embed`, `read`, or `remove` to help the manager pick the correct handler. The
> values are interchangeable as long as they match when both are supplied.

### Async orchestration

EmbedXMP's manager can be shared inside asynchronous workflows by deferring media-aware work to plugin hooks:

```python
import asyncio
from pathlib import Path

from EmbedXMP import EmbedXMP, embed


async def embed_all(paths: list[str], packet: str) -> None:
    manager = EmbedXMP()
    for path in paths:
        data = Path(path).read_bytes()
        await asyncio.to_thread(embed, data, packet, hint=path)


asyncio.run(embed_all(["one.png", "two.svg"], "<x:xmpmeta>...</x:xmpmeta>"))
```

## Project Resources

- Source: <https://github.com/swarmauri/swarmauri-sdk/tree/master/pkgs/plugins/EmbedXMP>
- Documentation: <https://github.com/swarmauri/swarmauri-sdk/tree/master/pkgs/plugins/EmbedXMP#readme>
- Issues: <https://github.com/swarmauri/swarmauri-sdk/issues>
- Releases: <https://github.com/swarmauri/swarmauri-sdk/releases>
- Discussions: <https://github.com/orgs/swarmauri/discussions>

