Hello community, here is the log from the commit of package python-xattr for openSUSE:Factory checked in at 2016-06-07 23:48:53 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/python-xattr (Old) and /work/SRC/openSUSE:Factory/.python-xattr.new (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "python-xattr" Changes: -------- --- /work/SRC/openSUSE:Factory/python-xattr/python-xattr.changes 2015-10-22 12:59:03.000000000 +0200 +++ /work/SRC/openSUSE:Factory/.python-xattr.new/python-xattr.changes 2016-06-07 23:48:54.000000000 +0200 @@ -1,0 +2,9 @@ +Wed Jun 1 13:09:27 UTC 2016 - [email protected] + +- update to 0.8.0: + * Use os.fsencode where available to better handle filesystem quirks related + to surrogates + * Options bugfix and compatibility module for pyxattr API + * Added xattr/tests/*.py to MANIFEST.in + +------------------------------------------------------------------- Old: ---- v0.7.8.tar.gz New: ---- v0.8.0.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ python-xattr.spec ++++++ --- /var/tmp/diff_new_pack.c8afnh/_old 2016-06-07 23:48:55.000000000 +0200 +++ /var/tmp/diff_new_pack.c8afnh/_new 2016-06-07 23:48:55.000000000 +0200 @@ -1,7 +1,7 @@ # # spec file for package python-xattr # -# Copyright (c) 2015 SUSE LINUX GmbH, Nuernberg, Germany. +# Copyright (c) 2016 SUSE LINUX GmbH, Nuernberg, Germany. # # All modifications and additions to the file contributed by third parties # remain the property of their copyright owners, unless otherwise agreed @@ -17,7 +17,7 @@ Name: python-xattr -Version: 0.7.8 +Version: 0.8.0 Release: 0 Summary: Python wrapper for extended filesystem attributes License: MIT @@ -27,7 +27,12 @@ BuildRequires: python-cffi BuildRequires: python-devel BuildRequires: python-setuptools +%if 0%{?suse_version} && 0%{?suse_version} <= 1310 +BuildRequires: update-alternatives +%endif %requires_eq python-cffi +Requires(post): update-alternatives +Requires(postun): update-alternatives BuildRoot: %{_tmppath}/%{name}-%{version}-build Provides: pyxattr = %{version} Obsoletes: pyxattr < %{version} @@ -52,12 +57,30 @@ %install python setup.py install --prefix=%{_prefix} --root=%{buildroot} +mv %{buildroot}%{_bindir}/xattr %{buildroot}%{_bindir}/xattr-%{py_ver} + +%if 0%{?suse_version} && 0%{?suse_version} > 1310 +mkdir -p %{buildroot}%{_sysconfdir}/alternatives +ln -s -f %{_sysconfdir}/alternatives/xattr %{buildroot}%{_bindir}/xattr +%endif + +%post +%{_sbindir}/update-alternatives \ + --install %_bindir/xattr xattr %_bindir/xattr-%{py_ver} 10 + +%preun +%{_sbindir}/update-alternatives \ + --remove xattr %_bindir/xattr %files %defattr(-,root,root) %doc README.txt -%{_bindir}/xattr +%{_bindir}/xattr-%{py_ver} %{python_sitelib}/xattr %{python_sitelib}/xattr-*egg-info +%if 0%{?suse_version} && 0%{?suse_version} > 1310 +%{_bindir}/xattr +%ghost %_sysconfdir/alternatives/xattr +%endif %changelog ++++++ v0.7.8.tar.gz -> v0.8.0.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/xattr-0.7.8/.travis/install.sh new/xattr-0.8.0/.travis/install.sh --- old/xattr-0.7.8/.travis/install.sh 1970-01-01 01:00:00.000000000 +0100 +++ new/xattr-0.8.0/.travis/install.sh 2016-02-28 20:10:07.000000000 +0100 @@ -0,0 +1,17 @@ +#!/bin/bash + +set -e +set -x + +if [[ -n "$PYENV_VERSION" ]]; then + if [ ! -e "$HOME/.pyenv" ]; then + git clone https://github.com/yyuu/pyenv.git ~/.pyenv + fi + PYENV_ROOT="$HOME/.pyenv" + PATH="$PYENV_ROOT/bin:$PATH" + eval "$(pyenv init -)" + hash -r + pyenv install --list + pyenv install -s $PYENV_VERSION + pip install wheel +fi diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/xattr-0.7.8/.travis/run.sh new/xattr-0.8.0/.travis/run.sh --- old/xattr-0.7.8/.travis/run.sh 1970-01-01 01:00:00.000000000 +0100 +++ new/xattr-0.8.0/.travis/run.sh 2016-02-28 20:10:07.000000000 +0100 @@ -0,0 +1,18 @@ +#!/bin/bash + +set -e +set -x + +if [[ -n "$PYENV_VERSION" ]]; then + PYENV_ROOT="$HOME/.pyenv" + PATH="$PYENV_ROOT/bin:$PATH" + eval "$(pyenv init -)" +fi + +python setup.py build_ext -i +python -m compileall -f . +python setup.py test + +if [[ -n "$PYENV_VERSION" && $TRAVIS_OS_NAME == 'osx' ]]; then + python setup.py bdist_wheel +fi diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/xattr-0.7.8/.travis.yml new/xattr-0.8.0/.travis.yml --- old/xattr-0.7.8/.travis.yml 2015-06-25 19:25:42.000000000 +0200 +++ new/xattr-0.8.0/.travis.yml 2016-02-28 20:10:07.000000000 +0100 @@ -1,5 +1,35 @@ -language: objective-c +language: python +cache: + directories: + - "$HOME/.cache/pip" + - "$HOME/.pyenv" +matrix: + include: + - os: osx + language: objective-c + - os: osx + language: objective-c + env: PYENV_VERSION=pypy3-2.4.0 + - os: osx + language: objective-c + env: PYENV_VERSION=pypy-4.0.1 + - os: osx + language: objective-c + env: PYENV_VERSION=2.7.11 + - os: osx + language: objective-c + env: PYENV_VERSION=3.5.1 +install: +- "./.travis/install.sh" script: - - ARCHFLAGS="-Wno-error=unused-command-line-argument-hard-error-in-future" python setup.py build_ext -i - - python -m compileall -f xattr - - python setup.py test +- "./.travis/run.sh" +deploy: + provider: releases + api_key: + secure: Z5m7K1UVq0812nNtR+QAkUE3lxUwhMjM3EDWUOyPmfh0rmOsU2RgQ8oBfT1vatYfY8ExnrG4rRNWmwUqPEIzZmRLmw9zv+ixA3gcVPn6WbbMkwoeIurOPsC9wjgCckDFKYhMda8a92FSL2hVto3JPcRNTZnsKBR35Queray55SM= + file: dist/*.whl + file_glob: true + on: + repo: xattr/xattr + tags: true + skip_cleanup: true diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/xattr-0.7.8/CHANGES.txt new/xattr-0.8.0/CHANGES.txt --- old/xattr-0.7.8/CHANGES.txt 2015-06-25 19:25:42.000000000 +0200 +++ new/xattr-0.8.0/CHANGES.txt 2016-02-28 20:10:07.000000000 +0100 @@ -1,3 +1,16 @@ +Version 0.8.0 released 2016-02-28 + +* Use os.fsencode where available to better handle filesystem quirks related + to surrogates + https://github.com/xattr/xattr/pull/46 +* Options bugfix and compatibility module for pyxattr API + https://github.com/xattr/xattr/pull/38 + +Version 0.7.9 released 2016-02-12 + +* Added xattr/tests/*.py to MANIFEST.in + https://github.com/xattr/xattr/issues/43 + Version 0.7.8 released 2015-06-25 * Added MANIFEST.in to ensure that the .txt files are included diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/xattr-0.7.8/MANIFEST.in new/xattr-0.8.0/MANIFEST.in --- old/xattr-0.7.8/MANIFEST.in 2015-06-25 19:25:42.000000000 +0200 +++ new/xattr-0.8.0/MANIFEST.in 2016-02-28 20:10:07.000000000 +0100 @@ -1,3 +1,4 @@ include *.py include *.txt include MANIFEST.in +include xattr/tests/*.py diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/xattr-0.7.8/scripts/artifacts.py new/xattr-0.8.0/scripts/artifacts.py --- old/xattr-0.7.8/scripts/artifacts.py 1970-01-01 01:00:00.000000000 +0100 +++ new/xattr-0.8.0/scripts/artifacts.py 2016-02-28 20:10:07.000000000 +0100 @@ -0,0 +1,50 @@ +#!/usr/bin/env python + +try: + from urllib.request import urlopen +except ImportError: + from urllib import urlopen + +import io +import json +import subprocess + + +def get_json(url): + return json.loads(urlopen(url).read().decode('utf-8')) + + +def download_file(src_url, dest_path): + print(dest_path) + subprocess.call( + ['curl', '-L', '-#', '-o', dest_path, src_url]) + + +def download_appveyor_artifacts(): + api_url = 'https://ci.appveyor.com/api' + builds = get_json( + '{}/projects/etrepum/xattr'.format(api_url)) + + for job in builds['build']['jobs']: + url = '{api_url}/buildjobs/{jobId}/artifacts'.format( + api_url=api_url, **job) + for artifact in get_json(url): + download_file( + '{url}/{fileName}'.format(url=url, **artifact), + artifact['fileName']) + + +def download_github_artifacts(): + release = get_json( + 'https://api.github.com/repos/xattr/xattr/releases/latest') + for asset in release['assets']: + download_file(asset['browser_download_url'], 'dist/{name}'.format(**asset)) + + +def main(): + #download_appveyor_artifacts() + download_github_artifacts() + + +if __name__ == '__main__': + main() diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/xattr-0.7.8/setup.py new/xattr-0.8.0/setup.py --- old/xattr-0.7.8/setup.py 2015-06-25 19:25:42.000000000 +0200 +++ new/xattr-0.8.0/setup.py 2016-02-28 20:10:07.000000000 +0100 @@ -16,7 +16,7 @@ self.distribution.ext_modules = [ffi.verifier.get_extension()] build.finalize_options(self) -VERSION = '0.7.8' +VERSION = '0.8.0' DESCRIPTION = "Python wrapper for extended filesystem attributes" LONG_DESCRIPTION = """ Extended attributes extend the basic attributes of files and directories diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/xattr-0.7.8/xattr/__init__.py new/xattr-0.8.0/xattr/__init__.py --- old/xattr-0.7.8/xattr/__init__.py 2015-06-25 19:25:42.000000000 +0200 +++ new/xattr-0.8.0/xattr/__init__.py 2016-02-28 20:10:07.000000000 +0100 @@ -7,7 +7,7 @@ that exposes these extended attributes. """ -__version__ = '0.7.8' +__version__ = '0.8.0' from .lib import (XATTR_NOFOLLOW, XATTR_CREATE, XATTR_REPLACE, XATTR_NOSECURITY, XATTR_MAXNAMELEN, XATTR_FINDERINFO_NAME, diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/xattr-0.7.8/xattr/lib.py new/xattr-0.8.0/xattr/lib.py --- old/xattr-0.7.8/xattr/lib.py 2015-06-25 19:25:42.000000000 +0200 +++ new/xattr-0.8.0/xattr/lib.py 2016-02-28 20:10:07.000000000 +0100 @@ -5,10 +5,10 @@ ffi = cffi.FFI() ffi.cdef(""" -#define XATTR_NOFOLLOW ... -#define XATTR_CREATE ... -#define XATTR_REPLACE ... -#define XATTR_NOSECURITY ... +#define XATTR_XATTR_NOFOLLOW ... +#define XATTR_XATTR_CREATE ... +#define XATTR_XATTR_REPLACE ... +#define XATTR_XATTR_NOSECURITY ... #define XATTR_MAXNAMELEN ... ssize_t xattr_getxattr(const char *, const char *, void *, ssize_t, uint32_t, int); @@ -543,7 +543,7 @@ } else if (options != 0) { return -1; } - if (options & XATTR_XATTR_NOFOLLOW) { + if (nofollow) { return -1; } else { return fsetxattr(fd, name, value, size, options); @@ -582,36 +582,42 @@ #define xattr_fsetxattr fsetxattr #define xattr_listxattr listxattr #define xattr_flistxattr flistxattr + +/* define these for use in python (see below) */ +#define XATTR_XATTR_NOFOLLOW XATTR_NOFOLLOW +#define XATTR_XATTR_CREATE XATTR_CREATE +#define XATTR_XATTR_REPLACE XATTR_REPLACE +#define XATTR_XATTR_NOSECURITY XATTR_NOSECURITY #endif #ifndef XATTR_MAXNAMELEN #define XATTR_MAXNAMELEN 127 #endif - -#ifndef XATTR_NOFOLLOW -#define XATTR_NOFOLLOW 0x0001 -#endif - -#ifndef XATTR_NOSECURITY -#define XATTR_NOSECURITY 0x0008 -#endif """, ext_package='xattr') -XATTR_NOFOLLOW = lib.XATTR_NOFOLLOW -XATTR_CREATE = lib.XATTR_CREATE -XATTR_REPLACE = lib.XATTR_REPLACE -XATTR_NOSECURITY = lib.XATTR_NOSECURITY +XATTR_NOFOLLOW = lib.XATTR_XATTR_NOFOLLOW +XATTR_CREATE = lib.XATTR_XATTR_CREATE +XATTR_REPLACE = lib.XATTR_XATTR_REPLACE +XATTR_NOSECURITY = lib.XATTR_XATTR_NOSECURITY XATTR_MAXNAMELEN = lib.XATTR_MAXNAMELEN XATTR_FINDERINFO_NAME = "com.apple.FinderInfo" XATTR_RESOURCEFORK_NAME = "com.apple.ResourceFork" - -def fs_encode(val): - if not isinstance(val, bytes): - return val.encode(sys.getfilesystemencoding()) - else: - return val +try: + fs_encode = os.fsencode +except AttributeError: + def fs_encode(val): + encoding = sys.getfilesystemencoding() + if encoding == 'mbcs': + errors = 'strict' + else: + errors = 'surrogateescape' + + if not isinstance(val, bytes): + return val.encode(encoding, errors) + else: + return val def _check_bytes(val): diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/xattr-0.7.8/xattr/pyxattr_compat.py new/xattr-0.8.0/xattr/pyxattr_compat.py --- old/xattr-0.7.8/xattr/pyxattr_compat.py 1970-01-01 01:00:00.000000000 +0100 +++ new/xattr-0.8.0/xattr/pyxattr_compat.py 2016-02-28 20:10:07.000000000 +0100 @@ -0,0 +1,110 @@ +""" +pyxattr and xattr have differing API, for example xattr assumes +that (like on OSX) attribute keys are valid UTF-8, while pyxattr +just passes through the raw bytestring. + +This module provides compatibility for the pyxattr API. +""" + +import sys + +from .lib import (XATTR_NOFOLLOW, XATTR_CREATE, XATTR_REPLACE, + XATTR_NOSECURITY, XATTR_MAXNAMELEN, XATTR_FINDERINFO_NAME, + XATTR_RESOURCEFORK_NAME, _getxattr, _fgetxattr, _setxattr, _fsetxattr, + _removexattr, _fremovexattr, _listxattr, _flistxattr) + +__all__ = [ + "NS_SECURITY", "NS_USER", "NS_SYSTEM", "NS_TRUSTED", + "getxattr", "get", "get_all", "setxattr", "set", + "removexattr", "remove", "listxattr", "list" +] + +NS_SECURITY = "security" +NS_USER = "user" +NS_SYSTEM = "system" +NS_TRUSTED = "trusted" + +_NO_NS = object() + +_fsencoding = sys.getfilesystemencoding() + +def _call(item, name_func, fd_func, *args): + if isinstance(item, int): + return fd_func(item, *args) + elif hasattr(item, 'fileno'): + return fd_func(item.fileno(), *args) + elif isinstance(item, str): + return name_func(item, *args) + elif isinstance(item, unicode): + item = item.encode(_fsencoding) + return name_func(item, *args) + else: + raise TypeError("argument must be string, int or file object") + +def _add_ns(item, ns): + if ns is None: + raise TypeError("namespace must not be None") + if ns == _NO_NS: + return item + return "%s.%s" % (ns, item) + +def getxattr(item, attribute, nofollow=False): + options = nofollow and XATTR_NOFOLLOW or 0 + return _call(item, _getxattr, _fgetxattr, attribute, 0, 0, options) + +def get(item, name, nofollow=False, namespace=_NO_NS): + name = _add_ns(name, namespace) + return getxattr(item, name, nofollow=nofollow) + +def get_all(item, nofollow=False, namespace=_NO_NS): + if namespace is not None and namespace != _NO_NS: + namespace = '%s.' % namespace + l = listxattr(item, nofollow=nofollow) + result = [] + for name in l: + try: + if namespace is not None and namespace != _NO_NS: + if not name.startswith(namespace): + continue + result.append((name[len(namespace):], + getxattr(item, name, nofollow=nofollow))) + else: + result.append((name, getxattr(item, name, nofollow=nofollow))) + except IOError: + pass + return result + +def setxattr(item, name, value, flags=0, nofollow=False): + options = nofollow and XATTR_NOFOLLOW or 0 + options |= flags + return _call(item, _setxattr, _fsetxattr, name, value, 0, options) + +def set(item, name, value, nofollow=False, flags=0, namespace=_NO_NS): + name = _add_ns(name, namespace) + return setxattr(item, name, value, flags=flags, nofollow=nofollow) + +def removexattr(item, name, nofollow=False): + options = nofollow and XATTR_NOFOLLOW or 0 + return _call(item, _removexattr, _fremovexattr, name, options) + +def remove(item, name, nofollow=False, namespace=_NO_NS): + name = _add_ns(name, namespace) + return removexattr(item, name, nofollow=nofollow) + +def listxattr(item, nofollow=False): + options = nofollow and XATTR_NOFOLLOW or 0 + res = _call(item, _listxattr, _flistxattr, options).split(b'\x00') + res.pop() + return res + +def list(item, nofollow=False, namespace=_NO_NS): + if not namespace or namespace == _NO_NS: + return listxattr(item, nofollow=nofollow) + namespace = "%s." % namespace + l = listxattr(item, nofollow=nofollow) + result = [] + for name in l: + if not name.startswith(namespace): + continue + result.append(name[len(namespace):]) + return result diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/xattr-0.7.8/xattr/tests/test_xattr.py new/xattr-0.8.0/xattr/tests/test_xattr.py --- old/xattr-0.7.8/xattr/tests/test_xattr.py 2015-06-25 19:25:42.000000000 +0200 +++ new/xattr-0.8.0/xattr/tests/test_xattr.py 2016-02-28 20:10:07.000000000 +0100 @@ -1,5 +1,6 @@ import os import sys +import unittest from unittest import TestCase from tempfile import mkdtemp, NamedTemporaryFile @@ -96,3 +97,17 @@ def tearDown(self): os.rmdir(self.tempfile) + + +try: + # SkipTest is only available in Python 2.7+ + unittest.SkipTest +except AttributeError: + pass +else: + class TestFileWithSurrogates(TestFile): + def setUp(self): + if sys.platform != 'linux': + raise unittest.SkipTest('Files with invalid encoded names are only supported under linux') + self.tempfile = NamedTemporaryFile(prefix=b'invalid-\xe9'.decode('utf8','surrogateescape')) + self.tempfilename = self.tempfile.name
