Commit 8c42fbdf authored by Iustin Pop's avatar Iustin Pop

New upstream version 0.6.0

parent 7ab3b462
......@@ -24,20 +24,28 @@ dist:
test:
@for ver in 2.4 2.5 2.6 2.7 3.0 3.1 3.2 3.3 3.4 3.5; do \
if type python$$ver >/dev/null; then \
echo Testing with python$$ver; \
python$$ver ./setup.py test -q; \
fi; \
for flavour in "" "-dbg"; do \
if type python$$ver$$flavour >/dev/null; then \
echo Testing with python$$ver$$flavour; \
python$$ver$$flavour ./setup.py test -q; \
fi; \
done; \
done;
@if type pypy >/dev/null; then \
echo Testing with pypy; \
pypy ./setup.py test -q; \
fi
coverage:
$(MAKE) clean
$(MAKE) test CFLAGS="-coverage"
lcov --capture --directory . --output-file coverage.info
genhtml coverage.info --output-directory out
clean:
rm -rf $(DOCHTML) $(DOCTREES)
rm -f $(MODNAME)
rm -f *.so
rm -rf build
.PHONY: doc test clean dist
.PHONY: doc test clean dist coverage
News
====
Version 0.6.0
-------------
*released Mon, 23 Jan 2017*
Bugfix and feature release (hence the version bump).
The main change is to the implementation of how attributes are listed
and read. This was done due to existing race issues when attributes are
modified while being read (github issue #12), but basically all various
internal paths that dealt with retrieving an attribute value or listing
attributes were unified in a single helper function that does handle
such concurrent modifications. As a side effect, the size of the buffers
used for such reads have changed, which (depending on attribute value)
might change the trade-off between number of syscalls done and memory
usage.
As feature release, OSX support was contributed by Adam Knight
<adam@movq.us>, thanks a lot! I don't have access to OSX so the testing
for it is done via Travis builds; please report any issues.
Version 0.5.6
-------------
......
Metadata-Version: 1.1
Name: pyxattr
Version: 0.5.6
Version: 0.6.0
Summary: Filesystem extended attributes for python
Home-page: http://pyxattr.k1024.org/
Author: Iustin Pop
......
......@@ -6,7 +6,7 @@ to the extended attributes for filesystem objects available in some
operating systems.
Downloads: go to http://pyxattr.k1024.org/downloads/. Latest
version is 0.5.6. The source repository is either at
version is 0.6.0. The source repository is either at
http://git.k1024.org/pyxattr.git or at
https://github.com/iustin/pyxattr.
......
......@@ -48,9 +48,9 @@ copyright = u'2002, 2003, 2006, 2008, 2012, 2013, 2014, 2015, Iustin Pop'
# built documents.
#
# The short X.Y version.
version = '0.5.6'
version = '0.6.0'
# The full version, including alpha/beta/rc tags.
release = '0.5.6'
release = '0.6.0'
# The language for content autogenerated by Sphinx. Refer to documentation
# for a list of supported languages.
......
......@@ -18,21 +18,22 @@ Constants
.. data:: NS_SECURITY
The security namespace, used by kernel security modules.
The security name space, used by kernel security modules to store
(for example) capabilities information.
.. data:: NS_SYSTEM
The system namespace, used by the kernel to store things such as
ACLs and capabilities.
The system name space, used by the kernel to store (for example)
ACLs.
.. data:: NS_TRUSTED
The trusted namespace, visible and accessibly only to trusted
The trusted name space, visible and accessibly only to trusted
processes, used to implement mechanisms in user space.
.. data:: NS_USER
The user namespace; this is the namespace accessible to
The user name space; this is the name space accessible to
non-privileged processes.
Functions
......
../NEWS
\ No newline at end of file
News
====
Version 0.6.0
-------------
*released Mon, 23 Jan 2017*
Bugfix and feature release (hence the version bump).
The main change is to the implementation of how attributes are listed
and read. This was done due to existing race issues when attributes are
modified while being read (github issue #12), but basically all various
internal paths that dealt with retrieving an attribute value or listing
attributes were unified in a single helper function that does handle
such concurrent modifications. As a side effect, the size of the buffers
used for such reads have changed, which (depending on attribute value)
might change the trade-off between number of syscalls done and memory
usage.
As feature release, OSX support was contributed by Adam Knight
<adam@movq.us>, thanks a lot! I don't have access to OSX so the testing
for it is done via Travis builds; please report any issues.
Version 0.5.6
-------------
*released Sat, 09 Apr 2016*
Small bugfix release:
* Fixes some sign-compare warnings
* Fixes potential name truncation in merge_ns()
* Fixes building on systems which don't have ENODATA
Tested with Python 2.7.11, Python 3.5.1 and PyPy 5.0.1.
Version 0.5.5
-------------
*released Fri, 01 May 2015*
Bugfix release:
* fixes some more memory leaks when handling out-of-memory in get_all()
function
* improve error reporting when an attribute disappears after we asked
for its length but before we managed to read it
* fix int/size_t issues found by RedHat/Fedora,
https://bugzilla.redhat.com/show_bug.cgi?id=1127310; the fix is
different than their fix, but it should accomplish the same thing
* convert all code to only do explicit casts after checking boundaries,
making the code `-Wconversion`-clean (although that warning is not
enabled by default)
Version 0.5.4
-------------
*released Thu, 30 Apr 2015*
Fix memory leaks on some of the error-handling paths of the `get()`
function.
Version 0.5.3
-------------
*released Fri, 23 May 2014*
Small optimisations release:
* ari edelkind contributed a speed-up optimisation for handling of files
without xattrs (which is, in general, the expected case)
* Jonas Borgström contributed a behaviour change to the handling of file
names: under Python 3 and up, unicode paths are encoded/decoded using
the 'surogatee' handler, instead of the 'strict' handler; while this
can hide encoding errors, it mirrors what Python libraries do
(e.g. see os.fsencode/fsdecode)
* Sean Patrick Santos contributed improvements to the test suite so that
it can be used even on files systems which have built-in attributes
(e.g. when using SELinux, or NFSv4); to enable this, define the
attributes in the TEST_IGNORE_XATTRS environment variable
Version 0.5.2
-------------
*released Thu, 03 Jan 2013*
Bug-fix release. Thanks to Michał Górny, it looked like the library had
problem running under pypy, but actually there was a bug in the
PyArg_ParseTuple use of et# (signed vs. unsigned, and lack of compiler
warnings). This was fixed, and now the test suite passed with many
CPython versions and PyPy (version 1.9).
Version 0.5.1
-------------
*released Wed, 16 May 2012*
Bug-fix release. Thanks to Dave Malcolm and his cpychecker tool, a
number of significant bugs (refcount leaks and potential NULL-pointer
dereferences) have been fixed.
Furthermore, compatibility with Python 3 has been improved; this however
required changing the meaning of the ``namespace`` argument to the
functions: if passed, None is no longer a valid value; pass an empty
string if (due to the structure of your program) you have to pass this
argument but want to specify no namespace.
Also, the project home page has changed from SourceForge to GitHub, and
the documentation has been converted from epydoc-based to sphinx.
Version 0.5
-----------
*released Sun, 27 Dec 2009*
Implemented support for Python 3. This required a significant change to
the C module, hence the new version number.
Version 0.4
-----------
*released Mon, 30 Jun 2008*
API
~~~
The old functions ({get,set,list,remove}xattr) are deprecated and replaced with
a new API that is namespace-aware and hopefully will allow other OSes (e.g.
FreeBSD) to be supported more naturally.
Both the old and the new API are supported in the 0.4 versions, however users
are encouraged to migrate to the new API.
New features
~~~~~~~~~~~~
A new bulk get function called get_all() has been added that should be somewhat
faster in case of querying files which have many attributes.
License
~~~~~~~
Since LGPLv3 is not compatible with GPLv2 (which unfortunately I didn't realize
before), the license was changed to LGPLv2.1 or later.
Internals
~~~~~~~~~
Unittest coverage was improved.
Version 0.3
-----------
*released Sun, 09 Mar 2008*
* changed licence from GPL to LGPL (3 or later)
* changed listxattr return type from tuple to a list
* developer-related: added unittests
Version 0.2.2
-------------
*released Sun, 01 Jul 2007*
* fixed listing symlink xattrs
Version 0.2.1
-------------
*released Sat, 11 Feb 2006*
* fixed a bug when reading symlink EAs (you weren't able to
do it, actually)
* fixed a possible memory leak when the actual read of the EA
failed but the call to get the length of the EA didn't
.. Local Variables:
.. mode: rst
.. fill-column: 72
.. End:
Metadata-Version: 1.1
Name: pyxattr
Version: 0.5.6
Version: 0.6.0
Summary: Filesystem extended attributes for python
Home-page: http://pyxattr.k1024.org/
Author: Iustin Pop
......
......@@ -5,5 +5,4 @@ requires = libattr
[egg_info]
tag_build =
tag_date = 0
tag_svn_revision = 0
#!/usr/bin/python
import distutils
import platform
try:
from setuptools import setup, Extension
except ImportError:
......@@ -9,9 +10,12 @@ except ImportError:
long_desc = """This is a C extension module for Python which
implements extended attributes manipulation. It is a wrapper on top
of the attr C library - see attr(5)."""
version = "0.5.6"
version = "0.6.0"
author = "Iustin Pop"
author_email = "iustin@k1024.org"
libraries = []
if platform.system() == 'Linux':
libraries.append("attr")
macros = [
("_XATTR_VERSION", '"%s"' % version),
("_XATTR_AUTHOR", '"%s"' % author),
......@@ -27,7 +31,7 @@ setup(name = "pyxattr",
download_url = "http://pyxattr.k1024.org/downloads/",
license = "LGPL",
ext_modules = [Extension("xattr", ["xattr.c"],
libraries=["attr"],
libraries=libraries,
define_macros=macros,
extra_compile_args=["-Wall", "-Werror", "-Wsign-compare"],
)],
......
......@@ -31,12 +31,16 @@ class xattrTest(unittest.TestCase):
USER_NN = "test"
USER_ATTR = NS_USER.decode() + "." + USER_NN
USER_VAL = "abc"
EMPTY_VAL = ""
LARGE_VAL = "x" * 2048
MANYOPS_COUNT = 131072
if PY3K:
USER_NN = USER_NN.encode()
USER_VAL = USER_VAL.encode()
USER_ATTR = USER_ATTR.encode()
EMPTY_VAL = EMPTY_VAL.encode()
LARGE_VAL = LARGE_VAL.encode()
@staticmethod
def _ignore_tuples(attrs):
......@@ -51,11 +55,11 @@ class xattrTest(unittest.TestCase):
if attr not in TEST_IGNORE_XATTRS]
def checkList(self, attrs, value):
"""Helper to check attribute list equivalence, skipping TEST_IGNORE_XATTRS."""
"""Helper to check list equivalence, skipping TEST_IGNORE_XATTRS."""
self.assertEqual(self._ignore(attrs), value)
def checkTuples(self, attrs, value):
"""Helper to check attribute list equivalence, skipping TEST_IGNORE_XATTRS."""
"""Helper to check list equivalence, skipping TEST_IGNORE_XATTRS."""
self.assertEqual(self._ignore_tuples(attrs), value)
def setUp(self):
......@@ -109,9 +113,11 @@ class xattrTest(unittest.TestCase):
xattr.setxattr(item, self.USER_ATTR, self.USER_VAL, 0, symlink)
except IOError:
err = sys.exc_info()[1]
if err.errno == errno.EPERM and symlink:
if symlink and (err.errno == errno.EPERM or
err.errno == errno.ENOENT):
# symlinks may fail, in which case we abort the rest
# of the test for this case
# of the test for this case (Linux returns EPERM; OS X
# returns ENOENT)
return
raise
self.assertRaises(EnvironmentError, xattr.setxattr, item,
......@@ -146,9 +152,11 @@ class xattrTest(unittest.TestCase):
nofollow=symlink)
except IOError:
err = sys.exc_info()[1]
if err.errno == errno.EPERM and symlink:
if symlink and (err.errno == errno.EPERM or
err.errno == errno.ENOENT):
# symlinks may fail, in which case we abort the rest
# of the test for this case
# of the test for this case (Linux returns EPERM; OS X
# returns ENOENT)
return
raise
self.assertRaises(EnvironmentError, xattr.set, item,
......@@ -188,12 +196,19 @@ class xattrTest(unittest.TestCase):
fh, fname = self._getfile()
self.checkList(xattr.listxattr(fname), [])
self.checkTuples(xattr.get_all(fname), [])
self.assertRaises(EnvironmentError, xattr.getxattr, fname,
self.USER_ATTR)
dname = self._getdir()
self.checkList(xattr.listxattr(dname), [])
self.checkTuples(xattr.get_all(dname), [])
self.assertRaises(EnvironmentError, xattr.getxattr, dname,
self.USER_ATTR)
_, sname = self._getsymlink()
self.checkList(xattr.listxattr(sname, True), [])
self.checkTuples(xattr.get_all(sname, nofollow=True), [])
self.assertRaises(EnvironmentError, xattr.getxattr, fname,
self.USER_ATTR, True)
def testNoXattr(self):
"""test no attributes"""
......@@ -202,11 +217,15 @@ class xattrTest(unittest.TestCase):
self.assertEqual(xattr.list(fname, namespace=NS_USER), [])
self.checkTuples(xattr.get_all(fname), [])
self.assertEqual(xattr.get_all(fname, namespace=NS_USER), [])
self.assertRaises(EnvironmentError, xattr.get, fname,
self.USER_NN, namespace=NS_USER)
dname = self._getdir()
self.checkList(xattr.list(dname), [])
self.assertEqual(xattr.list(dname, namespace=NS_USER), [])
self.checkTuples(xattr.get_all(dname), [])
self.assertEqual(xattr.get_all(dname, namespace=NS_USER), [])
self.assertRaises(EnvironmentError, xattr.get, dname,
self.USER_NN, namespace=NS_USER)
_, sname = self._getsymlink()
self.checkList(xattr.list(sname, nofollow=True), [])
self.assertEqual(xattr.list(sname, nofollow=True,
......@@ -214,6 +233,8 @@ class xattrTest(unittest.TestCase):
self.checkTuples(xattr.get_all(sname, nofollow=True), [])
self.assertEqual(xattr.get_all(sname, nofollow=True,
namespace=NS_USER), [])
self.assertRaises(EnvironmentError, xattr.get, sname,
self.USER_NN, namespace=NS_USER, nofollow=True)
def testFileByNameDeprecated(self):
"""test set and retrieve one attribute by file name (deprecated)"""
......@@ -397,6 +418,36 @@ class xattrTest(unittest.TestCase):
self.assertRaises(TypeError, xattr.get, fh, self.USER_ATTR,
namespace=None)
def testEmptyValue(self):
fh, fname = self._getfile()
xattr.set(fh, self.USER_ATTR, self.EMPTY_VAL)
self.assertEqual(xattr.get(fh, self.USER_ATTR), self.EMPTY_VAL)
def testWrongCall(self):
for call in [xattr.get,
xattr.list, xattr.listxattr,
xattr.remove, xattr.removexattr,
xattr.set, xattr.setxattr,
xattr.get, xattr.getxattr]:
self.assertRaises(TypeError, call)
def testWrongType(self):
self.assertRaises(TypeError, xattr.get, object(), self.USER_ATTR)
for call in [xattr.listxattr, xattr.list]:
self.assertRaises(TypeError, call, object())
for call in [xattr.remove, xattr.removexattr,
xattr.get, xattr.getxattr]:
self.assertRaises(TypeError, call, object(), self.USER_ATTR)
for call in [xattr.set, xattr.setxattr]:
self.assertRaises(TypeError, call, object(), self.USER_ATTR, self.USER_VAL)
def testLargeAttribute(self):
fh, fname = self._getfile()
xattr.set(fh, self.USER_ATTR, self.LARGE_VAL)
self.assertEqual(xattr.get(fh, self.USER_ATTR), self.LARGE_VAL)
if __name__ == "__main__":
unittest.main()
This diff is collapsed.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment