From 4dfc7676692279682e93b8b7c68c64cc0aafe928 Mon Sep 17 00:00:00 2001 From: Tomas Mlcoch Date: Thu, 6 Jun 2013 16:18:17 +0200 Subject: [PATCH] python: Add ContentStat object. --- src/python/CMakeLists.txt | 2 +- src/python/__init__.py | 22 +++++++++++++----- src/python/createrepo_cmodule.c | 7 ++++++ src/python/repomdrecord-py.c | 1 + src/python/xml_file-py.c | 32 ++++++++++++++++++++++---- tests/python/tests/test_contentstat.py | 42 ++++++++++++++++++++++++++++++++++ tests/python/tests/test_xml_file.py | 22 +++++++++++++----- 7 files changed, 111 insertions(+), 17 deletions(-) create mode 100644 tests/python/tests/test_contentstat.py diff --git a/src/python/CMakeLists.txt b/src/python/CMakeLists.txt index a93c192..00aef57 100644 --- a/src/python/CMakeLists.txt +++ b/src/python/CMakeLists.txt @@ -13,11 +13,11 @@ SET (createrepo_c_COPIES __init__.py) FILE(COPY ${createrepo_c_COPIES} DESTINATION ./createrepo_c/) SET (craeterepo_cmodule_SRCS + contentstat-py.c createrepo_cmodule.c exception-py.c load_metadata-py.c locate_metadata-py.c - #metadata_hashtable.c package-py.c parsepkg-py.c repomd-py.c diff --git a/src/python/__init__.py b/src/python/__init__.py index 5960e3a..afbae43 100644 --- a/src/python/__init__.py +++ b/src/python/__init__.py @@ -46,6 +46,10 @@ XML_WARNING_BADATTRVAL = _createrepo_c.XML_WARNING_BADATTRVAL CreaterepoCError = _createrepo_c.CreaterepoCError +# ContentStat class + +ContentStat = _createrepo_c.ContentStat + # Metadata class Metadata = _createrepo_c.Metadata @@ -103,16 +107,22 @@ class OtherSqlite(Sqlite): XmlFile = _createrepo_c.XmlFile class PrimaryXmlFile(XmlFile): - def __init__(self, filename, compressiontype=GZ_COMPRESSION): - XmlFile.__init__(self, filename, XMLFILE_PRIMARY, compressiontype) + def __init__(self, filename, compressiontype=GZ_COMPRESSION, + contentstat=None): + XmlFile.__init__(self, filename, XMLFILE_PRIMARY, + compressiontype, contentstat) class FilelistsXmlFile(XmlFile): - def __init__(self, filename, compressiontype=GZ_COMPRESSION): - XmlFile.__init__(self, filename, XMLFILE_FILELISTS, compressiontype) + def __init__(self, filename, compressiontype=GZ_COMPRESSION, + contentstat=None): + XmlFile.__init__(self, filename, XMLFILE_FILELISTS, + compressiontype, contentstat) class OtherXmlFile(XmlFile): - def __init__(self, filename, compressiontype=GZ_COMPRESSION): - XmlFile.__init__(self, filename, XMLFILE_OTHER, compressiontype) + def __init__(self, filename, compressiontype=GZ_COMPRESSION, + contentstat=None): + XmlFile.__init__(self, filename, XMLFILE_OTHER, + compressiontype, contentstat) # Functions diff --git a/src/python/createrepo_cmodule.c b/src/python/createrepo_cmodule.c index 9165a25..8fa9e0d 100644 --- a/src/python/createrepo_cmodule.c +++ b/src/python/createrepo_cmodule.c @@ -21,6 +21,7 @@ #include "src/createrepo_c.h" +#include "contentstat-py.h" #include "exception-py.h" #include "load_metadata-py.h" #include "locate_metadata-py.h" @@ -71,6 +72,12 @@ init_createrepo_c(void) /* Objects */ + /* _createrepo_c.ContentStat */ + if (PyType_Ready(&ContentStat_Type) < 0) + return; + Py_INCREF(&ContentStat_Type); + PyModule_AddObject(m, "ContentStat", (PyObject *)&ContentStat_Type); + /* _createrepo_c.Package */ if (PyType_Ready(&Package_Type) < 0) return; diff --git a/src/python/repomdrecord-py.c b/src/python/repomdrecord-py.c index 2938c5c..c9fc656 100644 --- a/src/python/repomdrecord-py.c +++ b/src/python/repomdrecord-py.c @@ -288,6 +288,7 @@ set_int(_RepomdRecordObject *self, PyObject *value, void *member_offset) *((int *) ((size_t) rec + (size_t) member_offset)) = (int) val; return 0; } + static int set_str(_RepomdRecordObject *self, PyObject *value, void *member_offset) { diff --git a/src/python/xml_file-py.c b/src/python/xml_file-py.c index 8cc780c..46a2d6e 100644 --- a/src/python/xml_file-py.c +++ b/src/python/xml_file-py.c @@ -24,11 +24,13 @@ #include "xml_file-py.h" #include "package-py.h" #include "exception-py.h" +#include "contentstat-py.h" #include "typeconversion.h" typedef struct { PyObject_HEAD cr_XmlFile *xmlfile; + cr_ContentStat *stat; } _XmlFileObject; static PyObject * xmlfile_close(_XmlFileObject *self, void *nothing); @@ -54,8 +56,10 @@ xmlfile_new(PyTypeObject *type, PyObject *args, PyObject *kwds) CR_UNUSED(args); CR_UNUSED(kwds); _XmlFileObject *self = (_XmlFileObject *)type->tp_alloc(type, 0); - if (self) + if (self) { self->xmlfile = NULL; + self->stat = NULL; + } return (PyObject *)self; } @@ -65,11 +69,13 @@ xmlfile_init(_XmlFileObject *self, PyObject *args, PyObject *kwds) char *path; int type, comtype; GError *err = NULL; - PyObject *ret; + PyObject *py_stat, *ret; + cr_ContentStat *stat; CR_UNUSED(kwds); - if (!PyArg_ParseTuple(args, "sii|:xmlfile_init", &path, &type, &comtype)) + if (!PyArg_ParseTuple(args, "siiO|:xmlfile_init", + &path, &type, &comtype, &py_stat)) return -1; /* Check arguments */ @@ -83,21 +89,34 @@ xmlfile_init(_XmlFileObject *self, PyObject *args, PyObject *kwds) return -1; } + if (py_stat == Py_None) { + stat = NULL; + } else if (ContentStatObject_Check(py_stat)) { + stat = ContentStat_FromPyObject(py_stat); + } else { + PyErr_SetString(PyExc_ValueError, "Use ContentStat or None"); + return -1; + } + /* Free all previous resources when reinitialization */ ret = xmlfile_close(self, NULL); Py_XDECREF(ret); + Py_XDECREF(self->stat); + self->stat = NULL; if (ret == NULL) { // Error encountered! return -1; } /* Init */ - self->xmlfile = cr_xmlfile_open(path, type, comtype, &err); + self->xmlfile = cr_xmlfile_sopen(path, type, comtype, stat, &err); if (err) { PyErr_Format(CrErr_Exception, "XmlFile initialization failed: %s", err->message); g_clear_error(&err); return -1; } + self->stat = stat; + Py_XINCREF(stat); return 0; } @@ -106,6 +125,7 @@ static void xmlfile_dealloc(_XmlFileObject *self) { cr_xmlfile_close(self->xmlfile, NULL); + Py_XDECREF(self->stat); Py_TYPE(self)->tp_free(self); } @@ -206,6 +226,9 @@ xmlfile_close(_XmlFileObject *self, void *nothing) CR_UNUSED(nothing); + Py_XDECREF(self->stat); + self->stat = NULL; + if (self->xmlfile) { cr_xmlfile_close(self->xmlfile, &err); self->xmlfile = NULL; @@ -215,6 +238,7 @@ xmlfile_close(_XmlFileObject *self, void *nothing) return NULL; } } + Py_RETURN_NONE; } diff --git a/tests/python/tests/test_contentstat.py b/tests/python/tests/test_contentstat.py new file mode 100644 index 0000000..ef24202 --- /dev/null +++ b/tests/python/tests/test_contentstat.py @@ -0,0 +1,42 @@ +import unittest +import shutil +import tempfile +import os.path +import createrepo_c as cr + +from fixtures import * + +class TestCaseContentStat(unittest.TestCase): + + # TODO: + # - Test rename_file() for files with checksum + + def setUp(self): + self.tmpdir = tempfile.mkdtemp(prefix="createrepo_ctest-") + + def tearDown(self): + shutil.rmtree(self.tmpdir) + + def test_contentstat(self): + pkg = cr.package_from_rpm(PKG_ARCHER_PATH) + self.assertTrue(pkg) + + cs = cr.ContentStat(cr.SHA256) + self.assertEqual(cs.size, 0) + self.assertEqual(cs.checksum_type, cr.SHA256) + self.assertEqual(cs.checksum, None) + + path = os.path.join(self.tmpdir, "primary.xml.gz") + f = cr.PrimaryXmlFile(path, cr.GZ_COMPRESSION, cs) + self.assertTrue(f) + self.assertTrue(os.path.isfile(path)) + f.add_pkg(pkg) + f.close() + + self.assertTrue(os.path.isfile(path)) + + self.assertEqual(cs.size, 2686) + self.assertEqual(cs.checksum_type, cr.SHA256) + self.assertEqual(cs.checksum, "05509ef37239eb123d41c077626b788352ef94"\ + "5200231a901802ef59e565978f") + diff --git a/tests/python/tests/test_xml_file.py b/tests/python/tests/test_xml_file.py index a12e86c..f3518d8 100644 --- a/tests/python/tests/test_xml_file.py +++ b/tests/python/tests/test_xml_file.py @@ -17,19 +17,22 @@ class TestCaseXmlFile(unittest.TestCase): def test_xmlfile_basic_operations(self): pri = cr.XmlFile(self.tmpdir+"/primary.xml.gz", cr.XMLFILE_PRIMARY, - cr.GZ_COMPRESSION) + cr.GZ_COMPRESSION, + None) self.assertTrue(pri) self.assertTrue(os.path.isfile(self.tmpdir+"/primary.xml.gz")) fil = cr.XmlFile(self.tmpdir+"/filelists.xml.gz", cr.XMLFILE_FILELISTS, - cr.GZ_COMPRESSION) + cr.GZ_COMPRESSION, + None) self.assertTrue(fil) self.assertTrue(os.path.isfile(self.tmpdir+"/filelists.xml.gz")) oth = cr.XmlFile(self.tmpdir+"/other.xml.gz", cr.XMLFILE_OTHER, - cr.GZ_COMPRESSION) + cr.GZ_COMPRESSION, + None) self.assertTrue(oth) self.assertTrue(os.path.isfile(self.tmpdir+"/other.xml.gz")) @@ -54,16 +57,23 @@ class TestCaseXmlFile(unittest.TestCase): self.assertFalse(os.path.exists(path)) # Bad file type - self.assertRaises(ValueError, cr.XmlFile, path, 86, cr.GZ_COMPRESSION) + self.assertRaises(ValueError, cr.XmlFile, path, 86, + cr.GZ_COMPRESSION, None) self.assertFalse(os.path.exists(path)) # Bad compression type - self.assertRaises(ValueError, cr.XmlFile, path, cr.XMLFILE_PRIMARY, 678) + self.assertRaises(ValueError, cr.XmlFile, path, + cr.XMLFILE_PRIMARY, 678, None) + self.assertFalse(os.path.exists(path)) + + # Bad contentstat object + self.assertRaises(ValueError, cr.XmlFile, path, + cr.XMLFILE_PRIMARY, 678, "foo") self.assertFalse(os.path.exists(path)) # Non existing path self.assertRaises(cr.CreaterepoCError, cr.PrimaryXmlFile, - "foobar/foo/xxx/cvydmaticxuiowe") + "foobar/foo/xxx/cvydmaticxuiowe") # Already existing file open(path, "w").write("foobar") -- 2.7.4