API Reference¶
Error¶
Properties and values¶
xmpkit.XmpProperty
¶
A property entry produced by iterating an XmpMeta instance.
Methods:
-
__new__–Create a new XMP property object from the provided values
Attributes:
xmpkit.XmpValue
¶
XMP value types
This classes defines subclasses for the value types that can be stored in XMP properties.
All child classes inherit from this class, but the documentation doesn't allow for this kind of recursive inheritance, so the child classes are typed this way. The typing is still valid but just doesn't represent the full structure of the objects
Classes:
-
Array–Array of values
-
Boolean–Boolean value
-
DateTime–Date/time value (ISO 8601 format)
-
Integer–Integer value
-
String–String value
-
Structure–Structure (key-value pairs)
Methods:
-
as_array–Get the value as a list, if it is an
Array. -
as_bool–Get the value as a boolean, if it is a boolean type, or can be converted to.
-
as_int–Get the value as an integer, if it is an integer type, or can be converted to.
-
as_str–Get the value as a string, if it is a string or date/time type
-
as_structure–Get the value as a dict, if it is a
Structure.
Array
¶
Boolean
¶
DateTime
¶
Integer
¶
String
¶
String value
Methods:
Structure
¶
as_bool
¶
as_bool() -> bool | None
Get the value as a boolean, if it is a boolean type, or can be converted to.
xmpkit.XmpDateTime
¶
XMP Date/Time structure
Represents a date/time value with optional components. XMP supports partial dates (e.g., just year, or year-month).
Methods:
-
__new__–Create a new XMP date/time from the provided values
-
parse–Parse an XMP date/time string
-
format–Format an XMP date/time to string
-
validate–Validate the date/time values
Attributes:
-
day(int) –Day (1-31, 0 means not set)
-
has_date(bool) –Whether date components are present
-
has_time(bool) –Whether time components are present
-
has_timezone(bool) –Whether timezone is present
-
hour(int) –Hour (0-23)
-
minute(int) –Minute (0-59)
-
month(int) –Month (1-12, 0 means not set)
-
nanosecond(int) –Nanoseconds (0-999999999)
-
second(int) –Second (0-59)
-
tz_hour(int) –Timezone hour offset (0-23)
-
tz_minute(int) –Timezone minute offset (0-59)
-
tz_sign(int) –Timezone sign: -1 (west), 0 (UTC), +1 (east)
-
year(int) –Year (can be negative for BCE dates)
__new__
¶
__new__(year: int = 0, month: int = 0, day: int = 0, hour: int = 0, minute: int = 0, second: int = 0, nanosecond: int = 0, has_date: bool = False, has_time: bool = False, has_timezone: bool = False, tz_sign: int = 0, tz_hour: int = 0, tz_minute: int = 0) -> XmpDateTime
Create a new XMP date/time from the provided values
parse
classmethod
¶
parse(s: str) -> XmpDateTime
Parse an XMP date/time string
Parameters:
-
s(str) –The date/time string to parse
Raises:
-
XmpError–If the string could not be parsed
XMP date/time format:
YYYY- year onlyYYYY-MM- year and monthYYYY-MM-DD- date onlyYYYY-MM-DDThh:mm:ss- date and timeYYYY-MM-DDThh:mm:ss.sss- with fractional secondsYYYY-MM-DDThh:mm:ssZ- UTC timezoneYYYY-MM-DDThh:mm:ss+hh:mm- timezone offsetYYYY-MM-DDThh:mm:ss-hh:mm- negative timezone offset
Example::
from xmpkit import XmpDateTime
dt = XmpDateTime.parse("2023-12-25T10:30:00Z")
assert dt.year == 2023
assert dt.month == 12
assert dt.day == 25
format
¶
format() -> str
Format an XMP date/time to string
Formats the date/time according to XMP specification:
- Year only:
YYYY - Year and month:
YYYY-MM - Date only:
YYYY-MM-DD - Date and time:
YYYY-MM-DDThh:mm:ss - With fractional seconds:
YYYY-MM-DDThh:mm:ss.sss - With timezone:
YYYY-MM-DDThh:mm:ssZorYYYY-MM-DDThh:mm:ss+hh:mm
Metadata¶
xmpkit.XmpMeta
¶
Main structure for working with XMP metadata
Methods:
-
__new__–Create a new empty XMP metadata object
-
all_properties–Returns all top-level properties in this metadata object.
-
append_array_item–Append an item to an array property
-
delete_array_item–Delete an item from an array property
-
delete_property–Delete a property
-
delete_struct_field–Delete a structure field
-
get_array_item–Get an array item by index
-
get_array_size–Get the size of an array property
-
get_date_time–Get a date/time property
-
get_localized_text–Get a localized text property
-
get_property–Get a property value. It will return an
XmpValue.Array,XmpValue.Structureor anXmpValue.String. -
get_struct_field–Get a structure field value
-
has_property–Check if a property exists
-
insert_array_item–Insert an item into an array property at a specific index
-
parse–Parse XMP metadata from a string
-
serialize–Serialize to RDF/XML string
-
serialize_packet–Serialize to XMP Packet format
-
serialize_packet_with_padding–Serialize to XMP Packet format with padding to reach a target length
-
set_date_time–Set a date/time property
-
set_localized_text–Set a localized text property
-
set_property–Set a property value
-
set_struct_field–Set a structure field value
Attributes:
all_properties
¶
all_properties() -> list[XmpProperty]
Returns all top-level properties in this metadata object.
append_array_item
¶
delete_array_item
¶
delete_property
¶
delete_struct_field
¶
get_array_item
¶
get_array_size
¶
get_date_time
¶
get_date_time(namespace: str, path: str) -> XmpDateTime | None
Get a date/time property
This is a convenience method that parses a date/time property value
and returns it as an XmpDateTime.
Parameters:
Returns:
-
XmpDateTime | None–An XMP date/time object if the property exists and can be parsed,
Noneotherwise.
Example::
from xmpkit import XmpMeta, XmpValue, XmpDateTime
meta = XmpMeta()
meta.set_property(
"http://ns.adobe.com/xap/1.0/",
"ModifyDate",
XmpValue.DateTime("2023-12-25T10:30:00Z")
)
dt = meta.get_date_time("http://ns.adobe.com/xap/1.0/", "ModifyDate")
assert dt.year = 2023
assert dt.month = 12
assert dt.day = 25
get_localized_text
¶
get_localized_text(namespace: str, property: str, generic_lang: str, specific_lang: str) -> tuple[str, str] | None
Get a localized text property
This method searches for a localized text value matching the specified language codes. It follows XMP language matching rules:
- Exact match for specific_lang
- Match for generic_lang if specific_lang not found
- Fallback to "x-default" if neither found
Parameters:
-
namespace(str) –The namespace URI or prefix
-
property(str) –The property name
-
generic_lang(str) –Generic language code (e.g., "en"), can be empty string
-
specific_lang(str) –Specific language code (e.g., "en-US"), required
Returns:
-
tuple[str, str] | None–If the localized text if found, a tuple holding the text value and the actual language code used (may differ from requested).
Noneif the property doesn't exist or no matching language found.
Example::
from xmpkit import XmpMeta
meta = XmpMeta()
meta.set_localized_text(
"http://purl.org/dc/elements/1.1/",
"title",
"",
"x-default",
"Default Title"
)
value, lang = meta.get_localized_text(
"http://purl.org/dc/elements/1.1/",
"title",
"",
"x-default"
)
assert value == "Default Title"
assert lang == "x-default"
get_property
¶
Get a property value. It will return an XmpValue.Array, XmpValue.Structure or an XmpValue.String.
Parameters:
-
namespace(str) –The namespace URI or prefix
-
path(str) –The property path (e.g., "CreatorTool" or "creator[1]")
get_struct_field
¶
has_property
¶
insert_array_item
¶
parse
classmethod
¶
Parse XMP metadata from a string
The string should contain a complete XMP Packet (with or without
the <?xpacket> wrapper).
Parameters:
-
s(str) –The string to parse the metadata from
serialize_packet_with_padding
¶
Serialize to XMP Packet format with padding to reach a target length
This is useful for in-place updates where the new packet needs to fit within the space of an existing packet.
Parameters:
-
target_length(int) –The desired total packet length in bytes
Raises:
-
XmpError–If the serialized packet exceeds target_length
Returns:
-
str–The serialized packet with padding
set_date_time
¶
set_date_time(namespace: str, path: str, dt: XmpDateTime) -> None
Set a date/time property
This is a convenience method that validates and formats the date/time value before setting it as a property.
Parameters:
-
namespace(str) –The namespace URI or prefix
-
path(str) –The property path
-
dt(XmpDateTime) –The date/time value
Example::
from xmpkit import XmpMeta, XmpDateTime
meta = XmpMeta()
dt = XmpDateTime()
dt.has_date = true
dt.has_time = true
dt.year = 2023
dt.month = 12
dt.day = 25
dt.hour = 10
dt.minute = 30
dt.second = 0
dt.has_timezone = true
dt.tz_sign = 0 # UTC
meta.set_date_time("http://ns.adobe.com/xap/1.0/", "ModifyDate", dt)
set_localized_text
¶
set_localized_text(namespace: str, property: str, _generic_lang: str, specific_lang: str, value: str) -> None
Set a localized text property
Localized text properties are stored as rdf:Alt arrays, where each item
has an xml:lang qualifier indicating its language.
Parameters:
-
namespace(str) –The namespace URI or prefix
-
property(str) –The property name
-
generic_lang–Generic language code (e.g., "en"), can be empty string
-
specific_lang(str) –Specific language code (e.g., "en-US"), required
-
value(str) –The text value to set
Example::
from xmpkit import XmpMeta, XmpValue
meta = XmpMeta()
meta.set_localized_text(
"http://purl.org/dc/elements/1.1/",
"title",
"",
"x-default",
"Default Title"
)
set_property
¶
set_struct_field
¶
File¶
xmpkit.XmpFile
¶
High-level API for working with XMP metadata in files
File Update Behavior¶
When a file is opened with XmpOptions.with_for_update, changes made via
put_xmp are not written to disk immediately. The file remains open
and changes are only written when close or try_close is called.
Example::
from xmpkit import XmpFile, XmpOptions, XmpMeta, XmpValue
file = XmpFile()
file.open_with("image.jpg", XmpOptions().for_update())
if (meta := file.get_xmp()) is not None:
meta.set_property(
"http://ns.adobe.com/xap/1.0/",
"CreatorTool",
XmpValue.String("MyApp"),
)
file.put_xmp(meta)
# Changes are written to disk when try_close() is called
file.try_close()
Methods:
-
__new__–Create a new empty XMP file object
-
open–Open a file from a
path -
open_with–Open a file from a path with
options -
from_bytes–Open a file from bytes represented by
data -
from_bytes_with–Open a file from bytes with options
-
get_xmp–Get the XMP metadata
-
put_xmp–Put XMP metadata represented by
meta -
write_to_bytes–Write XMP metadata to bytes
-
save–Write XMP metadata to a file
path -
close–Explicitly closes an opened file.
-
try_close–Explicitly closes an opened file with error handling.
-
scan_for_xmp_packet–Scan file content for XMP packet (packet scanning mode)
__new__
¶
__new__() -> XmpFile
Create a new empty XMP file object
Use open* or from_*() methods to load metadata from a file.
open
¶
open(path: str) -> None
Open a file from a path
Example::
from xmpkit import XmpFile
file = XmpFile()
file.open("image.jpg")
open_with
¶
open_with(path: str, options: XmpOptions) -> None
Open a file from a path with options
Parameters:
-
path(str) –The path to the file with the metadata
-
options(XmpOptions) –The XMP options to open the file with
Example::
from xmpkit import XmpFile, XmpOptions
file = XmpFile()
file.open_with("image.jpg", XmpOptions().for_update())
from_bytes
¶
from_bytes(data: bytes) -> None
Open a file from bytes represented by data
Example::
from xmpkit import XmpFile
jpeg_data: bytes = ... # your JPEG file data
file = XmpFile()
file.from_bytes(jpeg_data)
from_bytes_with
¶
from_bytes_with(data: bytes, options: XmpOptions) -> None
Open a file from bytes with options
This method allows you to specify opening options, such as forcing packet scanning or requiring a smart handler.
Parameters:
-
data(bytes) –The bytes representing the file to open
-
option–The XMP options to open the file with
Example::
from xmpkit import XmpFile, XmpOptions
data: bytes = ... # your file data
file = XmpFile()
file.from_bytes_with(data, XmpOptions().with_use_packet_scanning())
get_xmp
¶
get_xmp() -> XmpMeta | None
Get the XMP metadata
Returns:
-
XmpMeta | None–The metadata object if loaded or found,
Noneotherwise.
put_xmp
¶
put_xmp(meta: XmpMeta) -> None
Put XMP metadata represented by meta
Replaces any existing metadata.
Update Behavior¶
- If the file was opened with
XmpOptions.with_for_update, changes are not written to disk immediately. Callcloseortry_closeto write changes to disk. - If the file was opened read-only, this only updates the in-memory metadata.
Example::
from xmpkit import XmpFile, XmpOptions, XmpMeta, XmpValue
file = XmpFile()
file.open_with("image.jpg", XmpOptions().with_for_update())
meta = file.get_xmp() or XmpMeta();
meta.set_property(
"http://ns.adobe.com/xap/1.0/",
"CreatorTool",
XmpValue.String("MyApp"),
)
file.put_xmp(meta)
# Write changes to disk
file.try_close()
write_to_bytes
¶
write_to_bytes() -> bytes
Write XMP metadata to bytes
Example::
from xmpkit import XmpFile
input_data: bytes = ... # your JPEG file data
file = XmpFile()
file.from_bytes(input_data)
# ... modify metadata ...
output_data = file.write_to_bytes()
save
¶
save(path: str) -> None
Write XMP metadata to a file path
Example::
from xmpkit import XmpFile, XmpMeta
file = XmpFile()
file.open("image.jpg")
# ... modify metadata ...
file.save("output.jpg")
close
¶
Explicitly closes an opened file.
Performs any necessary output to the file and closes it. Files that are
opened for update are written to only when closing. If the file is opened
for read-only access (using [XmpOptions.with_for_read()][xmpkit.XmpOptions.with_for_read()]), the disk
file is closed immediately after reading the data from it; the XmpFile
object, however, remains in the open state. You must call close
when finished using it.
Errors¶
This method ignores errors for backward compatibility. If you want to
handle errors, use try_close instead.
Example::
use xmpkit::{XmpFile, XmpOptions};
# fn main() -> Result<(), Box<dyn std::error::Error>> {
let mut file = XmpFile::new();
file.open_with("image.jpg", XmpOptions::default().for_update())?;
// ... modify metadata ...
file.close(); // Ignores errors
try_close
¶
Explicitly closes an opened file with error handling.
Performs any necessary output to the file and closes it. Files that are
opened for update are written to only when closing. If the file is opened
for read-only access (using XmpOptions.with_for_read), the disk file
is closed immediately after reading the data from it; the XmpFile object,
however, remains in the open state. You must call try_close when
finished using it.
Raises:
-
XmpError–If writing the file fails.
Example::
from xmpkit import XmpFile, XmpOptions
file = XmpFile()
file.open_with("image.jpg", XmpOptions().with_for_update())
# ... modify metadata ...
file.try_close() # Raises error if write fails
xmpkit.XmpOptions
¶
Options for XMP file operations.
Use the builder pattern to configure options. These options control how file handlers read and process XMP metadata.
Example::
from xmpkit import XmpFile, XmpOptions
file = XmpFile()
# Open for update with strict mode
file.open_with("photo.jpg", XmpOptions().with_for_update().with_strict())
# ... modify metadata ...
file.try_close()
Methods:
-
__new__–Create a new XMP options object from the provided values
-
with_for_read–Open for read-only access (default).
-
with_for_update–Open for reading and writing.
-
with_force_given_handler–Force use of the given handler (format).
-
with_limited_scanning–Only packet scan files "known" to need scanning.
-
with_only_xmp–Only the XMP is wanted.
-
with_strict–Be strict about only attempting to use the designated file handler.
-
with_use_packet_scanning–Force packet scanning.
-
with_use_smart_handler–Require the use of a smart handler.
Attributes:
-
for_update(bool) –Open for reading and writing (default: read-only)
-
force_given_handler(bool) –Force use of the given handler (format)
-
limited_scanning(bool) –Only packet scan files "known" to need scanning
-
only_xmp(bool) –Only the XMP is wanted, skip reconciliation with native metadata
-
strict(bool) –Be strict about only attempting to use the designated file handler
-
use_packet_scanning(bool) –Force packet scanning (do not use smart handler)
-
use_smart_handler(bool) –Require the use of a smart handler
force_given_handler
property
writable
¶
force_given_handler: bool
Force use of the given handler (format)
limited_scanning
property
writable
¶
limited_scanning: bool
Only packet scan files "known" to need scanning
only_xmp
property
writable
¶
only_xmp: bool
Only the XMP is wanted, skip reconciliation with native metadata
strict
property
writable
¶
strict: bool
Be strict about only attempting to use the designated file handler
use_packet_scanning
property
writable
¶
use_packet_scanning: bool
Force packet scanning (do not use smart handler)
__new__
¶
__new__(for_update: bool = False, only_xmp: bool = False, force_given_handler: bool = False, strict: bool = False, use_smart_handler: bool = False, use_packet_scanning: bool = False, limited_scanning: bool = False) -> XmpOptions
Create a new XMP options object from the provided values
with_for_update
¶
with_for_update() -> XmpOptions
Open for reading and writing.
Files opened for update are written to only when closing.
with_force_given_handler
¶
with_force_given_handler() -> XmpOptions
Force use of the given handler (format).
Do not even verify the format.
with_limited_scanning
¶
with_limited_scanning() -> XmpOptions
Only packet scan files "known" to need scanning.
with_only_xmp
¶
with_only_xmp() -> XmpOptions
Only the XMP is wanted.
This allows space/time optimizations by skipping reconciliation with native metadata formats (e.g., QuickTime metadata in MPEG4).
with_strict
¶
with_strict() -> XmpOptions
Be strict about only attempting to use the designated file handler.
Do not fall back to other handlers.
with_use_packet_scanning
¶
with_use_packet_scanning() -> XmpOptions
Force packet scanning.
Do not use a smart handler.
with_use_smart_handler
¶
with_use_smart_handler() -> XmpOptions
Require the use of a smart handler.
Do not fall back to packet scanning.
Namespaces¶
xmpkit.get_all_registered_namespaces
builtin
¶
Get all registered namespaces from global registry
Returns a list of (uri, prefix) tuples for all registered namespaces.
xmpkit.get_builtin_namespace_uris
builtin
¶
Get all built-in namespace URIs
Returns a list of built-in namespace URIs.
xmpkit.get_global_namespace_prefix
builtin
¶
Get the prefix for a namespace uri from global registry
xmpkit.get_global_namespace_uri
builtin
¶
Get the URI for a namespace prefix from global registry
xmpkit.is_namespace_registered
builtin
¶
Check if a namespace uri is registered globally
xmpkit.register_namespace
builtin
¶
Register a namespace URI with a prefix
This is a convenience function that uses a global namespace map.
For per-instance namespace management, use NamespaceMap directly.
This function registers namespaces globally (per thread) for convenience.
xmpkit.NamespaceMap
¶
Methods:
-
__new__–Create a new namespace map with built-in namespaces registered
-
get_all_namespaces–Get all registered namespaces as a list of (uri, prefix) tuples
-
get_prefix–Get the prefix for a namespace
uri -
get_uri–Get the URI for a namespace
prefix -
has_prefix–Check if a namespace
prefixis registered -
has_uri–Check if a namespace
uriis registered -
register–Register a namespace URI with a prefix
get_all_namespaces
¶
Get all registered namespaces as a list of (uri, prefix) tuples
xmpkit.ns
¶
Built-in XMP namespaces
Attributes:
-
XMP(Final[str]) –XMP Basic namespace
-
DC(Final[str]) –Dublin Core namespace
-
EXIF(Final[str]) –EXIF namespace
-
EXIF_AUX(Final[str]) –EXIF Aux namespace
-
EXIF_EX(Final[str]) –EXIF 2.32 Extension namespace
-
IPTC_CORE(Final[str]) –IPTC Core namespace
-
IPTC_EXT(Final[str]) –IPTC Extension namespace
-
PHOTOSHOP(Final[str]) –Photoshop namespace
-
CAMERA_RAW(Final[str]) –Camera Raw namespace
-
XMP_RIGHTS(Final[str]) –XMP Rights namespace
-
XMP_MM(Final[str]) –XMP Media Management namespace
-
XMP_BJ(Final[str]) –XMP Basic Job Ticket namespace
-
TIFF(Final[str]) –TIFF namespace
-
PDF(Final[str]) –PDF namespace
-
PDFX(Final[str]) –PDF/X namespace
-
PDFA(Final[str]) –PDF/A namespace
-
XMP_DM(Final[str]) –XMP Dynamic Media namespace
-
XMP_PAGED(Final[str]) –XMP PagedText namespace
-
XMP_GRAPHICS(Final[str]) –XMP Graphics namespace
-
XMP_IMAGE(Final[str]) –XMP Image namespace
-
RDF(Final[str]) –RDF namespace
-
XML(Final[str]) –XML namespace (for xml:lang, etc.)
-
XMP_PREFIX(Final[str]) –XMP namespace prefix
-
DC_PREFIX(Final[str]) –Dublin Core prefix
-
EXIF_PREFIX(Final[str]) –EXIF prefix
-
RDF_PREFIX(Final[str]) –RDF prefix
-
XML_PREFIX(Final[str]) –XML prefix
-
EXIF_AUX_PREFIX(Final[str]) –EXIF Aux prefix
-
EXIF_EX_PREFIX(Final[str]) –EXIF 2.32 Extension prefix
-
IPTC_CORE_PREFIX(Final[str]) –IPTC Core prefix
-
IPTC_EXT_PREFIX(Final[str]) –IPTC Extension prefix
-
PHOTOSHOP_PREFIX(Final[str]) –Photoshop prefix
-
CAMERA_RAW_PREFIX(Final[str]) –Camera Raw prefix
-
XMP_RIGHTS_PREFIX(Final[str]) –XMP Rights prefix
-
XMP_MM_PREFIX(Final[str]) –XMP Media Management prefix
-
XMP_BJ_PREFIX(Final[str]) –XMP Basic Job Ticket prefix
-
TIFF_PREFIX(Final[str]) –TIFF prefix
-
PDF_PREFIX(Final[str]) –PDF prefix
-
PDFX_PREFIX(Final[str]) –PDF/X prefix
-
PDFA_PREFIX(Final[str]) –PDF/A prefix
-
XMP_DM_PREFIX(Final[str]) –XMP Dynamic Media prefix
-
XMP_PAGED_PREFIX(Final[str]) –XMP PagedText prefix
-
XMP_GRAPHICS_PREFIX(Final[str]) –XMP Graphics prefix
-
XMP_IMAGE_PREFIX(Final[str]) –XMP Image prefix
EXIF_AUX
module-attribute
¶
EXIF Aux namespace
EXIF_EX
module-attribute
¶
EXIF 2.32 Extension namespace
IPTC_CORE
module-attribute
¶
IPTC Core namespace
IPTC_EXT
module-attribute
¶
IPTC Extension namespace
PHOTOSHOP
module-attribute
¶
Photoshop namespace
CAMERA_RAW
module-attribute
¶
Camera Raw namespace
XMP_RIGHTS
module-attribute
¶
XMP Rights namespace
XMP_MM
module-attribute
¶
XMP Media Management namespace
XMP_BJ
module-attribute
¶
XMP Basic Job Ticket namespace
XMP_DM
module-attribute
¶
XMP Dynamic Media namespace
XMP_PAGED
module-attribute
¶
XMP PagedText namespace
XMP_GRAPHICS
module-attribute
¶
XMP Graphics namespace
XMP_IMAGE
module-attribute
¶
XMP Image namespace
RDF
module-attribute
¶
RDF namespace
XML
module-attribute
¶
XML namespace (for xml:lang, etc.)
IPTC_EXT_PREFIX
module-attribute
¶
IPTC Extension prefix