python: Add ContentStat object.
authorTomas Mlcoch <tmlcoch@redhat.com>
Thu, 6 Jun 2013 14:18:17 +0000 (16:18 +0200)
committerTomas Mlcoch <tmlcoch@redhat.com>
Thu, 6 Jun 2013 14:18:17 +0000 (16:18 +0200)
src/python/CMakeLists.txt
src/python/__init__.py
src/python/createrepo_cmodule.c
src/python/repomdrecord-py.c
src/python/xml_file-py.c
tests/python/tests/test_contentstat.py [new file with mode: 0644]
tests/python/tests/test_xml_file.py

index a93c192..00aef57 100644 (file)
@@ -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
index 5960e3a..afbae43 100644 (file)
@@ -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
 
index 9165a25..8fa9e0d 100644 (file)
@@ -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;
index 2938c5c..c9fc656 100644 (file)
@@ -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)
 {
index 8cc780c..46a2d6e 100644 (file)
 #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 (file)
index 0000000..ef24202
--- /dev/null
@@ -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")
+
index a12e86c..f3518d8 100644 (file)
@@ -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")