11

Where can I find a good introduction to using the subversion python bindings?

I found one section in the svnbook that talks about it; and some basic examples from 1.3.

Is there something a bit more thorough and up-to-date?

retracile
  • 12,167
  • 4
  • 35
  • 42

4 Answers4

7

Just wanted to add a little clarification here.

Thanks to the above two answers (@BenjaminWohlwend and @Logan), I became aware there are more than one set of Python bindings/interfaces for Subversion; I did this on my Ubuntu 11.04 box:

$ apt-cache search '[Ss]vn|[Ss]ubversion' | grep -i python
python-svn - A(nother) Python interface to Subversion
python-svn-dbg - A(nother) Python interface to Subversion (debug extension)
python-subversion - Python bindings for Subversion
python-subversion-dbg - Python bindings for Subversion (debug extension)
python-opster - a python command line parsing speedster
python-py - Advanced Python testing tool and networking lib
python-rope - Python refactoring library
python-subvertpy - Alternative Python bindings for Subversion

One can look at the Debian package filelist, to determine which libraries these refer to; so we have:

... and I also found another in the repository:

The link http://svn.apache.org/repos/asf/subversion (which I got from @BenjaminWohlwend) is apparently the Apache Software Foundation (asf?) Subversion repository for Subversion source code itself.

The OP's quest for documentation seems related to python-subversion (or SWIG bindings (or libsvn); whose build-from-source instructions are in @Logan's post. I couldn't find much better documentation source from the svn.developer: Using the APIs already referred in the OP, except for the bindings/swig/python/README; it explains how SWIG generates Python interfaces from C:

TRANSLATING PARAMETER LISTS

The argument-reductions laws of the SWIG bindings something go like
this:

- The module prefix can be omitted.  o:  

     void *some_C_function = svn_client_foo;  

  becomes:  

     import svn.client  
     func = svn.client.foo  

[...]

Then, one could look in, say, svn/core.py, and find functions (and "Symbols defined explicitly") like svn_mergeinfo_merge; noting that core.py imports libsvn.core - where libsvn probably refers to the shared object (.so) files built from the C file libsvn_swig_py/swigutil_py.c.

Then, we can look up svn_mergeinfo_merge, and find a commit message like SVNSearch: Subversion (commit 23570 05.03.2007), which refers to that function, and a svn_mergeinfo.h; looking up that file further, we find it in the ASF repository: svn_mergeinfo.h, which indeed contains:

/** Like svn_mergeinfo_merge2, but uses only one pool.
 *
 * @deprecated Provided for backward compatibility with the 1.5 API.
 */
SVN_DEPRECATED
svn_error_t *
svn_mergeinfo_merge(svn_mergeinfo_t mergeinfo,
                    svn_mergeinfo_t changes,
                    apr_pool_t *pool);

Seeing DEPRECATED there, it's probably good here to refer to svn commit: r1175903 (Mon Sep 26 2011):

  • subversion/libsvn_subr/mergeinfo.c

    (svn_mergeinfo_merge2): New.

    (svn_mergeinfo_merge): Move to deprecated.c.

    (svn_mergeinfo_catalog_merge): Use the new API.

That is - that particular function has been deprecated in 2011 - so hopefully, one's Python SVN bindings and SVN installation should be matching...

Community
  • 1
  • 1
sdaau
  • 36,975
  • 46
  • 198
  • 278
2

If you build Subversion from source the Subversion Python bindings aren't automatically included. You have to specifically build and include them. Luckily, you can do this after you've installed Subversion. The source for the bindings is included within the Subversion source code.

These instructions are for Subversion 1.5.9 and Python 2.4.3 on Red Hat Enterprise Linux, but they should be easily hackable for recent versions of Subversion and Python and generic unix installs.

First, download swig from http://downloads.sourceforge.net/swig

tar -xvf swig-<version>.tar.gz
cd swig-<version>

At this point you have to make a decision. You can install swig for all supported languages or you can install for just what you need. 'make check' can take up to an hour to run and may fail due to errors from languages you aren't concerned with.

If you want to use all supported languages run:

./configure 

If you want to scope down to just python, run:

./configure --with-python=/usr/local/bin/python2.4 --without-perl --without-ruby --without-php4

Next, run:

make

If you opted for the full install, run:

make -k check

If you scoped down to just python you only need to run the python tests:

make check-python-examples
make check-python-test-suite

If everything's OK, you're ready to install swig:

make install

From here, installing the subversion python bindings should be fairly straightforward:

tar -xvf subversion-1.5.9.tar.gz --gzip 
cd subversion-1.5.9
make swig-py
make install-swig-py
touch /usr/lib64/python2.4/site-packages/svn-python.pth
echo /usr/local/lib/svn-python > /usr/lib64/python2.4/site-packages/svn-python.pth

As always, your mileage may vary depending on your specific versions and architecture. Good luck.

Logan
  • 4,177
  • 3
  • 20
  • 35
  • 5
    While that may be helpful to those who are looking for information about how to install the bindings, that doesn't address my question about _using_ the bindings. I'm looking for API and programming documentation, not installation help. – retracile Sep 09 '11 at 14:11
1

This looks like a pretty complete documentation:

http://pysvn.tigris.org/docs/pysvn_prog_ref.html

And here are a couple examples:

http://svn.apache.org/repos/asf/subversion/trunk/tools/examples/

martin clayton
  • 76,436
  • 32
  • 213
  • 198
Benjamin Wohlwend
  • 30,958
  • 11
  • 90
  • 100
  • 6
    pysvn is a different set of python bindings than the ones I'm wanting to use. But those examples may be useful. – retracile Sep 19 '09 at 16:42
  • +1 the svnshell.py will be quite useful. But I'm not seeing much related to checkouts and merges, so I'm still looking for more. – retracile Sep 19 '09 at 16:56
0

Hope it's OK with another post re: python-subversion: I wanted to try Example 8.3. A Python status crawler - Using the APIs (svnbook). on Ubuntu 11.04, Python 2.7, svn_client_status2 crashed on a filename with UTF-8 characters with "Error (22): Error converting entry in directory 'path' to UTF-8" - the solution to this is to call setlocale before any calls to this function.

I also realized there are svn_client_status3 and svn_client_status4 in the Python API; svn_client_status3 has a slightly different call, and also needs setlocale. However, svn_client_status4 should NOT be used - it segfaults, since it needs a struct argument which Python cannot deliver; for more, see #16027750 Debugging: stepping through Python script using gdb?.

To wrap it up, here is the Example 8.3 with locale setting which uses svn_client_status3 - and doesn't crash on my system (even on filenames with UTF-8 characters):

#!/usr/bin/env python

# modified from:
# http://svnbook.red-bean.com/en/1.5/svn.developer.usingapi.html
# does the same as `svn status`, and is marked:
"""Crawl a working copy directory, printing status information."""

# tested on Python 2.7, Ubuntu Natty 11.04; needs:
# sudo apt-get install python-subversion

import locale
print locale.getlocale() # (None, None) - in C: ANSI_X3.4-1968
locale.setlocale(locale.LC_ALL, '') # would print en_US.UTF-8
print locale.getlocale() # NOW it is ('en_US', 'UTF-8')

import sys
import os.path

import getopt
import svn.core, svn.client, svn.wc


def generate_status_code(status):
  """Translate a status value into a single-character status code,
  using the same logic as the Subversion command-line client."""
  code_map = { svn.wc.svn_wc_status_none        : ' ',
               svn.wc.svn_wc_status_normal      : ' ',
               svn.wc.svn_wc_status_added       : 'A',
               svn.wc.svn_wc_status_missing     : '!',
               svn.wc.svn_wc_status_incomplete  : '!',
               svn.wc.svn_wc_status_deleted     : 'D',
               svn.wc.svn_wc_status_replaced    : 'R',
               svn.wc.svn_wc_status_modified    : 'M',
               svn.wc.svn_wc_status_merged      : 'G',
               svn.wc.svn_wc_status_conflicted  : 'C',
               svn.wc.svn_wc_status_obstructed  : '~',
               svn.wc.svn_wc_status_ignored     : 'I',
               svn.wc.svn_wc_status_external    : 'X',
               svn.wc.svn_wc_status_unversioned : '?',
             }
  return code_map.get(status, '?')


def do_status(wc_path, verbose):
  # Build a client context baton.
  ctx = svn.client.svn_client_ctx_t()

  def _status_callback(path, status):
      """A callback function for svn_client_status."""

      # Print the path, minus the bit that overlaps with the root of
      # the status crawl
      text_status = generate_status_code(status.text_status)
      prop_status = generate_status_code(status.prop_status)
      print '%s%s  %s' % (text_status, prop_status, path)

  # Do the status crawl, using _status_callback() as our callback function.
  revision = svn.core.svn_opt_revision_t()
  revision.type = svn.core.svn_opt_revision_head
  #~ svn.client.svn_client_status2(wc_path, revision, _status_callback,
                                #~ svn.core.svn_depth_infinity, verbose,
                                #~ 0, 0, 1, ctx)
  svn.client.svn_client_status3(wc_path, revision, _status_callback,
                                svn.core.svn_depth_infinity, verbose,
                                0, 0, 1, (), ctx)
  # DO NOT USE svn_client_status4! (needs a C struct argument)


def usage_and_exit(errorcode):
    """Print usage message, and exit with ERRORCODE."""
    stream = errorcode and sys.stderr or sys.stdout
    stream.write("""Usage: %s OPTIONS WC-PATH
Options:
  --help, -h    : Show this usage message
  --verbose, -v : Show all statuses, even uninteresting ones
""" % (os.path.basename(sys.argv[0])))
    sys.exit(errorcode)

if __name__ == '__main__':
  # Parse command-line options.
  try:
    opts, args = getopt.getopt(sys.argv[1:], "hv", ["help", "verbose"])
  except getopt.GetoptError:
    usage_and_exit(1)
  verbose = 0
  for opt, arg in opts:
    if opt in ("-h", "--help"):
      usage_and_exit(0)
    if opt in ("-v", "--verbose"):
      verbose = 1
  if len(args) != 1:
    usage_and_exit(2)

  # Canonicalize the repository path.
  wc_path = svn.core.svn_path_canonicalize(args[0])

  # Do the real work.
  try:
    do_status(wc_path, verbose)
  except svn.core.SubversionException, e:
    sys.stderr.write("Error (%d): %s\n" % (e.apr_err, e.message))
    sys.exit(1)
Community
  • 1
  • 1
sdaau
  • 36,975
  • 46
  • 198
  • 278