Skip to content

Commit c8fa02e

Browse files
Use MP_ASS_SUBSCRIPT macro in data containers
1 parent 9d6e59a commit c8fa02e

File tree

7 files changed

+1977
-4645
lines changed

7 files changed

+1977
-4645
lines changed

src/interface/shared/containers.i

Lines changed: 51 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -25,31 +25,20 @@
2525

2626
METADATUM_WRAPPERS(base_class, datum_type)
2727

28-
// Turn off exception checking for methods that are guaranteed not to throw
29-
%noexception Exiv2::base_class::begin;
30-
%noexception Exiv2::base_class::end;
31-
%noexception Exiv2::base_class::clear;
32-
%noexception Exiv2::base_class::count;
33-
%noexception Exiv2::base_class::empty;
34-
// Add dict-like behaviour
35-
%feature("python:slot", "tp_iter", functype="getiterfunc")
36-
Exiv2::base_class::begin;
37-
%feature("python:slot", "mp_length", functype="lenfunc")
38-
Exiv2::base_class::count;
39-
MP_SUBSCRIPT(Exiv2::base_class, Exiv2::datum_type&, (*self)[key])
40-
%feature("python:slot", "mp_ass_subscript", functype="objobjargproc")
41-
Exiv2::base_class::__setitem__;
42-
%feature("python:slot", "sq_contains", functype="objobjproc")
43-
Exiv2::base_class::__contains__;
44-
%extend Exiv2::base_class {
45-
%fragment("get_type_id"{Exiv2::datum_type});
46-
PyObject* __setitem__(const std::string& key, Exiv2::Value* value) {
47-
Exiv2::datum_type* datum = &(*$self)[key];
48-
datum->setValue(value);
49-
return SWIG_Py_Void();
50-
}
51-
PyObject* __setitem__(const std::string& key, const std::string& value) {
52-
Exiv2::datum_type* datum = &(*$self)[key];
28+
/* Set a datum's value from a Python object. String or Exiv2::Value objects
29+
* are used directly. Other objects are used in the constructor of a Python
30+
* Exiv2::Value using the datum's current or default type.
31+
*/
32+
%ignore Exiv2::datum_type::setValue(const Value*);
33+
%ignore Exiv2::datum_type::setValue(const std::string&);
34+
%fragment("set_value_from_py"{Exiv2::datum_type}, "header",
35+
fragment="get_type_object",
36+
fragment="get_type_id"{Exiv2::datum_type}) {
37+
static PyObject* set_value_from_py(Exiv2::datum_type* datum,
38+
PyObject* py_value) {
39+
// Try std::string value
40+
if (PyUnicode_Check(py_value)) {
41+
std::string value = PyUnicode_AsUTF8(py_value);
5342
Exiv2::TypeId old_type = get_type_id(datum);
5443
if (datum->setValue(value) != 0)
5544
return PyErr_Format(PyExc_ValueError,
@@ -58,36 +47,14 @@ MP_SUBSCRIPT(Exiv2::base_class, Exiv2::datum_type&, (*self)[key])
5847
value.c_str());
5948
return SWIG_Py_Void();
6049
}
61-
#if SWIG_VERSION >= 0x040400
62-
PyObject* __setitem__(PyObject* py_self, const std::string& key) {
63-
#else
64-
PyObject* __setitem__(const std::string& key) {
65-
#endif
66-
Exiv2::base_class::iterator pos = $self->findKey(
67-
Exiv2::key_type(key));
68-
if (pos == $self->end()) {
69-
PyErr_SetString(PyExc_KeyError, key.c_str());
70-
return NULL;
71-
}
72-
#if SWIG_VERSION >= 0x040400
73-
invalidate_pointers(py_self, pos);
74-
#endif
75-
$self->erase(pos);
50+
// Try Exiv2::Value value
51+
Exiv2::Value* value = NULL;
52+
if (SWIG_IsOK(SWIG_ConvertPtr(
53+
py_value, (void**)&value, $descriptor(Exiv2::Value*), 0))) {
54+
datum->setValue(value);
7655
return SWIG_Py_Void();
7756
}
78-
bool __contains__(const std::string& key) {
79-
return $self->findKey(Exiv2::key_type(key)) != $self->end();
80-
}
81-
}
82-
83-
// Set the datum's value from a Python object. The datum's current or default
84-
// type is used to create an Exiv2::Value object (via Python) from the Python
85-
// object.
86-
%fragment("set_value_from_py"{Exiv2::datum_type}, "header",
87-
fragment="get_type_object",
88-
fragment="get_type_id"{Exiv2::datum_type}) {
89-
static PyObject* set_value_from_py(Exiv2::datum_type* datum,
90-
PyObject* py_value) {
57+
// Try converting Python object to a value
9158
swig_type_info* ty_info = get_type_object.at(get_type_id(datum));
9259
SwigPyClientData *cl_data = (SwigPyClientData*)ty_info->clientdata;
9360
// Call type object to invoke constructor
@@ -96,7 +63,6 @@ static PyObject* set_value_from_py(Exiv2::datum_type* datum,
9663
if (!swig_obj)
9764
return NULL;
9865
// Convert constructed object to Exiv2::Value
99-
Exiv2::Value* value = 0;
10066
if (!SWIG_IsOK(SWIG_ConvertPtr(swig_obj, (void**)&value, ty_info, 0))) {
10167
PyErr_SetString(
10268
PyExc_RuntimeError, "set_value_from_py: invalid conversion");
@@ -109,17 +75,41 @@ static PyObject* set_value_from_py(Exiv2::datum_type* datum,
10975
return SWIG_Py_Void();
11076
};
11177
}
78+
79+
// Turn off exception checking for methods that are guaranteed not to throw
80+
%noexception Exiv2::base_class::begin;
81+
%noexception Exiv2::base_class::end;
82+
%noexception Exiv2::base_class::clear;
83+
%noexception Exiv2::base_class::count;
84+
%noexception Exiv2::base_class::empty;
85+
// Add dict-like behaviour
86+
%feature("python:slot", "tp_iter", functype="getiterfunc")
87+
Exiv2::base_class::begin;
88+
%feature("python:slot", "mp_length", functype="lenfunc")
89+
Exiv2::base_class::count;
90+
MP_SUBSCRIPT(Exiv2::base_class, Exiv2::datum_type&, (*self)[key])
91+
%fragment("set_value_from_py"{Exiv2::datum_type});
92+
MP_ASS_SUBSCRIPT(Exiv2::base_class, PyObject*,
93+
// setfunc
94+
return set_value_from_py(&(*self)[key], value),
95+
// delfunc
96+
auto pos = self->findKey(Exiv2::key_type(key));
97+
if (pos == self->end())
98+
return PyErr_Format(PyExc_KeyError, "'%s'", key);
99+
self->erase(pos))
100+
%feature("python:slot", "sq_contains", functype="objobjproc")
101+
Exiv2::base_class::__contains__;
102+
%extend Exiv2::base_class {
103+
%fragment("get_type_id"{Exiv2::datum_type});
104+
bool __contains__(const std::string& key) {
105+
return $self->findKey(Exiv2::key_type(key)) != $self->end();
106+
}
107+
}
108+
112109
%extend Exiv2::datum_type {
113110
%fragment("set_value_from_py"{Exiv2::datum_type});
114111
PyObject* setValue(PyObject* py_value) {
115112
return set_value_from_py($self, py_value);
116113
}
117114
}
118-
%extend Exiv2::base_class {
119-
%fragment("set_value_from_py"{Exiv2::datum_type});
120-
PyObject* __setitem__(const std::string& key, PyObject* py_value) {
121-
Exiv2::datum_type* datum = &(*$self)[key];
122-
return set_value_from_py(datum, py_value);
123-
}
124-
}
125115
%enddef // DATA_CONTAINER

0 commit comments

Comments
 (0)