You are viewing a plain text version of this content. The canonical link for it is here.
Posted to users@subversion.apache.org by Mark Ziesemer <on...@mark.ziesemer.com> on 2015/09/02 02:01:40 UTC
How to call SVN's fs.change_rev_prop2 from Python / SWIG - passing old_value_p as a double pointer?
I'm trying to call fs.change_rev_prop2 (https://goo.gl/6b6TG5) from Python /
SWIG - and apparently can't figure out how to pass old_value_p as what I'm
assuming needs to be a double pointer from Python.
(Also posted to http://stackoverflow.com/q/32239234/751158 . Looking for
more visibility, and/or for someone here to earn a bounty there that I've
already posted.)
Minimized code sample:
#!/usr/bin/env python
from svn import repos, fs, core
fs_ptr = repos.fs(repos.open("/opt/app/svn/repos/test"))
rev_num = 1
user = fs.revision_prop(fs_ptr, rev_num, "svn:author")
# Works, but is is deprecated in favor of fs.change_rev_prop2 .
fs.change_rev_prop(fs_ptr, rev_num, "svn:author", user.lower())
# fs.change_rev_prop2(fs_ptr, rev_num, "svn:author", user, user.lower())
# > svn.core.SubversionException: 160049 - revprop 'svn:author' has
unexpected value in filesystem
# fs.change_rev_prop2(fs_ptr, rev_num, "svn:author", None, user.lower())
# Per svn_ra.h: If the capability is not advertised, then @a old_value_p
MUST be @c NULL.
# This results in a successful change of the revision property, but then
this program ends with a segmentation fault.
Details of the # 160049 error:
Traceback (most recent call last):
File "./normalize-usernames.py", line 10, in <module>
fs.change_rev_prop2(fs_ptr, rev_num, "svn:author", user, user.lower())
File "/opt/app/subversion/lib/svn-python/libsvn/fs.py", line 711, in
svn_fs_change_rev_prop2
return _fs.svn_fs_change_rev_prop2(*args)
svn.core.SubversionException: 160049 - revprop 'svn:author' has unexpected
value in filesystem
I believe the value I'm attempting to pass is "correct". After all, I'm
obtaining it from the API immediately before attempting to set it back. I'm
assuming I'm just not passing the value correctly in a way that the native
API can accept it.
So I could just continue using change_rev_prop - but it is clearly marked as
deprecated in the API ("Provided for backward compatibility with the 1.6
API"). Should be able to do better, though...
Interestingly, calling change_rev_prop2 with None for old_value_p results in
the desired change taking effect in the repository - but not without causing
the Python program to then immediately terminate with a Segmentation Fault.
It would seem that I need to pass the old / current value as a pointer -
possibly to be able to differentiate to the API the difference between a
null pointer (value not provided) and a pointer to a null value (value is
provided, but value is null)? However, I've tried all the combinations I can
think of here without success - including using various wrappers from ctypes.
StackOverflow is appropriately suggesting a good number of questions that
may already have the answer here - but it appears that most of them cover
cases where the author has control over the C sources and with
recommendations to alter the C API to avoid the complexity entirely - which
I don't see to be an option here. This is largely my only experience with
Python and SWIG so far, and any tips would be appreciated, thanks!
Re: How to call SVN's fs.change_rev_prop2 from Python / SWIG -
passing old_value_p as a double pointer?
Posted by Daniel Shahaf <d....@daniel.shahaf.name>.
Daniel Shahaf wrote on Wed, Sep 02, 2015 at 15:35:04 +0000:
> [ Summary for dev@: calling svn_fs_change_rev_prop() from Python works;
> calling svn_fs_change_rev_prop2() with old_value_p=None changes the
> property and then segfaults. ]
I've plugged the segfault in r1700966.
I don't see a particular need to backport it, since the only way to
trigger the segfault is by writing new code that will always trigger
the segfault when tested, and old code (using the deprecated APIs)
works.
Re: How to call SVN's fs.change_rev_prop2 from Python / SWIG -
passing old_value_p as a double pointer?
Posted by Daniel Shahaf <d....@daniel.shahaf.name>.
[ Summary for dev@: calling svn_fs_change_rev_prop() from Python works;
calling svn_fs_change_rev_prop2() with old_value_p=None changes the
property and then segfaults. ]
Mark Ziesemer wrote on Wed, Sep 02, 2015 at 00:01:40 +0000:
> I'm trying to call fs.change_rev_prop2 (https://goo.gl/6b6TG5) from Python /
> SWIG - and apparently can't figure out how to pass old_value_p as what I'm
> assuming needs to be a double pointer from Python.
>
In short, I don't think that's currently possible; I think the bindings
will need to be patched for this to work. The 'const svn_string_t
*const *old_value_p' parameter of svn_fs_change_rev_prop2() will need to
be wrapped correctly. (Currently it is wrapped incorrectly: passing
None to it segfaults although NULL is a valid value.)
How should that parameter be presented to Python code? In particular,
how should Python code that passes a "pointer to a NULL pointer" as the
argument look like?
(Moving the thread to dev@. I'll reply separately on users@ with a few
notes about your code.)
Cheers,
Daniel
Re: How to call SVN's fs.change_rev_prop2 from Python / SWIG -
passing old_value_p as a double pointer?
Posted by Daniel Shahaf <d....@daniel.shahaf.name>.
[ Summary for dev@: calling svn_fs_change_rev_prop() from Python works;
calling svn_fs_change_rev_prop2() with old_value_p=None changes the
property and then segfaults. ]
Mark Ziesemer wrote on Wed, Sep 02, 2015 at 00:01:40 +0000:
> I'm trying to call fs.change_rev_prop2 (https://goo.gl/6b6TG5) from Python /
> SWIG - and apparently can't figure out how to pass old_value_p as what I'm
> assuming needs to be a double pointer from Python.
>
In short, I don't think that's currently possible; I think the bindings
will need to be patched for this to work. The 'const svn_string_t
*const *old_value_p' parameter of svn_fs_change_rev_prop2() will need to
be wrapped correctly. (Currently it is wrapped incorrectly: passing
None to it segfaults although NULL is a valid value.)
How should that parameter be presented to Python code? In particular,
how should Python code that passes a "pointer to a NULL pointer" as the
argument look like?
(Moving the thread to dev@. I'll reply separately on users@ with a few
notes about your code.)
Cheers,
Daniel
Re: How to call SVN's fs.change_rev_prop2 from Python / SWIG -
passing old_value_p as a double pointer?
Posted by Daniel Shahaf <d....@daniel.shahaf.name>.
Mark Ziesemer wrote on Wed, Sep 02, 2015 at 00:01:40 +0000:
> I'm trying to call fs.change_rev_prop2 (https://goo.gl/6b6TG5) from Python /
> SWIG - and apparently can't figure out how to pass old_value_p as what I'm
> assuming needs to be a double pointer from Python.
>
[ I've replied to this part on dev@. tldr: Not currently possible. More
below. ]
> user = fs.revision_prop(fs_ptr, rev_num, "svn:author")
>
> # Works, but is is deprecated in favor of fs.change_rev_prop2 .
> fs.change_rev_prop(fs_ptr, rev_num, "svn:author", user.lower())
>
> # fs.change_rev_prop2(fs_ptr, rev_num, "svn:author", user, user.lower())
> # > svn.core.SubversionException: 160049 - revprop 'svn:author' has
> unexpected value in filesystem
>
> # fs.change_rev_prop2(fs_ptr, rev_num, "svn:author", None, user.lower())
> # Per svn_ra.h: If the capability is not advertised, then @a old_value_p
> MUST be @c NULL.
You should be looking at svn_fs.h, not svn_ra.h, since that's the layer
you're working with.
And, once the svn_fs-based code works, you should probably switch to
using the svn_repos layer instead (i.e., svn_repos_fs_change_rev_prop4()).
> I believe the value I'm attempting to pass is "correct". After all, I'm
> obtaining it from the API immediately before attempting to set it back. I'm
> assuming I'm just not passing the value correctly in a way that the native
> API can accept it.
You certainly aren't: you're passing a wrapped svn_string_t* to
a parameter that expects a wrapped svn_string_t**.
> So I could just continue using change_rev_prop - but it is clearly marked as
> deprecated in the API ("Provided for backward compatibility with the 1.6
> API"). Should be able to do better, though...
The deprecation just means we remove the API when we release 2.0, which
might be sometime before the Sun stops working. Or maybe after. We
have an issue somewhere reminding us to decide between these two options.
Basically, don't worry about it.