Call (sub)type tp_free from destructors
[platform/upstream/rpm.git] / python / rpmps-py.c
1 #include "rpmsystem-py.h"
2
3 #include "rpmps-py.h"
4
5 #include "debug.h"
6
7 struct rpmpsObject_s {
8     PyObject_HEAD
9     PyObject *md_dict;          /*!< to look like PyModuleObject */
10     rpmps       ps;
11     rpmpsi      psi;
12 };
13
14 static int
15 rpmps_append(rpmpsObject * s, PyObject * value)
16 {
17     char *pkgNEVR, *altNEVR, *str1;
18     unsigned long ulong1;
19     int ignoreProblem;
20     rpmProblemType type;
21     fnpyKey key;
22
23     if (!PyArg_ParseTuple(value, "ssOiisN:rpmps value tuple",
24                         &pkgNEVR, &altNEVR, &key,
25                         &type, &ignoreProblem, &str1,
26                         &ulong1))
27     {
28         return -1;
29     }
30     rpmpsAppend(s->ps, type, pkgNEVR, key, str1, NULL, altNEVR, ulong1);
31     return 0;
32 }
33
34 static PyObject *
35 rpmps_iternext(rpmpsObject * s)
36 {
37     PyObject * result = NULL;
38
39     /* Reset loop indices on 1st entry. */
40     if (s->psi == NULL) {
41         s->psi = rpmpsInitIterator(s->ps);
42     }
43
44     /* If more to do, return a problem set string. */
45     if (rpmpsNextIterator(s->psi) >= 0) {
46         char * ps = rpmProblemString(rpmpsGetProblem(s->psi));
47         result = Py_BuildValue("s", ps);
48         free(ps);
49     } else {
50         s->psi = rpmpsFreeIterator(s->psi);
51     }
52
53     return result;
54 }
55
56 static struct PyMethodDef rpmps_methods[] = {
57   {"append",    (PyCFunction)rpmps_append,      METH_VARARGS, NULL},
58  {NULL,         NULL}           /* sentinel */
59 };
60
61 static void
62 rpmps_dealloc(rpmpsObject * s)
63 {
64     s->ps = rpmpsFree(s->ps);
65     s->ob_type->tp_free((PyObject *)s);
66 }
67
68 static int
69 rpmps_length(rpmpsObject * s)
70 {
71     int rc;
72     rc = rpmpsNumProblems(s->ps);
73     return rc;
74 }
75
76 static PyObject *
77 rpmps_subscript(rpmpsObject * s, PyObject * key)
78 {
79     PyObject * result = NULL;
80     rpmpsi psi;
81     int ix, i;
82
83     if (!PyInt_Check(key)) {
84         PyErr_SetString(PyExc_TypeError, "integer expected");
85         return NULL;
86     }
87
88     ix = (int) PyInt_AsLong(key);
89     /* XXX range check */
90
91     psi = rpmpsInitIterator(s->ps);
92     while ((i = rpmpsNextIterator(psi)) >= 0) {
93         if (i == ix) {
94             char * ps = rpmProblemString(rpmpsGetProblem(psi));
95             result = Py_BuildValue("s", ps);
96             free(ps);
97             break;
98         }
99     }
100     psi = rpmpsFreeIterator(psi);
101
102     return result;
103 }
104
105 static PyMappingMethods rpmps_as_mapping = {
106         (lenfunc) rpmps_length,         /* mp_length */
107         (binaryfunc) rpmps_subscript,   /* mp_subscript */
108 };
109
110 static void rpmps_free(rpmpsObject * s)
111 {
112     s->ps = rpmpsFree(s->ps);
113
114     PyObject_Del((PyObject *)s);
115 }
116
117 static PyObject * rpmps_new(PyTypeObject * subtype, PyObject *args, PyObject *kwds)
118 {
119     rpmps ps = rpmpsCreate();
120     return rpmps_Wrap(subtype, ps);
121 }
122
123 static char rpmps_doc[] =
124 "";
125
126 PyTypeObject rpmps_Type = {
127         PyObject_HEAD_INIT(&PyType_Type)
128         0,                              /* ob_size */
129         "rpm.ps",                       /* tp_name */
130         sizeof(rpmpsObject),            /* tp_basicsize */
131         0,                              /* tp_itemsize */
132         /* methods */
133         (destructor) rpmps_dealloc,     /* tp_dealloc */
134         0,                              /* tp_print */
135         (getattrfunc)0,                 /* tp_getattr */
136         (setattrfunc)0,                 /* tp_setattr */
137         (cmpfunc)0,                     /* tp_compare */
138         (reprfunc)0,                    /* tp_repr */
139         0,                              /* tp_as_number */
140         0,                              /* tp_as_sequence */
141         &rpmps_as_mapping,              /* tp_as_mapping */
142         (hashfunc)0,                    /* tp_hash */
143         (ternaryfunc)0,                 /* tp_call */
144         (reprfunc)0,                    /* tp_str */
145         PyObject_GenericGetAttr,        /* tp_getattro */
146         PyObject_GenericSetAttr,        /* tp_setattro */
147         0,                              /* tp_as_buffer */
148         Py_TPFLAGS_DEFAULT,             /* tp_flags */
149         rpmps_doc,                      /* tp_doc */
150         0,                              /* tp_traverse */
151         0,                              /* tp_clear */
152         (richcmpfunc)0,                 /* tp_richcompare */
153         0,                              /* tp_weaklistoffset */
154         PyObject_SelfIter,              /* tp_iter */
155         (iternextfunc) rpmps_iternext,  /* tp_iternext */
156         rpmps_methods,                  /* tp_methods */
157         0,                              /* tp_members */
158         0,                              /* tp_getset */
159         0,                              /* tp_base */
160         0,                              /* tp_dict */
161         0,                              /* tp_descr_get */
162         0,                              /* tp_descr_set */
163         0,                              /* tp_dictoffset */
164         0,                              /* tp_init */
165         0,                              /* tp_alloc */
166         (newfunc) rpmps_new,            /* tp_new */
167         (freefunc) rpmps_free,          /* tp_free */
168         0,                              /* tp_is_gc */
169 };
170
171 rpmps psFromPs(rpmpsObject * s)
172 {
173     return s->ps;
174 }
175
176 PyObject * rpmps_Wrap(PyTypeObject *subtype, rpmps ps)
177 {
178     rpmpsObject * s = (rpmpsObject *)subtype->tp_alloc(subtype, 0);
179     if (s == NULL) return PyErr_NoMemory();
180
181     s->ps = ps; /* XXX refcounts? */
182     s->psi = NULL;
183     return (PyObject *) s;
184 }