c2pa-python


Namec2pa-python JSON
Version 0.4.0 PyPI version JSON
download
home_pageNone
SummaryPython bindings for the C2PA Content Authenticity Initiative (CAI) library
upload_time2024-01-29 13:28:31
maintainerNone
docs_urlNone
authorGavin Peacock <gpeacock@adobe.com
requires_python>=3.7
licenseNone
keywords c2pa cai content credentials metadata provenance
VCS
bugtrack_url
requirements No requirements were recorded.
Travis-CI No Travis.
coveralls test coverage No coveralls.
            # C2PA Python

Python bindings for the C2PA Content Authenticity Initiative (CAI) library.

This library enables you to read and validate C2PA data in supported media files and add signed manifests to supported media files.

**WARNING**: This is an early prerelease version of this library.  There may be bugs and unimplemented features, and the API is subject to change.

## Installation

Install from PyPI by entering this command:

```
pip install -U c2pa-python
```

This is a platform wheel built with Rust. If your platform is not already supported,
see the development section for info on how to build from source.

```
## Usage

### Import

Import the C2PA module as follows:

```py
import c2pa
```

### Read and validate C2PA data in a file

Use the `read_file` function to read C2PA data from the specified file:

```py
json_store = c2pa.read_file("path/to/media_file.jpg", "path/to/data_dir")
```

This function examines the specified media file for C2PA data and generates a JSON report of any data it finds. If there are validation errors, the report includes a `validation_status` field.  For a summary of supported media types, see [Supported file formats](#supported-file-formats).

A media file may contain many manifests in a manifest store. The most recent manifest is identified by the value of the `active_manifest` field in the manifests map.

If the optional `data_dir` is provided, the function extracts any binary resources, such as thumbnails, icons, and C2PA data into that directory. These files are referenced by the identifier fields in the manifest store report.

NOTE: For a comprehensive reference to the JSON manifest structure, see the [CAI manifest store reference](https://contentauth.github.io/json-manifest-reference/manifest-reference).

### Add a signed manifest to a media file

Use the `sign_file` function to add a signed manifest to a media file.

```py
result = c2pa.sign_file("path/to/source.jpg", 
                                        "path/to/dest.jpg", 
                                        manifest_json, 
                                        sign_info, 
                                        data_dir)
```

The parameters (in order) are:
- The source (original) media file.
- The destination file that will contain a copy of the source file with the manifest data added.
- `manifest_json`, a JSON-formatted string containing the manifest data you want to add; see [Creating a manifest JSON definition file](#creating-a-manifest-json-definition-file) below.
- `sign_info`, a `SignerInfo` object instance; see [Generating SignerInfo](#generating-signerinfo) below.
- `data_dir` optionally specifies a directory path from which to load resource files referenced in the manifest JSON identifier fields; for example, thumbnails, icons, and manifest data for ingredients.

### Create a SignerInfo Instance

A `SignerInfo` object contains information about a signature.  To create an instance of `SignerInfo`, first set up the signer information from the public and private key `.pem` files as follows:

```py
certs = open("path/to/public_certs.pem","rb").read()
prv_key = open("path/to/private_key.pem","rb").read()
```

Then create a new `SignerInfo` instance using the keys as follows, specifying the signing algorithm used and optionally a time stamp authority URL:

```py
sign_info = c2pa.SignerInfo("es256", certs, priv_key, "http://timestamp.digicert.com")
```

For the list of supported signing algorithms, see [Creating and using an X.509 certificate](https://opensource.contentauthenticity.org/docs/c2patool/x_509).

### Creating a manifest JSON definition file

The manifest JSON string defines the C2PA manifest to add to the file.

```py
manifest_json = json.dumps({
    "claim_generator": "python_test/0.1",
    "assertions": [
    {
      "label": "c2pa.training-mining",
      "data": {
        "entries": {
          "c2pa.ai_generative_training": { "use": "notAllowed" },
          "c2pa.ai_inference": { "use": "notAllowed" },
          "c2pa.ai_training": { "use": "notAllowed" },
          "c2pa.data_mining": { "use": "notAllowed" }
        }
      }
    }
  ]
 })
```

## Development

It is best to [set up a virtual environment](https://virtualenv.pypa.io/en/latest/installation.html) for development and testing.

To build from source on Linux, install curl and rustup and set up python

First update apt
```
apt update
```

Install Rust
```apt install curl
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
source "$HOME/.cargo/env"
```

Install Python, pip and venv
```
apt install python3
apt install pip
apt install python3.11-venv
python3 -m venv .venv
```

Build the wheel for your platform
```
source .venv/bin/activate
pip install maturin
pip install uniffi-bindgen
python3 -m pip install build
pip install -U pytest

python3 -m build --wheel
```

### ManyLinux build
```
docker run -it quay.io/pypa/manylinux_2_28_aarch64 bash
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
source "$HOME/.cargo/env"
export PATH=/opt/python/cp312-cp312/bin:$PATH
pip install maturin
pip install venv
pip install build
pip install -U pytest

cd home
git clone https://github.com/contentauth/c2pa-python.git 
cd c2pa-python
python3 -m build --wheel
auditwheel repair target/wheels/c2pa_python-0.4.0-py3-none-linux_aarch64.whl 

```

### Testing

We use [PyTest](https://docs.pytest.org/) for testing.

Run tests by entering this command:

```
source .venv/bin/activate
maturin develop
pytest
deactivate
```

### Example 

Run the example code like this:

```
source .venv/bin/activate
maturin develop
python3 tests/training.py
deactivate
```

## Supported file formats

 | Extensions    | MIME type                                           |
 | ------------- | --------------------------------------------------- |
 | `avi`         | `video/msvideo`, `video/avi`, `application-msvideo` |
 | `avif`        | `image/avif`                                        |
 | `c2pa`        | `application/x-c2pa-manifest-store`                 |
 | `dng`         | `image/x-adobe-dng`                                 |
 | `heic`        | `image/heic`                                        |
 | `heif`        | `image/heif`                                        |
 | `jpg`, `jpeg` | `image/jpeg`                                        |
 | `m4a`         | `audio/mp4`                                         |
 | `mp4`         | `video/mp4`, `application/mp4`                      |
 | `mov`         | `video/quicktime`                                   |
 | `png`         | `image/png`                                         |
 | `svg`         | `image/svg+xml`                                     |
 | `tif`,`tiff`  | `image/tiff`                                        |
 | `wav`         | `audio/x-wav`                                       |
 | `webp`        | `image/webp`                                        |


## Change Notes:

Version 0.3.0 changes:
There are some breaking changes to align with future APIs:
- `C2paSignerInfo` moves the `alg` to the first parameter from the 3rd.
- `c2pa.verify_from_file_json` is now `c2pa.read_file`.
- `c2pa.ingredient_from_file_json` is now `c2pa.read_ingredient_file`.
- `c2pa.add_manifest_to_file_json` is now `c2pa.sign_file`.
- There are many more specific errors types now, and Error messages always start with the name of the error i.e (str(err.value).startswith("ManifestNotFound")).
- The ingredient thumbnail identifier may be jumbf uri reference if a valid thumb already exists in the active manifest.
- Extracted file paths for read_file now use a folder structure and different naming conventions.

## License

This package is distributed under the terms of both the [MIT license](https://github.com/contentauth/c2pa-rs/blob/main/LICENSE-MIT) and the [Apache License (Version 2.0)](https://github.com/contentauth/c2pa-rs/blob/main/LICENSE-APACHE).

Note that some components and dependent crates are licensed under different terms; please check the license terms for each crate and component for details.

### Contributions and feedback

We welcome contributions to this project.  For information on contributing, providing feedback, and about ongoing work, see [Contributing](https://github.com/contentauth/c2pa-js/blob/main/CONTRIBUTING.md).




            

Raw data

            {
    "_id": null,
    "home_page": null,
    "name": "c2pa-python",
    "maintainer": null,
    "docs_url": null,
    "requires_python": ">=3.7",
    "maintainer_email": "Gavin Peacock <gpeacock@adobe.com>",
    "keywords": "C2PA,CAI,content credentials,metadata,provenance",
    "author": "Gavin Peacock <gpeacock@adobe.com",
    "author_email": "Gavin Peacock <gpeacock@adobe.com>",
    "download_url": "https://files.pythonhosted.org/packages/9c/4d/3c21ab17831494b2555c4347227754a2fedf3061393b7d9c08dde69a9fd4/c2pa_python-0.4.0.tar.gz",
    "platform": null,
    "description": "# C2PA Python\n\nPython bindings for the C2PA Content Authenticity Initiative (CAI) library.\n\nThis library enables you to read and validate C2PA data in supported media files and add signed manifests to supported media files.\n\n**WARNING**: This is an early prerelease version of this library.  There may be bugs and unimplemented features, and the API is subject to change.\n\n## Installation\n\nInstall from PyPI by entering this command:\n\n```\npip install -U c2pa-python\n```\n\nThis is a platform wheel built with Rust. If your platform is not already supported,\nsee the development section for info on how to build from source.\n\n```\n## Usage\n\n### Import\n\nImport the C2PA module as follows:\n\n```py\nimport c2pa\n```\n\n### Read and validate C2PA data in a file\n\nUse the `read_file` function to read C2PA data from the specified file:\n\n```py\njson_store = c2pa.read_file(\"path/to/media_file.jpg\", \"path/to/data_dir\")\n```\n\nThis function examines the specified media file for C2PA data and generates a JSON report of any data it finds. If there are validation errors, the report includes a `validation_status` field.  For a summary of supported media types, see [Supported file formats](#supported-file-formats).\n\nA media file may contain many manifests in a manifest store. The most recent manifest is identified by the value of the `active_manifest` field in the manifests map.\n\nIf the optional `data_dir` is provided, the function extracts any binary resources, such as thumbnails, icons, and C2PA data into that directory. These files are referenced by the identifier fields in the manifest store report.\n\nNOTE: For a comprehensive reference to the JSON manifest structure, see the [CAI manifest store reference](https://contentauth.github.io/json-manifest-reference/manifest-reference).\n\n### Add a signed manifest to a media file\n\nUse the `sign_file` function to add a signed manifest to a media file.\n\n```py\nresult = c2pa.sign_file(\"path/to/source.jpg\", \n                                        \"path/to/dest.jpg\", \n                                        manifest_json, \n                                        sign_info, \n                                        data_dir)\n```\n\nThe parameters (in order) are:\n- The source (original) media file.\n- The destination file that will contain a copy of the source file with the manifest data added.\n- `manifest_json`, a JSON-formatted string containing the manifest data you want to add; see [Creating a manifest JSON definition file](#creating-a-manifest-json-definition-file) below.\n- `sign_info`, a `SignerInfo` object instance; see [Generating SignerInfo](#generating-signerinfo) below.\n- `data_dir` optionally specifies a directory path from which to load resource files referenced in the manifest JSON identifier fields; for example, thumbnails, icons, and manifest data for ingredients.\n\n### Create a SignerInfo Instance\n\nA `SignerInfo` object contains information about a signature.  To create an instance of `SignerInfo`, first set up the signer information from the public and private key `.pem` files as follows:\n\n```py\ncerts = open(\"path/to/public_certs.pem\",\"rb\").read()\nprv_key = open(\"path/to/private_key.pem\",\"rb\").read()\n```\n\nThen create a new `SignerInfo` instance using the keys as follows, specifying the signing algorithm used and optionally a time stamp authority URL:\n\n```py\nsign_info = c2pa.SignerInfo(\"es256\", certs, priv_key, \"http://timestamp.digicert.com\")\n```\n\nFor the list of supported signing algorithms, see [Creating and using an X.509 certificate](https://opensource.contentauthenticity.org/docs/c2patool/x_509).\n\n### Creating a manifest JSON definition file\n\nThe manifest JSON string defines the C2PA manifest to add to the file.\n\n```py\nmanifest_json = json.dumps({\n    \"claim_generator\": \"python_test/0.1\",\n    \"assertions\": [\n    {\n      \"label\": \"c2pa.training-mining\",\n      \"data\": {\n        \"entries\": {\n          \"c2pa.ai_generative_training\": { \"use\": \"notAllowed\" },\n          \"c2pa.ai_inference\": { \"use\": \"notAllowed\" },\n          \"c2pa.ai_training\": { \"use\": \"notAllowed\" },\n          \"c2pa.data_mining\": { \"use\": \"notAllowed\" }\n        }\n      }\n    }\n  ]\n })\n```\n\n## Development\n\nIt is best to [set up a virtual environment](https://virtualenv.pypa.io/en/latest/installation.html) for development and testing.\n\nTo build from source on Linux, install curl and rustup and set up python\n\nFirst update apt\n```\napt update\n```\n\nInstall Rust\n```apt install curl\ncurl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh\nsource \"$HOME/.cargo/env\"\n```\n\nInstall Python, pip and venv\n```\napt install python3\napt install pip\napt install python3.11-venv\npython3 -m venv .venv\n```\n\nBuild the wheel for your platform\n```\nsource .venv/bin/activate\npip install maturin\npip install uniffi-bindgen\npython3 -m pip install build\npip install -U pytest\n\npython3 -m build --wheel\n```\n\n### ManyLinux build\n```\ndocker run -it quay.io/pypa/manylinux_2_28_aarch64 bash\ncurl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh\nsource \"$HOME/.cargo/env\"\nexport PATH=/opt/python/cp312-cp312/bin:$PATH\npip install maturin\npip install venv\npip install build\npip install -U pytest\n\ncd home\ngit clone https://github.com/contentauth/c2pa-python.git \ncd c2pa-python\npython3 -m build --wheel\nauditwheel repair target/wheels/c2pa_python-0.4.0-py3-none-linux_aarch64.whl \n\n```\n\n### Testing\n\nWe use [PyTest](https://docs.pytest.org/) for testing.\n\nRun tests by entering this command:\n\n```\nsource .venv/bin/activate\nmaturin develop\npytest\ndeactivate\n```\n\n### Example \n\nRun the example code like this:\n\n```\nsource .venv/bin/activate\nmaturin develop\npython3 tests/training.py\ndeactivate\n```\n\n## Supported file formats\n\n | Extensions    | MIME type                                           |\n | ------------- | --------------------------------------------------- |\n | `avi`         | `video/msvideo`, `video/avi`, `application-msvideo` |\n | `avif`        | `image/avif`                                        |\n | `c2pa`        | `application/x-c2pa-manifest-store`                 |\n | `dng`         | `image/x-adobe-dng`                                 |\n | `heic`        | `image/heic`                                        |\n | `heif`        | `image/heif`                                        |\n | `jpg`, `jpeg` | `image/jpeg`                                        |\n | `m4a`         | `audio/mp4`                                         |\n | `mp4`         | `video/mp4`, `application/mp4`                      |\n | `mov`         | `video/quicktime`                                   |\n | `png`         | `image/png`                                         |\n | `svg`         | `image/svg+xml`                                     |\n | `tif`,`tiff`  | `image/tiff`                                        |\n | `wav`         | `audio/x-wav`                                       |\n | `webp`        | `image/webp`                                        |\n\n\n## Change Notes:\n\nVersion 0.3.0 changes:\nThere are some breaking changes to align with future APIs:\n- `C2paSignerInfo` moves the `alg` to the first parameter from the 3rd.\n- `c2pa.verify_from_file_json` is now `c2pa.read_file`.\n- `c2pa.ingredient_from_file_json` is now `c2pa.read_ingredient_file`.\n- `c2pa.add_manifest_to_file_json` is now `c2pa.sign_file`.\n- There are many more specific errors types now, and Error messages always start with the name of the error i.e (str(err.value).startswith(\"ManifestNotFound\")).\n- The ingredient thumbnail identifier may be jumbf uri reference if a valid thumb already exists in the active manifest.\n- Extracted file paths for read_file now use a folder structure and different naming conventions.\n\n## License\n\nThis package is distributed under the terms of both the [MIT license](https://github.com/contentauth/c2pa-rs/blob/main/LICENSE-MIT) and the [Apache License (Version 2.0)](https://github.com/contentauth/c2pa-rs/blob/main/LICENSE-APACHE).\n\nNote that some components and dependent crates are licensed under different terms; please check the license terms for each crate and component for details.\n\n### Contributions and feedback\n\nWe welcome contributions to this project.  For information on contributing, providing feedback, and about ongoing work, see [Contributing](https://github.com/contentauth/c2pa-js/blob/main/CONTRIBUTING.md).\n\n\n\n",
    "bugtrack_url": null,
    "license": null,
    "summary": "Python bindings for the C2PA Content Authenticity Initiative (CAI) library",
    "version": "0.4.0",
    "project_urls": {
        "homepage": "https://contentauthenticity.org",
        "repository": "https://github.com/contentauth/c2pa-python"
    },
    "split_keywords": [
        "c2pa",
        "cai",
        "content credentials",
        "metadata",
        "provenance"
    ],
    "urls": [
        {
            "comment_text": null,
            "digests": {
                "blake2b_256": "9b342f10929ffcc10541e5501693943901f1bff391cfcfe3c16a3a115f968f9f",
                "md5": "7ade973c342e4f107761e651a8ef7e21",
                "sha256": "a2f53a0f74ff59ee160151ef24a7c4593b9d7ca2fa796caf96eb3a65edf260e4"
            },
            "downloads": -1,
            "filename": "c2pa_python-0.4.0-py3-none-macosx_10_12_x86_64.whl",
            "has_sig": false,
            "md5_digest": "7ade973c342e4f107761e651a8ef7e21",
            "packagetype": "bdist_wheel",
            "python_version": "py3",
            "requires_python": ">=3.7",
            "size": 4100155,
            "upload_time": "2024-01-29T13:28:21",
            "upload_time_iso_8601": "2024-01-29T13:28:21.179748Z",
            "url": "https://files.pythonhosted.org/packages/9b/34/2f10929ffcc10541e5501693943901f1bff391cfcfe3c16a3a115f968f9f/c2pa_python-0.4.0-py3-none-macosx_10_12_x86_64.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": null,
            "digests": {
                "blake2b_256": "702036d9f85525f254d6c7102fe2cace531d08e4f3d8fc1a49a8f66432039e3c",
                "md5": "0c53ce5d0055abf2e87bb1598d64ec79",
                "sha256": "ce30c6dfc55d8563e5b01cb727b90e3f1b7200dba578c8440a9de20f13b67b15"
            },
            "downloads": -1,
            "filename": "c2pa_python-0.4.0-py3-none-macosx_11_0_arm64.whl",
            "has_sig": false,
            "md5_digest": "0c53ce5d0055abf2e87bb1598d64ec79",
            "packagetype": "bdist_wheel",
            "python_version": "py3",
            "requires_python": ">=3.7",
            "size": 3834545,
            "upload_time": "2024-01-29T13:28:23",
            "upload_time_iso_8601": "2024-01-29T13:28:23.349941Z",
            "url": "https://files.pythonhosted.org/packages/70/20/36d9f85525f254d6c7102fe2cace531d08e4f3d8fc1a49a8f66432039e3c/c2pa_python-0.4.0-py3-none-macosx_11_0_arm64.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": null,
            "digests": {
                "blake2b_256": "62f751ded1e14a38a541764805595fd6455405899bd6da1e4d61cda540fc4724",
                "md5": "2ed0a43eace0b07816f14efa2293f58d",
                "sha256": "8d441acc7ebd217da6f1c31b1e06d26a12b2e31cc051b8e0d26e2c89866b25c7"
            },
            "downloads": -1,
            "filename": "c2pa_python-0.4.0-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",
            "has_sig": false,
            "md5_digest": "2ed0a43eace0b07816f14efa2293f58d",
            "packagetype": "bdist_wheel",
            "python_version": "py3",
            "requires_python": ">=3.7",
            "size": 6005396,
            "upload_time": "2024-01-29T13:28:24",
            "upload_time_iso_8601": "2024-01-29T13:28:24.915382Z",
            "url": "https://files.pythonhosted.org/packages/62/f7/51ded1e14a38a541764805595fd6455405899bd6da1e4d61cda540fc4724/c2pa_python-0.4.0-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": null,
            "digests": {
                "blake2b_256": "0a0641d0beecce9cddd1b33c7e5b14b1d4d713ed4040af76218ccc85054ac4da",
                "md5": "c281c2ee8e274da63beb50d3bb442b12",
                "sha256": "c0053a8f8873f0a80a4ea1d463feb22db9b05cf031d25765502d3326d778df2f"
            },
            "downloads": -1,
            "filename": "c2pa_python-0.4.0-py3-none-manylinux_2_28_aarch64.whl",
            "has_sig": false,
            "md5_digest": "c281c2ee8e274da63beb50d3bb442b12",
            "packagetype": "bdist_wheel",
            "python_version": "py3",
            "requires_python": ">=3.7",
            "size": 5231631,
            "upload_time": "2024-01-29T13:28:26",
            "upload_time_iso_8601": "2024-01-29T13:28:26.448732Z",
            "url": "https://files.pythonhosted.org/packages/0a/06/41d0beecce9cddd1b33c7e5b14b1d4d713ed4040af76218ccc85054ac4da/c2pa_python-0.4.0-py3-none-manylinux_2_28_aarch64.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": null,
            "digests": {
                "blake2b_256": "87dc70db3b930ba73511ab21371db6115bd92cefa5220bc8ecd7a9795a296038",
                "md5": "ce7f897b8459b02a53c26003ad47687b",
                "sha256": "eeee1023a7414cf691d83e9d3da08a5d806142989a17a070cf8cfc69a4c89ce5"
            },
            "downloads": -1,
            "filename": "c2pa_python-0.4.0-py3-none-win32.whl",
            "has_sig": false,
            "md5_digest": "ce7f897b8459b02a53c26003ad47687b",
            "packagetype": "bdist_wheel",
            "python_version": "py3",
            "requires_python": ">=3.7",
            "size": 3566724,
            "upload_time": "2024-01-29T13:28:28",
            "upload_time_iso_8601": "2024-01-29T13:28:28.005899Z",
            "url": "https://files.pythonhosted.org/packages/87/dc/70db3b930ba73511ab21371db6115bd92cefa5220bc8ecd7a9795a296038/c2pa_python-0.4.0-py3-none-win32.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": null,
            "digests": {
                "blake2b_256": "a8d9215ecd0eb071f53f5aee1132a6e264982a877f664b14551ec1cd777f7413",
                "md5": "fe70411125b9605f0672c47c35d955c9",
                "sha256": "1fd9b817fce8473fe4bd6b9884a6a06d6072d2bccace86ce1bd72ef696d15ad5"
            },
            "downloads": -1,
            "filename": "c2pa_python-0.4.0-py3-none-win_amd64.whl",
            "has_sig": false,
            "md5_digest": "fe70411125b9605f0672c47c35d955c9",
            "packagetype": "bdist_wheel",
            "python_version": "py3",
            "requires_python": ">=3.7",
            "size": 3995628,
            "upload_time": "2024-01-29T13:28:29",
            "upload_time_iso_8601": "2024-01-29T13:28:29.489724Z",
            "url": "https://files.pythonhosted.org/packages/a8/d9/215ecd0eb071f53f5aee1132a6e264982a877f664b14551ec1cd777f7413/c2pa_python-0.4.0-py3-none-win_amd64.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": null,
            "digests": {
                "blake2b_256": "9c4d3c21ab17831494b2555c4347227754a2fedf3061393b7d9c08dde69a9fd4",
                "md5": "7ee9c3891d0f4a02c2ff260592d53038",
                "sha256": "06101b536265c7b8eee1dd87b729eca1017faf176220c84b7a598e7ebee46450"
            },
            "downloads": -1,
            "filename": "c2pa_python-0.4.0.tar.gz",
            "has_sig": false,
            "md5_digest": "7ee9c3891d0f4a02c2ff260592d53038",
            "packagetype": "sdist",
            "python_version": "source",
            "requires_python": ">=3.7",
            "size": 108704,
            "upload_time": "2024-01-29T13:28:31",
            "upload_time_iso_8601": "2024-01-29T13:28:31.746730Z",
            "url": "https://files.pythonhosted.org/packages/9c/4d/3c21ab17831494b2555c4347227754a2fedf3061393b7d9c08dde69a9fd4/c2pa_python-0.4.0.tar.gz",
            "yanked": false,
            "yanked_reason": null
        }
    ],
    "upload_time": "2024-01-29 13:28:31",
    "github": true,
    "gitlab": false,
    "bitbucket": false,
    "codeberg": false,
    "github_user": "contentauth",
    "github_project": "c2pa-python",
    "travis_ci": false,
    "coveralls": false,
    "github_actions": true,
    "requirements": [],
    "lcname": "c2pa-python"
}
        
Elapsed time: 0.15280s