Hello community,
here is the log from the commit of package python-pylibacl for openSUSE:Factory
checked in at 2020-01-09 22:52:48
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/python-pylibacl (Old)
and /work/SRC/openSUSE:Factory/.python-pylibacl.new.6675 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "python-pylibacl"
Thu Jan 9 22:52:48 2020 rev:3 rq:762227 version:0.5.4
Changes:
--------
--- /work/SRC/openSUSE:Factory/python-pylibacl/python-pylibacl.changes
2019-10-16 09:15:31.459430610 +0200
+++
/work/SRC/openSUSE:Factory/.python-pylibacl.new.6675/python-pylibacl.changes
2020-01-09 22:53:25.710794377 +0100
@@ -1,0 +2,8 @@
+Thu Jan 9 14:06:28 UTC 2020 - Tomáš Chvátal <[email protected]>
+
+- Update to 0.5.4:
+ * Switch to python3 interpreter
+ * minor documentation improvements
+- Switch to singlespec
+
+-------------------------------------------------------------------
Old:
----
pylibacl-0.5.3.tar.gz
New:
----
pylibacl-0.5.4.tar.gz
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Other differences:
------------------
++++++ python-pylibacl.spec ++++++
--- /var/tmp/diff_new_pack.p7uaBC/_old 2020-01-09 22:53:27.730795388 +0100
+++ /var/tmp/diff_new_pack.p7uaBC/_new 2020-01-09 22:53:27.754795401 +0100
@@ -1,7 +1,7 @@
#
# spec file for package python-pylibacl
#
-# Copyright (c) 2019 SUSE LINUX GmbH, Nuernberg, Germany.
+# Copyright (c) 2020 SUSE LLC
#
# All modifications and additions to the file contributed by third parties
# remain the property of their copyright owners, unless otherwise agreed
@@ -16,54 +16,44 @@
#
+%{?!python_module:%define python_module() python-%{**} python3-%{**}}
Name: python-pylibacl
-Version: 0.5.3
+Version: 0.5.4
Release: 0
-Summary: Python POSIX.1e ACL module
+Summary: POSIX1e ACLs for python
License: LGPL-2.1-or-later
URL: https://pylibacl.k1024.org/
-Source:
https://github.com/iustin/pylibacl/releases/download/pylibacl-v%{version}/pylibacl-%{version}.tar.gz
+Source:
https://files.pythonhosted.org/packages/source/p/pylibacl/pylibacl-%{version}.tar.gz
+BuildRequires: %{python_module devel}
+BuildRequires: %{python_module pytest}
+BuildRequires: %{python_module setuptools}
BuildRequires: fdupes
-BuildRequires: libacl-devel
-# Documentation requirements:
-BuildRequires: python-Sphinx
-BuildRequires: python-devel
-BuildRequires: python-setuptools
+BuildRequires: pkgconfig
+BuildRequires: python-rpm-macros
+BuildRequires: pkgconfig(libacl)
+%python_subpackages
%description
-This Python 2.4+ extension module allows you to manipulate the POSIX.1e Access
-Control Lists present in some OS/file-systems combinations. It is a wrapper on
-top of the systems's acl C library - see acl(5).
-
-%package doc
-Summary: Python POSIX.1e ACL module
-Requires: %{name} = %{version}
-
-%description doc
-This Python 2.4+ extension module allows you to manipulate the POSIX.1e Access
-Control Lists present in some OS/file-systems combinations. It is a wrapper on
-top of the systems's acl C library - see acl(5).
+This is a C extension module for Python which
+implements POSIX ACLs manipulation. It is a wrapper on top
+of the systems's acl C library - see acl(5).
%prep
%setup -q -n pylibacl-%{version}
%build
-CFLAGS="%{optflags} -fno-strict-aliasing" python setup.py build
-python setup.py build_sphinx
+%python_build
%install
-python setup.py install --prefix=%{_prefix} --root=%{buildroot}
-%fdupes %{buildroot}/%{_prefix}
+%python_install
+%python_expand %fdupes %{buildroot}%{$python_sitearch}
%check
-python setup.py test
+%pytest_arch
-%files
+%files %{python_files}
%license COPYING
-%doc NEWS README
+%doc NEWS README.rst
%{python_sitearch}/*
-%files doc
-%doc build/sphinx/html
-
%changelog
++++++ pylibacl-0.5.3.tar.gz -> pylibacl-0.5.4.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/pylibacl-0.5.3/MANIFEST.in
new/pylibacl-0.5.4/MANIFEST.in
--- old/pylibacl-0.5.3/MANIFEST.in 2012-05-17 04:49:28.000000000 +0200
+++ new/pylibacl-0.5.4/MANIFEST.in 2015-05-01 21:56:38.000000000 +0200
@@ -1,7 +1,7 @@
include COPYING
include Makefile
include NEWS
-include README
+include README.rst
include acl.c
include setup.cfg
include doc/conf.py
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/pylibacl-0.5.3/Makefile new/pylibacl-0.5.4/Makefile
--- old/pylibacl-0.5.3/Makefile 2015-04-30 22:11:29.000000000 +0200
+++ new/pylibacl-0.5.4/Makefile 2019-11-14 11:37:56.000000000 +0100
@@ -1,38 +1,49 @@
+PYTHON = python3
SPHINXOPTS = -W
-SPHINXBUILD = sphinx-build
+SPHINXBUILD = $(PYTHON) -m sphinx
DOCDIR = doc
DOCHTML = $(DOCDIR)/html
DOCTREES = $(DOCDIR)/doctrees
ALLSPHINXOPTS = -d $(DOCTREES) $(SPHINXOPTS) $(DOCDIR)
MODNAME = posix1e.so
-RSTFILES = doc/index.rst doc/module.rst NEWS README doc/conf.py
+RSTFILES = doc/index.rst doc/module.rst NEWS README.rst doc/conf.py
all: doc test
$(MODNAME): acl.c
- ./setup.py build_ext --inplace
+ $(PYTHON) ./setup.py build_ext --inplace
-$(DOCHTML)/index.html: $(MODNAME) $(RSTFILES)
+$(DOCHTML)/index.html: $(MODNAME) $(RSTFILES) acl.c
$(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(DOCHTML)
touch $@
doc: $(DOCHTML)/index.html
dist:
- fakeroot ./setup.py sdist
+ fakeroot $(PYTHON) ./setup.py sdist
test:
- @for ver in 2.4 2.5 2.6 2.7 3.0 3.1 3.2 3.3 3.4; do \
- if type python$$ver >/dev/null; then \
- echo Testing with python$$ver; \
- python$$ver ./setup.py test -q; \
+ @for ver in 2.7 3.0 3.1 3.2 3.3 3.4 3.5 3.6 3.7; do \
+ 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; \
+ for pp in pypy pypy3; do \
+ if type $$pp >/dev/null; then \
+ echo Testing with $$pp; \
+ $$pp ./setup.py test -q; \
fi; \
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)
@@ -40,4 +51,4 @@
rm -f *.so
rm -rf build
-.PHONY: doc test clean dist
+.PHONY: doc test clean dist coverage
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/pylibacl-0.5.3/NEWS new/pylibacl-0.5.4/NEWS
--- old/pylibacl-0.5.3/NEWS 2015-04-30 22:20:00.000000000 +0200
+++ new/pylibacl-0.5.4/NEWS 2019-11-14 11:57:12.000000000 +0100
@@ -1,9 +1,28 @@
News
====
+Version 0.5.4
+-------------
+
+*released Thu, 14 Nov 2019*
+
+Maintenance release:
+
+- Switch build system to Python 3 by default (can be overridden if
+ needed).
+- Internal improvements for better cpychecker support.
+- Fix compatibility with PyPy.
+- Test improvements (both local and on Travis), testing more variations
+ (debug, PyPy).
+- Improve test coverage, and allow gathering test coverage results.
+- Drop support (well, drop testing) for Python lower than 2.7.
+- Minor documentation improvements (closes #9, #12).
+
Version 0.5.3
-------------
+*released Thu, 30 Apr 2015*
+
FreeBSD fixes:
- Enable all FreeBSD versions after 7.x at level 2 (thanks to Garrett
@@ -15,11 +34,15 @@
Version 0.5.2
-------------
+*released Sat, 24 May 2014*
+
No visible changes release: just fix tests when running under pypy.
Version 0.5.1
-------------
+*released Sun, 13 May 2012*
+
A bug-fix only release. Critical bugs (memory leaks and possible
segmentation faults) have been fixed thanks to Dave Malcolm and his
``cpychecker`` tool. Additionally, some compatibility issues with Python
@@ -36,16 +59,20 @@
Version 0.5
-----------
+*released Sun, 27 Dec 2009*
+
Added support for Python 3.x and improved support for Unicode filenames.
Version 0.4
-----------
+*released Sat, 28 Jun 2008*
+
License
~~~~~~~
Starting with this version, pylibacl is licensed under LGPL 2.1,
-Febryary 1999 or any later versions (see README and COPYING).
+Febryary 1999 or any later versions (see README.rst and COPYING).
Linux support
~~~~~~~~~~~~~
@@ -97,6 +124,8 @@
Version 0.3
-----------
+*released Sun, 21 Oct 2007*
+
Linux support
~~~~~~~~~~~~~
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/pylibacl-0.5.3/PKG-INFO new/pylibacl-0.5.4/PKG-INFO
--- old/pylibacl-0.5.3/PKG-INFO 2015-04-30 22:22:25.000000000 +0200
+++ new/pylibacl-0.5.4/PKG-INFO 2019-11-14 12:03:24.000000000 +0100
@@ -1,6 +1,6 @@
Metadata-Version: 1.0
Name: pylibacl
-Version: 0.5.3
+Version: 0.5.4
Summary: POSIX.1e ACLs for python
Home-page: http://pylibacl.k1024.org/
Author: Iustin Pop
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/pylibacl-0.5.3/README new/pylibacl-0.5.4/README
--- old/pylibacl-0.5.3/README 2015-04-30 22:18:19.000000000 +0200
+++ new/pylibacl-0.5.4/README 1970-01-01 01:00:00.000000000 +0100
@@ -1,41 +0,0 @@
-pylibacl
-========
-
-This is a Python 2.4+ extension module allows you to manipulate the
-POSIX.1e Access Control Lists present in some OS/file-systems
-combinations.
-
-Downloads: go to http://pylibacl.k1024.org/downloads. Latest
-version is 0.5.3. The source repository is either
-at `<git://git.k1024.org/pylibacl.git>`_ or
-at https://github.com/iustin/pylibacl.
-
-For any issues, please file bugs at
-https://github.com/iustin/pylibacl/issues.
-
-Requirements
-------------
-
-pylibacl has been written and tested on Linux, kernel v2.4 or newer,
-with XFS filesystems; ext2/ext3 should also work. Since release 0.4.0,
-FreeBSD 7 also has quite good support. If any other platform
-implements the POSIX.1e draft, pylibacl can be used. I heard that
-Solaris does, but I can't test it.
-
-- Python 2.4 or newer
-- operating system:
- - Linux, kernel v2.4 or newer, and the libacl library and
- development packages (all modern distributions should have this,
- under various names); also the file-systems you use must have
- ACLs turned on, either as a compile or mount option
- - FreeBSD 7.0 or newer
-
-License
--------
-
-pylibacl is Copyright (C) 2002-2009, 2012, 2014, 2015 Iustin Pop.
-
-pylibacl is free software; you can redistribute it and/or modify it under the
-terms of the GNU Lesser General Public License as published by the Free
-Software Foundation; either version 2.1 of the License, or (at your option) any
-later version. See the COPYING file for the full license terms.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/pylibacl-0.5.3/README.rst
new/pylibacl-0.5.4/README.rst
--- old/pylibacl-0.5.3/README.rst 1970-01-01 01:00:00.000000000 +0100
+++ new/pylibacl-0.5.4/README.rst 2019-11-14 11:57:57.000000000 +0100
@@ -0,0 +1,60 @@
+pylibacl
+========
+
+This is a Python 2.7+ extension module allows you to manipulate the
+POSIX.1e Access Control Lists present in some OS/file-systems
+combinations.
+
+Downloads: go to http://pylibacl.k1024.org/downloads. Latest version
+is 0.5.4. The source repository is either at
+https://git.k1024.org/pylibacl.git or at
+https://github.com/iustin/pylibacl.
+
+For any issues, please file bugs at
+https://github.com/iustin/pylibacl/issues.
+
+Requirements
+------------
+
+pylibacl has been written and tested on Linux, kernel v2.4 or newer,
+with XFS filesystems; ext2/ext3 should also work. Since release 0.4.0,
+FreeBSD 7 also has quite good support. If any other platform
+implements the POSIX.1e draft, pylibacl can be used. I heard that
+Solaris does, but I can't test it.
+
+- Python 2.7 or newer.
+- Operating system:
+ - Linux, kernel v2.4 or newer, and the libacl library and
+ development packages (all modern distributions should have this,
+ under various names); also the file-systems you use must have
+ ACLs turned on, either as a compile or mount option.
+ - FreeBSD 7.0 or newer.
+- The sphinx python module, for your python version, if building the
+ documentation.
+
+Note: to build from source, by default, Python 3 is needed. It can
+still be built with Python 2, by calling `make PYTHON=python2`.
+
+FreeBSD
++++++++
+
+Note that on FreeBSD, ACLs are not enabled by default (at least on UFS
+file systems). To enable them, run `tunefs -a enabled` on the file
+system in question (after mounting it read-only). Then install:
+
+- pkg install py36-setuptools py36-sphinx
+
+or:
+
+- pkg install py37-setuptools
+
+
+License
+-------
+
+pylibacl is Copyright (C) 2002-2009, 2012, 2014, 2015 Iustin Pop.
+
+pylibacl is free software; you can redistribute it and/or modify it under the
+terms of the GNU Lesser General Public License as published by the Free
+Software Foundation; either version 2.1 of the License, or (at your option) any
+later version. See the COPYING file for the full license terms.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/pylibacl-0.5.3/acl.c new/pylibacl-0.5.4/acl.c
--- old/pylibacl-0.5.3/acl.c 2015-04-30 22:14:27.000000000 +0200
+++ new/pylibacl-0.5.4/acl.c 2019-11-14 11:45:22.000000000 +0100
@@ -1,7 +1,7 @@
/*
posix1e - a python module exposing the posix acl functions
- Copyright (C) 2002-2009, 2012, 2014 Iustin Pop <[email protected]>
+ Copyright (C) 2002-2009, 2012, 2014, 2015 Iustin Pop <[email protected]>
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
@@ -45,7 +45,6 @@
#define PyInt_AsUnsignedLongMask PyLong_AsUnsignedLongMask
#define PyInt_AsUnsignedLongLongMask PyLong_AsUnsignedLongLongMask
#define PyInt_AS_LONG PyLong_AS_LONG
-#define MyString_ConcatAndDel PyUnicode_AppendAndDel
#define MyString_FromFormat PyUnicode_FromFormat
#define MyString_FromString PyUnicode_FromString
#define MyString_FromStringAndSize PyUnicode_FromStringAndSize
@@ -55,19 +54,34 @@
#define PyBytes_FromStringAndSize PyString_FromStringAndSize
#define PyBytes_FromString PyString_FromString
#define PyBytes_FromFormat PyString_FromFormat
-#define PyBytes_ConcatAndDel PyString_ConcatAndDel
-#define MyString_ConcatAndDel PyBytes_ConcatAndDel
#define MyString_FromFormat PyBytes_FromFormat
#define MyString_FromString PyBytes_FromString
#define MyString_FromStringAndSize PyBytes_FromStringAndSize
+#endif
-/* Python 2.6 already defines Py_TYPE */
-#ifndef Py_TYPE
-#define Py_TYPE(o) (((PyObject*)(o))->ob_type)
+/* Used for cpychecker: */
+/* The checker automatically defines this preprocessor name when creating
+ the custom attribute: */
+#if defined(WITH_CPYCHECKER_TYPE_OBJECT_FOR_TYPEDEF_ATTRIBUTE)
+#define CPYCHECKER_TYPE_OBJECT_FOR_TYPEDEF(typename) \
+ __attribute__((cpychecker_type_object_for_typedef(typename)))
+#else
+/* This handles the case where we're compiling with a "vanilla"
+ compiler that doesn't supply this attribute: */
+#define CPYCHECKER_TYPE_OBJECT_FOR_TYPEDEF(typename)
#endif
+
+/* The checker automatically defines this preprocessor name when creating
+ the custom attribute: */
+#if defined(WITH_CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION_ATTRIBUTE)
+ #define CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION \
+__attribute__((cpychecker_negative_result_sets_exception))
+ #else
+ #define CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION
#endif
-static PyTypeObject ACL_Type;
+static PyTypeObject ACL_Type
+ CPYCHECKER_TYPE_OBJECT_FOR_TYPEDEF("ACL_Object");
static PyObject* ACL_applyto(PyObject* obj, PyObject* args);
static PyObject* ACL_valid(PyObject* obj, PyObject* args);
@@ -77,8 +91,10 @@
#endif
#ifdef HAVE_LEVEL2
-static PyTypeObject Entry_Type;
-static PyTypeObject Permset_Type;
+static PyTypeObject Entry_Type
+ CPYCHECKER_TYPE_OBJECT_FOR_TYPEDEF("Entry_Object");
+static PyTypeObject Permset_Type
+ CPYCHECKER_TYPE_OBJECT_FOR_TYPEDEF("Permset_Object");
static PyObject* Permset_new(PyTypeObject* type, PyObject* args,
PyObject *keywds);
#endif
@@ -134,8 +150,8 @@
#ifdef HAVE_LINUX
static char *kwlist[] = { "file", "fd", "text", "acl", "filedef",
"mode", NULL };
- char *format = "|etisO!sH";
- mode_t mode = 0;
+ char *format = "|etisO!si";
+ int mode = -1;
#else
static char *kwlist[] = { "file", "fd", "text", "acl", "filedef", NULL };
char *format = "|etisO!s";
@@ -177,7 +193,7 @@
else if(filedef != NULL)
self->acl = acl_get_file(filedef, ACL_TYPE_DEFAULT);
#ifdef HAVE_LINUX
- else if(PyMapping_HasKeyString(keywds, kwlist[5]))
+ else if(mode != -1)
self->acl = acl_from_mode(mode);
#endif
else
@@ -343,7 +359,8 @@
ret = n == 1 ? Py_True : Py_False;
break;
default:
- ret = Py_NotImplemented;
+ PyErr_SetString(PyExc_TypeError, "ACLs are not orderable");
+ return NULL;
}
Py_INCREF(ret);
return ret;
@@ -371,12 +388,14 @@
}
#endif
+#ifndef IS_PY3K
/* Implementation of the compare for ACLs */
static int ACL_nocmp(PyObject* o1, PyObject* o2) {
PyErr_SetString(PyExc_TypeError, "cannot compare ACLs using cmp()");
return -1;
}
+#endif
/* Custom methods */
static char __applyto_doc__[] =
@@ -680,27 +699,31 @@
};
} tag_qual;
+/* Pre-declaring the function is more friendly to cpychecker, sigh. */
+static int get_tag_qualifier(acl_entry_t entry, tag_qual *tq)
+ CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION;
+
/* Helper function to get the tag and qualifier of an Entry at the
same time. This is "needed" because the acl_get_qualifier function
returns a pointer to different types, based on the tag value, and
thus it's not straightforward to get the right type.
- It sets a Python exception if an error occurs, and return 0 in this
- case. If successful, the tag is set to the tag type, and the
+ It sets a Python exception if an error occurs, and returns -1 in
+ this case. If successful, the tag is set to the tag type, the
qualifier (if any) to either the uid or the gid entry in the
- tag_qual structure.
+ tag_qual structure, and the return value is 0.
*/
-int get_tag_qualifier(acl_entry_t entry, tag_qual *tq) {
+static int get_tag_qualifier(acl_entry_t entry, tag_qual *tq) {
void *p;
if(acl_get_tag_type(entry, &tq->tag) == -1) {
PyErr_SetFromErrno(PyExc_IOError);
- return 0;
+ return -1;
}
if (tq->tag == ACL_USER || tq->tag == ACL_GROUP) {
if((p = acl_get_qualifier(entry)) == NULL) {
PyErr_SetFromErrno(PyExc_IOError);
- return 0;
+ return -1;
}
if (tq->tag == ACL_USER) {
tq->uid = *(uid_t*)p;
@@ -709,7 +732,7 @@
}
acl_free(p);
}
- return 1;
+ return 0;
}
/* Creation of a new Entry instance */
@@ -769,7 +792,7 @@
Entry_Object *self = (Entry_Object*) obj;
tag_qual tq;
- if(!get_tag_qualifier(self->entry, &tq)) {
+ if(get_tag_qualifier(self->entry, &tq) < 0) {
return NULL;
}
@@ -810,8 +833,15 @@
Py_DECREF(format);
return NULL;
}
- MyString_ConcatAndDel(&format, kind);
+#ifdef IS_PY3K
+ PyObject *ret = PyUnicode_Concat(format, kind);
+ Py_DECREF(format);
+ Py_DECREF(kind);
+ return ret;
+#else
+ PyString_ConcatAndDel(&format, kind);
return format;
+#endif
}
/* Sets the tag type of the entry */
@@ -930,7 +960,7 @@
PyErr_SetString(PyExc_AttributeError, "entry attribute");
return NULL;
}
- if(!get_tag_qualifier(self->entry, &tq)) {
+ if(get_tag_qualifier(self->entry, &tq) < 0) {
return NULL;
}
if (tq.tag == ACL_USER) {
@@ -1116,8 +1146,8 @@
int nerr;
if(!PyInt_Check(value)) {
- PyErr_SetString(PyExc_ValueError, "a maximum of one argument must"
- " be passed");
+ PyErr_SetString(PyExc_ValueError, "invalid argument, an integer"
+ " is expected");
return -1;
}
on = PyInt_AsLong(value);
@@ -1230,17 +1260,20 @@
".. note:: only one keyword parameter should be provided\n"
"\n"
":param string file: creates an ACL representing\n"
- " the access ACL of the specified file\n"
+ " the access ACL of the specified file.\n"
":param string filedef: creates an ACL representing\n"
- " the default ACL of the given directory\n"
+ " the default ACL of the given directory.\n"
":param int fd: creates an ACL representing\n"
- " the access ACL of the given file descriptor\n"
+ " the access ACL of the given file descriptor.\n"
":param string text: creates an ACL from a \n"
- " textual description\n"
- ":param ACL acl: creates a copy of an existing ACL instance\n"
+ " textual description; note the ACL must be valid, which\n"
+ " means including a mask for extended ACLs, similar to\n"
+ " ``setfacl --no-mask``\n"
+ ":param ACL acl: creates a copy of an existing ACL instance.\n"
":param int mode: creates an ACL from a numeric mode\n"
- " (e.g. mode=0644) (this is valid only when the C library\n"
- " provides the acl_from_mode call)\n"
+ " (e.g. ``mode=0644``); this is valid only when the C library\n"
+ " provides the ``acl_from_mode call``, and\n"
+ " note that no validation is done on the given value.\n"
"\n"
"If no parameters are passed, an empty ACL will be created; this\n"
"makes sense only when your OS supports ACL modification\n"
@@ -1288,7 +1321,12 @@
0, /* tp_print */
0, /* tp_getattr */
0, /* tp_setattr */
+#ifdef IS_PY3K
+ 0, /* formerly tp_compare, in 3.0 deprecated, in
+ 3.5 tp_as_async */
+#else
ACL_nocmp, /* tp_compare */
+#endif
0, /* tp_repr */
0, /* tp_as_number */
0, /* tp_as_sequence */
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/pylibacl-0.5.3/doc/conf.py
new/pylibacl-0.5.4/doc/conf.py
--- old/pylibacl-0.5.3/doc/conf.py 2015-04-30 22:18:44.000000000 +0200
+++ new/pylibacl-0.5.4/doc/conf.py 2019-11-14 11:58:24.000000000 +0100
@@ -48,9 +48,9 @@
# built documents.
#
# The short X.Y version.
-version = '0.5.3'
+version = '0.5.4'
# The full version, including alpha/beta/rc tags.
-release = '0.5.3'
+release = '0.5.4'
# The language for content autogenerated by Sphinx. Refer to documentation
# for a list of supported languages.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/pylibacl-0.5.3/doc/index.rst
new/pylibacl-0.5.4/doc/index.rst
--- old/pylibacl-0.5.3/doc/index.rst 2012-05-13 06:13:49.000000000 +0200
+++ new/pylibacl-0.5.4/doc/index.rst 2019-11-14 11:47:30.000000000 +0100
@@ -2,7 +2,7 @@
Welcome to pylibacl's documentation!
======================================
-.. include:: ../README
+.. include:: ../README.rst
:start-line: 2
Contents
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/pylibacl-0.5.3/doc/news.rst
new/pylibacl-0.5.4/doc/news.rst
--- old/pylibacl-0.5.3/doc/news.rst 2020-01-09 22:53:28.006795527 +0100
+++ new/pylibacl-0.5.4/doc/news.rst 2019-11-14 11:57:12.000000000 +0100
@@ -1 +1,142 @@
-symbolic link to ../NEWS
+News
+====
+
+Version 0.5.4
+-------------
+
+*released Thu, 14 Nov 2019*
+
+Maintenance release:
+
+- Switch build system to Python 3 by default (can be overridden if
+ needed).
+- Internal improvements for better cpychecker support.
+- Fix compatibility with PyPy.
+- Test improvements (both local and on Travis), testing more variations
+ (debug, PyPy).
+- Improve test coverage, and allow gathering test coverage results.
+- Drop support (well, drop testing) for Python lower than 2.7.
+- Minor documentation improvements (closes #9, #12).
+
+Version 0.5.3
+-------------
+
+*released Thu, 30 Apr 2015*
+
+FreeBSD fixes:
+
+- Enable all FreeBSD versions after 7.x at level 2 (thanks to Garrett
+ Cooper).
+- Make test suite pass under FreeBSD, which has a stricter behaviour
+ with regards to invalid ACLs (which we do exercise in the test suite),
+ thanks again to Garret for the bug reports.
+
+Version 0.5.2
+-------------
+
+*released Sat, 24 May 2014*
+
+No visible changes release: just fix tests when running under pypy.
+
+Version 0.5.1
+-------------
+
+*released Sun, 13 May 2012*
+
+A bug-fix only release. Critical bugs (memory leaks and possible
+segmentation faults) have been fixed thanks to Dave Malcolm and his
+``cpychecker`` tool. Additionally, some compatibility issues with Python
+3.x have been fixed (str() methods returning bytes).
+
+The documentation has been improved and changed from epydoc to sphinx;
+note however that the documentation is still auto-generated from the
+docstrings.
+
+Project reorganisation: the project home page has been moved from
+SourceForge to GitHub.
+
+
+Version 0.5
+-----------
+
+*released Sun, 27 Dec 2009*
+
+Added support for Python 3.x and improved support for Unicode filenames.
+
+Version 0.4
+-----------
+
+*released Sat, 28 Jun 2008*
+
+License
+~~~~~~~
+
+Starting with this version, pylibacl is licensed under LGPL 2.1,
+Febryary 1999 or any later versions (see README.rst and COPYING).
+
+Linux support
+~~~~~~~~~~~~~
+
+A few more Linux-specific functions:
+
+- add the ACL.equiv_mode() method, which will return the equivalent
+ octal mode if this is a basic ACL and raise an IOError exception
+ otherwise
+
+- add the acl_extended(...) function, which will check if an fd or path
+ has an extended ACL
+
+FreeBSD support
+~~~~~~~~~~~~~~~
+
+FreeBSD 7.x will have almost all the acl manipulation functions that
+Linux has, with the exception of __getstate__/__setstate__. As a
+workaround, use the str() and ACL(text=...) methods to pass around
+textual representations.
+
+Interface
+~~~~~~~~~
+
+At module level there are now a few constants exported for easy-checking
+at runtime what features have been compiled in:
+
+- HAS_ACL_FROM_MODE, denoting whether the ACL constructor supports the
+ mode=0xxx parameter
+
+- HAS_ACL_CHECK, denoting whether ACL instances support the check()
+ method
+
+- HAS_ACL_ENTRY, denoting whether ACL manipulation is possible and the
+ Entry and Permset classes are available
+
+- HAS_EXTENEDED_CHECK, denoting whether the acl_extended function is
+ supported
+
+- HAS_EQUIV_MODE, denoting whether ACL instances support the
+ equiv_mode() method
+
+Internals
+~~~~~~~~~
+
+Many functions have now unittests, which is a good thing.
+
+
+Version 0.3
+-----------
+
+*released Sun, 21 Oct 2007*
+
+Linux support
+~~~~~~~~~~~~~
+
+Under Linux, implement more functions from libacl:
+
+- add ACL(mode=...), implementing acl_from_mode
+- add ACL().to_any_text, implementing acl_to_any_text
+- add ACL comparison, using acl_cmp
+- add ACL().check, which is a more descriptive function than validate
+
+.. Local Variables:
+.. mode: rst
+.. fill-column: 72
+.. End:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/pylibacl-0.5.3/pylibacl.egg-info/PKG-INFO
new/pylibacl-0.5.4/pylibacl.egg-info/PKG-INFO
--- old/pylibacl-0.5.3/pylibacl.egg-info/PKG-INFO 2015-04-30
22:22:25.000000000 +0200
+++ new/pylibacl-0.5.4/pylibacl.egg-info/PKG-INFO 2019-11-14
12:03:23.000000000 +0100
@@ -1,6 +1,6 @@
Metadata-Version: 1.0
Name: pylibacl
-Version: 0.5.3
+Version: 0.5.4
Summary: POSIX.1e ACLs for python
Home-page: http://pylibacl.k1024.org/
Author: Iustin Pop
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/pylibacl-0.5.3/pylibacl.egg-info/SOURCES.txt
new/pylibacl-0.5.4/pylibacl.egg-info/SOURCES.txt
--- old/pylibacl-0.5.3/pylibacl.egg-info/SOURCES.txt 2015-04-30
22:22:25.000000000 +0200
+++ new/pylibacl-0.5.4/pylibacl.egg-info/SOURCES.txt 2019-11-14
12:03:23.000000000 +0100
@@ -2,7 +2,7 @@
MANIFEST.in
Makefile
NEWS
-README
+README.rst
acl.c
setup.cfg
setup.py
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/pylibacl-0.5.3/setup.cfg new/pylibacl-0.5.4/setup.cfg
--- old/pylibacl-0.5.3/setup.cfg 2015-04-30 22:22:25.000000000 +0200
+++ new/pylibacl-0.5.4/setup.cfg 2019-11-14 12:03:24.000000000 +0100
@@ -5,5 +5,4 @@
[egg_info]
tag_build =
tag_date = 0
-tag_svn_revision = 0
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/pylibacl-0.5.3/setup.py new/pylibacl-0.5.4/setup.py
--- old/pylibacl-0.5.3/setup.py 2015-04-30 22:18:52.000000000 +0200
+++ new/pylibacl-0.5.4/setup.py 2019-11-14 11:58:31.000000000 +0100
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python3
import os
from setuptools import setup, Extension
@@ -30,7 +30,7 @@
implements POSIX ACLs manipulation. It is a wrapper on top
of the systems's acl C library - see acl(5)."""
-version = "0.5.3"
+version = "0.5.4"
setup(name="pylibacl",
version=version,
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/pylibacl-0.5.3/test/test_acls.py
new/pylibacl-0.5.4/test/test_acls.py
--- old/pylibacl-0.5.3/test/test_acls.py 2015-04-30 22:14:44.000000000
+0200
+++ new/pylibacl-0.5.4/test/test_acls.py 2019-03-03 12:47:04.000000000
+0100
@@ -28,10 +28,16 @@
import platform
import re
import errno
+import operator
import posix1e
from posix1e import *
+try:
+ import __pypy__
+except ImportError:
+ __pypy__ = None
+
TEST_DIR = os.environ.get("TEST_DIR", ".")
BASIC_ACL_TEXT = "u::rw,g::r,o::-"
@@ -42,22 +48,16 @@
M0644 = 420 # octal 0644
M0755 = 493 # octal 755
-# Check if running under Python 3
-IS_PY_3K = sys.hexversion >= 0x03000000
-
-def _skip_test(fn):
- """Wrapper to skip a test"""
- new_fn = lambda x: None
- new_fn.__doc__ = "SKIPPED %s" % fn.__doc__
- return new_fn
+# Permset permission information
+PERMSETS = {
+ posix1e.ACL_READ: ("read", posix1e.Permset.read),
+ posix1e.ACL_WRITE: ("write", posix1e.Permset.write),
+ posix1e.ACL_EXECUTE: ("execute", posix1e.Permset.execute),
+ }
-def has_ext(extension):
- """Decorator to skip tests based on platform support"""
- if not extension:
- return _skip_test
- else:
- return lambda x: x
+# Check if running under Python 3
+IS_PY_3K = sys.hexversion >= 0x03000000
def ignore_ioerror(errnum, fn, *args, **kwargs):
"""Call a function while ignoring some IOErrors.
@@ -74,6 +74,14 @@
return
raise
+def encode(s):
+ """Encode a string if needed (under Python 3)"""
+ if IS_PY_3K:
+ return s.encode()
+ else:
+ return s
+
+
class aclTest:
"""Support functions ACLs"""
@@ -145,17 +153,38 @@
self.assertTrue(acl1.valid(),
"ACL based on standard description should be valid")
+ def testFromACL(self):
+ """Test creating an ACL from an existing ACL"""
+ acl1 = posix1e.ACL()
+ acl2 = posix1e.ACL(acl=acl1)
+
+ def testInvalidCreationParams(self):
+ """Test that creating an ACL from multiple objects fails"""
+ fd, _ = self._getfile()
+ self.assertRaises(ValueError, posix1e.ACL, text=BASIC_ACL_TEXT, fd=fd)
+
+ def testInvalidValueCreation(self):
+ """Test that creating an ACL from wrong specification fails"""
+ self.assertRaises(EnvironmentError, posix1e.ACL, text="foobar")
+ self.assertRaises(TypeError, posix1e.ACL, foo="bar")
+
+ def testDoubleInit(self):
+ acl1 = posix1e.ACL(text=BASIC_ACL_TEXT)
+ self.assertTrue(acl1.valid())
+ acl1.__init__(text=BASIC_ACL_TEXT)
+ self.assertTrue(acl1.valid())
+
class AclExtensions(aclTest, unittest.TestCase):
"""ACL extensions checks"""
- @has_ext(HAS_ACL_FROM_MODE)
+ @unittest.skipUnless(HAS_ACL_FROM_MODE, "Missing HAS_ACL_FROM_MODE")
def testFromMode(self):
"""Test loading ACLs from an octal mode"""
acl1 = posix1e.ACL(mode=M0644)
self.assertTrue(acl1.valid(),
"ACL created via octal mode shoule be valid")
- @has_ext(HAS_ACL_CHECK)
+ @unittest.skipUnless(HAS_ACL_CHECK, "ACL check not supported")
def testAclCheck(self):
"""Test the acl_check method"""
acl1 = posix1e.ACL(text=BASIC_ACL_TEXT)
@@ -163,7 +192,7 @@
acl2 = posix1e.ACL()
self.assertTrue(acl2.check(), "Empty ACL should not be valid")
- @has_ext(HAS_EXTENDED_CHECK)
+ @unittest.skipUnless(HAS_EXTENDED_CHECK, "Extended ACL check not
supported")
def testExtended(self):
"""Test the acl_extended function"""
fd, fname = self._getfile()
@@ -180,7 +209,12 @@
self.assertTrue(has_extended(item),
"An extended ACL should be reported as such")
- @has_ext(HAS_EQUIV_MODE)
+ @unittest.skipUnless(HAS_EXTENDED_CHECK, "Extended ACL check not
supported")
+ def testExtendedArgHandling(self):
+ self.assertRaises(TypeError, has_extended)
+ self.assertRaises(TypeError, has_extended, object())
+
+ @unittest.skipUnless(HAS_EQUIV_MODE, "equiv_mode not supported")
def testEquivMode(self):
"""Test the equiv_mode function"""
if HAS_ACL_FROM_MODE:
@@ -192,6 +226,51 @@
acl = posix1e.ACL(text="u::rx,g::-,o::-")
self.assertEqual(acl.equiv_mode(), M0500)
+ @unittest.skipUnless(HAS_ACL_CHECK, "ACL check not supported")
+ def testToAnyText(self):
+ acl = posix1e.ACL(text=BASIC_ACL_TEXT)
+ self.assertIn(encode("u::"),
+ acl.to_any_text(options=posix1e.TEXT_ABBREVIATE))
+ self.assertIn(encode("user::"), acl.to_any_text())
+
+ @unittest.skipUnless(HAS_ACL_CHECK, "ACL check not supported")
+ def testToAnyTextWrongArgs(self):
+ acl = posix1e.ACL(text=BASIC_ACL_TEXT)
+ self.assertRaises(TypeError, acl.to_any_text, foo="bar")
+
+
+ @unittest.skipUnless(HAS_ACL_CHECK, "ACL check not supported")
+ def testRichCompare(self):
+ acl1 = posix1e.ACL(text="u::rw,g::r,o::r")
+ acl2 = posix1e.ACL(acl=acl1)
+ acl3 = posix1e.ACL(text="u::rw,g::rw,o::r")
+ self.assertEqual(acl1, acl2)
+ self.assertNotEqual(acl1, acl3)
+ self.assertRaises(TypeError, operator.lt, acl1, acl2)
+ self.assertRaises(TypeError, operator.ge, acl1, acl3)
+ self.assertTrue(acl1 != True)
+ self.assertFalse(acl1 == 1)
+ self.assertRaises(TypeError, operator.gt, acl1, True)
+
+ @unittest.skipUnless(hasattr(posix1e.ACL, "__cmp__"), "__cmp__ is missing")
+ @unittest.skipUnless(__pypy__ is None, "Disabled under pypy")
+ def testCmp(self):
+ acl1 = posix1e.ACL()
+ self.assertRaises(TypeError, acl1.__cmp__, acl1)
+
+ def testApplyToWithWrongObject(self):
+ acl1 = posix1e.ACL(text=BASIC_ACL_TEXT)
+ self.assertTrue(acl1.valid())
+ self.assertRaises(TypeError, acl1.applyto, object())
+ self.assertRaises(TypeError, acl1.applyto, object(), object())
+
+ @unittest.skipUnless(HAS_ACL_ENTRY, "ACL entries not supported")
+ def testAclIterator(self):
+ acl = posix1e.ACL(text=BASIC_ACL_TEXT)
+ #self.assertEqual(len(acl), 3)
+ for entry in acl:
+ self.assertIs(entry.parent, acl)
+
class WriteTests(aclTest, unittest.TestCase):
"""Write tests"""
@@ -201,6 +280,10 @@
dname = self._getdir()
posix1e.delete_default(dname)
+ @unittest.skipUnless(__pypy__ is None, "Disabled under pypy")
+ def testDeleteDefaultWrongArg(self):
+ self.assertRaises(TypeError, posix1e.delete_default, object())
+
def testReapply(self):
"""Test re-applying an ACL"""
fd, fname = self._getfile()
@@ -212,6 +295,7 @@
acl2.applyto(dname)
[email protected](HAS_ACL_ENTRY, "ACL entries not supported")
class ModificationTests(aclTest, unittest.TestCase):
"""ACL modification tests"""
@@ -233,7 +317,6 @@
str_acl = str(acl)
self.checkRef(str_acl)
- @has_ext(HAS_ACL_ENTRY)
def testAppend(self):
"""Test append a new Entry to the ACL"""
acl = posix1e.ACL()
@@ -242,8 +325,27 @@
ignore_ioerror(errno.EINVAL, acl.calc_mask)
str_format = str(e)
self.checkRef(str_format)
+ e2 = acl.append(e)
+ ignore_ioerror(errno.EINVAL, acl.calc_mask)
+ self.assertFalse(acl.valid())
+
+ def testWrongAppend(self):
+ """Test append a new Entry to the ACL based on wrong object type"""
+ acl = posix1e.ACL()
+ self.assertRaises(TypeError, acl.append, object())
+
+ def testEntryCreation(self):
+ acl = posix1e.ACL()
+ e = posix1e.Entry(acl)
+ ignore_ioerror(errno.EINVAL, acl.calc_mask)
+ str_format = str(e)
+ self.checkRef(str_format)
+
+ def testEntryFailedCreation(self):
+ # Checks for partial initialisation and deletion on error
+ # path.
+ self.assertRaises(TypeError, posix1e.Entry, object())
- @has_ext(HAS_ACL_ENTRY)
def testDelete(self):
"""Test delete Entry from the ACL"""
acl = posix1e.ACL()
@@ -253,7 +355,36 @@
acl.delete_entry(e)
ignore_ioerror(errno.EINVAL, acl.calc_mask)
- @has_ext(HAS_ACL_ENTRY)
+ def testDoubleDelete(self):
+ """Test delete Entry from the ACL"""
+ # This is not entirely valid/correct, since the entry object
+ # itself is invalid after the first deletion, so we're
+ # actually testing deleting an invalid object, not a
+ # non-existing entry...
+ acl = posix1e.ACL()
+ e = acl.append()
+ e.tag_type = posix1e.ACL_OTHER
+ ignore_ioerror(errno.EINVAL, acl.calc_mask)
+ acl.delete_entry(e)
+ ignore_ioerror(errno.EINVAL, acl.calc_mask)
+ self.assertRaises(EnvironmentError, acl.delete_entry, e)
+
+ # This currently fails as this deletion seems to be accepted :/
+ @unittest.skip("Entry deletion is unreliable")
+ def testDeleteInvalidEntry(self):
+ """Test delete foreign Entry from the ACL"""
+ acl1 = posix1e.ACL()
+ acl2 = posix1e.ACL()
+ e = acl1.append()
+ e.tag_type = posix1e.ACL_OTHER
+ ignore_ioerror(errno.EINVAL, acl1.calc_mask)
+ self.assertRaises(EnvironmentError, acl2.delete_entry, e)
+
+ def testDeleteInvalidObject(self):
+ """Test delete a non-Entry from the ACL"""
+ acl = posix1e.ACL()
+ self.assertRaises(TypeError, acl.delete_entry, object())
+
def testDoubleEntries(self):
"""Test double entries"""
acl = posix1e.ACL(text=BASIC_ACL_TEXT)
@@ -268,7 +399,6 @@
" should not be valid")
acl.delete_entry(e)
- @has_ext(HAS_ACL_ENTRY)
def testMultipleGoodEntries(self):
"""Test multiple valid entries"""
acl = posix1e.ACL(text=BASIC_ACL_TEXT)
@@ -285,7 +415,6 @@
"ACL should be able to hold multiple"
" user/group entries")
- @has_ext(HAS_ACL_ENTRY)
def testMultipleBadEntries(self):
"""Test multiple invalid entries"""
for tag_type in (posix1e.ACL_USER,
@@ -312,7 +441,64 @@
# entry, even though it still exists.
ignore_ioerror(errno.EINVAL, acl.delete_entry, e2)
- @has_ext(HAS_ACL_ENTRY)
+ def testCopy(self):
+ acl = ACL()
+ e1 = acl.append()
+ e1.tag_type = ACL_USER
+ p1 = e1.permset
+ p1.clear()
+ p1.read = True
+ p1.write = True
+ e2 = acl.append()
+ e2.tag_type = ACL_GROUP
+ p2 = e2.permset
+ p2.clear()
+ p2.read = True
+ self.assertFalse(p2.write)
+ e2.copy(e1)
+ self.assertTrue(p2.write)
+ self.assertEqual(e1.tag_type, e2.tag_type)
+
+ def testCopyWrongArg(self):
+ acl = ACL()
+ e = acl.append()
+ self.assertRaises(TypeError, e.copy, object())
+
+ def testSetPermset(self):
+ acl = ACL()
+ e1 = acl.append()
+ e1.tag_type = ACL_USER
+ p1 = e1.permset
+ p1.clear()
+ p1.read = True
+ p1.write = True
+ e2 = acl.append()
+ e2.tag_type = ACL_GROUP
+ p2 = e2.permset
+ p2.clear()
+ p2.read = True
+ self.assertFalse(p2.write)
+ e2.permset = p1
+ self.assertTrue(e2.permset.write)
+ self.assertEqual(e2.tag_type, ACL_GROUP)
+
+ def testSetPermsetWrongArg(self):
+ acl = ACL()
+ e = acl.append()
+ def setter(v):
+ e.permset = v
+ self.assertRaises(TypeError, setter, object())
+
+ def testPermsetCreation(self):
+ acl = ACL()
+ e = acl.append()
+ p1 = e.permset
+ p2 = Permset(e)
+ #self.assertEqual(p1, p2)
+
+ def testPermsetCreationWrongArg(self):
+ self.assertRaises(TypeError, Permset, object())
+
def testPermset(self):
"""Test permissions"""
acl = posix1e.ACL()
@@ -321,27 +507,65 @@
ps.clear()
str_ps = str(ps)
self.checkRef(str_ps)
- pmap = {
- posix1e.ACL_READ: "read",
- posix1e.ACL_WRITE: "write",
- posix1e.ACL_EXECUTE: "execute",
- }
- for perm in pmap:
+ for perm in PERMSETS:
str_ps = str(ps)
+ txt = PERMSETS[perm][0]
self.checkRef(str_ps)
self.assertFalse(ps.test(perm), "Empty permission set should not"
- " have permission '%s'" % pmap[perm])
+ " have permission '%s'" % txt)
ps.add(perm)
self.assertTrue(ps.test(perm), "Permission '%s' should exist"
- " after addition" % pmap[perm])
+ " after addition" % txt)
str_ps = str(ps)
self.checkRef(str_ps)
ps.delete(perm)
self.assertFalse(ps.test(perm), "Permission '%s' should not exist"
- " after deletion" % pmap[perm])
+ " after deletion" % txt)
+ def testPermsetViaAccessors(self):
+ """Test permissions"""
+ acl = posix1e.ACL()
+ e = acl.append()
+ ps = e.permset
+ ps.clear()
+ str_ps = str(ps)
+ self.checkRef(str_ps)
+ def getter(perm):
+ return PERMSETS[perm][1].__get__(ps)
+ def setter(parm, value):
+ return PERMSETS[perm][1].__set__(ps, value)
+ for perm in PERMSETS:
+ str_ps = str(ps)
+ self.checkRef(str_ps)
+ txt = PERMSETS[perm][0]
+ self.assertFalse(getter(perm), "Empty permission set should not"
+ " have permission '%s'" % txt)
+ setter(perm, True)
+ self.assertTrue(ps.test(perm), "Permission '%s' should exist"
+ " after addition" % txt)
+ self.assertTrue(getter(perm), "Permission '%s' should exist"
+ " after addition" % txt)
+ str_ps = str(ps)
+ self.checkRef(str_ps)
+ setter(perm, False)
+ self.assertFalse(ps.test(perm), "Permission '%s' should not exist"
+ " after deletion" % txt)
+ self.assertFalse(getter(perm), "Permission '%s' should not exist"
+ " after deletion" % txt)
+
+ def testPermsetInvalidType(self):
+ acl = posix1e.ACL()
+ e = acl.append()
+ ps = e.permset
+ ps.clear()
+ def setter():
+ ps.write = object()
+ self.assertRaises(TypeError, ps.add, "foobar")
+ self.assertRaises(TypeError, ps.delete, "foobar")
+ self.assertRaises(TypeError, ps.test, "foobar")
+ self.assertRaises(ValueError, setter)
- @has_ext(HAS_ACL_ENTRY and IS_PY_3K)
+ @unittest.skipUnless(IS_PY_3K, "Only supported under Python 3")
def testQualifierValues(self):
"""Tests qualifier correct store/retrieval"""
acl = posix1e.ACL()
@@ -368,7 +592,7 @@
fn(str(e), regex)
qualifier *= 2
- @has_ext(HAS_ACL_ENTRY and IS_PY_3K)
+ @unittest.skipUnless(IS_PY_3K, "Only supported under Python 3")
def testQualifierOverflow(self):
"""Tests qualifier overflow handling"""
acl = posix1e.ACL()
@@ -379,7 +603,7 @@
with self.assertRaises(OverflowError):
e.qualifier = qualifier
- @has_ext(HAS_ACL_ENTRY and IS_PY_3K)
+ @unittest.skipUnless(IS_PY_3K, "Only supported under Python 3")
def testNegativeQualifier(self):
"""Tests negative qualifier handling"""
# Note: this presumes that uid_t/gid_t in C are unsigned...
@@ -391,6 +615,61 @@
with self.assertRaises(OverflowError):
e.qualifier = qualifier
+ def testInvalidQualifier(self):
+ """Tests invalid qualifier handling"""
+ acl = posix1e.ACL()
+ e = acl.append()
+ def set_qual(x):
+ e.qualifier = x
+ def del_qual():
+ del e.qualifier
+ self.assertRaises(TypeError, set_qual, object())
+ self.assertRaises((TypeError, AttributeError), del_qual)
+
+ def testQualifierOnWrongTag(self):
+ """Tests qualifier setting on wrong tag"""
+ acl = posix1e.ACL()
+ e = acl.append()
+ e.tag_type = posix1e.ACL_OTHER
+ def set_qual(x):
+ e.qualifier = x
+ def get_qual():
+ return e.qualifier
+ self.assertRaises(TypeError, set_qual, 1)
+ self.assertRaises(TypeError, get_qual)
+
+
+ def testTagTypes(self):
+ """Tests tag type correct set/get"""
+ acl = posix1e.ACL()
+ e = acl.append()
+ for tag in [posix1e.ACL_USER, posix1e.ACL_GROUP, posix1e.ACL_USER_OBJ,
+ posix1e.ACL_GROUP_OBJ, posix1e.ACL_MASK,
+ posix1e.ACL_OTHER]:
+ e.tag_type = tag
+ self.assertEqual(e.tag_type, tag)
+ # check we can show all tag types without breaking
+ self.assertTrue(str(e))
+
+ def testInvalidTags(self):
+ """Tests tag type incorrect set/get"""
+ acl = posix1e.ACL()
+ e = acl.append()
+ def set_tag(x):
+ e.tag_type = x
+ self.assertRaises(TypeError, set_tag, object())
+ def delete_tag():
+ del e.tag_type
+ # For some reason, PyPy raises AttributeError. Strange...
+ self.assertRaises((TypeError, AttributeError), delete_tag)
+
+ e.tag_type = posix1e.ACL_USER_OBJ
+ tag = max([posix1e.ACL_USER, posix1e.ACL_GROUP, posix1e.ACL_USER_OBJ,
+ posix1e.ACL_GROUP_OBJ, posix1e.ACL_MASK,
+ posix1e.ACL_OTHER]) + 1
+ self.assertRaises(EnvironmentError, set_tag, tag)
+ # Check tag is still valid.
+ self.assertEqual(e.tag_type, posix1e.ACL_USER_OBJ)
if __name__ == "__main__":
unittest.main()