Skip to content

Commit aa3ae6a

Browse files
Use a dict to store references to other objects
1 parent d69916a commit aa3ae6a

File tree

15 files changed

+450
-103
lines changed

15 files changed

+450
-103
lines changed

src/interface/image.i

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
// python-exiv2 - Python interface to libexiv2
22
// http://github.com/jim-easterbrook/python-exiv2
3-
// Copyright (C) 2021-24 Jim Easterbrook [email protected]
3+
// Copyright (C) 2021-25 Jim Easterbrook [email protected]
44
//
55
// This program is free software: you can redistribute it and/or modify
66
// it under the terms of the GNU General Public License as published by
@@ -71,10 +71,8 @@ INPUT_BUFFER_RO(const Exiv2::byte* data, long A)
7171
INPUT_BUFFER_RO(const Exiv2::byte* data, size_t A)
7272

7373
// Release memory buffer after writeMetadata, as it creates its own copy
74-
%typemap(ret) void writeMetadata %{
75-
if (PyObject_HasAttrString(self, "_refers_to")) {
76-
PyObject_DelAttrString(self, "_refers_to");
77-
}
74+
%typemap(ret, fragment="private_data") void writeMetadata %{
75+
store_private(self, "_refers_to", NULL);
7876
%}
7977

8078
// Convert path encoding on Windows

src/interface/shared/buffers.i

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
// python-exiv2 - Python interface to libexiv2
22
// http://github.com/jim-easterbrook/python-exiv2
3-
// Copyright (C) 2023-24 Jim Easterbrook [email protected]
3+
// Copyright (C) 2023-25 Jim Easterbrook [email protected]
44
//
55
// This program is free software: you can redistribute it and/or modify
66
// it under the terms of the GNU General Public License as published by
@@ -42,8 +42,8 @@
4242
// Macro for input read only byte buffer, result keeps reference to input
4343
%define INPUT_BUFFER_RO_EX(buf_type, len_type)
4444
INPUT_BUFFER_RO(buf_type, len_type)
45-
%typemap(argout) (buf_type, len_type) %{
46-
PyObject_SetAttrString(resultobj, "_refers_to", _global_view);
45+
%typemap(argout, fragment="private_data") (buf_type, len_type) %{
46+
store_private(resultobj, "_refers_to", _global_view);
4747
%}
4848
%enddef // INPUT_BUFFER_RO_EX
4949

src/interface/shared/keep_reference.i

Lines changed: 32 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
// python-exiv2 - Python interface to libexiv2
22
// http://github.com/jim-easterbrook/python-exiv2
3-
// Copyright (C) 2023-24 Jim Easterbrook [email protected]
3+
// Copyright (C) 2023-25 Jim Easterbrook [email protected]
44
//
55
// This program is free software: you can redistribute it and/or modify
66
// it under the terms of the GNU General Public License as published by
@@ -16,11 +16,40 @@
1616
// along with this program. If not, see <http://www.gnu.org/licenses/>.
1717

1818

19+
// Functions to store and retrieve "private" data attached to Pyhon object
20+
%fragment("private_data", "header") {
21+
static PyObject* _get_store(PyObject* py_self) {
22+
if (!PyObject_HasAttrString(py_self, "_private_data_")) {
23+
PyObject* dict = PyDict_New();
24+
if (!dict)
25+
return NULL;
26+
int error = PyObject_SetAttrString(py_self, "_private_data_", dict);
27+
Py_DECREF(dict);
28+
if (error)
29+
return NULL;
30+
}
31+
return PyObject_GetAttrString(py_self, "_private_data_");
32+
};
33+
static int store_private(PyObject* py_self, const char* name,
34+
PyObject* val) {
35+
PyObject* dict = _get_store(py_self);
36+
if (!dict)
37+
return -1;
38+
int result = 0;
39+
if (val)
40+
result = PyDict_SetItemString(dict, name, val);
41+
else if (PyDict_GetItemString(dict, name))
42+
result = PyDict_DelItemString(dict, name);
43+
Py_DECREF(dict);
44+
return result;
45+
};
46+
}
47+
1948
// Macro to keep a reference to any object when returning a particular type.
2049
%define KEEP_REFERENCE_EX(return_type, target)
21-
%typemap(ret) return_type %{
50+
%typemap(ret, fragment="private_data") return_type %{
2251
if ($result != Py_None)
23-
if (PyObject_SetAttrString($result, "_refers_to", target)) {
52+
if (store_private($result, "_refers_to", target)) {
2453
SWIG_fail;
2554
}
2655
%}

src/swig-0_27_7/basicio_wrap.cxx

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4831,6 +4831,33 @@ SWIGINTERN char const *Exiv2_BasicIo_ioType(Exiv2::BasicIo *self){
48314831
SWIGINTERN DataContext *Exiv2_BasicIo_data(Exiv2::BasicIo *self,bool isWriteable){
48324832
return new DataContext(self, isWriteable);
48334833
}
4834+
4835+
static PyObject* _get_store(PyObject* py_self) {
4836+
if (!PyObject_HasAttrString(py_self, "_private_data_")) {
4837+
PyObject* dict = PyDict_New();
4838+
if (!dict)
4839+
return NULL;
4840+
int error = PyObject_SetAttrString(py_self, "_private_data_", dict);
4841+
Py_DECREF(dict);
4842+
if (error)
4843+
return NULL;
4844+
}
4845+
return PyObject_GetAttrString(py_self, "_private_data_");
4846+
};
4847+
static int store_private(PyObject* py_self, const char* name,
4848+
PyObject* val) {
4849+
PyObject* dict = _get_store(py_self);
4850+
if (!dict)
4851+
return -1;
4852+
int result = 0;
4853+
if (val)
4854+
result = PyDict_SetItemString(dict, name, val);
4855+
else if (PyDict_GetItemString(dict, name))
4856+
result = PyDict_DelItemString(dict, name);
4857+
Py_DECREF(dict);
4858+
return result;
4859+
};
4860+
48344861
#ifdef __cplusplus
48354862
extern "C" {
48364863
#endif
@@ -5799,7 +5826,7 @@ SWIGINTERN PyObject *_wrap_BasicIo_data(PyObject *self, PyObject *args) {
57995826
resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_DataContext, SWIG_POINTER_OWN | 0 );
58005827

58015828
if (resultobj != Py_None)
5802-
if (PyObject_SetAttrString(resultobj, "_refers_to", self)) {
5829+
if (store_private(resultobj, "_refers_to", self)) {
58035830
SWIG_fail;
58045831
}
58055832

src/swig-0_27_7/exif_wrap.cxx

Lines changed: 39 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -4429,6 +4429,33 @@ class ExifData_iterator : public ExifData_iterator_base {
44294429
};
44304430

44314431

4432+
static PyObject* _get_store(PyObject* py_self) {
4433+
if (!PyObject_HasAttrString(py_self, "_private_data_")) {
4434+
PyObject* dict = PyDict_New();
4435+
if (!dict)
4436+
return NULL;
4437+
int error = PyObject_SetAttrString(py_self, "_private_data_", dict);
4438+
Py_DECREF(dict);
4439+
if (error)
4440+
return NULL;
4441+
}
4442+
return PyObject_GetAttrString(py_self, "_private_data_");
4443+
};
4444+
static int store_private(PyObject* py_self, const char* name,
4445+
PyObject* val) {
4446+
PyObject* dict = _get_store(py_self);
4447+
if (!dict)
4448+
return -1;
4449+
int result = 0;
4450+
if (val)
4451+
result = PyDict_SetItemString(dict, name, val);
4452+
else if (PyDict_GetItemString(dict, name))
4453+
result = PyDict_DelItemString(dict, name);
4454+
Py_DECREF(dict);
4455+
return result;
4456+
};
4457+
4458+
44324459
SWIGINTERNINLINE PyObject*
44334460
SWIG_From_bool (bool value)
44344461
{
@@ -5539,7 +5566,7 @@ SWIGINTERN PyObject *_wrap_ExifData_iterator_base___iter__(PyObject *self, PyObj
55395566
}
55405567

55415568
if (resultobj != Py_None)
5542-
if (PyObject_SetAttrString(resultobj, "_refers_to", self)) {
5569+
if (store_private(resultobj, "_refers_to", self)) {
55435570
SWIG_fail;
55445571
}
55455572

@@ -6874,7 +6901,7 @@ SWIGINTERN PyObject *_wrap_ExifData_iterator_value__SWIG_0(PyObject *self, PyObj
68746901
}
68756902

68766903
if (resultobj != Py_None)
6877-
if (PyObject_SetAttrString(resultobj, "_refers_to", self)) {
6904+
if (store_private(resultobj, "_refers_to", self)) {
68786905
SWIG_fail;
68796906
}
68806907

@@ -6926,7 +6953,7 @@ SWIGINTERN PyObject *_wrap_ExifData_iterator_value__SWIG_1(PyObject *self, PyObj
69266953
}
69276954

69286955
if (resultobj != Py_None)
6929-
if (PyObject_SetAttrString(resultobj, "_refers_to", self)) {
6956+
if (store_private(resultobj, "_refers_to", self)) {
69306957
SWIG_fail;
69316958
}
69326959

@@ -8231,7 +8258,7 @@ SWIGINTERN PyObject *_wrap_Exifdatum_value__SWIG_0(PyObject *self, PyObject *arg
82318258
}
82328259

82338260
if (resultobj != Py_None)
8234-
if (PyObject_SetAttrString(resultobj, "_refers_to", self)) {
8261+
if (store_private(resultobj, "_refers_to", self)) {
82358262
SWIG_fail;
82368263
}
82378264

@@ -8432,7 +8459,7 @@ SWIGINTERN PyObject *_wrap_Exifdatum_value__SWIG_1(PyObject *self, PyObject *arg
84328459
}
84338460

84348461
if (resultobj != Py_None)
8435-
if (PyObject_SetAttrString(resultobj, "_refers_to", self)) {
8462+
if (store_private(resultobj, "_refers_to", self)) {
84368463
SWIG_fail;
84378464
}
84388465

@@ -8850,7 +8877,7 @@ SWIGINTERN int _wrap_new_ExifThumb(PyObject *self, PyObject *args, PyObject *kwa
88508877
resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_Exiv2__ExifThumb, SWIG_BUILTIN_INIT | 0 );
88518878

88528879
if (resultobj != Py_None)
8853-
if (PyObject_SetAttrString(resultobj, "_refers_to", args)) {
8880+
if (store_private(resultobj, "_refers_to", args)) {
88548881
SWIG_fail;
88558882
}
88568883

@@ -9423,7 +9450,7 @@ SWIGINTERN PyObject *_wrap_ExifData_erase__SWIG_0(PyObject *self, PyObject *args
94239450
}
94249451

94259452
if (resultobj != Py_None)
9426-
if (PyObject_SetAttrString(resultobj, "_refers_to", self)) {
9453+
if (store_private(resultobj, "_refers_to", self)) {
94279454
SWIG_fail;
94289455
}
94299456

@@ -9494,7 +9521,7 @@ SWIGINTERN PyObject *_wrap_ExifData_erase__SWIG_1(PyObject *self, PyObject *args
94949521
}
94959522

94969523
if (resultobj != Py_None)
9497-
if (PyObject_SetAttrString(resultobj, "_refers_to", self)) {
9524+
if (store_private(resultobj, "_refers_to", self)) {
94989525
SWIG_fail;
94999526
}
95009527

@@ -9638,7 +9665,7 @@ SWIGINTERN PyObject *_wrap_ExifData_begin(PyObject *self, PyObject *args) {
96389665
}
96399666

96409667
if (resultobj != Py_None)
9641-
if (PyObject_SetAttrString(resultobj, "_refers_to", self)) {
9668+
if (store_private(resultobj, "_refers_to", self)) {
96429669
SWIG_fail;
96439670
}
96449671

@@ -9671,7 +9698,7 @@ SWIGINTERN PyObject *_wrap_ExifData_end(PyObject *self, PyObject *args) {
96719698
}
96729699

96739700
if (resultobj != Py_None)
9674-
if (PyObject_SetAttrString(resultobj, "_refers_to", self)) {
9701+
if (store_private(resultobj, "_refers_to", self)) {
96759702
SWIG_fail;
96769703
}
96779704

@@ -9724,7 +9751,7 @@ SWIGINTERN PyObject *_wrap_ExifData_findKey(PyObject *self, PyObject *args) {
97249751
}
97259752

97269753
if (resultobj != Py_None)
9727-
if (PyObject_SetAttrString(resultobj, "_refers_to", self)) {
9754+
if (store_private(resultobj, "_refers_to", self)) {
97289755
SWIG_fail;
97299756
}
97309757

@@ -9816,7 +9843,7 @@ SWIGINTERN PyObject *_wrap_ExifData___getitem__(PyObject *self, PyObject *args)
98169843
if (SWIG_IsNewObj(res2)) delete arg2;
98179844

98189845
if (resultobj != Py_None)
9819-
if (PyObject_SetAttrString(resultobj, "_refers_to", self)) {
9846+
if (store_private(resultobj, "_refers_to", self)) {
98209847
SWIG_fail;
98219848
}
98229849

src/swig-0_27_7/image_wrap.cxx

Lines changed: 35 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -4631,6 +4631,33 @@ static PyObject* _get_enum_list(int dummy, ...) {
46314631
};
46324632

46334633

4634+
static PyObject* _get_store(PyObject* py_self) {
4635+
if (!PyObject_HasAttrString(py_self, "_private_data_")) {
4636+
PyObject* dict = PyDict_New();
4637+
if (!dict)
4638+
return NULL;
4639+
int error = PyObject_SetAttrString(py_self, "_private_data_", dict);
4640+
Py_DECREF(dict);
4641+
if (error)
4642+
return NULL;
4643+
}
4644+
return PyObject_GetAttrString(py_self, "_private_data_");
4645+
};
4646+
static int store_private(PyObject* py_self, const char* name,
4647+
PyObject* val) {
4648+
PyObject* dict = _get_store(py_self);
4649+
if (!dict)
4650+
return -1;
4651+
int result = 0;
4652+
if (val)
4653+
result = PyDict_SetItemString(dict, name, val);
4654+
else if (PyDict_GetItemString(dict, name))
4655+
result = PyDict_DelItemString(dict, name);
4656+
Py_DECREF(dict);
4657+
return result;
4658+
};
4659+
4660+
46344661
/* Return string from Python obj. NOTE: obj must remain in scope in order
46354662
to use the returned cptr (but only when alloc is set to SWIG_OLDOBJ) */
46364663
SWIGINTERN int
@@ -5124,9 +5151,7 @@ SWIGINTERN PyObject *_wrap_Image_writeMetadata(PyObject *self, PyObject *args) {
51245151
}
51255152
resultobj = SWIG_Py_Void();
51265153

5127-
if (PyObject_HasAttrString(self, "_refers_to")) {
5128-
PyObject_DelAttrString(self, "_refers_to");
5129-
}
5154+
store_private(self, "_refers_to", NULL);
51305155

51315156
return resultobj;
51325157
fail:
@@ -5622,7 +5647,7 @@ SWIGINTERN PyObject *_wrap_Image_iccProfile(PyObject *self, PyObject *args) {
56225647
resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_Exiv2__DataBuf, 0 | 0 );
56235648

56245649
if (resultobj != Py_None)
5625-
if (PyObject_SetAttrString(resultobj, "_refers_to", self)) {
5650+
if (store_private(resultobj, "_refers_to", self)) {
56265651
SWIG_fail;
56275652
}
56285653

@@ -5726,7 +5751,7 @@ SWIGINTERN PyObject *_wrap_Image_exifData(PyObject *self, PyObject *args) {
57265751
resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_Exiv2__ExifData, 0 | 0 );
57275752

57285753
if (resultobj != Py_None)
5729-
if (PyObject_SetAttrString(resultobj, "_refers_to", self)) {
5754+
if (store_private(resultobj, "_refers_to", self)) {
57305755
SWIG_fail;
57315756
}
57325757

@@ -5761,7 +5786,7 @@ SWIGINTERN PyObject *_wrap_Image_iptcData(PyObject *self, PyObject *args) {
57615786
resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_Exiv2__IptcData, 0 | 0 );
57625787

57635788
if (resultobj != Py_None)
5764-
if (PyObject_SetAttrString(resultobj, "_refers_to", self)) {
5789+
if (store_private(resultobj, "_refers_to", self)) {
57655790
SWIG_fail;
57665791
}
57675792

@@ -5796,7 +5821,7 @@ SWIGINTERN PyObject *_wrap_Image_xmpData(PyObject *self, PyObject *args) {
57965821
resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_Exiv2__XmpData, 0 | 0 );
57975822

57985823
if (resultobj != Py_None)
5799-
if (PyObject_SetAttrString(resultobj, "_refers_to", self)) {
5824+
if (store_private(resultobj, "_refers_to", self)) {
58005825
SWIG_fail;
58015826
}
58025827

@@ -6118,7 +6143,7 @@ SWIGINTERN PyObject *_wrap_Image_io(PyObject *self, PyObject *args) {
61186143
resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_Exiv2__BasicIo, 0 | 0 );
61196144

61206145
if (resultobj != Py_None)
6121-
if (PyObject_SetAttrString(resultobj, "_refers_to", self)) {
6146+
if (store_private(resultobj, "_refers_to", self)) {
61226147
SWIG_fail;
61236148
}
61246149

@@ -6526,7 +6551,7 @@ SWIGINTERN PyObject *_wrap_ImageFactory_open__SWIG_1(PyObject *self, Py_ssize_t
65266551
resultobj = SWIG_NewPointerObj((&result)->release(), SWIGTYPE_p_Exiv2__Image, SWIG_POINTER_OWN | 0 );
65276552

65286553

6529-
PyObject_SetAttrString(resultobj, "_refers_to", _global_view);
6554+
store_private(resultobj, "_refers_to", _global_view);
65306555

65316556

65326557
Py_XDECREF(_global_view);
@@ -7031,7 +7056,7 @@ SWIGINTERN PyObject *_wrap_ImageFactory_createIo__SWIG_1(PyObject *self, Py_ssiz
70317056
resultobj = SWIG_NewPointerObj((&result)->release(), SWIGTYPE_p_Exiv2__BasicIo, SWIG_POINTER_OWN | 0 );
70327057

70337058

7034-
PyObject_SetAttrString(resultobj, "_refers_to", _global_view);
7059+
store_private(resultobj, "_refers_to", _global_view);
70357060

70367061

70377062
Py_XDECREF(_global_view);

0 commit comments

Comments
 (0)