You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@subversion.apache.org by rd...@apache.org on 2012/09/23 15:31:10 UTC

svn commit: r1389054 - in /subversion/trunk/subversion/bindings/swig: python/libsvn_swig_py/swigutil_py.c python/libsvn_swig_py/swigutil_py.h python/svn/delta.py svn_delta.i

Author: rdonch
Date: Sun Sep 23 13:31:09 2012
New Revision: 1389054

URL: http://svn.apache.org/viewvc?rev=1389054&view=rev
Log:
In the SWIG/Python bindings, replace the ugly hack that made
svn_txdelta_window_t.ops work with a much less ugly one.

The new approach is similar to what I have previously outlined in a
comment in svn_txdelta_window_t_ops_get, but didn't implement back
then because I couldn't work out the details. It's better than the
old approach, because:

1) It doesn't involve manipulating the GIL more than is necessary.

2) It doesn't use an additional global Python function (although I have kept
   the old function for backwards compatibility). Nor does it need extra code
   in the Python wrapper module (svn.delta).

3) It's consistent with other bindings support code.

[in subversion/bindings/swig]

* python/libsvn_swig_py/swigutil_py.c,
  python/libsvn_swig_py/swigutil_py.h:
  (svn_swig_py_convert_txdelta_op_c_array): New function to replace
    svn_swig_py_txdelta_window_t_ops_get.
  (svn_swig_py_txdelta_window_t_ops_get): Remove.

* python/svn/delta.py:
  Remove the svn_txdelta_window_t.ops override.

* svn_delta.i:
  Extend svn_txdelta_window_t with a custom getter for ops, and add
  a typemap that specifically covers that getter. Remove the
  svn_txdelta_window_t_ops_get inline function and replace it with
  a backwards compatibility shim.

Modified:
    subversion/trunk/subversion/bindings/swig/python/libsvn_swig_py/swigutil_py.c
    subversion/trunk/subversion/bindings/swig/python/libsvn_swig_py/swigutil_py.h
    subversion/trunk/subversion/bindings/swig/python/svn/delta.py
    subversion/trunk/subversion/bindings/swig/svn_delta.i

Modified: subversion/trunk/subversion/bindings/swig/python/libsvn_swig_py/swigutil_py.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/bindings/swig/python/libsvn_swig_py/swigutil_py.c?rev=1389054&r1=1389053&r2=1389054&view=diff
==============================================================================
--- subversion/trunk/subversion/bindings/swig/python/libsvn_swig_py/swigutil_py.c (original)
+++ subversion/trunk/subversion/bindings/swig/python/libsvn_swig_py/swigutil_py.c Sun Sep 23 13:31:09 2012
@@ -2159,6 +2159,24 @@ svn_swig_py_make_stream(PyObject *py_io,
   return stream;
 }
 
+PyObject *
+svn_swig_py_convert_txdelta_op_c_array(int num_ops,
+                                       svn_txdelta_op_t *ops,
+                                       swig_type_info *op_type_info,
+                                       PyObject *parent_pool)
+{
+  PyObject *result = PyList_New(num_ops);
+  int i;
+
+  if (!result) return NULL;
+
+  for (i = 0; i < num_ops; ++i)
+      PyList_SET_ITEM(result, i,
+                      svn_swig_NewPointerObj(ops + i, op_type_info,
+                                             parent_pool, NULL));
+
+  return result;
+}
 
 void svn_swig_py_notify_func(void *baton,
                              const char *path,
@@ -4173,19 +4191,3 @@ svn_swig_py_setup_wc_diff_callbacks2(voi
   callbacks->dir_props_changed  = wc_diff_callbacks2_dir_props_changed;
   return callbacks;
 }
-
-PyObject *
-svn_swig_py_txdelta_window_t_ops_get(svn_txdelta_window_t *window,
-                                     swig_type_info * op_type_info,
-                                     PyObject *window_pool)
-{
-  PyObject *result = PyList_New(window->num_ops);
-  int i;
-
-  for (i = 0; i < window->num_ops; ++i)
-      PyList_SET_ITEM(result, i,
-                      svn_swig_NewPointerObj(window->ops + i, op_type_info,
-                                             window_pool, NULL));
-
-  return result;
-}

Modified: subversion/trunk/subversion/bindings/swig/python/libsvn_swig_py/swigutil_py.h
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/bindings/swig/python/libsvn_swig_py/swigutil_py.h?rev=1389054&r1=1389053&r2=1389054&view=diff
==============================================================================
--- subversion/trunk/subversion/bindings/swig/python/libsvn_swig_py/swigutil_py.h (original)
+++ subversion/trunk/subversion/bindings/swig/python/libsvn_swig_py/swigutil_py.h Sun Sep 23 13:31:09 2012
@@ -299,6 +299,15 @@ SVN_SWIG_SWIGUTIL_EXPORT
 svn_stream_t *svn_swig_py_make_stream(PyObject *py_io,
                                       apr_pool_t *pool);
 
+/* Convert ops, a C array of num_ops elements, to a Python list of SWIG
+   objects with descriptor op_type_info and pool set to parent_pool. */
+SVN_SWIG_SWIGUTIL_EXPORT
+PyObject *
+svn_swig_py_convert_txdelta_op_c_array(int num_ops,
+                                       svn_txdelta_op_t *ops,
+                                       swig_type_info * op_type_info,
+                                       PyObject *parent_pool);
+
 /* a notify function that executes a Python function that is passed in
    via the baton argument */
 SVN_SWIG_SWIGUTIL_EXPORT
@@ -520,17 +529,6 @@ svn_error_t *svn_swig_py_ra_lock_callbac
 SVN_SWIG_SWIGUTIL_EXPORT
 extern const svn_ra_reporter2_t swig_py_ra_reporter2;
 
-/* Get a list of ops from a window. Used to replace the naive
-   svn_txdelta_window_t.ops accessor. op_type_info is supposed to be
-   the SWIG descriptor of "svn_txdelta_op_t *". window_pool is supposed
-   to be the pool associated with the window proxy and used for wrapping
-   the op objects. */
-SVN_SWIG_SWIGUTIL_EXPORT
-PyObject *
-svn_swig_py_txdelta_window_t_ops_get(svn_txdelta_window_t *window,
-                                     swig_type_info * op_type_info,
-                                     PyObject *window_pool);
-
 #ifdef __cplusplus
 }
 #endif /* __cplusplus */

Modified: subversion/trunk/subversion/bindings/swig/python/svn/delta.py
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/bindings/swig/python/svn/delta.py?rev=1389054&r1=1389053&r2=1389054&view=diff
==============================================================================
--- subversion/trunk/subversion/bindings/swig/python/svn/delta.py (original)
+++ subversion/trunk/subversion/bindings/swig/python/svn/delta.py Sun Sep 23 13:31:09 2012
@@ -30,10 +30,6 @@ _unprefix_names(locals(), 'svn_txdelta_'
 __all__ = filter(lambda x: x.lower().startswith('svn_'), locals().keys())
 del _unprefix_names
 
-# Force our accessor since it appears that there isn't a more civilized way
-# to make SWIG use it.
-svn_txdelta_window_t.ops = property(svn_txdelta_window_t_ops_get)
-
 class Editor:
 
   def set_target_revision(self, target_revision, pool=None):

Modified: subversion/trunk/subversion/bindings/swig/svn_delta.i
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/bindings/swig/svn_delta.i?rev=1389054&r1=1389053&r2=1389054&view=diff
==============================================================================
--- subversion/trunk/subversion/bindings/swig/svn_delta.i (original)
+++ subversion/trunk/subversion/bindings/swig/svn_delta.i Sun Sep 23 13:31:09 2012
@@ -174,61 +174,47 @@ svn_txdelta_window_t_ops_get(svn_txdelta
 
 #ifdef SWIGPYTHON
 %ignore svn_txdelta_window_t::ops;
-%inline %{
-static PyObject *
-svn_txdelta_window_t_ops_get(PyObject *window_ob)
+%extend svn_txdelta_window_t {
+
+void _ops_get(int *num_ops, svn_txdelta_op_t **ops)
 {
-  void *window;
-  PyObject *ops_list, *window_pool;
-  int status;
-  
-  /* Kludge alert!
-     Normally, these kinds of conversions would belong in a typemap.
-     However, typemaps won't allow us to change the result type to an array,
-     so we have to make this custom accessor function.
-     A cleaner approach would be to use something like: 
-     
-     %extend svn_txdelta_window_t { void get_ops(apr_array_header_t ** ops); }
-     
-     But that means unnecessary copying, plus more hacks to get the pool for the
-     array and for wrapping the individual op objects. So we just don't bother.
-  */
+  *num_ops = $self->num_ops;
+  *ops = $self->ops;
+}
+
+%pythoncode {
+  ops = property(_ops_get)
+}
+}
+
+%typemap(argout) (int *num_ops, svn_txdelta_op_t **ops) {
+  apr_pool_t *parent_pool;
+  PyObject *parent_py_pool;
+  PyObject *ops_list;
   
-  /* Note: the standard svn-python typemap releases the GIL while calling the
-     wrapped function, but this function does Python stuff, so we have to
-     reacquire it again. */
-  svn_swig_py_acquire_py_lock();
-  status = svn_swig_ConvertPtr(window_ob, &window,
-    SWIG_TypeQuery("svn_txdelta_window_t *"));
-    
-  if (status != 0)
-    {
-      PyErr_SetString(PyExc_TypeError,
-                      "expected an svn_txdelta_window_t* proxy");
-      svn_swig_py_release_py_lock();
-      return NULL;
-    }
-    
-  window_pool = PyObject_GetAttrString(window_ob, "_parent_pool");
-
-  if (window_pool == NULL)
-    {
-      svn_swig_py_release_py_lock();
-      return NULL;
-    }
-    
-  ops_list = svn_swig_py_txdelta_window_t_ops_get(window,
-    SWIG_TypeQuery("svn_txdelta_op_t *"), window_pool);
-    
-  svn_swig_py_release_py_lock();
+  if (svn_swig_py_get_parent_pool(args, $descriptor(apr_pool_t *),
+                                  &parent_py_pool, &parent_pool))
+    SWIG_fail;
   
-  return ops_list;
+  ops_list = svn_swig_py_convert_txdelta_op_c_array(*$1, *$2,
+    $descriptor(svn_txdelta_op_t *), parent_py_pool);
+
+  if (!ops_list) SWIG_fail;
+
+  %append_output(ops_list);
 }
-%}
 #endif
 
 %include svn_delta_h.swg
 
+#ifdef SWIGPYTHON
+%pythoncode {
+# This function is for backwards compatibility only.
+# Use svn_txdelta_window_t.ops instead.
+svn_txdelta_window_t_ops_get = svn_txdelta_window_t._ops_get
+}
+#endif
+
 #ifdef SWIGRUBY
 %inline %{
 static VALUE