aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorOlivier Tilloy <olivier@tilloy.net>2010-11-29 20:36:41 +0100
committerOlivier Tilloy <olivier@tilloy.net>2010-11-29 20:36:41 +0100
commit6ec0844a732a8d8b1aebbee3bf3dec1441af5bbd (patch)
treeace48eac0440d4fd9bd9b7081f4294409981ec3e
parent17c9ce29dd1b25537b9570191276e13cc3baa690 (diff)
downloadpyexiv2-6ec0844a732a8d8b1aebbee3bf3dec1441af5bbd.tar.gz
Functions in the xmp module to register and unregister custom namespaces.
-rw-r--r--src/exiv2wrapper.cpp59
-rw-r--r--src/exiv2wrapper.hpp6
-rw-r--r--src/exiv2wrapper_python.cpp4
-rw-r--r--src/pyexiv2/__init__.py3
-rw-r--r--src/pyexiv2/xmp.py66
5 files changed, 137 insertions, 1 deletions
diff --git a/src/exiv2wrapper.cpp b/src/exiv2wrapper.cpp
index 0d80e05..4512222 100644
--- a/src/exiv2wrapper.cpp
+++ b/src/exiv2wrapper.cpp
@@ -34,6 +34,9 @@
#define NON_REPEATABLE 102
#define KEY_NOT_FOUND 103
#define INVALID_VALUE 104
+#define EXISTING_PREFIX 105
+#define BUILTIN_NS 106
+#define NOT_REGISTERED 107
// Custom macros
#define CHECK_METADATA_READ \
@@ -1279,6 +1282,15 @@ void translateExiv2Error(Exiv2::Error const& error)
case INVALID_VALUE:
PyErr_SetString(PyExc_ValueError, "Invalid value");
break;
+ case EXISTING_PREFIX:
+ PyErr_SetString(PyExc_KeyError, "A namespace with this prefix already exists");
+ break;
+ case BUILTIN_NS:
+ PyErr_SetString(PyExc_KeyError, "Cannot unregister a builtin namespace");
+ break;
+ case NOT_REGISTERED:
+ PyErr_SetString(PyExc_KeyError, "No namespace registered under this name");
+ break;
// Default handler
default:
@@ -1286,5 +1298,52 @@ void translateExiv2Error(Exiv2::Error const& error)
}
}
+
+void registerXmpNs(const std::string& name, const std::string& prefix)
+{
+ try
+ {
+ const std::string& ns = Exiv2::XmpProperties::ns(prefix);
+ }
+ catch (Exiv2::Error& error)
+ {
+ // No namespace exists with the requested prefix, it is safe to
+ // register a new one.
+ Exiv2::XmpProperties::registerNs(name, prefix);
+ return;
+ }
+ throw Exiv2::Error(EXISTING_PREFIX, prefix);
+}
+
+void unregisterXmpNs(const std::string& name)
+{
+ const std::string& prefix = Exiv2::XmpProperties::prefix(name);
+ if (prefix != "")
+ {
+ Exiv2::XmpProperties::unregisterNs(name);
+ try
+ {
+ const Exiv2::XmpNsInfo* info = Exiv2::XmpProperties::nsInfo(prefix);
+ }
+ catch (Exiv2::Error& error)
+ {
+ // The namespace has been successfully unregistered.
+ return;
+ }
+ // The namespace hasn’t been unregistered because it’s builtin.
+ throw Exiv2::Error(BUILTIN_NS, name);
+ }
+ else
+ {
+ throw Exiv2::Error(NOT_REGISTERED, name);
+ }
+}
+
+void unregisterAllXmpNs()
+{
+ // Unregister all custom namespaces.
+ Exiv2::XmpProperties::unregisterNs();
+}
+
} // End of namespace exiv2wrapper
diff --git a/src/exiv2wrapper.hpp b/src/exiv2wrapper.hpp
index 5058d56..3c87628 100644
--- a/src/exiv2wrapper.hpp
+++ b/src/exiv2wrapper.hpp
@@ -272,6 +272,12 @@ private:
// Translate an Exiv2 generic exception into a Python exception
void translateExiv2Error(Exiv2::Error const& error);
+
+// Functions to manipulate custom XMP namespaces
+void registerXmpNs(const std::string& name, const std::string& prefix);
+void unregisterXmpNs(const std::string& name);
+void unregisterAllXmpNs();
+
} // End of namespace exiv2wrapper
#endif
diff --git a/src/exiv2wrapper_python.cpp b/src/exiv2wrapper_python.cpp
index 5b793f7..bd20774 100644
--- a/src/exiv2wrapper_python.cpp
+++ b/src/exiv2wrapper_python.cpp
@@ -153,5 +153,9 @@ BOOST_PYTHON_MODULE(libexiv2python)
.def("_setExifThumbnailFromFile", &Image::setExifThumbnailFromFile)
.def("_setExifThumbnailFromData", &Image::setExifThumbnailFromData)
;
+
+ def("_registerXmpNs", registerXmpNs, args("name", "prefix"));
+ def("_unregisterXmpNs", unregisterXmpNs, args("name"));
+ def("_unregisterAllXmpNs", unregisterAllXmpNs);
}
diff --git a/src/pyexiv2/__init__.py b/src/pyexiv2/__init__.py
index 54d7ebe..9aa3185 100644
--- a/src/pyexiv2/__init__.py
+++ b/src/pyexiv2/__init__.py
@@ -62,7 +62,8 @@ import libexiv2python
from pyexiv2.metadata import ImageMetadata
from pyexiv2.exif import ExifValueError, ExifTag, ExifThumbnail
from pyexiv2.iptc import IptcValueError, IptcTag
-from pyexiv2.xmp import XmpValueError, XmpTag
+from pyexiv2.xmp import XmpValueError, XmpTag, register_namespace, \
+ unregister_namespace, unregister_namespaces
from pyexiv2.preview import Preview
from pyexiv2.utils import FixedOffset, Rational, NotifyingList, \
undefined_to_string, string_to_undefined, \
diff --git a/src/pyexiv2/xmp.py b/src/pyexiv2/xmp.py
index 2142c41..c6488a1 100644
--- a/src/pyexiv2/xmp.py
+++ b/src/pyexiv2/xmp.py
@@ -440,6 +440,18 @@ class XmpTag(object):
else:
raise XmpValueError(value, type)
+ elif type == '':
+ # Unknown type, assume string
+ if isinstance(value, unicode):
+ try:
+ return value.encode('utf-8')
+ except UnicodeEncodeError:
+ raise XmpValueError(value, type)
+ elif isinstance(value, str):
+ return value
+ else:
+ raise XmpValueError(value, type)
+
raise NotImplementedError('XMP conversion for type [%s]' % type)
def __str__(self):
@@ -454,3 +466,57 @@ class XmpTag(object):
right = self._raw_value
return '<%s = %s>' % (left, right)
+
+def register_namespace(name, prefix):
+ """
+ Register a custom XMP namespace.
+
+ Overriding the prefix of a known or previously registered namespace is not
+ allowed.
+
+ :param name: the name of the custom namespace (ending with a ``/``),
+ typically a URL (e.g. http://purl.org/dc/elements/1.1/)
+ :type name: string
+ :param prefix: the prefix for the custom namespace (keys in this namespace
+ will be in the form ``Xmp.{prefix}.{something}``)
+ :type prefix: string
+
+ :raise ValueError: if the name doesn’t end with a ``/``
+ :raise KeyError: if a namespace already exist with this prefix
+ """
+ if not name.endswith('/'):
+ raise ValueError('Name should end with a /')
+ libexiv2python._registerXmpNs(name, prefix)
+
+
+def unregister_namespace(name):
+ """
+ Unregister a custom XMP namespace.
+
+ A custom namespace is identified by its name, **not** by its prefix.
+
+ Attempting to unregister an unknown namespace raises an error, as does
+ attempting to unregister a builtin namespace.
+
+ :param name: the name of the custom namespace (ending with a ``/``),
+ typically a URL (e.g. http://purl.org/dc/elements/1.1/)
+ :type name: string
+
+ :raise ValueError: if the name doesn’t end with a ``/``
+ :raise KeyError: if the namespace is unknown or a builtin namespace
+ """
+ if not name.endswith('/'):
+ raise ValueError('Name should end with a /')
+ libexiv2python._unregisterXmpNs(name)
+
+
+def unregister_namespaces():
+ """
+ Unregister all custom XMP namespaces.
+
+ Builtin namespaces are not unregistered.
+
+ This function always succeeds.
+ """
+ libexiv2python._unregisterAllXmpNs()
+