11// python-exiv2 - Python interface to libexiv2
22// http://github.com/jim-easterbrook/python-exiv2
3- // Copyright (C) 2024 Jim Easterbrook [email protected] 3+ // Copyright (C) 2024-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
@@ -35,41 +35,33 @@ static PyObject* list_getset(
3535 }
3636 return result;
3737};
38- static PyGetSetDef* find_getset (PyObject* obj, const char * name) {
39- size_t len = strlen (name);
40- PyGetSetDef* getset = obj->ob_type ->tp_getset ;
41- while (getset->name ) {
42- size_t cmp_len = strlen (getset->name );
43- if (getset->name [cmp_len-1 ] == ' _' )
44- cmp_len--;
45- if ((cmp_len == len) && (strncmp (getset->name , name, len) == 0 ))
46- return getset;
47- getset++;
48- }
49- PyErr_Format (
50- PyExc_KeyError, " '%s' not in '%s'" , name, obj->ob_type ->tp_name );
51- return NULL ;
38+ static PyObject* getset_to_value (PyObject* obj, PyGetSetDef* getset) {
39+ return Py_BuildValue (" N" , getset->get (obj, getset->closure ));
5240};
53- static PyObject* getset_to_item (PyObject* obj, PyGetSetDef* getset) {
54- size_t len = strlen (getset-> name );
55- if (getset-> name [len- 1 ] == ' _ ' )
56- len--;
57- return Py_BuildValue (" (s#N)" , getset->name , len ,
41+ }
42+ %fragment( " getset_functions_strip " , " header " ,
43+ fragment= " getset_functions " ) {
44+ static PyObject* getset_to_item_strip (PyObject* obj, PyGetSetDef* getset) {
45+ return Py_BuildValue (" (s#N)" , getset->name , strlen (getset-> name ) - 1 ,
5846 getset->get (obj, getset->closure ));
5947};
60- static PyObject* getset_to_key (PyObject* obj, PyGetSetDef* getset) {
61- size_t len = strlen (getset->name );
62- if (getset->name [len-1 ] == ' _' )
63- len--;
64- return Py_BuildValue (" s#" , getset->name , len);
48+ static PyObject* getset_to_key_strip (PyObject* obj, PyGetSetDef* getset) {
49+ return Py_BuildValue (" s#" , getset->name , strlen (getset->name ) - 1 );
6550};
66- static PyObject* getset_to_value (PyObject* obj, PyGetSetDef* getset) {
67- return Py_BuildValue (" N" , getset->get (obj, getset->closure ));
51+ }
52+ %fragment(" getset_functions_nostrip" , " header" ,
53+ fragment=" getset_functions" ) {
54+ static PyObject* getset_to_item_nostrip (PyObject* obj, PyGetSetDef* getset) {
55+ return Py_BuildValue (" (sN)" , getset->name ,
56+ getset->get (obj, getset->closure ));
57+ };
58+ static PyObject* getset_to_key_nostrip (PyObject* obj, PyGetSetDef* getset) {
59+ return Py_BuildValue (" s" , getset->name );
6860};
6961}
7062
7163// Macro definition
72- %define STRUCT_DICT (struct_type, mutable )
64+ %define STRUCT_DICT (struct_type, mutable , strip_underscore )
7365// Type slots
7466%feature(" python:slot" , " tp_iter" , functype=" getiterfunc" )
7567 struct_type::__iter__;
@@ -92,13 +84,23 @@ static PyObject* getset_to_value(PyObject* obj, PyGetSetDef* getset) {
9284:return: structure member values."
9385// Add functions
9486%extend struct_type {
95- %fragment (" getset_functions" );
87+ #if #strip_underscore == "true"
88+ %fragment (" getset_functions_strip" );
9689 PyObject* items (PyObject* py_self) {
97- return list_getset (py_self, getset_to_item );
90+ return list_getset (py_self, getset_to_item_strip );
9891 }
9992 PyObject* keys (PyObject* py_self) {
100- return list_getset (py_self, getset_to_key);
93+ return list_getset (py_self, getset_to_key_strip);
94+ }
95+ #else
96+ %fragment (" getset_functions_nostrip" );
97+ PyObject* items (PyObject* py_self) {
98+ return list_getset (py_self, getset_to_item_nostrip);
10199 }
100+ PyObject* keys (PyObject* py_self) {
101+ return list_getset (py_self, getset_to_key_nostrip);
102+ }
103+ #endif // strip_underscore
102104 PyObject* values (PyObject* py_self) {
103105 return list_getset (py_self, getset_to_value);
104106 }
@@ -110,10 +112,11 @@ static PyObject* getset_to_value(PyObject* obj, PyGetSetDef* getset) {
110112 return result;
111113 }
112114 PyObject* __getitem__ (PyObject* py_self, const std::string& key) {
113- PyGetSetDef* getset = find_getset (py_self, key.c_str ());
114- if (!getset)
115- return NULL ;
116- return getset->get (py_self, getset->closure );
115+ #if #strip_underscore == "true"
116+ return PyObject_GetAttrString (py_self, (key + ' _' ).c_str ());
117+ #else
118+ return PyObject_GetAttrString (py_self, key.c_str ());
119+ #endif // strip_underscore
117120 }
118121}
119122#if #mutable == "true"
@@ -122,17 +125,17 @@ static PyObject* getset_to_value(PyObject* obj, PyGetSetDef* getset) {
122125%extend struct_type {
123126 PyObject* __setitem__ (PyObject* py_self, const std::string& key,
124127 PyObject* value) {
125- PyGetSetDef* getset = find_getset (py_self, key.c_str ());
126- if (!getset)
127- return NULL ;
128128 if (!value)
129129 return PyErr_Format (PyExc_TypeError,
130130 " %s['%s'] can not be deleted" , py_self->ob_type ->tp_name ,
131131 key.c_str ());
132- if (!getset->set )
133- return PyErr_Format (PyExc_TypeError, " %s['%s'] is read-only" ,
134- py_self->ob_type ->tp_name , key.c_str ());
135- if (getset->set (py_self, value, getset->closure ) != 0 )
132+ #if #strip_underscore == "true"
133+ int error = PyObject_SetAttrString (
134+ py_self, (key + ' _' ).c_str (), value);
135+ #else
136+ int error = PyObject_SetAttrString (py_self, key.c_str (), value);
137+ #endif // strip_underscore
138+ if (error)
136139 return NULL ;
137140 return SWIG_Py_Void ();
138141 }
0 commit comments