1 /*
2 * Copyright (C) 2013 Red Hat, Inc.
3 *
4 * Licensed under the GNU Lesser General Public License Version 2.1
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19 */
20
21 #include <Python.h>
22
23 // libsolv
24 #include <solv/util.h>
25
26 // hawkey
27 #include "hy-query.h"
28 #include "dnf-sack.h"
29
30 // pyhawkey
31 #include "exception-py.hpp"
32 #include "iutil-py.hpp"
33 #include "nevra-py.hpp"
34 #include "pycomp.hpp"
35 #include "query-py.hpp"
36 #include "sack-py.hpp"
37
38 typedef struct {
39 PyObject_HEAD
40 libdnf::Nevra *nevra;
41 } _NevraObject;
42
43 libdnf::Nevra *
nevraFromPyObject(PyObject * o)44 nevraFromPyObject(PyObject *o)
45 {
46 if (!PyObject_TypeCheck(o, &nevra_Type)) {
47 PyErr_SetString(PyExc_TypeError, "Expected a _hawkey.NEVRA object.");
48 return NULL;
49 }
50 return ((_NevraObject *)o)->nevra;
51 }
52
53 PyObject *
nevraToPyObject(libdnf::Nevra * nevra)54 nevraToPyObject(libdnf::Nevra *nevra)
55 {
56 _NevraObject *self = (_NevraObject *)nevra_Type.tp_alloc(&nevra_Type, 0);
57 if (self)
58 self->nevra = nevra;
59 return (PyObject *)self;
60 }
61
62 // getsetters
63 static int
set_epoch(_NevraObject * self,PyObject * value,void * closure)64 set_epoch(_NevraObject *self, PyObject *value, void *closure) try
65 {
66 if (value == NULL)
67 self->nevra->setEpoch(libdnf::Nevra::EPOCH_NOT_SET);
68 else if (PyInt_Check(value))
69 self->nevra->setEpoch(PyLong_AsLong(value));
70 else if (value == Py_None)
71 self->nevra->setEpoch(libdnf::Nevra::EPOCH_NOT_SET);
72 else
73 return -1;
74 return 0;
75 } CATCH_TO_PYTHON_INT
76
77 static PyObject *
get_epoch(_NevraObject * self,void * closure)78 get_epoch(_NevraObject *self, void *closure) try
79 {
80 if (self->nevra->getEpoch() == libdnf::Nevra::EPOCH_NOT_SET)
81 Py_RETURN_NONE;
82 #if PY_MAJOR_VERSION >= 3
83 return PyLong_FromLong(self->nevra->getEpoch());
84 #else
85 return PyInt_FromLong(self->nevra->getEpoch());
86 #endif
87 } CATCH_TO_PYTHON
88
89 template<const std::string & (libdnf::Nevra::*getMethod)() const>
90 static PyObject *
get_attr(_NevraObject * self,void * closure)91 get_attr(_NevraObject *self, void *closure) try
92 {
93 auto str = (self->nevra->*getMethod)();
94 if (str.empty())
95 Py_RETURN_NONE;
96 else
97 return PyString_FromString(str.c_str());
98 } CATCH_TO_PYTHON
99
100 template<void (libdnf::Nevra::*setMethod)(std::string &&)>
101 static int
set_attr(_NevraObject * self,PyObject * value,void * closure)102 set_attr(_NevraObject *self, PyObject *value, void *closure) try
103 {
104 PycompString str_value(value);
105 if (!str_value.getCString())
106 return -1;
107 (self->nevra->*setMethod)(str_value.getCString());
108 return 0;
109 } CATCH_TO_PYTHON_INT
110
111 static PyGetSetDef nevra_getsetters[] = {
112 {(char*)"name", (getter)get_attr<&libdnf::Nevra::getName>,
113 (setter)set_attr<&libdnf::Nevra::setName>, NULL, NULL},
114 {(char*)"epoch", (getter)get_epoch, (setter)set_epoch,
115 NULL, NULL},
116 {(char*)"version", (getter)get_attr<&libdnf::Nevra::getVersion>,
117 (setter)set_attr<&libdnf::Nevra::setVersion>, NULL, NULL},
118 {(char*)"release", (getter)get_attr<&libdnf::Nevra::getRelease>,
119 (setter)set_attr<&libdnf::Nevra::setRelease>, NULL, NULL},
120 {(char*)"arch", (getter)get_attr<&libdnf::Nevra::getArch>,
121 (setter)set_attr<&libdnf::Nevra::setArch>, NULL, NULL},
122 {NULL} /* sentinel */
123 };
124
125 static PyObject *
nevra_new(PyTypeObject * type,PyObject * args,PyObject * kwds)126 nevra_new(PyTypeObject *type, PyObject *args, PyObject *kwds) try
127 {
128 _NevraObject *self = (_NevraObject*)type->tp_alloc(type, 0);
129 if (self)
130 self->nevra = new libdnf::Nevra;
131 return (PyObject*)self;
132 } CATCH_TO_PYTHON
133
134 static void
nevra_dealloc(_NevraObject * self)135 nevra_dealloc(_NevraObject *self)
136 {
137 delete self->nevra;
138 Py_TYPE(self)->tp_free(self);
139 }
140
141 static int
nevra_init(_NevraObject * self,PyObject * args,PyObject * kwds)142 nevra_init(_NevraObject *self, PyObject *args, PyObject *kwds) try
143 {
144 char *name = NULL, *version = NULL, *release = NULL, *arch = NULL;
145 PyObject *epoch_o = NULL;
146 libdnf::Nevra * cnevra = NULL;
147
148 const char *kwlist[] = {"name", "epoch", "version", "release", "arch",
149 "nevra", NULL};
150
151 if (!PyArg_ParseTupleAndKeywords(args, kwds, "|zOzzzO&", (char**) kwlist,
152 &name, &epoch_o, &version, &release, &arch, nevra_converter, &cnevra))
153 return -1;
154 if (!name && !cnevra) {
155 PyErr_SetString(PyExc_ValueError,
156 "Name is required parameter.");
157 return -1;
158 }
159 if (cnevra) {
160 *self->nevra = *cnevra;
161 return 0;
162 }
163 if (set_epoch(self, epoch_o, NULL) == -1) {
164 PyErr_SetString(PyExc_TypeError,
165 "An integer value or None expected for epoch.");
166 return -1;
167 }
168 if (name)
169 self->nevra->setName(name);
170 if (version)
171 self->nevra->setVersion(version);
172 if (release)
173 self->nevra->setRelease(release);
174 if (arch)
175 self->nevra->setArch(arch);
176 return 0;
177 } CATCH_TO_PYTHON_INT
178
179 /* object methods */
180
181 static PyObject *
evr(_NevraObject * self,PyObject * unused)182 evr(_NevraObject *self, PyObject *unused) try
183 {
184 return PyString_FromString(self->nevra->getEvr().c_str());;
185 } CATCH_TO_PYTHON
186
187 int
nevra_converter(PyObject * o,libdnf::Nevra ** nevra_ptr)188 nevra_converter(PyObject *o, libdnf::Nevra **nevra_ptr)
189 {
190 auto nevra = nevraFromPyObject(o);
191 if (nevra == NULL)
192 return 0;
193 *nevra_ptr = nevra;
194 return 1;
195 }
196
197 static PyObject *
evr_cmp(_NevraObject * self,PyObject * args)198 evr_cmp(_NevraObject *self, PyObject *args) try
199 {
200 DnfSack *sack;
201 libdnf::Nevra *nevra;
202 if (!PyArg_ParseTuple(args, "O&O&", nevra_converter, &nevra, sack_converter, &sack)) {
203 return NULL;
204 }
205 if (sack == NULL || nevra == NULL)
206 return NULL;
207 int cmp = self->nevra->compareEvr(*nevra, sack);
208 return PyLong_FromLong(cmp);
209 } CATCH_TO_PYTHON
210
211 static PyObject *
has_just_name(_NevraObject * self,PyObject * unused)212 has_just_name(_NevraObject *self, PyObject *unused) try
213 {
214 return PyBool_FromLong(self->nevra->hasJustName());
215 } CATCH_TO_PYTHON
216
217 static PyObject *
to_query(_NevraObject * self,PyObject * args,PyObject * kwds)218 to_query(_NevraObject *self, PyObject *args, PyObject *kwds) try
219 {
220 PyObject *sack;
221 DnfSack *csack;
222 const char *kwlist[] = {"sack", "icase", NULL};
223 PyObject *icase = NULL;
224
225 if (!PyArg_ParseTupleAndKeywords(args, kwds, "O!|O!", (char**) kwlist, &sack_Type, &sack,
226 &PyBool_Type, &icase)) {
227 return NULL;
228 }
229 gboolean c_icase = icase!=NULL && PyObject_IsTrue(icase);
230 csack = sackFromPyObject(sack);
231 HyQuery query = hy_query_from_nevra(self->nevra, csack, c_icase);
232 PyObject *q = queryToPyObject(query, sack, &query_Type);
233 return q;
234 } CATCH_TO_PYTHON
235
236 static struct PyMethodDef nevra_methods[] = {
237 {"evr_cmp", (PyCFunction) evr_cmp, METH_VARARGS, NULL},
238 {"evr", (PyCFunction) evr, METH_NOARGS, NULL},
239 {"has_just_name", (PyCFunction) has_just_name, METH_NOARGS, NULL},
240 {"to_query", (PyCFunction) to_query, METH_VARARGS | METH_KEYWORDS, NULL},
241
242 {NULL} /* sentinel */
243 };
244
245 static PyObject *
nevra_richcompare(PyObject * self,PyObject * other,int op)246 nevra_richcompare(PyObject *self, PyObject *other, int op) try
247 {
248 PyObject *v;
249 libdnf::Nevra *other_nevra, *self_nevra;
250 other_nevra = nevraFromPyObject(other);
251 self_nevra = nevraFromPyObject(self);
252
253 if (!other_nevra) {
254 if(PyErr_Occurred() && PyErr_ExceptionMatches(PyExc_TypeError))
255 PyErr_Clear();
256 Py_INCREF(Py_NotImplemented);
257 return Py_NotImplemented;
258 }
259
260 long result = self_nevra->compare(*other_nevra);
261
262 switch (op) {
263 case Py_EQ:
264 v = TEST_COND(result == 0);
265 break;
266 case Py_NE:
267 v = TEST_COND(result != 0);
268 break;
269 case Py_LE:
270 v = TEST_COND(result <= 0);
271 break;
272 case Py_GE:
273 v = TEST_COND(result >= 0);
274 break;
275 case Py_LT:
276 v = TEST_COND(result < 0);
277 break;
278 case Py_GT:
279 v = TEST_COND(result > 0);
280 break;
281 default:
282 PyErr_BadArgument();
283 return NULL;
284 }
285 Py_INCREF(v);
286 return v;
287 } CATCH_TO_PYTHON
288
289 PyTypeObject nevra_Type = {
290 PyVarObject_HEAD_INIT(NULL, 0)
291 "_hawkey.NEVRA", /*tp_name*/
292 sizeof(_NevraObject), /*tp_basicsize*/
293 0, /*tp_itemsize*/
294 (destructor) nevra_dealloc, /*tp_dealloc*/
295 0, /*tp_print*/
296 0, /*tp_getattr*/
297 0, /*tp_setattr*/
298 0, /*tp_compare*/
299 0, /*tp_repr*/
300 0, /*tp_as_number*/
301 0, /*tp_as_sequence*/
302 0, /*tp_as_mapping*/
303 0, /*tp_hash */
304 0, /*tp_call*/
305 0, /*tp_str*/
306 0, /*tp_getattro*/
307 0, /*tp_setattro*/
308 0, /*tp_as_buffer*/
309 Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE, /*tp_flags*/
310 "NEVRA object", /* tp_doc */
311 0, /* tp_traverse */
312 0, /* tp_clear */
313 nevra_richcompare, /* tp_richcompare */
314 0, /* tp_weaklistoffset */
315 0, /* tp_iter */
316 0, /* tp_iternext */
317 nevra_methods, /* tp_methods */
318 0, /* tp_members */
319 nevra_getsetters, /* tp_getset */
320 0, /* tp_base */
321 0, /* tp_dict */
322 0, /* tp_descr_get */
323 0, /* tp_descr_set */
324 0, /* tp_dictoffset */
325 (initproc)nevra_init, /* tp_init */
326 0, /* tp_alloc */
327 nevra_new, /* tp_new */
328 0, /* tp_free */
329 0, /* tp_is_gc */
330 };
331