From ed828cd66920ecb1d2d28ce5e6a710940e987a1f Mon Sep 17 00:00:00 2001 From: Iustin Pop Date: Fri, 29 Nov 2019 14:35:11 +0100 Subject: [PATCH] Restore setstate/getstate support Sigh, another brown-bag issue. One small typo in a place, plus a missing macro, and this went unseen for ages. Also add a basic test for it. Probably should add Pickle as well. --- NEWS | 4 ++++ acl.c | 14 +++++++++++++- setup.py | 1 + tests/test_acls.py | 13 +++++++++++++ 4 files changed, 31 insertions(+), 1 deletion(-) diff --git a/NEWS b/NEWS index 005a68d..0105cdc 100644 --- a/NEWS +++ b/NEWS @@ -23,6 +23,10 @@ Important API changes/bug fixes: paths; this also (implicitly) fixes memory leaks on re-initialisation (calling `__init__(…)` on an existing object) and segfaults (!) on non-initialised object attribute access. +- Restore `__setstate__`/`__getstate__` support on Linux; this was + inadvertently removed due a typo(!) when adding support for it in + FreeBSD. Pickle should work again for ACL instances, although not sure + how stable this serialisation format actually is. Minor improvements: diff --git a/acl.c b/acl.c index 16004b5..3d0c0f6 100644 --- a/acl.c +++ b/acl.c @@ -1256,7 +1256,7 @@ static PyMethodDef ACL_methods[] = { {"check", ACL_check, METH_NOARGS, __check_doc__}, {"equiv_mode", ACL_equiv_mode, METH_NOARGS, __equiv_mode_doc__}, #endif -#ifdef HAVE_ACL_COPYEXT +#ifdef HAVE_ACL_COPY_EXT {"__getstate__", ACL_get_state, METH_NOARGS, "Dumps the ACL to an external format."}, {"__setstate__", ACL_set_state, METH_VARARGS, @@ -1653,6 +1653,8 @@ static char __posix1e_doc__[] = " - :py:data:`HAS_EXTENDED_CHECK` for the module-level\n" " :py:func:`has_extended` function\n" " - :py:data:`HAS_EQUIV_MODE` for the :py:func:`ACL.equiv_mode` method\n" + " - :py:data:`HAS_COPY_EXT` for the :py:func:`ACL.__getstate__` and\n" + " :py:func:`ACL.__setstate__` functions (pickle protocol)\n" "\n" "Example:\n" "\n" @@ -1722,6 +1724,9 @@ static char __posix1e_doc__[] = ".. py:data:: HAS_EQUIV_MODE\n\n" " denotes support for the equiv_mode function\n" "\n" + ".. py:data:: HAS_COPY_EXT\n\n" + " denotes support for __getstate__()/__setstate__() on an ACL\n" + "\n" ; static struct PyModuleDef posix1emodule = { @@ -1824,5 +1829,12 @@ PyInit_posix1e(void) PyModule_AddIntConstant(m, "HAS_EXTENDED_CHECK", LINUX_EXT_VAL); PyModule_AddIntConstant(m, "HAS_EQUIV_MODE", LINUX_EXT_VAL); + PyModule_AddIntConstant(m, "HAS_COPY_EXT", +#ifdef HAVE_ACL_COPY_EXT + 1 +#else + 0 +#endif + ); return m; } diff --git a/setup.py b/setup.py index 5b258e8..8c3aa63 100755 --- a/setup.py +++ b/setup.py @@ -10,6 +10,7 @@ libs = [] if u_sysname == "Linux": macros.append(("HAVE_LINUX", None)) macros.append(("HAVE_LEVEL2", None)) + macros.append(("HAVE_ACL_COPY_EXT", None)) libs.append("acl") elif u_sysname == "GNU/kFreeBSD": macros.append(("HAVE_LINUX", None)) diff --git a/tests/test_acls.py b/tests/test_acls.py index b827b8d..c3e693f 100644 --- a/tests/test_acls.py +++ b/tests/test_acls.py @@ -169,6 +169,7 @@ require_acl_check = pytest.mark.skipif("not HAS_ACL_CHECK") require_acl_entry = pytest.mark.skipif("not HAS_ACL_ENTRY") require_extended_check = pytest.mark.skipif("not HAS_EXTENDED_CHECK") require_equiv_mode = pytest.mark.skipif("not HAS_EQUIV_MODE") +require_copy_ext = pytest.mark.skipif("not HAS_COPY_EXT") # Note: ACLs are valid only for files/directories, not symbolic links # themselves, so we only create valid symlinks. @@ -435,6 +436,18 @@ class TestAclExtensions: for entry in acl: assert entry.parent is acl + @require_copy_ext + def test_acl_copy_ext(self): + a = posix1e.ACL(text=BASIC_ACL_TEXT) + b = posix1e.ACL() + c = posix1e.ACL(acl=b) + assert a != b + assert b == c + state = a.__getstate__() + b.__setstate__(state) + assert a == b + assert b != c + class TestWrite: """Write tests""" -- 2.39.5