summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.travis.yml8
-rwxr-xr-x.travis/install.sh10
-rwxr-xr-x.travis/run.sh3
-rw-r--r--CHANGES.txt5
-rw-r--r--README.rst (renamed from README.txt)6
-rwxr-xr-xscripts/artifacts.py31
-rw-r--r--xattr/__init__.py5
-rw-r--r--xattr/compat.py11
-rw-r--r--xattr/pyxattr_compat.py7
-rw-r--r--xattr/tests/test_xattr.py25
-rwxr-xr-xxattr/tool.py15
11 files changed, 97 insertions, 29 deletions
diff --git a/.travis.yml b/.travis.yml
index 8683af6..72da8c7 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -9,16 +9,16 @@ matrix:
language: objective-c
- os: osx
language: objective-c
- env: PYENV_VERSION=pypy3-2.4.0
+ env: PYENV_VERSION=pypy3.3-5.2-alpha1
- os: osx
language: objective-c
- env: PYENV_VERSION=pypy-4.0.1
+ env: PYENV_VERSION=pypy-5.4.1
- os: osx
language: objective-c
- env: PYENV_VERSION=2.7.11
+ env: PYENV_VERSION=2.7.12
- os: osx
language: objective-c
- env: PYENV_VERSION=3.5.1
+ env: PYENV_VERSION=3.5.2
install:
- "./.travis/install.sh"
script:
diff --git a/.travis/install.sh b/.travis/install.sh
index 40e88df..a90c451 100755
--- a/.travis/install.sh
+++ b/.travis/install.sh
@@ -4,11 +4,15 @@ set -e
set -x
if [[ -n "$PYENV_VERSION" ]]; then
- if [ ! -e "$HOME/.pyenv" ]; then
- git clone https://github.com/yyuu/pyenv.git ~/.pyenv
+ if [ ! -e "$HOME/.pyenv-xattr/.git" ]; then
+ if [ -e "$HOME/.pyenv-xattr" ]; then
+ rm -rf ~/.pyenv-xattr
+ fi
+ git clone https://github.com/yyuu/pyenv.git ~/.pyenv-xattr
fi
- PYENV_ROOT="$HOME/.pyenv"
+ PYENV_ROOT="$HOME/.pyenv-xattr"
PATH="$PYENV_ROOT/bin:$PATH"
+ hash -r
eval "$(pyenv init -)"
hash -r
pyenv install --list
diff --git a/.travis/run.sh b/.travis/run.sh
index a18c09c..3c1a219 100755
--- a/.travis/run.sh
+++ b/.travis/run.sh
@@ -4,8 +4,9 @@ set -e
set -x
if [[ -n "$PYENV_VERSION" ]]; then
- PYENV_ROOT="$HOME/.pyenv"
+ PYENV_ROOT="$HOME/.pyenv-xattr"
PATH="$PYENV_ROOT/bin:$PATH"
+ hash -r
eval "$(pyenv init -)"
fi
diff --git a/CHANGES.txt b/CHANGES.txt
index 07ca7d0..1734b00 100644
--- a/CHANGES.txt
+++ b/CHANGES.txt
@@ -1,3 +1,8 @@
+Version 0.9.0 released XXXX-XX-XX
+
+* Allow (Python 2) long for fd
+ https://github.com/xattr/xattr/pull/51
+
Version 0.8.0 released 2016-02-28
* Use os.fsencode where available to better handle filesystem quirks related
diff --git a/README.txt b/README.rst
index c1962ee..c2c9214 100644
--- a/README.txt
+++ b/README.rst
@@ -1,3 +1,9 @@
+xattr
+-----
+
+.. image:: https://travis-ci.org/xattr/xattr.svg?branch=master
+ :target: https://travis-ci.org/xattr/xattr
+
xattr is a Python wrapper for extended filesystem attributes.
Extended attributes extend the basic attributes of files and directories
diff --git a/scripts/artifacts.py b/scripts/artifacts.py
index 089bf9b..8be54b9 100755
--- a/scripts/artifacts.py
+++ b/scripts/artifacts.py
@@ -40,10 +40,39 @@ def download_github_artifacts():
for asset in release['assets']:
download_file(asset['browser_download_url'], 'dist/{name}'.format(**asset))
+def get_version():
+ return subprocess.check_output([sys.executable, 'setup.py', '--version']).strip()
+
+def artifact_matcher(version):
+ return re.compile('^simplejson-{}.*\\.(exe|whl)$'.format(re.escape(version)))
+
+def sign_artifacts(version):
+ artifacts = set(os.listdir('dist'))
+ pattern = artifact_matcher(version)
+ for fn in artifacts:
+ if pattern.search(fn) and '{}.asc'.format(fn) not in artifacts:
+ sign_artifact(os.path.join('dist', fn))
+
+def sign_artifact(path):
+ print(' '.join(['gpg', '--detach-sign', '-a', path]))
+ subprocess.check_call(['gpg', '--detach-sign', '-a', path])
+
+def upload_artifacts(version):
+ artifacts = set(os.listdir('dist'))
+ pattern = artifact_matcher(version)
+ args = ['twine', 'upload']
+ for fn in artifacts:
+ if pattern.search(fn):
+ filename = os.path.join('dist', fn)
+ args.extend([filename, filename + '.asc'])
+ subprocess.check_call(args)
def main():
- #download_appveyor_artifacts()
+ # download_appveyor_artifacts()
download_github_artifacts()
+ version = get_version()
+ sign_artifacts(version)
+ upload_artifacts(version)
if __name__ == '__main__':
diff --git a/xattr/__init__.py b/xattr/__init__.py
index dad8e5a..57a771e 100644
--- a/xattr/__init__.py
+++ b/xattr/__init__.py
@@ -9,6 +9,7 @@ that exposes these extended attributes.
__version__ = '0.8.0'
+from .compat import integer_types
from .lib import (XATTR_NOFOLLOW, XATTR_CREATE, XATTR_REPLACE,
XATTR_NOSECURITY, XATTR_MAXNAMELEN, XATTR_FINDERINFO_NAME,
XATTR_RESOURCEFORK_NAME, _getxattr, _fgetxattr, _setxattr, _fsetxattr,
@@ -46,14 +47,14 @@ class xattr(object):
self.value = obj
def __repr__(self):
- if isinstance(self.value, int):
+ if isinstance(self.value, integer_types):
flavor = "fd"
else:
flavor = "file"
return "<%s %s=%r>" % (type(self).__name__, flavor, self.value)
def _call(self, name_func, fd_func, *args):
- if isinstance(self.value, int):
+ if isinstance(self.value, integer_types):
return fd_func(self.value, *args)
else:
return name_func(self.value, *args)
diff --git a/xattr/compat.py b/xattr/compat.py
new file mode 100644
index 0000000..b3094e3
--- /dev/null
+++ b/xattr/compat.py
@@ -0,0 +1,11 @@
+"""Python 3 compatibility shims
+"""
+import sys
+if sys.version_info[0] < 3:
+ integer_types = (int, long)
+ text_type = unicode
+ binary_type = str
+else:
+ integer_types = (int,)
+ text_type = str
+ binary_type = bytes
diff --git a/xattr/pyxattr_compat.py b/xattr/pyxattr_compat.py
index 0ef913b..3d594de 100644
--- a/xattr/pyxattr_compat.py
+++ b/xattr/pyxattr_compat.py
@@ -8,6 +8,7 @@ This module provides compatibility for the pyxattr API.
import sys
+from .compat import (binary_type, integer_types, text_type)
from .lib import (XATTR_NOFOLLOW, XATTR_CREATE, XATTR_REPLACE,
XATTR_NOSECURITY, XATTR_MAXNAMELEN, XATTR_FINDERINFO_NAME,
XATTR_RESOURCEFORK_NAME, _getxattr, _fgetxattr, _setxattr, _fsetxattr,
@@ -29,13 +30,13 @@ _NO_NS = object()
_fsencoding = sys.getfilesystemencoding()
def _call(item, name_func, fd_func, *args):
- if isinstance(item, int):
+ if isinstance(item, integer_types):
return fd_func(item, *args)
elif hasattr(item, 'fileno'):
return fd_func(item.fileno(), *args)
- elif isinstance(item, str):
+ elif isinstance(item, binary_type):
return name_func(item, *args)
- elif isinstance(item, unicode):
+ elif isinstance(item, text_type):
item = item.encode(_fsencoding)
return name_func(item, *args)
else:
diff --git a/xattr/tests/test_xattr.py b/xattr/tests/test_xattr.py
index 548f735..c63a240 100644
--- a/xattr/tests/test_xattr.py
+++ b/xattr/tests/test_xattr.py
@@ -8,6 +8,11 @@ import xattr
class BaseTestXattr(object):
+ # TESTDIR for temporary files usually defaults to "/tmp",
+ # which may not have XATTR support (e.g. tmpfs);
+ # manual override here.
+ TESTDIR = None
+
def test_attr(self):
x = xattr.xattr(self.tempfile)
@@ -66,15 +71,17 @@ class BaseTestXattr(object):
self.assertEqual(str(e), msg)
def test_symlink_attrs(self):
- # Solaris doesn't support extended attributes on symlinks
- if sys.platform == 'sunos5':
- return
symlinkPath = self.tempfilename + '.link'
os.symlink(self.tempfilename, symlinkPath)
try:
symlink = xattr.xattr(symlinkPath, options=xattr.XATTR_NOFOLLOW)
realfile = xattr.xattr(self.tempfilename)
- symlink['user.islink'] = b'true'
+ try:
+ symlink['user.islink'] = b'true'
+ except IOError:
+ # Solaris, Linux don't support extended attributes on symlinks
+ raise unittest.SkipTest("XATTRs on symlink not allowed"
+ " on filesystem/platform")
self.assertEqual(dict(realfile), {})
self.assertEqual(symlink['user.islink'], b'true')
finally:
@@ -83,7 +90,7 @@ class BaseTestXattr(object):
class TestFile(TestCase, BaseTestXattr):
def setUp(self):
- self.tempfile = NamedTemporaryFile()
+ self.tempfile = NamedTemporaryFile(dir=self.TESTDIR)
self.tempfilename = self.tempfile.name
def tearDown(self):
@@ -92,7 +99,7 @@ class TestFile(TestCase, BaseTestXattr):
class TestDir(TestCase, BaseTestXattr):
def setUp(self):
- self.tempfile = mkdtemp()
+ self.tempfile = mkdtemp(dir=self.TESTDIR)
self.tempfilename = self.tempfile
def tearDown(self):
@@ -107,7 +114,9 @@ except AttributeError:
else:
class TestFileWithSurrogates(TestFile):
def setUp(self):
- if sys.platform != 'linux':
+ if sys.platform not in ('linux', 'linux2'):
raise unittest.SkipTest('Files with invalid encoded names are only supported under linux')
- self.tempfile = NamedTemporaryFile(prefix=b'invalid-\xe9'.decode('utf8','surrogateescape'))
+ if sys.version_info[0] < 3:
+ raise unittest.SkipTest('Test is only available on Python3') # surrogateescape not avail in py2
+ self.tempfile = NamedTemporaryFile(prefix=b'invalid-\xe9'.decode('utf8','surrogateescape'), dir=self.TESTDIR)
self.tempfilename = self.tempfile.name
diff --git a/xattr/tool.py b/xattr/tool.py
index 573261f..5cdecbd 100755
--- a/xattr/tool.py
+++ b/xattr/tool.py
@@ -3,7 +3,7 @@
##
# Copyright (c) 2007 Apple Inc.
#
-# This is the MIT license. This software may also be distributed under the
+# This is the MIT license. This software may also be distributed under the
# same terms as Python (the PSF license).
#
# Permission is hereby granted, free of charge, to any person obtaining a
@@ -35,6 +35,10 @@ import zlib
import xattr
+class NullsInString(Exception):
+ """Nulls in string."""
+
+
def usage(e=None):
if e:
print(e)
@@ -62,10 +66,6 @@ def usage(e=None):
sys.exit(0)
-class NullsInString(Exception):
- """Nulls in string."""
-
-
_FILTER = ''.join([(len(repr(chr(x))) == 3) and chr(x) or '.' for x in range(256)])
@@ -127,7 +127,7 @@ def main():
if write:
if not args:
usage("No attr_value")
- attr_value = args.pop(0)
+ attr_value = args.pop(0).encode('utf-8')
if len(args) > 1:
multiple_files = True
@@ -185,13 +185,14 @@ def main():
attr_value = decompress(attrs[attr_name])
except zlib.error:
attr_value = attrs[attr_name]
+ attr_value = attr_value.decode('utf-8')
except KeyError:
onError("%sNo such xattr: %s" % (file_prefix, attr_name))
continue
if long_format:
try:
- if attr_value.find('\0') >= 0:
+ if '\0' in attr_value:
raise NullsInString
print("".join((file_prefix, "%s: " % (attr_name,), attr_value)))
except (UnicodeDecodeError, NullsInString):