Hello community, here is the log from the commit of package python-augeas for openSUSE:Factory checked in at 2016-01-01 19:47:21 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/python-augeas (Old) and /work/SRC/openSUSE:Factory/.python-augeas.new (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Package is "python-augeas" Changes: -------- --- /work/SRC/openSUSE:Factory/python-augeas/python-augeas.changes 2013-12-11 15:43:58.000000000 +0100 +++ /work/SRC/openSUSE:Factory/.python-augeas.new/python-augeas.changes 2016-01-01 19:47:59.000000000 +0100 @@ -1,0 +2,22 @@ +Sun Dec 13 00:27:16 UTC 2015 - ecsos@opensuse.org + +- New upstream release 0.5.0 + * Make syntax-compatible with both Python 3 and 2. + * Remove the libpython hack. + * Make tests syntax compatible with both Python 3 and 2. + * Make test failures more verbose. + * Improve error messages. + * Fix exception tests. + * Convert unicode at the C boundary. + * Add Python 3.3 to CI, and disallow failures. + * Add Travis CI settings + * Allow failures for python 3.2 + * Add text_store to the API + * Add text_retrieve to the API + * Add rename to the API + * Add transform to the API + * Add label to the API + * Use the packages from the augeas-dev PPA + * Warning: the 'name' parameter in add_transform is deprecated + +------------------------------------------------------------------- Old: ---- python-augeas-0.4.1.tar.gz New: ---- python-augeas-0.5.0.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ python-augeas.spec ++++++ --- /var/tmp/diff_new_pack.VgtyVb/_old 2016-01-01 19:48:00.000000000 +0100 +++ /var/tmp/diff_new_pack.VgtyVb/_new 2016-01-01 19:48:00.000000000 +0100 @@ -1,7 +1,7 @@ # # spec file for package python-augeas # -# Copyright (c) 2013 SUSE LINUX Products GmbH, Nuernberg, Germany. +# Copyright (c) 2015 SUSE LINUX GmbH, Nuernberg, Germany. # # All modifications and additions to the file contributed by third parties # remain the property of their copyright owners, unless otherwise agreed @@ -17,7 +17,7 @@ Name: python-augeas -Version: 0.4.1 +Version: 0.5.0 Release: 0 Summary: Python bindings for Augeas License: LGPL-2.1+ ++++++ python-augeas-0.4.1.tar.gz -> python-augeas-0.5.0.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/python-augeas-0.4.1/PKG-INFO new/python-augeas-0.5.0/PKG-INFO --- old/python-augeas-0.4.1/PKG-INFO 2012-01-10 06:37:22.000000000 +0100 +++ new/python-augeas-0.5.0/PKG-INFO 2014-08-31 19:13:07.000000000 +0200 @@ -1,6 +1,6 @@ Metadata-Version: 1.0 Name: python-augeas -Version: 0.4.1 +Version: 0.5.0 Summary: Python bindings for Augeas Home-page: http://augeas.net/ Author: Harald Hoyer diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/python-augeas-0.4.1/augeas.py new/python-augeas-0.5.0/augeas.py --- old/python-augeas-0.4.1/augeas.py 2011-11-16 02:35:10.000000000 +0100 +++ new/python-augeas-0.5.0/augeas.py 2014-08-31 18:44:49.000000000 +0200 @@ -42,6 +42,28 @@ import ctypes import ctypes.util from sys import version_info as _pyver +from functools import reduce + + +PY3 = _pyver >= (3,) +AUGENC = 'utf8' + + +if PY3: + string_types = str +else: + string_types = basestring + + +def enc(st): + if st: + return st.encode(AUGENC) + + +def dec(st): + if st: + return st.decode(AUGENC) + def _dlopen(*args): """Search for one of the libraries given as arguments and load it. @@ -56,12 +78,6 @@ class Augeas(object): "Class wrapper for the augeas library" - # Load libpython (for 'PyFile_AsFile()' and 'PyMem_Free()') - # pylint: disable-msg=W0142 - _libpython = _dlopen(*["python" + _v % _pyver[:2] - for _v in ("%d.%d", "%d%d")]) - _libpython.PyFile_AsFile.restype = ctypes.c_void_p - # Load libaugeas _libaugeas = _dlopen("augeas") _libaugeas.aug_init.restype = ctypes.c_void_p @@ -91,15 +107,15 @@ 'flags' is a bitmask made up of values from AUG_FLAGS.""" # Sanity checks - if not isinstance(root, basestring) and root != None: + if not isinstance(root, string_types) and root != None: raise TypeError("root MUST be a string or None!") - if not isinstance(loadpath, basestring) and loadpath != None: + if not isinstance(loadpath, string_types) and loadpath != None: raise TypeError("loadpath MUST be a string or None!") if not isinstance(flags, int): raise TypeError("flag MUST be a flag!") # Create the Augeas object - self.__handle = Augeas._libaugeas.aug_init(root, loadpath, flags) + self.__handle = Augeas._libaugeas.aug_init(enc(root), enc(loadpath), flags) if not self.__handle: raise RuntimeError("Unable to create Augeas object!") # Make sure self.__handle is a void*, not an integer @@ -114,7 +130,7 @@ It is an error if more than one node matches 'path'.""" # Sanity checks - if not isinstance(path, basestring): + if not isinstance(path, string_types): raise TypeError("path MUST be a string!") if not self.__handle: raise RuntimeError("The Augeas object has already been closed!") @@ -123,12 +139,34 @@ value = ctypes.c_char_p() # Call the function and pass value by reference (char **) - ret = Augeas._libaugeas.aug_get(self.__handle, path, + ret = Augeas._libaugeas.aug_get(self.__handle, enc(path), ctypes.byref(value)) if ret > 1: raise ValueError("path specified had too many matches!") - return value.value + return dec(value.value) + + def label(self, path): + """Lookup the label associated with 'path'. + Returns the label of the path specified. + It is an error if more than one node matches 'path'.""" + + # Sanity checks + if not isinstance(path, string_types): + raise TypeError("path MUST be a string!") + if not self.__handle: + raise RuntimeError("The Augeas object has already been closed!") + + # Create the char * value + label = ctypes.c_char_p() + + # Call the function and pass value by reference (char **) + ret = Augeas._libaugeas.aug_label(self.__handle, enc(path), + ctypes.byref(label)) + if ret > 1: + raise ValueError("path specified had too many matches!") + + return dec(label.value) def set(self, path, value): """Set the value associated with 'path' to 'value'. @@ -136,15 +174,15 @@ It is an error if more than one node matches 'path'.""" # Sanity checks - if not isinstance(path, basestring): + if not isinstance(path, string_types): raise TypeError("path MUST be a string!") - if not isinstance(value, basestring) and type(value) != types.NoneType: + if not isinstance(value, string_types) and type(value) != type(None): raise TypeError("value MUST be a string or None!") if not self.__handle: raise RuntimeError("The Augeas object has already been closed!") # Call the function - ret = Augeas._libaugeas.aug_set(self.__handle, path, value) + ret = Augeas._libaugeas.aug_set(self.__handle, enc(path), enc(value)) if ret != 0: raise ValueError("Unable to set value to path!") @@ -157,18 +195,65 @@ # Sanity checks if type(base) != str: - raise TypeError, "base MUST be a string!" + raise TypeError("base MUST be a string!") if type(sub) != str and sub != None: - raise TypeError, "sub MUST be a string or None!" + raise TypeError("sub MUST be a string or None!") if type(value) != str: - raise TypeError, "value MUST be a string!" + raise TypeError("value MUST be a string!") if not self.__handle: - raise RuntimeError, "The Augeas object has already been closed!" + raise RuntimeError("The Augeas object has already been closed!") # Call the function - ret = Augeas._libaugeas.aug_setm(self.__handle, base, sub, value) + ret = Augeas._libaugeas.aug_setm( + self.__handle, enc(base), enc(sub), enc(value)) if ret < 0: - raise ValueError, "Unable to set value to path!" + raise ValueError("Unable to set value to path!") + return ret + + def text_store(self, lens, node, path): + """Use the value of node 'node' as a string and transform it into a tree + using the lens 'lens' and store it in the tree at 'path', which will be + overwritten. 'path' and 'node' are path expressions.""" + + # Sanity checks + if not isinstance(lens, string_types): + raise TypeError("lens MUST be a string!") + if not isinstance(node, string_types): + raise TypeError("node MUST be a string!") + if not isinstance(path, string_types): + raise TypeError("path MUST be a string!") + if not self.__handle: + raise RuntimeError("The Augeas object has already been closed!") + + # Call the function + ret = Augeas._libaugeas.aug_text_store( + self.__handle, enc(lens), enc(node), enc(path)) + if ret != 0: + raise ValueError("Unable to store text at node!") + return ret + + def text_retrieve(self, lens, node_in, path, node_out): + """Transform the tree at 'path' into a string using lens 'lens' and store it in + the node 'node_out', assuming the tree was initially generated using the + value of node 'node_in'. 'path', 'node_in', and 'node_out' are path expressions.""" + + # Sanity checks + if not isinstance(lens, string_types): + raise TypeError("lens MUST be a string!") + if not isinstance(node_in, string_types): + raise TypeError("node_in MUST be a string!") + if not isinstance(path, string_types): + raise TypeError("path MUST be a string!") + if not isinstance(node_out, string_types): + raise TypeError("node_out MUST be a string!") + if not self.__handle: + raise RuntimeError("The Augeas object has already been closed!") + + # Call the function + ret = Augeas._libaugeas.aug_text_retrieve( + self.__handle, enc(lens), enc(node_in), enc(path), enc(node_out)) + if ret != 0: + raise ValueError("Unable to store text at node!") return ret def defvar(self, name, expr): @@ -184,16 +269,16 @@ # Sanity checks if type(name) != str: - raise TypeError, "name MUST be a string!" + raise TypeError("name MUST be a string!") if type(expr) != str and expr != None: - raise TypeError, "expr MUST be a string or None!" + raise TypeError("expr MUST be a string or None!") if not self.__handle: - raise RuntimeError, "The Augeas object has already been closed!" + raise RuntimeError("The Augeas object has already been closed!") # Call the function - ret = Augeas._libaugeas.aug_defvar(self.__handle, name, expr) + ret = Augeas._libaugeas.aug_defvar(self.__handle, enc(name), enc(expr)) if ret < 0: - raise ValueError, "Unable to register variable!" + raise ValueError("Unable to register variable!") return ret def defnode(self, name, expr, value): @@ -208,18 +293,19 @@ # Sanity checks if type(name) != str: - raise TypeError, "name MUST be a string!" + raise TypeError("name MUST be a string!") if type(expr) != str: - raise TypeError, "expr MUST be a string!" + raise TypeError("expr MUST be a string!") if type(value) != str: - raise TypeError, "value MUST be a string!" + raise TypeError("value MUST be a string!") if not self.__handle: - raise RuntimeError, "The Augeas object has already been closed!" + raise RuntimeError("The Augeas object has already been closed!") # Call the function - ret = Augeas._libaugeas.aug_defnode(self.__handle, name, expr, value, None) + ret = Augeas._libaugeas.aug_defnode( + self.__handle, enc(name), enc(expr), enc(value), None) if ret < 0: - raise ValueError, "Unable to register node!" + raise ValueError("Unable to register node!") return ret def move(self, src, dst): @@ -230,18 +316,35 @@ does not exist yet, it and all its missing ancestors are created.""" # Sanity checks - if not isinstance(src, basestring): + if not isinstance(src, string_types): raise TypeError("src MUST be a string!") - if not isinstance(dst, basestring): + if not isinstance(dst, string_types): raise TypeError("dst MUST be a string!") if not self.__handle: raise RuntimeError("The Augeas object has already been closed!") # Call the function - ret = Augeas._libaugeas.aug_mv(self.__handle, src, dst) + ret = Augeas._libaugeas.aug_mv(self.__handle, enc(src), enc(dst)) if ret != 0: raise ValueError("Unable to move src to dst!") + def rename(self, src, dst): + """Rename the label of all nodes matching 'src' to 'lbl'.""" + + # Sanity checks + if not isinstance(src, string_types): + raise TypeError("src MUST be a string!") + if not isinstance(dst, string_types): + raise TypeError("dst MUST be a string!") + if not self.__handle: + raise RuntimeError("The Augeas object has already been closed!") + + # Call the function + ret = Augeas._libaugeas.aug_rename(self.__handle, enc(src), enc(dst)) + if ret < 0: + raise ValueError("Unable to rename src as dst!") + return ret + def insert(self, path, label, before=True): """Create a new sibling 'label' for 'path' by inserting into the tree just before 'path' (if 'before' is True) or just after 'path' @@ -252,16 +355,16 @@ index '[N]'.""" # Sanity checks - if not isinstance(path, basestring): + if not isinstance(path, string_types): raise TypeError("path MUST be a string!") - if not isinstance(label, basestring): + if not isinstance(label, string_types): raise TypeError("label MUST be a string!") if not self.__handle: raise RuntimeError("The Augeas object has already been closed!") # Call the function - ret = Augeas._libaugeas.aug_insert(self.__handle, path, - label, before and 1 or 0) + ret = Augeas._libaugeas.aug_insert(self.__handle, enc(path), + enc(label), before and 1 or 0) if ret != 0: raise ValueError("Unable to insert label!") @@ -271,13 +374,13 @@ removed.""" # Sanity checks - if not isinstance(path, basestring): + if not isinstance(path, string_types): raise TypeError("path MUST be a string!") if not self.__handle: raise RuntimeError("The Augeas object has already been closed!") # Call the function - return Augeas._libaugeas.aug_rm(self.__handle, path) + return Augeas._libaugeas.aug_rm(self.__handle, enc(path)) def match(self, path): """Return the matches of the path expression 'path'. The returned paths @@ -296,7 +399,7 @@ matches more than one path segment.""" # Sanity checks - if not isinstance(path, basestring): + if not isinstance(path, string_types): raise TypeError("path MUST be a string!") if not self.__handle: raise RuntimeError("The Augeas object has already been closed!") @@ -306,25 +409,25 @@ array = ctypes.POINTER(ctypes.c_void_p)() # Call the function and pass the void ** by reference (void ***) - ret = Augeas._libaugeas.aug_match(self.__handle, path, + ret = Augeas._libaugeas.aug_match(self.__handle, enc(path), ctypes.byref(array)) if ret < 0: - raise RuntimeError("Error during match procedure!") + raise RuntimeError("Error during match procedure!", path) # Loop through the string array matches = [] for i in range(ret): if array[i]: # Create a python string and append it to our matches list - matches.append(str(ctypes.cast(array[i], + matches.append(dec(ctypes.cast(array[i], ctypes.c_char_p).value)) # Free the string at this point in the array # Wrap the string as a void* as it was not allocated by Python - Augeas._libpython.PyMem_Free(ctypes.c_void_p(array[i])) + ctypes.pythonapi.PyMem_Free(ctypes.c_void_p(array[i])) # Free the array itself - Augeas._libpython.PyMem_Free(array) + ctypes.pythonapi.PyMem_Free(array) return matches @@ -336,7 +439,7 @@ belong to a file or is doesn't exists, ValueError is raised.""" # Sanity checks - if not isinstance(path, basestring): + if not isinstance(path, string_types): raise TypeError("path MUST be a string!") if not self.__handle: raise RuntimeError("The Augeas object has already been closed!") @@ -351,14 +454,14 @@ r = ctypes.byref - ret = Augeas._libaugeas.aug_span(self.__handle, path, r(filename), + ret = Augeas._libaugeas.aug_span(self.__handle, enc(path), r(filename), r(label_start), r(label_end), r(value_start), r(value_end), r(span_start), r(span_end)) if (ret < 0): raise ValueError("Error during span procedure") - return (filename.value, label_start.value, label_end.value, + return (dec(filename.value), label_start.value, label_end.value, value_start.value, value_end.value, span_start.value, span_end.value) @@ -426,23 +529,44 @@ lens: the (file)name of the lens to use incl: one or more glob patterns for the files to transform - name: a unique name; use the module name of the lens if omitted + name: deprecated parameter excl: zero or more glob patterns of files to exclude from transforming """ - if not name: - name = lens.split(".")[0].replace("@", "", 1) - if isinstance (incl, basestring): + if name: + import warnings + warnings.warn("name is now deprecated in this function", DeprecationWarning, + stacklevel=2) + if isinstance (incl, string_types): incl = [incl] - if isinstance (excl, basestring): + if isinstance (excl, string_types): excl = [excl] - xfm = "/augeas/load/%s/" % name - self.set (xfm + "lens", lens) for i in range(len(incl)): - self.set(xfm + "incl[%d]" % (i+1), incl[i]) + self.transform(lens, incl[i], False) for i in range(len(excl)): - self.set(xfm + "excl[%d]" % (i+1), excl[i]) + self.transform(lens, excl[i], True) + + def transform(self, lens, file, excl=False): + """Add a transform for 'file' using 'lens'. + 'excl' specifies if this the file is to be included (False) + or excluded (True) from the 'lens'. + The 'lens' may be a module name or a full lens name. + If a module name is given, then lns will be the lens assumed. + """ + + if not isinstance(lens, string_types): + raise TypeError("lens MUST be a string!") + if not isinstance(file, string_types): + raise TypeError("file MUST be a string!") + if not isinstance(excl, bool): + raise TypeError("excl MUST be a boolean!") + if not self.__handle: + raise RuntimeError("The Augeas object has already been closed!") + + ret = Augeas._libaugeas.aug_transform(self.__handle, enc(lens), enc(file), excl) + if ret != 0: + raise RuntimeError("Unable to add transform!") def close(self): """Close this Augeas instance and free any storage associated with it. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/python-augeas-0.4.1/setup.py new/python-augeas-0.5.0/setup.py --- old/python-augeas-0.4.1/setup.py 2012-01-10 06:37:04.000000000 +0100 +++ new/python-augeas-0.5.0/setup.py 2014-08-31 19:13:05.000000000 +0200 @@ -10,7 +10,7 @@ from distutils.core import setup setup (name = 'python-augeas', - version = '0.4.1', + version = '0.5.0', author = "Harald Hoyer", author_email = "augeas-devel@redhat.com", description = """Python bindings for Augeas""", diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/python-augeas-0.4.1/test/test_augeas.py new/python-augeas-0.5.0/test/test_augeas.py --- old/python-augeas-0.4.1/test/test_augeas.py 2011-10-14 04:15:02.000000000 +0200 +++ new/python-augeas-0.5.0/test/test_augeas.py 2014-08-31 18:44:49.000000000 +0200 @@ -1,3 +1,5 @@ +from __future__ import print_function + import unittest import sys import os @@ -23,7 +25,7 @@ if path != "/": aug.match(path) for i in m: - for x in recurmatch(aug, i): + for x in recurmatch(aug, i): yield x else: for i in aug.match(path + "/*"): @@ -54,7 +56,7 @@ path = "/" matches = recurmatch(a, path) for (p, attr) in matches: - print >> output, p, attr + print(p, attr, file=output) self.failUnless(p != None and attr != None) output.close() @@ -64,13 +66,13 @@ num = 0 for entry in a.match("/files/etc/grub.conf/title"): num += 1 - self.failUnless(num == 2) + self.assertEqual(num, 2) default = int(a.get("/files/etc/grub.conf/default")) - self.failUnless(default == 0) + self.assertEqual(default, 0) a.set("/files/etc/grub.conf/default", str(1)) a.save() default = int(a.get("/files/etc/grub.conf/default")) - self.failUnless(default == 1) + self.assertEqual(default, 1) a.set("/files/etc/grub.conf/default", str(0)) a.save() @@ -90,7 +92,7 @@ a = augeas.Augeas(root=MYROOT) a.defnode("bighost", "/files/etc/hosts/50/ipaddr", "192.168.1.1") value = a.get("$bighost") - self.failUnless(value == "192.168.1.1") + self.assertEqual(value, "192.168.1.1") del a def test07Setm(self): @@ -100,7 +102,7 @@ self.failUnless(matches) a.setm("/files/etc/hosts", "*/ipaddr", "192.168.1.1") for i in matches: - self.failUnless(a.get(i) == "192.168.1.1") + self.assertEqual(a.get(i), "192.168.1.1") del a def test08Span(self): @@ -130,19 +132,92 @@ error = None try: r = a.span("/files") - except ValueError, e: + except ValueError as e: error = e - self.assertTrue(isinstance(e, ValueError)) + self.assertTrue(isinstance(error, ValueError)) error = None try: r = a.span("/random") - except ValueError, e: + except ValueError as e: error = e - self.assertTrue(isinstance(e, ValueError)) + self.assertTrue(isinstance(error, ValueError)) del a + def test09TextStore(self): + hosts = "192.168.0.1 rtr.example.com router\n" + a = augeas.Augeas(root=MYROOT) + r = a.set("/raw/hosts", hosts); + r = a.text_store("Hosts.lns", "/raw/hosts", "/t1") + + # Test bad lens name + try: + r = a.text_store("Notthere.lns", "/raw/hosts", "/t2") + except ValueError as e: + error = e + self.assertTrue(isinstance(error, ValueError)) + + def test10TextRetrieve(self): + hosts = "192.168.0.1 rtr.example.com router\n" + a = augeas.Augeas(root=MYROOT) + r = a.set("/raw/hosts", hosts); + r = a.text_store("Hosts.lns", "/raw/hosts", "/t1") + r = a.text_retrieve("Hosts.lns", "/raw/hosts", "/t1", "/out/hosts") + hosts_out = a.get("/out/hosts") + self.assertEqual(hosts, hosts_out) + + # Test bad lens name + try: + r = a.text_store("Notthere.lns", "/raw/hosts", "/t2") + except ValueError as e: + error = e + self.assertTrue(isinstance(error, ValueError)) + + def test11Rename(self): + a = augeas.Augeas(root=MYROOT) + r = a.set("/a/b/c", "value"); + r = a.rename("/a/b/c", "d"); + self.assertEqual(r, 1) + r = a.set("/a/e/d", "value2"); + r = a.rename("/a//d", "x"); + self.assertEqual(r, 2) + try: + r = a.rename("/a/e/x", "a/b"); + except ValueError as e: + error = e + self.assertTrue(isinstance(error, ValueError)) + + def test12Transform(self): + a = augeas.Augeas(root=MYROOT) + + r = a.transform("Foo", "/tmp/bar") + lens = a.get("/augeas/load/Foo/lens") + self.assertEqual(lens, "Foo.lns") + incl = a.get("/augeas/load/Foo/incl") + self.assertEqual(incl, "/tmp/bar") + + r = a.transform("Foo", "/tmp/baz", True) + excl = a.get("/augeas/load/Foo/excl") + self.assertEqual(excl, "/tmp/baz") + + def test13AddTransform(self): + a = augeas.Augeas(root=MYROOT) + + r = a.add_transform("Foo", "/tmp/bar") + incl = a.get("/augeas/load/Foo/incl") + self.assertEqual(incl, "/tmp/bar") + + r = a.add_transform("Foo", "/tmp/bar", "Faz", "/tmp/baz") + excl = a.get("/augeas/load/Foo/excl") + self.assertEqual(excl, "/tmp/baz") + + def test14Label(self): + a = augeas.Augeas(root=MYROOT) + + lbl = a.label("/augeas/version") + self.assertEqual(lbl, "version") + def getsuite(): suite = unittest.TestSuite() suite = unittest.makeSuite(TestAugeas, 'test')