2013-10-21 05:07 Mike Frysinger napisał(a):
Rather than each module implementing its own shim around the various
methods for accessing extended attributes, start a dedicated module
that exports a consistent API.
---
v2
- passes unittests w/python 2.6 2.7 3.2 3.3
But portage.util._xattr._XattrSystemCommands does not work :) .
import portage.util._xattr
portage.util._xattr._XattrSystemCommands.list(/tmp)
...
See below.
bin/xattr-helper.py | 11 +-
pym/portage/tests/util/test_xattr.py | 178 ++
pym/portage/util/_xattr.py | 205
+++
pym/portage/util/movefile.py | 100 -
4 files changed, 407 insertions(+), 87 deletions(-)
create mode 100644 pym/portage/tests/util/test_xattr.py
create mode 100644 pym/portage/util/_xattr.py
diff --git a/bin/xattr-helper.py b/bin/xattr-helper.py
index 6d99521..69b83f7 100755
--- a/bin/xattr-helper.py
+++ b/bin/xattr-helper.py
@@ -17,16 +17,7 @@ import re
import sys
from portage.util._argparse import ArgumentParser
-
-if hasattr(os, getxattr):
-
- class xattr(object):
- get = os.getxattr
- set = os.setxattr
- list = os.listxattr
-
-else:
- import xattr
+from portage.util._xattr import xattr
_UNQUOTE_RE = re.compile(br'\\[0-7]{3}')
diff --git a/pym/portage/tests/util/test_xattr.py
b/pym/portage/tests/util/test_xattr.py
new file mode 100644
index 000..e1f6ee8
--- /dev/null
+++ b/pym/portage/tests/util/test_xattr.py
@@ -0,0 +1,178 @@
+# Copyright 2010-2013 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+
+Tests for the portage.util._xattr module
+
+from __future__ import print_function
+
+try:
+ # Try python-3.3 module first.
+ from unittest import mock
+except ImportError:
+ try:
+ # Try standalone module.
+ import mock
+ except ImportError:
+ mock = None
+
+import subprocess
+
+from portage.tests import TestCase
+from portage.util._xattr import (xattr as _xattr, _XattrSystemCommands,
+ _XattrStub)
+
+
+orig_popen = subprocess.Popen
+def MockSubprocessPopen(stdin):
+ Helper to mock (closely) a subprocess.Popen call
+
+ The module has minor tweaks in behavior when it comes to encoding and
+ python versions, so use a real subprocess.Popen call to fake out the
+ runtime behavior. This way we don't have to also implement different
+ encodings as that gets ugly real fast.
+
+ proc = orig_popen(['cat'], stdout=subprocess.PIPE,
stdin=subprocess.PIPE)
+ try:
+ proc.stdin.write(bytes(stdin))
+ except TypeError:
+ proc.stdin.write(bytes(stdin, 'ascii'))
It can fail with UnicodeEncodeError.
Use proc.stdin.write(portage._unicode_encode(stdin),
portage._encodings['stdio']) instead of above 4 lines.
+ return proc
+
+
+class SystemCommandsTest(TestCase):
+ Test _XattrSystemCommands
+
+ OUTPUT = '\n'.join([
+ '# file: /bin/ping',
+ 'security.capability=0sAQAAAgAgAAA=',
+ 'user.foo=asdf',
+ '',
+ ])
+
+ def _setUp(self):
+ if mock is None:
+ self.skipTest('need mock for testing')
+
+ return _XattrSystemCommands
+
+ def _testGetBasic(self):
+ Verify the get() behavior
+ xattr = self._setUp()
+ with mock.patch.object(subprocess, 'Popen') as call_mock:
+ # Verify basic behavior, and namespace arg works as
expected.
+ xattr.get('/some/file', 'user.foo')
+ xattr.get('/some/file', 'foo', namespace='user')
+ self.assertEqual(call_mock.call_args_list[0],
call_mock.call_args_list[1])
+
+ # Verify nofollow behavior.
+ call_mock.reset()
+ xattr.get('/some/file', 'user.foo', nofollow=True)
+ self.assertIn('-h', call_mock.call_args[0][0])
+
+ def testGetParsing(self):
+ Verify get() parses output sanely
+ xattr = self._setUp()
+ with mock.patch.object(subprocess, 'Popen') as call_mock:
+ # Verify output parsing.
+ call_mock.return_value = MockSubprocessPopen('\n'.join([
+ '# file: /some/file',
+ 'user.foo=asdf',
+ '',
+ ]))
+ call_mock.reset()
+ self.assertEqual(xattr.get('/some/file', 'user.foo'),
b'asdf')
+
+ def testGetAllBasic(self):
+ Verify the get_all() behavior
+ xattr = self._setUp()
+ with