Add support for install callbacks
authorKlaus Kämpf <kkaempf@suse.de>
Tue, 30 Aug 2011 14:35:17 +0000 (16:35 +0200)
committerKlaus Kämpf <kkaempf@suse.de>
Tue, 30 Aug 2011 14:35:17 +0000 (16:35 +0200)
swig/Callbacks.i
swig/CommitCallbacks.h
swig/python/tests/commit_callbacks.py

index 0aecb20..12c28a1 100644 (file)
@@ -135,6 +135,24 @@ remove_error2target(target::rpm::RemoveResolvableReport::Error error)
 
 /*
  * This is what makes people hate the ZYPP API. Why can't there
+ * be _one_ Error type ?!
+ */
+static Target_Type
+install_error2target(target::rpm::InstallResolvableReport::Error error)
+{
+  Target_Type e;
+  switch(error) {
+    case target::rpm::InstallResolvableReport::NO_ERROR:  e = error_no_error(); break;
+    case target::rpm::InstallResolvableReport::NOT_FOUND: e = error_not_found(); break;
+    case target::rpm::InstallResolvableReport::IO:        e = error_io(); break;
+    case target::rpm::InstallResolvableReport::INVALID:   e = error_invalid(); break;
+  }
+  return e;
+}
+
+
+/*
+ * This is what makes people hate the ZYPP API. Why can't there
  * be _one_ Action type ?!
  */
 static target::PatchScriptReport::Action
@@ -155,11 +173,11 @@ target2patch_script_action(Target_Type a)
   SWIG_exception_fail(SWIG_ArgError(SWIG_ValueError), "Expected \"abort\", \"retry\"  or \"ignore\"");
 #endif
 #if defined(SWIGRUBY)
-  if (a == action_abort_sym())
+  if (a == action_abort())
     return zypp::target::PatchScriptReport::ABORT;
-  else if (a == action_retry_sym())
+  else if (a == action_retry())
     return zypp::target::PatchScriptReport::RETRY;
-  else if (a == action_ignore_sym())
+  else if (a == action_ignore())
     return zypp::target::PatchScriptReport::IGNORE;
   SWIG_exception_fail(SWIG_ArgError(SWIG_ValueError), "Expected :abort, :retry  or :ignore");
 #endif
@@ -183,22 +201,53 @@ target2removal_action(Target_Type a)
     return zypp::target::rpm::RemoveResolvableReport::RETRY;
   else if (!strcmp(s, "ignore"))
     return zypp::target::rpm::RemoveResolvableReport::IGNORE;
-  SWIG_exception_fail(SWIG_ArgError(SWIG_ValueError), "Expected \"abort\", \"retry\"  or \"ignore\"");
+  SWIG_exception_fail(SWIG_ArgError(SWIG_ValueError), "Expected \"abort\", \"retry\" or \"ignore\"");
 #endif
 #if defined(SWIGRUBY)
-  if (a == action_abort_sym())
+  if (a == action_abort())
     return zypp::target::rpm::RemoveResolvableReport::ABORT;
-  else if (a == action_retry_sym())
+  else if (a == action_retry())
     return zypp::target::rpm::RemoveResolvableReport::RETRY;
-  else if (a == action_ignore_sym())
+  else if (a == action_ignore())
     return zypp::target::rpm::RemoveResolvableReport::IGNORE;
-  SWIG_exception_fail(SWIG_ArgError(SWIG_ValueError), "Expected :abort, :retry  or :ignore");
+  SWIG_exception_fail(SWIG_ArgError(SWIG_ValueError), "Expected :abort, :retry or :ignore");
 #endif
 fail:
   return zypp::target::rpm::RemoveResolvableReport::ABORT;
 }
 
 
+static target::rpm::InstallResolvableReport::Action
+target2install_action(Target_Type a)
+{
+#if defined(SWIGPYTHON)
+  const char *s;
+  if (!PyString_Check(a)) {
+    SWIG_exception_fail(SWIG_TypeError, "Expected string type");
+  }
+  s = PyString_AsString(a);
+  if (!strcmp(s, "abort"))
+    return zypp::target::rpm::InstallResolvableReport::ABORT;
+  else if (!strcmp(s, "retry"))
+    return zypp::target::rpm::InstallResolvableReport::RETRY;
+  else if (!strcmp(s, "ignore"))
+    return zypp::target::rpm::InstallResolvableReport::IGNORE;
+  SWIG_exception_fail(SWIG_ArgError(SWIG_ValueError), "Expected \"abort\", \"retry\" or \"ignore\"");
+#endif
+#if defined(SWIGRUBY)
+  if (a == action_abort())
+    return zypp::target::rpm::InstallResolvableReport::ABORT;
+  else if (a == action_retry())
+    return zypp::target::rpm::InstallResolvableReport::RETRY;
+  else if (a == action_ignore())
+    return zypp::target::rpm::InstallResolvableReport::IGNORE;
+  SWIG_exception_fail(SWIG_ArgError(SWIG_ValueError), "Expected :abort, :retry or :ignore");
+#endif
+fail:
+  return zypp::target::rpm::InstallResolvableReport::ABORT;
+}
+
+
 /*
  * target_call
  *
@@ -419,6 +468,9 @@ struct RemoveResolvableReportReceiver : public zypp::callback::ReceiveReport<zyp
     return;
   }
 
+ /**
+   * Return \c true to continue, \c false to abort commit.
+   */
   virtual bool progress(int value, zypp::Resolvable::constPtr resolvable)
   {
     bool result;
@@ -481,26 +533,68 @@ struct InstallResolvableReportReceiver : public zypp::callback::ReceiveReport<zy
 
   Target_Type instance;
 
-  void display_step( zypp::Resolvable::constPtr resolvable, int value )
-  {
-  }
-
   virtual void start( zypp::Resolvable::constPtr resolvable )
   {
+    Target_Type r = SWIG_NewPointerObj((void *)&(*resolvable), SWIGTYPE_p_zypp__Resolvable, 0);
+    Target_Type result = target_call(instance, "install_start", 1, r );
+#if defined(SWIGPYTHON)
+    Py_DecRef(r);
+    if (result) Py_DecRef(result);
+#endif
+    return;
   }
 
+ /**
+   * Return \c true to continue, \c false to abort commit.
+   */
   virtual bool progress(int value, zypp::Resolvable::constPtr resolvable)
   {
-    return true;
+    bool result;
+    Target_Type r = SWIG_NewPointerObj((void *)&(*resolvable), SWIGTYPE_p_zypp__Resolvable, 0);
+    Target_Type v = Target_Int(value);
+    Target_Type res = target_call(instance, "install_progress", 2, r, v );
+#if defined(SWIGPYTHON)
+    result = PyObject_IsTrue(res) ? true : false;
+    Py_DecRef(v);
+    Py_DecRef(r);
+    if (res) Py_DecRef(res);
+#endif
+#if defined(SWIGRUBY)
+    result = RTEST(res) ? true : false;
+#endif
+    return result;
   }
 
   virtual Action problem( zypp::Resolvable::constPtr resolvable, Error error, const std::string & description, RpmLevel level )
   {
-    return ABORT;
+    Action result;
+    Target_Type r = SWIG_NewPointerObj((void *)&(*resolvable), SWIGTYPE_p_zypp__Resolvable, 0);
+    Target_Type e = install_error2target(error);
+    Target_Type d = Target_String(description.c_str());
+    Target_Type res = target_call(instance, "install_problem", 3, r, e, d );
+    result = target2install_action(res);
+#if defined(SWIGPYTHON)
+    if (res) Py_DecRef(res);
+    Py_DecRef(d);
+    Py_DecRef(e);
+    Py_DecRef(r);
+#endif
+    return result;
   }
 
   virtual void finish( zypp::Resolvable::constPtr resolvable, Error error, const std::string & reason, RpmLevel level )
   {
+    Target_Type r = SWIG_NewPointerObj((void *)&(*resolvable), SWIGTYPE_p_zypp__Resolvable, 0);
+    Target_Type e = install_error2target(error);
+    Target_Type d = Target_String(reason.c_str());
+    Target_Type res = target_call(instance, "install_finish", 3, r, e, d );
+#if defined(SWIGPYTHON)
+    if (res) Py_DecRef(res);
+    Py_DecRef(d);
+    Py_DecRef(e);
+    Py_DecRef(r);
+#endif
+    return;
   }
 };
 
index ca7446a..6df36be 100644 (file)
@@ -190,3 +190,4 @@ class CommitCallbacksEmitter {
 };
 
 #define REMOVE_NO_ERROR target::rpm::RemoveResolvableReport::NO_ERROR
+#define INSTALL_NO_ERROR target::rpm::InstallResolvableReport::NO_ERROR
index 49e1232..24a1ff3 100644 (file)
@@ -33,6 +33,7 @@ import zypp
 #  actually run)
 #
 removals = 0
+installs = 0
 
 
 #
@@ -55,9 +56,19 @@ removals = 0
 #   removal_progress(zypp::Resolvable, Integer) - progress in percent
 #   removal_problem(zypp::Resolvable, zypp::Error, String) - problem report
 #   removal_finish(zypp::Resolvable, zypp::Error, String) - uninstall finish
+#
+# IV. Install
+#   install_start(zypp::Resolvable) - start of resolvable uninstall
+#   install_progress(zypp::Resolvable, Integer) - progress in percent
+#   install_problem(zypp::Resolvable, zypp::Error, String) - problem report
+#   install_finish(zypp::Resolvable, zypp::Error, String) - uninstall finish
 #   
 
 class CommitReceiver:
+    
+  ################################
+  # removal callbacks
+
   #
   # removal_start() will be called at the beginning of a resolvable (typically package) uninstall
   #   and be passed the resolvable to-be-removed
@@ -80,7 +91,7 @@ class CommitReceiver:
 
   #
   # removal_finish() is called after a resolvable (typically package) was uninstalled
-  #   and be passed the resolvable to-be-removed and a status (string) with detail (string)
+  #   and be passed the resolvable just removed and a status (string) with detail (string)
   # status is either
   # - "no_error":  typical 'good' status
   # - "not_found": resolvable not found (i.e. not installed)
@@ -100,6 +111,51 @@ class CommitReceiver:
     print "Remove of ", resolvable.name(), " has problem ", error, ": ", description
     return "ignore"
 
+  ################################
+  # install callbacks
+
+  #
+  # install_start() will be called at the beginning of a resolvable (typically package) install
+  #   and be passed the resolvable to-be-installed
+  #    
+  def install_start(self, resolvable):
+    # testing: increment the number of removals and print the resolvable
+    global installs
+    installs += 1
+    print "Starting to install ", resolvable
+
+  #
+  # install_progress() is called during a resolvable (typically package) install
+  #   and be passed the resolvable to-be-removed and a percentage value
+  # Must return True (continue) or False (abort install)
+  #    
+  def install_progress(self, resolvable, percentage):
+    assert percentage == 42
+    print "Install of ", resolvable, " at ", percentage, "%"
+    return True
+
+  #
+  # install_finish() is called after a resolvable (typically package) was installed
+  #   and be passed the resolvable just installed and a status (string) with detail (string)
+  # status is either
+  # - "no_error":  typical 'good' status
+  # - "not_found": resolvable not found
+  # - "io":        (disk) I/O error
+  # - "invalid":   any other error
+  #    
+  def install_finish(self, resolvable, status, detail):
+    print "Install of ", resolvable.name(), " finished with problem ", status, ": ", detail
+
+  #
+  # report a problem during resolvable install
+  # error is the same as 'status' of install_finish()
+  #
+  # Must return "abort", "retry" or "ignore"
+  #
+  def install_problem(self, resolvable, error, description):
+    print "Install of ", resolvable.name(), " has problem ", error, ": ", description
+    return "ignore"
+
 #
 # Testcase for Callbacks
 #
@@ -191,5 +247,27 @@ class CommitCallbacksTestCase(unittest.TestCase):
         #
         assert removals == 1
 
+    # this will test the install callback
+    def testInstallCallback(self):
+
+        #
+        # Loop over pool - just to get real instances of Resolvable
+        #
+        for item in self.Z.pool():
+            print "Emitting install of ", item.resolvable()
+            #
+            # Use the zypp.CommitCallbacksEmitter to fake an actual package removal
+            #
+            resolvable = item.resolvable()
+            self.commit_callbacks_emitter.install_start(resolvable)
+            self.commit_callbacks_emitter.install_progress(resolvable, 42)
+#            self.commit_callbacks_emitter.install_problem(resolvable, zypp.REMOVE_NO_ERROR, "All fine")
+#            self.commit_callbacks_emitter.install_finish(resolvable, zypp.REMOVE_NO_ERROR, "Done")
+            break # one is sufficient
+        #
+        # Did the actual callback got executed ?
+        #
+        assert installs == 1
+
 if __name__ == '__main__':
   unittest.main()