summaryrefslogtreecommitdiff
path: root/python/header-py.c
diff options
context:
space:
mode:
authorPanu Matilainen <pmatilai@redhat.com>2009-11-24 14:27:49 +0200
committerPanu Matilainen <pmatilai@redhat.com>2009-11-24 14:32:05 +0200
commit39e15e7a678dfcfc0c03449b2ebc327569933f31 (patch)
treee139e9a9ad62fb9859bedd6353b303c4677ee797 /python/header-py.c
parent897f06b9100437e6074ec5a816a83779662ddb4b (diff)
downloadlibrpm-tizen-39e15e7a678dfcfc0c03449b2ebc327569933f31.tar.gz
librpm-tizen-39e15e7a678dfcfc0c03449b2ebc327569933f31.tar.bz2
librpm-tizen-39e15e7a678dfcfc0c03449b2ebc327569933f31.zip
Support constructing header data from python
- no proper i18n string support yet, just the basic types - basic data type validation only, no overflow checking for integer types - for lists, validate all items before trying to insert anything - duplicate tag creation not permitted - appending not permitted, only assignment (and deletion already) - there are probably bugs... - watch out for librpm bugs when passed incomplete headers, ugh
Diffstat (limited to 'python/header-py.c')
-rw-r--r--python/header-py.c125
1 files changed, 121 insertions, 4 deletions
diff --git a/python/header-py.c b/python/header-py.c
index 9203156fb..e6a84c93f 100644
--- a/python/header-py.c
+++ b/python/header-py.c
@@ -454,6 +454,126 @@ static PyObject * hdrGetTag(Header h, rpmTag tag)
return res;
}
+static int validItem(rpmTagClass class, PyObject *item)
+{
+ int rc;
+
+ switch (class) {
+ case RPM_NUMERIC_CLASS:
+ rc = (PyLong_Check(item) || PyInt_Check(item));
+ break;
+ case RPM_STRING_CLASS:
+ rc = (PyBytes_Check(item) || PyUnicode_Check(item));
+ break;
+ case RPM_BINARY_CLASS:
+ rc = PyBytes_Check(item);
+ break;
+ default:
+ rc = 0;
+ break;
+ }
+ return rc;
+}
+
+static int validData(rpmTag tag, rpmTagType type, PyObject *value)
+{
+ rpmTagClass class = rpmTagGetClass(tag);
+ rpmTagReturnType retype = (type & RPM_MASK_RETURN_TYPE);
+ int valid = 1;
+
+ printf("%s: tag %s retype %x\n", __func__, rpmTagGetName(tag), retype);
+ if (retype == RPM_SCALAR_RETURN_TYPE) {
+ valid = validItem(class, value);
+ } else if (retype == RPM_ARRAY_RETURN_TYPE && PyList_Check(value)) {
+ /* python lists can contain arbitrary objects, validate each item */
+ Py_ssize_t len = PyList_Size(value);
+ for (Py_ssize_t i = 0; i < len; i++) {
+ PyObject *item = PyList_GetItem(value, i);
+ if (!validItem(class, item)) {
+ valid = 0;
+ break;
+ }
+ }
+ } else {
+ valid = 0;
+ }
+ return valid;
+}
+
+static int hdrAppendItem(Header h, rpmTag tag, rpmTagType type, PyObject *item)
+{
+ int rc = 0;
+
+ switch ((type & RPM_MASK_TYPE)) {
+ case RPM_I18NSTRING_TYPE: /* XXX this needs to be handled separately */
+ case RPM_STRING_TYPE:
+ case RPM_STRING_ARRAY_TYPE: {
+ PyObject *str = NULL;
+ if (utf8FromPyObject(item, &str))
+ rc = headerPutString(h, tag, PyBytes_AsString(str));
+ Py_XDECREF(str);
+ } break;
+ case RPM_BIN_TYPE: {
+ uint8_t *val = (uint8_t *) PyBytes_AsString(item);
+ rpm_count_t len = PyBytes_Size(item);
+ rc = headerPutBin(h, tag, val, len);
+ } break;
+ case RPM_INT64_TYPE: {
+ uint64_t val = PyInt_AsUnsignedLongLongMask(item);
+ rc = headerPutUint64(h, tag, &val, 1);
+ } break;
+ case RPM_INT32_TYPE: {
+ uint32_t val = PyInt_AsUnsignedLongMask(item);
+ rc = headerPutUint32(h, tag, &val, 1);
+ } break;
+ case RPM_INT16_TYPE: {
+ uint16_t val = PyInt_AsUnsignedLongMask(item);
+ rc = headerPutUint16(h, tag, &val, 1);
+ } break;
+ case RPM_INT8_TYPE:
+ case RPM_CHAR_TYPE: {
+ uint8_t val = PyInt_AsUnsignedLongMask(item);
+ rc = headerPutUint8(h, tag, &val, 1);
+ } break;
+ default:
+ PyErr_SetString(PyExc_TypeError, "unhandled datatype");
+ }
+ return rc;
+}
+
+static int hdrPutTag(Header h, rpmTag tag, PyObject *value)
+{
+ rpmTagType type = rpmTagGetType(tag);
+ rpmTagReturnType retype = (type & RPM_MASK_RETURN_TYPE);
+ int rc = 0;
+
+ /* XXX this isn't really right (i18n strings etc) but for now ... */
+ if (headerIsEntry(h, tag)) {
+ PyErr_SetString(PyExc_TypeError, "tag already exists");
+ return rc;
+ }
+
+ /* validate all data before trying to insert */
+ if (!validData(tag, type, value)) {
+ PyErr_SetString(PyExc_TypeError, "invalid type for tag");
+ return 0;
+ }
+
+ if (retype == RPM_SCALAR_RETURN_TYPE) {
+ rc = hdrAppendItem(h, tag, type, value);
+ } else if (retype == RPM_ARRAY_RETURN_TYPE && PyList_Check(value)) {
+ Py_ssize_t len = PyList_Size(value);
+ for (Py_ssize_t i = 0; i < len; i++) {
+ PyObject *item = PyList_GetItem(value, i);
+ rc = hdrAppendItem(h, tag, type, item);
+ }
+ } else {
+ PyErr_SetString(PyExc_RuntimeError, "cant happen, right?");
+ }
+
+ return rc;
+}
+
static PyObject * hdr_subscript(hdrObject * s, PyObject * item)
{
rpmTag tag;
@@ -465,15 +585,12 @@ static PyObject * hdr_subscript(hdrObject * s, PyObject * item)
static int hdr_ass_subscript(hdrObject *s, PyObject *key, PyObject *value)
{
rpmTag tag;
- rpmtd td;
if (!tagNumFromPyObject(key, &tag)) return -1;
if (value == NULL) {
/* XXX should failure raise key error? */
headerDel(s->h, tag);
- } else if (rpmtdFromPyObject(value, &td)) {
- headerPut(s->h, td, HEADERPUT_DEFAULT);
- } else {
+ } else if (!hdrPutTag(s->h, tag, value)) {
return -1;
}
return 0;