[svn.haxx.se] · SVN Dev · SVN Users · SVN Org · TSVN Dev · TSVN Users · Subclipse Dev · Subclipse Users · this month's index

[PRELIMINARY PATCH] High-level Python "Client" layer API, mark zero

From: Walter Mundt <emage_at_spamcop.net>
Date: 2006-07-10 14:05:28 CEST

Here's what I've got from before I stopped working. I'm not including a
log-message formatted summary because THIS PATCH IS NOT READY. djames
asked that I post it so everyone can get an idea of where things stand.

The AuthBaton stuff in core.py is more of a thought experiment than
anything, thinking about whether I want to separately wrap Subversion
auth_baton objects in a Python class. Auth batons include a "parameter"
map which is an apr_hash_t whole values vary in type depending on what
key you look up; thus the calls to (nonexistent) helpers which would try
to sort that out and marshal to Python in some mostly-sane manner.
Still no decision on whether this makes sense/is important enough to
justify building/is possible to do sanely given the lack of strong
typing guarantees on the auth parameters. Haven't yet looked at how the
other language bindings handle (or refuse to deal with) this.

The new Client class basically attempts to encapsulate the
svn_client_ctx_t; rather unambitious, but I'm trying to keep a
reasonable amount of congruence between the Python bindings and the C
API where I can.

I'm planning on writing a script to parse XML output from doxygen to
generate templates for the docstrings for the Client functions with
direct equivalents in the C API. Thus the total lack of any docs on
those for the moment.

Finally, I've left off the numeric suffixes on function variants
throughout. This is because most of the changes seem to involve
introducing new parameters. In Python, we can just add extra
optional/defaulted parameters and document "current" and (if needed)
"deprecated" call semantics without needing to introduce new function names.

Also note the COMPLETE LACK of any new tests at the moment. Aside from
making sure it compiles and still passes check-swig-py, I haven't tested
any of this; thus all the disclaimers about incompleteness and general
not-ready state of the patch.

Regardless, here you go! Feel free to discuss any of the points above
or any other issues that you might see with this patch.

-Walter

Index: subversion/bindings/swig/python/svn/core.py
===================================================================
--- subversion/bindings/swig/python/svn/core.py (revision 20489)
+++ subversion/bindings/swig/python/svn/core.py (working copy)
@@ -31,6 +31,13 @@
     if name.startswith(from_prefix):
       symbol_dict[to_prefix + name[len(from_prefix):]] = value
 
+def _get_poolarg(pool):
+ """Returns an empty tuple if pool is None, or (pool,) otherwise, for use in
+ functions taking an optional pool parameter."""
+ if pool is None:
+ return ()
+ else:
+ return (pool,)
 
 Pool = _libsvncore.svn_pool_create
 
@@ -159,6 +166,7 @@
     """
 
     return " ".join(map(escape_shell_arg, argv))
+
 # ============================================================================
 # Deprecated functions
 
@@ -219,3 +227,35 @@
   performed as the function exits (normally or via an exception).
   '''
   return apply(func, (application_pool,) + args, kw)
+
+# ============================================================================
+# Python wrapper interfaces
+
+class AuthBaton(object):
+ """ class AuthBaton(auth_providers): Create and return a Subversion
+ authentication baton object.
+
+ auth_providers is a sequence of authentication providers. These must
+ be values returned by the svn_auth_get_*_provider functions.
+
+ This class also acts as a dictionary of authentication runtime
+ parameters. Access it as you would any Python dictionary object.
+
+ See the overview of the Subversion authentication system in svn_auth.h
+ for the overall design and use of these objects."""
+ def __init__(self, auth_providers):
+ native_providers = [self._make_native_provider(p) for p in auth_providers]
+ self._native_baton = svn_auth_open(native_providers)
+
+ def __getitem__(self, parameter):
+ """ Retrieve a named runtime authentication parameter. """
+ return svn_swig_py_get_auth_parameter(self._native_baton, parameter)
+
+ def __setitem__(self, parameter, value):
+ """ Set a named runtime authentication parameter. """
+ return svn_swig_py_set_auth_parameter(self._native_baton, parameter, value)
+
+ def __delitem__(self, parameter):
+ """ Remove a named runtime authentication parameter. """
+ return svn_auth_set_parameter(parameter, None)
+
Index: subversion/bindings/swig/python/svn/client.py
===================================================================
--- subversion/bindings/swig/python/svn/client.py (revision 20489)
+++ subversion/bindings/swig/python/svn/client.py (working copy)
@@ -6,7 +6,7 @@
 #
 ######################################################################
 #
-# Copyright (c) 2000-2004 CollabNet. All rights reserved.
+# Copyright (c) 2000-2006 CollabNet. All rights reserved.
 #
 # This software is licensed as described in the file COPYING, which
 # you should have received as part of this distribution. The terms
@@ -16,8 +16,139 @@
 #
 ######################################################################
 
+"""Subversion API, "Client" layer.
+
+This module provides API-level access to most of the functionality needed to
+implement a Subversion Client. This functionality is available directly via
+legacy SWIG calls, but new code should use svn.client.Client instances
+instead.
+"""
+
 from libsvn.client import *
 from svn.core import _unprefix_names
 _unprefix_names(locals(), 'svn_client_')
 _unprefix_names(locals(), 'SVN_CLIENT_')
 del _unprefix_names
+
+from svn import core
+
+class Client(object):
+ """Subversion client layer encapsulation.
+
+ This class provides access to Subversion client functionality. For those
+ familiar with the C Subversion API, it encapsulates a 'svn_client_context'
+ structure.
+
+ All functions taking an optional 'pool' parameter accept an svn.core.Pool
+ object if one is passed, and will use that pool for any native-code
+ memory allocation that is required."""
+
+ def __init__(self, auth_providers = None, pool = None):
+ """Create a new svn.client.Client object.
+
+ auth_providers should be a list of authentication providers returned by
+ the (currently undocumented) svn.client.get_*_provider functions. For
+ now. see the C documentation in svn_client.h on svn_client_get_*_provider
+ for information on the providers avaiable. It is currently not possible
+ to implement an Subversion authentication provider in Python.
+ """
+ poolarg = core._get_poolarg(pool)
+ self.context = svn_create_client_context(*poolarg)
+ if auth_providers is None:
+ auth_providers = [get_simple_provider(*poolarg), get_username_provider(*poolarg)]
+ self.context.auth_baton = core.svn_auth_open(auth_providers, *poolarg)
+
+ def _set_context_func(self, ctxFuncName, thunk, ctxBatonName, callback):
+ if callback is None:
+ setattr(self.ctx, ctxFuncName, "null")
+ setattr(self.ctx, ctxBatonName, None)
+ else:
+ setattr(self.ctx, ctxFuncName, thunk)
+ setattr(self.ctx, ctxBatonName, callback)
+
+ def set_notify_func(self, notify_func):
+ """Set the 'notify' callback for this object. If set and not 'None', it
+ will be called by many client operations to provide progress and other status
+ information.
+
+ notify_func should either be None, or a Python callable taking one parameter.
+ This parameter will be an object with various fields set depending on the
+ operation in question. Currently undocumented in Python; see svn_wc_notify_t
+ in svn_wc.h for information on the fields available.
+
+ The value returned by notify_func, if any, will be ignored under all
+ circumstances."""
+ self._setContextFunc("notify_func2", svn_swig_py_notify_func, "notify_baton2", notify_func)
+
+ def set_log_msg_func(self, log_msg_func):
+ """Set the 'log_msg' callback for this object. If set and not 'None', it will
+ be called whenever a client operation results in an attempted commit to a
+ repository.
+
+ log_msg_func, if set, should be a Python callable taking one parameter; this
+ will be an iterable of items to be commited. Each item is an object;
+ currently undocumented in Python; see svn_client_commit_item2_t in
+ svn_client.h for info.
+
+ The return value should be a Python string containing the log message to
+ use."""
+ self._setContextFunc("log_msg_func2", svn_swig_py_log_msg_func, "log_msg_baton2", log_msg_func)
+
+ def set_cancel_func(self, cancel_func):
+ """Set the 'cancel' callback for this object. If set and not 'None', it
+ will be called periodically by long-running operations to allow them to be
+ cancelled.
+
+ cancel_func, if set, should be a Python callable taking no parameters. It
+ should return an integer; any non-zero value will cause the running
+ operation to be cancelled."""
+ self._setContextFunc("cancel_func", svn_swig_py_cancel_func, "cancel_baton", cancel_func)
+
+ def checkout(self, URL, path, peg_revision, revision, recurse, ignore_externals, pool = None):
+ poolarg = core._get_poolarg(pool)
+ revnum = svn_revnum_t()
+ checkout(revnum, URL, path, peg_revision, revision, recurse, ignore_externals, self.ctx, *poolarg)
+ return revnum
+
+ def update(self, paths, revision, recurse, ignore_externals, pool = None):
+ poolarg = core._get_poolarg(pool)
+ result_revs = update2(paths, revision, recurse, ignore_externals, self.ctx, *poolarg)
+ return result_revs
+
+ def switch(self, path, URL, revision, recurse, pool = None):
+ poolarg = core._get_poolarg(pool)
+ revnum = svn_revnum_t()
+ switch(revnum, path, URL, revision, recurse, self.ctx, *poolarg)
+ return revnum
+
+ def add(self, path, recursive, force, no_ignore, pool = None):
+ poolarg = core._get_poolarg(pool)
+ add3(path, recursive, force, no_ignore, self.ctx, *poolarg)
+
+ def mkdir(self, paths, pool = None):
+ poolarg = core._get_poolarg(pool)
+ return mkdir2(paths, self.ctx, *poolarg)
+
+ def delete(self, paths, force, pool = None):
+ poolarg = core._get_poolarg(pool)
+ return delete2(paths, force, self.ctx, *poolarg)
+
+ def import_(self, path, URL, nonrecursive, no_ignore, pool = None):
+ poolarg = core._get_poolarg(pool)
+ return import2(path, URL, nonrecursive, no_ignore, self.ctx, *poolarg)
+
+ def commit(self, targets, recurse, keep_locks, pool = None):
+ poolarg = core._get_poolarg(pool)
+ return commit3(targets, recurse, keep_locks, self.ctx, *poolarg)
+
+ def status(self, path, revision, status_func, recurse, get_all, update, no_ignore, ignore_externals, pool = None):
+ poolarg = core._get_poolarg(pool)
+ revnum = svn_revnum_t()
+ status2(revnum, path, revision, status_func, recurse, get_all, update, no_ignore, ignore_externals, self.ctx, *poolarg)
+ return revnum
+
+ def log(self, targets, peg_revision, start, end, limit, discover_changed_paths, strict_node_history, log_receiver_func, pool = None):
+ poolarg = core._get_poolarg(pool)
+ log3(targets, peg_revision, start, end, limit, discover_changed_paths, strict_node_history, log_receiver_func, self.ctx, *poolarg)
+
+

---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@subversion.tigris.org
For additional commands, e-mail: dev-help@subversion.tigris.org
Received on Mon Jul 10 14:06:10 2006

This is an archived mail posted to the Subversion Dev mailing list.