Giter Club home page Giter Club logo

xattr's Introduction

xattr

xattr is a Python wrapper for extended filesystem attributes.

xattr also ships with an xattr command line tool for viewing and editing extended filesystem attributes. On platforms that support or ship with the attr package, you may prefer to use the getfattr and setfattr command line tools from the attr package.

Extended attributes extend the basic attributes of files and directories in the file system. They are stored as name:data pairs associated with file system objects (files, directories, symlinks, etc).

Extended attributes are currently only available on Darwin 8.0+ (Mac OS X 10.4) and Linux 2.6+. Experimental support is included for Solaris and FreeBSD.

Python 3.8+ is required as of v1.0.0, and this is the minimum version that is compatible with Python 3.12+.

Versions older than v1.0.0 are no longer supported, but are available for use. v0.10.1 is the last version to support older versions of Python (including 2.7).

Note: On Linux, custom xattr keys need to be prefixed with the user namespace, ie: user.your_attr.

Note: If you need to read or write Spotlight metadata attributes on macOS, see osxmetadata which provides a native macOS means to do so without directly manipulating extended attributes. osxmetadata also provides access to other macOS metadata attributes and extended attributes via xattr.

xattr's People

Contributors

akira-kurogane avatar alex avatar bkmit avatar chrbrd avatar cyphar avatar devinlane avatar etrepum avatar ipsod avatar jmberg avatar jmberg-intel avatar jmgurney avatar kikuyan avatar maugier avatar novel avatar nyov avatar oturpe avatar phihag avatar rhettbull avatar rp-tanium avatar timbertson avatar tipabu avatar wedi avatar yszheda avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

xattr's Issues

solaris & solaris studio compiler support

I know there have been fixes for this in the past, but 0.7.4 doesn't build and work properly on Solaris with the 12.3 Studio compilers.

The issues are:

  • using the wrong #define for Solaris (at least for Studio)
  • using embedded NUL characters in C code
  • missing XATTR_CREATE and XATTR_REPLACE values (Solaris extended attributes operate on a whole different model than the others supported here, so they don't make sense, but they're still exported by the module)
  • openat() needs to be passed the O_XATTR flag
  • lib.xattr_flistxattr() returns -1 on failure, not 1
  • the test suite assumes that a file which hasn't had any extended attributes added to it won't have any extended attributes, which isn't true as of Solaris 11 (all files have SUNWattr_ro and SUNWattr_rw, containing "system attributes", which are very much like file flags on other OSes -- os.chflags())

I can submit a patch as a gist, or as a pull request, if you have a preference.

Add usage example somewhere in readme?

Getting attributes is pretty straightforward, but I am trying to set multiple _kMDItemUserTags and I don't know the syntax for having more than one value. When using a plist the structure of the fields seems to be different and I am not sure what xattr.setxattr() can do for several tags. Thanks!

Issues with Solaris port

Couple of issues with solaris port:

  1. xattr dumps core when specifying a non-existent file. This happens because we open the file with dirp = fdopendir() and dirp is used regardless of it being NULL.

  2. list() logic does not work and xattr_xflistxattr() needs a rewrite.

xattr -r option is gone

I'm using xattr version 0.9.1 on macOS 10.12.3, which no longer has recursive option -r. So, it is no longer possible to recursively remove extended attributes if target file is a directory.

xattr list fails on CIFS mounts under Linux (fix enclosed)

Hey there.

I found a little bug while mucking around trying to find a network filesystem under linux that supports xattrs.

How to reproduce:

I created a samba share and turned on extended attribute support (ea support = Yes). From the server side, I created a dummy file (test.txt), and added some xattrs to it. I was able to list these back with xattr, no problem:

 nuc  jayson  xattr -l test.txt 
user.org.interlaced.stat:
0000   00 00 00 00 00 00 00 09 00 00 00 00 56 04 D2 E3    ............V...

user.org.interlaced.sha512sum:
0000   9C 20 C9 BF 38 40 4A C0 25 3E 90 7D C6 8E BA FC    . ..8@J.%>.}....
0010   E7 D1 31 9E 45 2D 60 27 00 6D 44 31 93 6A 04 F5    ..1.E-`'.mD1.j..
0020   85 3F 87 7B D7 28 37 E1 D7 43 4B 58 01 04 05 2A    .?.{.(7..CKX...*
0030   32 68 AC 18 43 9E 56 82 5E A8 4D 30 E1 A9 62 DF    2h..C.V.^.M0..b.

When I mount this directory under CIFS, I get this:

 nuc  jayson  xattr -l test.txt 
[Errno 34] Numerical result out of range: 'test.txt'

To demonstrate that the xattrs were working and were coming across, I was able to retrieve the list of xattrs using the standard attr command, as such:

 nuc  jayson  attr -l test.txt 
Attribute "org.interlaced.stat" has a 16 byte value for test.txt
Attribute "org.interlaced.sha512sum" has a 64 byte value for test.txt

Root cause and fix:

To make a long story short, I did some digging, and found the origin of the issue. When you run listxattr with a length of 0, you get back the length of data that would have been returned... except using this value on a CIFS mount causes it to barf with the dreaded ERANGE error. Giving it a buffer size 1 byte higher concludes with the desired behavior.

To fix, add a + 1 to res in lib._listxattr and lib._flistxattr, as follows:

def _listxattr(path, options=0):
    """
    listxattr(path, options=0) -> str
    """
    path = fs_encode(path)
    res = lib.xattr_listxattr(path, ffi.NULL, 0, options)
    if res == -1:
        raise error(path)
    elif res == 0:
        return b""
    buf = ffi.new("char[]", res + 1)
    res = lib.xattr_listxattr(path, buf, res + 1, options)
    if res == -1:
        raise error(path)
    return ffi.buffer(buf)[:res]

def _flistxattr(fd, options=0):
    """
    flistxattr(fd, options=0) -> str
    """
    res = lib.xattr_flistxattr(fd, ffi.NULL, 0, options)
    if res == -1:
        raise error()
    buf = ffi.new("char[]", res + 1)
    res = lib.xattr_flistxattr(fd, buf, res + 1, options)
    if res == -1:
        raise error()
    return ffi.buffer(buf)[:res]

This may be a bug in CIFS or xattr, but your module is where I made my own workaround (and probably have the best chance of seeing it implemented in upstream so I don't have to install yet another custom package everywhere).

Cheers,
--Jays

xattr not installing via pip with m1 macintosh

setuptools 41.2.0 51.0.0 wheel
wheel 0.33.1 0.36.1 wheel

Pip 20.3.1
Python 3.8
Big Sur 11.0.1 (Apple M1)

Description

Clean install with Python 3.8.2, installed virtualenv, and trying to install various modules.
Specifically in this case xattr.

loading Xattr via pip results in this exception report:

'''
Collecting xattr
Using cached xattr-0.9.7.tar.gz (13 kB)
ERROR: Command errored out with exit status 1:
command: /Library/Developer/CommandLineTools/usr/bin/python3 -c 'import sys, setuptools, tokenize; sys.argv[0] = '"'"'/private/var/folders/6g/0vldjqgd5d55rdv163phqh6r0000gn/T/pip-install-jncbjfpu/xattr_08a31bc4fb204d82a4d62457ddff34ba/setup.py'"'"'; file='"'"'/private/var/folders/6g/0vldjqgd5d55rdv163phqh6r0000gn/T/pip-install-jncbjfpu/xattr_08a31bc4fb204d82a4d62457ddff34ba/setup.py'"'"';f=getattr(tokenize, '"'"'open'"'"', open)(file);code=f.read().replace('"'"'\r\n'"'"', '"'"'\n'"'"');f.close();exec(compile(code, file, '"'"'exec'"'"'))' egg_info --egg-base /private/var/folders/6g/0vldjqgd5d55rdv163phqh6r0000gn/T/pip-pip-egg-info-798hcrbo
cwd: /private/var/folders/6g/0vldjqgd5d55rdv163phqh6r0000gn/T/pip-install-jncbjfpu/xattr_08a31bc4fb204d82a4d62457ddff34ba/
Complete output (167 lines):
c/_cffi_backend.c:5887:16: warning: comparison of integers of different signs: 'ffi_status' and 'int' [-Wsign-compare]
if (status == -1) {
~~~~~~ ^ ~~
1 warning generated.
c/_cffi_backend.c:5887:16: warning: comparison of integers of different signs: 'ffi_status' and 'int' [-Wsign-compare]
if (status == -1) {
~~~~~~ ^ ~~
1 warning generated.
Traceback (most recent call last):
File "/Library/Developer/CommandLineTools/Library/Frameworks/Python3.framework/Versions/3.8/lib/python3.8/distutils/core.py", line 148, in setup
dist.run_commands()
File "/Library/Developer/CommandLineTools/Library/Frameworks/Python3.framework/Versions/3.8/lib/python3.8/distutils/dist.py", line 966, in run_commands
self.run_command(cmd)
File "/Library/Developer/CommandLineTools/Library/Frameworks/Python3.framework/Versions/3.8/lib/python3.8/distutils/dist.py", line 985, in run_command
cmd_obj.run()
File "/Library/Developer/CommandLineTools/Library/Frameworks/Python3.framework/Versions/3.8/lib/python3.8/site-packages/setuptools/command/bdist_egg.py", line 172, in run
cmd = self.call_command('install_lib', warn_dir=0)
File "/Library/Developer/CommandLineTools/Library/Frameworks/Python3.framework/Versions/3.8/lib/python3.8/site-packages/setuptools/command/bdist_egg.py", line 158, in call_command
self.run_command(cmdname)
File "/Library/Developer/CommandLineTools/Library/Frameworks/Python3.framework/Versions/3.8/lib/python3.8/distutils/cmd.py", line 313, in run_command
self.distribution.run_command(command)
File "/Library/Developer/CommandLineTools/Library/Frameworks/Python3.framework/Versions/3.8/lib/python3.8/distutils/dist.py", line 985, in run_command
cmd_obj.run()
File "/Library/Developer/CommandLineTools/Library/Frameworks/Python3.framework/Versions/3.8/lib/python3.8/site-packages/setuptools/command/install_lib.py", line 15, in run
self.byte_compile(outfiles)
File "/Library/Developer/CommandLineTools/Library/Frameworks/Python3.framework/Versions/3.8/lib/python3.8/distutils/command/install_lib.py", line 132, in byte_compile
byte_compile(files, optimize=0,
File "/Library/Developer/CommandLineTools/Library/Frameworks/Python3.framework/Versions/3.8/lib/python3.8/distutils/util.py", line 466, in byte_compile
compile(file, cfile, dfile)
File "/Library/Developer/CommandLineTools/Library/Frameworks/Python3.framework/Versions/3.8/lib/python3.8/py_compile.py", line 157, in compile
os.makedirs(dirname)
File "/Library/Developer/CommandLineTools/Library/Frameworks/Python3.framework/Versions/3.8/lib/python3.8/os.py", line 213, in makedirs
makedirs(head, exist_ok=exist_ok)
File "/Library/Developer/CommandLineTools/Library/Frameworks/Python3.framework/Versions/3.8/lib/python3.8/os.py", line 213, in makedirs
makedirs(head, exist_ok=exist_ok)
File "/Library/Developer/CommandLineTools/Library/Frameworks/Python3.framework/Versions/3.8/lib/python3.8/os.py", line 213, in makedirs
makedirs(head, exist_ok=exist_ok)
[Previous line repeated 2 more times]
File "/Library/Developer/CommandLineTools/Library/Frameworks/Python3.framework/Versions/3.8/lib/python3.8/os.py", line 223, in makedirs
mkdir(name, mode)
File "/Library/Developer/CommandLineTools/Library/Frameworks/Python3.framework/Versions/3.8/lib/python3.8/site-packages/setuptools/sandbox.py", line 310, in wrap
path = self._remap_input(name, path, *args, **kw)
File "/Library/Developer/CommandLineTools/Library/Frameworks/Python3.framework/Versions/3.8/lib/python3.8/site-packages/setuptools/sandbox.py", line 452, in _remap_input
self._violation(operation, os.path.realpath(path), *args, **kw)
File "/Library/Developer/CommandLineTools/Library/Frameworks/Python3.framework/Versions/3.8/lib/python3.8/site-packages/setuptools/sandbox.py", line 407, in _violation
raise SandboxViolation(operation, args, kw)
setuptools.sandbox.SandboxViolation: SandboxViolation: mkdir('/Users/benjamin/Library/Caches/com.apple.python/private/var/folders/6g/0vldjqgd5d55rdv163phqh6r0000gn/T/easy_install-259hw_9z', 511) {}

The package setup script has attempted to modify files on your system
that are not within the EasyInstall build area, and has been aborted.

This package cannot be safely installed by EasyInstall, and may not
support alternate installation locations even if you run its setup
script by hand.  Please inform the package's author and the EasyInstall
maintainers to find out if a fix or workaround is available.


During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/Library/Developer/CommandLineTools/Library/Frameworks/Python3.framework/Versions/3.8/lib/python3.8/site-packages/setuptools/sandbox.py", line 154, in save_modules
    yield saved
  File "/Library/Developer/CommandLineTools/Library/Frameworks/Python3.framework/Versions/3.8/lib/python3.8/site-packages/setuptools/sandbox.py", line 195, in setup_context
    yield
  File "/Library/Developer/CommandLineTools/Library/Frameworks/Python3.framework/Versions/3.8/lib/python3.8/site-packages/setuptools/sandbox.py", line 250, in run_setup
    _execfile(setup_script, ns)
  File "/Library/Developer/CommandLineTools/Library/Frameworks/Python3.framework/Versions/3.8/lib/python3.8/site-packages/setuptools/sandbox.py", line 45, in _execfile
    exec(code, globals, locals)
  File "/var/folders/6g/0vldjqgd5d55rdv163phqh6r0000gn/T/easy_install-259hw_9z/cffi-1.14.4/setup.py", line 179, in <module>
  File "/Library/Developer/CommandLineTools/Library/Frameworks/Python3.framework/Versions/3.8/lib/python3.8/site-packages/setuptools/__init__.py", line 145, in setup
    return distutils.core.setup(**attrs)
  File "/Library/Developer/CommandLineTools/Library/Frameworks/Python3.framework/Versions/3.8/lib/python3.8/distutils/core.py", line 163, in setup
    raise SystemExit("error: " + str(msg))
SystemExit: error: SandboxViolation: mkdir('/Users/benjamin/Library/Caches/com.apple.python/private/var/folders/6g/0vldjqgd5d55rdv163phqh6r0000gn/T/easy_install-259hw_9z', 511) {}

The package setup script has attempted to modify files on your system
that are not within the EasyInstall build area, and has been aborted.

This package cannot be safely installed by EasyInstall, and may not
support alternate installation locations even if you run its setup
script by hand.  Please inform the package's author and the EasyInstall
maintainers to find out if a fix or workaround is available.


During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/Library/Developer/CommandLineTools/Library/Frameworks/Python3.framework/Versions/3.8/lib/python3.8/site-packages/setuptools/command/easy_install.py", line 1144, in run_setup
    run_setup(setup_script, args)
  File "/Library/Developer/CommandLineTools/Library/Frameworks/Python3.framework/Versions/3.8/lib/python3.8/site-packages/setuptools/sandbox.py", line 253, in run_setup
    raise
  File "/Library/Developer/CommandLineTools/Library/Frameworks/Python3.framework/Versions/3.8/lib/python3.8/contextlib.py", line 131, in __exit__
    self.gen.throw(type, value, traceback)
  File "/Library/Developer/CommandLineTools/Library/Frameworks/Python3.framework/Versions/3.8/lib/python3.8/site-packages/setuptools/sandbox.py", line 195, in setup_context
    yield
  File "/Library/Developer/CommandLineTools/Library/Frameworks/Python3.framework/Versions/3.8/lib/python3.8/contextlib.py", line 131, in __exit__
    self.gen.throw(type, value, traceback)
  File "/Library/Developer/CommandLineTools/Library/Frameworks/Python3.framework/Versions/3.8/lib/python3.8/site-packages/setuptools/sandbox.py", line 166, in save_modules
    saved_exc.resume()
  File "/Library/Developer/CommandLineTools/Library/Frameworks/Python3.framework/Versions/3.8/lib/python3.8/site-packages/setuptools/sandbox.py", line 141, in resume
    six.reraise(type, exc, self._tb)
  File "/Library/Developer/CommandLineTools/Library/Frameworks/Python3.framework/Versions/3.8/lib/python3.8/site-packages/setuptools/_vendor/six.py", line 685, in reraise
    raise value.with_traceback(tb)
  File "/Library/Developer/CommandLineTools/Library/Frameworks/Python3.framework/Versions/3.8/lib/python3.8/site-packages/setuptools/sandbox.py", line 154, in save_modules
    yield saved
  File "/Library/Developer/CommandLineTools/Library/Frameworks/Python3.framework/Versions/3.8/lib/python3.8/site-packages/setuptools/sandbox.py", line 195, in setup_context
    yield
  File "/Library/Developer/CommandLineTools/Library/Frameworks/Python3.framework/Versions/3.8/lib/python3.8/site-packages/setuptools/sandbox.py", line 250, in run_setup
    _execfile(setup_script, ns)
  File "/Library/Developer/CommandLineTools/Library/Frameworks/Python3.framework/Versions/3.8/lib/python3.8/site-packages/setuptools/sandbox.py", line 45, in _execfile
    exec(code, globals, locals)
  File "/var/folders/6g/0vldjqgd5d55rdv163phqh6r0000gn/T/easy_install-259hw_9z/cffi-1.14.4/setup.py", line 179, in <module>
  File "/Library/Developer/CommandLineTools/Library/Frameworks/Python3.framework/Versions/3.8/lib/python3.8/site-packages/setuptools/__init__.py", line 145, in setup
    return distutils.core.setup(**attrs)
  File "/Library/Developer/CommandLineTools/Library/Frameworks/Python3.framework/Versions/3.8/lib/python3.8/distutils/core.py", line 163, in setup
    raise SystemExit("error: " + str(msg))
SystemExit: error: SandboxViolation: mkdir('/Users/benjamin/Library/Caches/com.apple.python/private/var/folders/6g/0vldjqgd5d55rdv163phqh6r0000gn/T/easy_install-259hw_9z', 511) {}

The package setup script has attempted to modify files on your system
that are not within the EasyInstall build area, and has been aborted.

This package cannot be safely installed by EasyInstall, and may not
support alternate installation locations even if you run its setup
script by hand.  Please inform the package's author and the EasyInstall
maintainers to find out if a fix or workaround is available.


During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "<string>", line 1, in <module>
  File "/private/var/folders/6g/0vldjqgd5d55rdv163phqh6r0000gn/T/pip-install-jncbjfpu/xattr_08a31bc4fb204d82a4d62457ddff34ba/setup.py", line 34, in <module>
    setup(
  File "/Library/Developer/CommandLineTools/Library/Frameworks/Python3.framework/Versions/3.8/lib/python3.8/site-packages/setuptools/__init__.py", line 144, in setup
    _install_setup_requires(attrs)
  File "/Library/Developer/CommandLineTools/Library/Frameworks/Python3.framework/Versions/3.8/lib/python3.8/site-packages/setuptools/__init__.py", line 139, in _install_setup_requires
    dist.fetch_build_eggs(dist.setup_requires)
  File "/Library/Developer/CommandLineTools/Library/Frameworks/Python3.framework/Versions/3.8/lib/python3.8/site-packages/setuptools/dist.py", line 716, in fetch_build_eggs
    resolved_dists = pkg_resources.working_set.resolve(
  File "/Library/Developer/CommandLineTools/Library/Frameworks/Python3.framework/Versions/3.8/lib/python3.8/site-packages/pkg_resources/__init__.py", line 780, in resolve
    dist = best[req.key] = env.best_match(
  File "/Library/Developer/CommandLineTools/Library/Frameworks/Python3.framework/Versions/3.8/lib/python3.8/site-packages/pkg_resources/__init__.py", line 1065, in best_match
    return self.obtain(req, installer)
  File "/Library/Developer/CommandLineTools/Library/Frameworks/Python3.framework/Versions/3.8/lib/python3.8/site-packages/pkg_resources/__init__.py", line 1077, in obtain
    return installer(requirement)
  File "/Library/Developer/CommandLineTools/Library/Frameworks/Python3.framework/Versions/3.8/lib/python3.8/site-packages/setuptools/dist.py", line 786, in fetch_build_egg
    return cmd.easy_install(req)
  File "/Library/Developer/CommandLineTools/Library/Frameworks/Python3.framework/Versions/3.8/lib/python3.8/site-packages/setuptools/command/easy_install.py", line 679, in easy_install
    return self.install_item(spec, dist.location, tmpdir, deps)
  File "/Library/Developer/CommandLineTools/Library/Frameworks/Python3.framework/Versions/3.8/lib/python3.8/site-packages/setuptools/command/easy_install.py", line 705, in install_item
    dists = self.install_eggs(spec, download, tmpdir)
  File "/Library/Developer/CommandLineTools/Library/Frameworks/Python3.framework/Versions/3.8/lib/python3.8/site-packages/setuptools/command/easy_install.py", line 890, in install_eggs
    return self.build_and_install(setup_script, setup_base)
  File "/Library/Developer/CommandLineTools/Library/Frameworks/Python3.framework/Versions/3.8/lib/python3.8/site-packages/setuptools/command/easy_install.py", line 1158, in build_and_install
    self.run_setup(setup_script, setup_base, args)
  File "/Library/Developer/CommandLineTools/Library/Frameworks/Python3.framework/Versions/3.8/lib/python3.8/site-packages/setuptools/command/easy_install.py", line 1146, in run_setup
    raise DistutilsError("Setup script exited with %s" % (v.args[0],))
distutils.errors.DistutilsError: Setup script exited with error: SandboxViolation: mkdir('/Users/benjamin/Library/Caches/com.apple.python/private/var/folders/6g/0vldjqgd5d55rdv163phqh6r0000gn/T/easy_install-259hw_9z', 511) {}

The package setup script has attempted to modify files on your system
that are not within the EasyInstall build area, and has been aborted.

This package cannot be safely installed by EasyInstall, and may not
support alternate installation locations even if you run its setup
script by hand.  Please inform the package's author and the EasyInstall
maintainers to find out if a fix or workaround is available.

----------------------------------------

ERROR: Command errored out with exit status 1: python setup.py egg_info Check the logs for full command output.
'''

If I download xattr, and manually import it (after installing CFFI), everything seems to work fine (at least via rosetta 2). I haven't tried that in M1 native yet.

0.7.7: missing some .txt files in release tarballs

The 0.7.7 tarball (as downloaded from pypi) misses some useful .txt files (e.g. LICENSE.txt) that were present in 0.7.5:

(19:42) novel@kloomba:/pyxattr %> ls xattr-0.7.7|grep -e "txt$"
README.txt
(19:43) novel@kloomba:
/pyxattr %> ls xattr-0.7.5|grep -e "txt$"
CHANGES.txt
INSTALLING.txt
LICENSE.txt
README.txt
TODO.txt
requirements.txt
(19:43) novel@kloomba:~/pyxattr %>

I'm not sure if all of them are needed, but LICENSE.txt is nice to have from distro packaging point of view.

Thanks

Linux/FreeBSD interoperability

Hey,

I've been trying to get OpenStack Swift running on a combination of Linux and FreeBSD machines, and I've come across a fun problem where Swift will add metadata to a file on linux that once it is rsync'd to FreeBSD, it can no longer access the metadata.

It seems that this is a namespacing problem -- on Linux the xattr calls expect the attribute name to be fully-qualified (i.e. starting with user. in this case), whereas on FreeBSD the namespace is specified as a separate argument (e.g. EXTATTR_NAMESPACE_USER).

What this means is that Swift creates/reads metadata with the name user.swift.metadata on Linux, but when that file is transferred to FreeBSD and Swift (using this library) tries to get user.swift.metadata, FreeBSD treats that like user.user.swift.metadata and things thus fail.

I've worked around the problem for now by patching Swift on FreeBSD to use swift.metadata instead of user.swift.metadata, but it seems that this is perhaps something that could be solved more generally in this library.

I'm pretty new (as in, yesterday) to extended attributes, so please forgive me if I've missed something simple, or if this is a known problem.

Thanks!

Create new attr/add attr_value

Hi again!
I can't find any docs or wiki for this.
I don't understand, how to create new attr or add attr value in exists attr?
I tried:

xattr -w "attr.name" "attr_val" filename
import xattr

x = xattr.xattr('file_name')
x['attr.name'] = 'attr_val'
import xattr

xattr.setxattr('file_name', 'attr.name', 'attr_val')

But I get TypeError: Value must be bytes, str was passed.

[BUG]xattr/_xattr.c:235:53: error: missing binary operator before token "("

There is a compilation error when I installed xattr:

xattr/_xattr.c:235:53: error: missing binary operator before token "("

And I found that line 235 of xattr/_xattr.c

#elif defined(__SUN__) || defined(__sun__) || define(sun)

should be

#elif defined(__SUN__) || defined(__sun__) || defined(sun)

The last define should be defined.
After fixing it, xattr could be installed correctly.

bup needs xattr.get_all()

This is the reason it wants to use python-pyxattr, it's probably easy to re-implement that?

Right now I have a conflict between bup and calendarserver, which is really annoying.

Thoughts? I might take a stab at it but am unfamiliar with all of this. Perhaps somebody else already took a look?

Multiple MOSX file "Color" labels?

I've found code that uses Xattr to display the color label from a MOSX file. But later versions of the OS can have multiple labels. (eg Grey, Blue, Red)

This is the code that I'm using right now.

from xattr import xattr
from struct import unpack
import sys

colornames = {
0: 'none',
1: 'gray',
2: 'green',
3: 'purple',
4: 'blue',
5: 'yellow',
6: 'red',
7: 'orange',
}

#attrs = xattr('./test.cpp')
attrs = xattr(sys.argv[1])
try:
finder_attrs = attrs[u'com.apple.FinderInfo']
flags = unpack(32*'B', finder_attrs)
color = flags[9] >> 1 & 7
print (flags)
except KeyError:
color = 0

print (colornames[color])

For example, I placed Grey and Yellow (1, 5) on the file, and the value I'm seeing in flags[9] is Decimal 10.

Does xattr support multiple labels? And if so, can someone point me in the right direction to decode the multiple labels?

Unable to download xattr with pip??

Unsure what the issue is but trying to get pip to download xattr seems broken in 0.7.2 due to inability to find CFFI. Unsure if this is a pip issue or a xattr issue.

[harlowja@skinbeen anvil]$ pip --version
pip 1.4 from /usr/lib/python2.6/site-packages (python 2.6)
[harlowja@skinbeen anvil]$ lsb_release -a
LSB Version: :base-4.0-amd64:base-4.0-noarch:core-4.0-amd64:core-4.0-noarch
Distributor ID: RedHatEnterpriseServer
Description: Red Hat Enterprise Linux Server release 6.4 (Santiago)
Release: 6.4
Codename: Santiago
[harlowja@skinbeen anvil]$ pip install --download /tmp 'xattr>=0.4'
Downloading/unpacking xattr>=0.4
File was already downloaded /tmp/xattr-0.7.2.tar.gz
Running setup.py egg_info for package xattr
No local packages or download links found for cffi>=0.4
Traceback (most recent call last):
File "", line 16, in
File "/tmp/pip-build-harlowja/xattr/setup.py", line 65, in
cmdclass={'build': cffi_build},
File "/usr/lib64/python2.6/distutils/core.py", line 113, in setup
_setup_distribution = dist = klass(attrs)
File "/usr/lib/python2.6/site-packages/setuptools/dist.py", line 265, in init
self.fetch_build_eggs(attrs.pop('setup_requires'))
File "/usr/lib/python2.6/site-packages/setuptools/dist.py", line 289, in fetch_build_eggs
parse_requirements(requires), installer=self.fetch_build_egg
File "/usr/lib/python2.6/site-packages/pkg_resources.py", line 618, in resolve
dist = best[req.key] = env.best_match(req, self, installer)
File "/usr/lib/python2.6/site-packages/pkg_resources.py", line 862, in best_match
return self.obtain(req, installer) # try and download/install
File "/usr/lib/python2.6/site-packages/pkg_resources.py", line 874, in obtain
return installer(requirement)
File "/usr/lib/python2.6/site-packages/setuptools/dist.py", line 339, in fetch_build_egg
return cmd.easy_install(req)
File "/usr/lib/python2.6/site-packages/setuptools/command/easy_install.py", line 617, in easy_install
raise DistutilsError(msg)
distutils.errors.DistutilsError: Could not find suitable distribution for Requirement.parse('cffi>=0.4')
Complete output from command python setup.py egg_info:
No local packages or download links found for cffi>=0.4

Traceback (most recent call last):

File "", line 16, in

File "/tmp/pip-build-harlowja/xattr/setup.py", line 65, in

cmdclass={'build': cffi_build},

File "/usr/lib64/python2.6/distutils/core.py", line 113, in setup

_setup_distribution = dist = klass(attrs)

File "/usr/lib/python2.6/site-packages/setuptools/dist.py", line 265, in init

self.fetch_build_eggs(attrs.pop('setup_requires'))

File "/usr/lib/python2.6/site-packages/setuptools/dist.py", line 289, in fetch_build_eggs

parse_requirements(requires), installer=self.fetch_build_egg

File "/usr/lib/python2.6/site-packages/pkg_resources.py", line 618, in resolve

dist = best[req.key] = env.best_match(req, self, installer)

File "/usr/lib/python2.6/site-packages/pkg_resources.py", line 862, in best_match

return self.obtain(req, installer) # try and download/install

File "/usr/lib/python2.6/site-packages/pkg_resources.py", line 874, in obtain

return installer(requirement)

File "/usr/lib/python2.6/site-packages/setuptools/dist.py", line 339, in fetch_build_egg

return cmd.easy_install(req)

File "/usr/lib/python2.6/site-packages/setuptools/command/easy_install.py", line 617, in easy_install

raise DistutilsError(msg)

distutils.errors.DistutilsError: Could not find suitable distribution for Requirement.parse('cffi>=0.4')

Cleaning up...
Command python setup.py egg_info failed with error code 1 in /tmp/pip-build-harlowja/xattr
Storing complete log in /home/harlowja/.pip/pip.log

OSX 10.9 Install Problem (clang: error: unknown argument: '-mno-fused-madd')

I've got two full gist outputs of failed attempts to install xattr using pip as sudo and under a virtualenv

The key lines seem to be:

clang: error: unknown argument: '-mno-fused-madd' [-Wunused-command-line-argument-hard-error-in-future]

clang: note: this will be a hard error (cannot be downgraded to a warning) in the future

From my Googling the error and my limited understanding of XCode it seems it could be a problem with OSX Mavericks.

Attempting to install the xcode command line tools xcode-select --install fails partway through which was a possible solution given.

The only other options I've seen are changing the setup.py script to account for these irregularities. Unfortunately I can't gather anymore info to help. I hope you have better luck than me in fixing the module for use on OSX 10.9 as at the moment it seems impossible to install.

PyPi package broken

The latest package out on PyPi gives the following errors:

tar -xzvf xattr-0.6.4.tar.gz

gzip: stdin: invalid compressed data--crc error

gzip: stdin: invalid compressed data--length error
xattr-0.6.4/
xattr-0.6.4/.gitignore
xattr-0.6.4/_build/
xattr-0.6.4/_build/_make_constants.py
xattr-0.6.4/CHANGES.txt
xattr-0.6.4/ez_setup.py
xattr-0.6.4/INSTALLING.txt
xattr-0.6.4/LICENSE.txt
xattr-0.6.4/PKG-INFO
xattr-0.6.4/README.txt
xattr-0.6.4/setup.cfg
xattr-0.6.4/setup.py
xattr-0.6.4/TODO.txt
xattr-0.6.4/xattr/
xattr-0.6.4/xattr/init.py
tar: Skipping to next header
tar: Child returned status 1
tar: Error is not recoverable: exiting now


easy_install xattr
Searching for xattr
Reading http://pypi.python.org/simple/xattr/
Reading http://github.com/xattr/xattr
Reading http://undefined.org/python/#xattr
Best match: xattr 0.6.4
Downloading http://pypi.python.org/packages/source/x/xattr/xattr-0.6.4.tar.gz#md5=1bef31afb7038800f8d5cfa2f4562b37
error: MD5 validation failed for xattr-0.6.4.tar.gz; possible download problem?

pip install has the same problem

Use a different command name

The xattr entry-point overrides the default xattr, and doesn't provide the same interface. It would be better to give it a new name, like xattr-py or something.

xattr unicode error decoding _values_

When a filesystem extended attribute has been set to a binary value, the xattr program cannot display it. xattr appears to assume that xattr values are utf-8-encoded text, but there is no such requirement of xattrs. The underlying python library seems to support the attributes but the executable tool does not.

Here's an example:

[2882/1]$ xattr example.txt
Traceback (most recent call last):
  File "/usr/bin/xattr", line 11, in <module>
    load_entry_point('xattr==0.9.6', 'console_scripts', 'xattr')()
  File "/usr/lib/python3/dist-packages/xattr/tool.py", line 196, in main
    attr_value = attr_value.decode('utf-8')
UnicodeDecodeError: 'utf-8' codec can't decode byte 0x9a in position 33: invalid start byte
[2883/1]$ getfattr --dump example.txt
# file: example.txt
user.DosStream.com.apple.metadata_kMDItemUserTags:$DATA=0sYnBsaXN0MDCiAQJWQmx1ZQo0U2ZvbwgLEgAAAAAAAAEBAAAAAAAAAAMAAAAAAAAAAAAAAAAAAAAWAA==
user.org.netatalk.Metadata=0sAAUWBwACAAAAAAAAAAAAAAAAAAAAAAAAAAgAAAAEAAAAmgAAAAAAAAAIAAABYgAAABAAAAAJAAAAegAAACAAAAAOAAABcgAAAASAREVWAAABdgAAAACASU5PAAABfgAAAACAU1lOAAABhgAAAACAU1Z+AAABjgAAAAAAAAAAAAAAAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJsRzPCbEczyAAAAAJsRzPAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA

(The getfattr tool encodes binary values as base64 internally.)

Corrective action: the xattr tool should attempt utf-8 decoding, then fall back on other decodings that might make sense in context and finally just display the binary value.

New release request

It would be great to have a new release that would include this FreeBSD fix: 798568b and that will be available on pypi.
It will ease venv setups on FreeBSD.

would you accept a windows *port* if I write it?

We all know extended attributes are not supported on windows.
However there is a windows thing called Alternate Data Streams.
I could use "https://github.com/RobinDavid/pyADS" to write extended attributes to
an alternate data stream as a JSON (say, call it x.json) and that way it would work in that
it would install and work with itself ( the get and set methods would function) on Windows,
even if no other programs would know about their existence.

I'm doing this for one project to work around the non-portability of xattr itself. Is that something you would want in xattr. I see there is #17, and I'm guessing there are many others who were bit.
I'll write the code if people are, in principle, OK with it. but if they say something like We are just implementing an non-portable interface, and don't want anything else confusing things I won't bother.

Truncated Extended Attributes Values

I've just recently started working with xattr in Python. I'm trying to write a simple script that will recurse through a directory and print the extended attributes of each subdirectory. The expected output is:

getfattr -d -m 'ceph.dir.*' /media/cephfs/labs
getfattr: Removing leading '/' from absolute path names
# file: media/cephfs/labs
ceph.dir.entries="21"
ceph.dir.files="3"
ceph.dir.rbytes="332103262384826"
ceph.dir.rctime="1497015869.09352143912"
ceph.dir.rentries="41983401"
ceph.dir.rfiles="41063529"
ceph.dir.rsubdirs="919872"
ceph.dir.subdirs="18"

However, with the following code:

import xattr
x = xattr.xattr('/media/cephfs/labs')
for k in x.keys():
    print(k, '=', x.get(k))

I get the following output:

ceph.dir.entries = b'2\x00'
ceph.dir.files = b'\x00'
ceph.dir.subdirs = b'1\x00'
ceph.dir.rentries = b'4198340\x00'
ceph.dir.rfiles = b'4106352\x00'
ceph.dir.rsubdirs = b'91987\x00'
ceph.dir.rbytes = b'33210326238482\x00'
ceph.dir.rctime = b'1497015869.0935214391\x00'

As you can see, each value has been truncated and appended with a pad byte.
I've looked over the xattr source code and the only explanation for this that I have seen is that the buffer being passed to extattr_get_file needs to be increased in size by 1. This may not be right, but it would seem that either extattr_get_file or ffi.buffer(buf) are introducing a pad byte into the buffer contents. I could be wrong though.

This is a project for my work so any help with this would be much appreciated.

installation of xattr from pip with pycparser 2.15 fails

I get the following error messages when installing xattr via:

pip install xattr
Collecting xattr (from -r .virtualenv.requirements.txt (line 19))

  Downloading xattr-0.8.0.tar.gz

    Complete output from command python setup.py egg_info:



    Installed /tmp/pip-build-k0l82obx/xattr/.eggs/cffi-1.8.3-py3.4-linux-x86_64.egg

    Searching for pycparser

    Reading https://pypi.python.org/simple/pycparser/

    Downloading https://pypi.python.org/packages/37/05/65d342ba500c6f9dbb1978e9dd01a1097530e0291003638bbef329ad4522/pycparser-2.15.tar.gz#md5=8629238be71db4d3f79b4fb1cd1397dc

    Best match: pycparser 2.15

    Processing pycparser-2.15.tar.gz

    Writing /tmp/easy_install-5d0094ay/pycparser-2.15/setup.cfg

    Running pycparser-2.15/setup.py -q bdist_egg --dist-dir /tmp/easy_install-5d0094ay/pycparser-2.15/egg-dist-tmp-vtpnieu3

    warning: no previously-included files matching 'yacctab.*' found under directory 'tests'

    warning: no previously-included files matching 'lextab.*' found under directory 'tests'

    warning: no previously-included files matching 'yacctab.*' found under directory 'examples'

    warning: no previously-included files matching 'lextab.*' found under directory 'examples'

    zip_safe flag not set; analyzing archive contents...

    pycparser.ply.__pycache__.ygen.cpython-34: module references __file__

    pycparser.ply.__pycache__.yacc.cpython-34: module references __file__

    pycparser.ply.__pycache__.yacc.cpython-34: module MAY be using inspect.getsourcefile

    pycparser.ply.__pycache__.yacc.cpython-34: module MAY be using inspect.stack

    pycparser.ply.__pycache__.lex.cpython-34: module references __file__

    pycparser.ply.__pycache__.lex.cpython-34: module MAY be using inspect.getsourcefile

    creating /tmp/pip-build-k0l82obx/xattr/.eggs/pycparser-2.15-py3.4.egg

    Extracting pycparser-2.15-py3.4.egg to /tmp/pip-build-k0l82obx/xattr/.eggs



    Installed /tmp/pip-build-k0l82obx/xattr/.eggs/pycparser-2.15-py3.4.egg

    running egg_info

    creating pip-egg-info/xattr.egg-info

    writing entry points to pip-egg-info/xattr.egg-info/entry_points.txt

    writing dependency_links to pip-egg-info/xattr.egg-info/dependency_links.txt

    writing requirements to pip-egg-info/xattr.egg-info/requires.txt

    writing pip-egg-info/xattr.egg-info/PKG-INFO

    writing top-level names to pip-egg-info/xattr.egg-info/top_level.txt

    writing manifest file 'pip-egg-info/xattr.egg-info/SOURCES.txt'

    warning: manifest_maker: standard file '-c' not found



    Traceback (most recent call last):

      File "<string>", line 1, in <module>

      File "/tmp/pip-build-k0l82obx/xattr/setup.py", line 67, in <module>

        cmdclass={'build': cffi_build},

      File "/opt/python/3.4.4/lib/python3.4/distutils/core.py", line 148, in setup

        dist.run_commands()

      File "/opt/python/3.4.4/lib/python3.4/distutils/dist.py", line 955, in run_commands

        self.run_command(cmd)

      File "/opt/python/3.4.4/lib/python3.4/distutils/dist.py", line 974, in run_command

        cmd_obj.run()

      File "/home/travis/build/SUSE/kiwi/.tox/3.4/lib/python3.4/site-packages/setuptools/command/egg_info.py", line 279, in run

        self.find_sources()

      File "/home/travis/build/SUSE/kiwi/.tox/3.4/lib/python3.4/site-packages/setuptools/command/egg_info.py", line 306, in find_sources

        mm.run()

      File "/home/travis/build/SUSE/kiwi/.tox/3.4/lib/python3.4/site-packages/setuptools/command/egg_info.py", line 533, in run

        self.add_defaults()

      File "/home/travis/build/SUSE/kiwi/.tox/3.4/lib/python3.4/site-packages/setuptools/command/egg_info.py", line 562, in add_defaults

        sdist.add_defaults(self)

      File "/home/travis/build/SUSE/kiwi/.tox/3.4/lib/python3.4/site-packages/setuptools/command/py36compat.py", line 34, in add_defaults

        self._add_defaults_python()

      File "/home/travis/build/SUSE/kiwi/.tox/3.4/lib/python3.4/site-packages/setuptools/command/sdist.py", line 131, in _add_defaults_python

        build_py = self.get_finalized_command('build_py')

      File "/opt/python/3.4.4/lib/python3.4/distutils/cmd.py", line 299, in get_finalized_command

        cmd_obj.ensure_finalized()

      File "/opt/python/3.4.4/lib/python3.4/distutils/cmd.py", line 107, in ensure_finalized

        self.finalize_options()

      File "/home/travis/build/SUSE/kiwi/.tox/3.4/lib/python3.4/site-packages/setuptools/command/build_py.py", line 34, in finalize_options

        orig.build_py.finalize_options(self)

      File "/opt/python/3.4.4/lib/python3.4/distutils/command/build_py.py", line 45, in finalize_options

        ('force', 'force'))

      File "/opt/python/3.4.4/lib/python3.4/distutils/cmd.py", line 287, in set_undefined_options

        src_cmd_obj.ensure_finalized()

      File "/opt/python/3.4.4/lib/python3.4/distutils/cmd.py", line 107, in ensure_finalized

        self.finalize_options()

      File "/tmp/pip-build-k0l82obx/xattr/setup.py", line 15, in finalize_options

        from xattr.lib import ffi

      File "/tmp/pip-build-k0l82obx/xattr/xattr/__init__.py", line 12, in <module>

        from .lib import (XATTR_NOFOLLOW, XATTR_CREATE, XATTR_REPLACE,

      File "/tmp/pip-build-k0l82obx/xattr/xattr/lib.py", line 26, in <module>

        """)

      File "/tmp/pip-build-k0l82obx/xattr/.eggs/cffi-1.8.3-py3.4-linux-x86_64.egg/cffi/api.py", line 105, in cdef

        self._cdef(csource, override=override, packed=packed)

      File "/tmp/pip-build-k0l82obx/xattr/.eggs/cffi-1.8.3-py3.4-linux-x86_64.egg/cffi/api.py", line 119, in _cdef

        self._parser.parse(csource, override=override, **options)

      File "/tmp/pip-build-k0l82obx/xattr/.eggs/cffi-1.8.3-py3.4-linux-x86_64.egg/cffi/cparser.py", line 299, in parse

        self._internal_parse(csource)

      File "/tmp/pip-build-k0l82obx/xattr/.eggs/cffi-1.8.3-py3.4-linux-x86_64.egg/cffi/cparser.py", line 304, in _internal_parse

        ast, macros, csource = self._parse(csource)

      File "/tmp/pip-build-k0l82obx/xattr/.eggs/cffi-1.8.3-py3.4-linux-x86_64.egg/cffi/cparser.py", line 260, in _parse

        ast = _get_parser().parse(csource)

      File "/tmp/pip-build-k0l82obx/xattr/.eggs/cffi-1.8.3-py3.4-linux-x86_64.egg/cffi/cparser.py", line 40, in _get_parser

        _parser_cache = pycparser.CParser()

      File "/tmp/pip-build-k0l82obx/xattr/.eggs/pycparser-2.15-py3.4.egg/pycparser/c_parser.py", line 87, in __init__

        outputdir=taboutputdir)

      File "/tmp/pip-build-k0l82obx/xattr/.eggs/pycparser-2.15-py3.4.egg/pycparser/c_lexer.py", line 66, in build

        self.lexer = lex.lex(object=self, **kwargs)

      File "/tmp/pip-build-k0l82obx/xattr/.eggs/pycparser-2.15-py3.4.egg/pycparser/ply/lex.py", line 911, in lex

        lexobj.readtab(lextab, ldict)

      File "/tmp/pip-build-k0l82obx/xattr/.eggs/pycparser-2.15-py3.4.egg/pycparser/ply/lex.py", line 233, in readtab

        titem.append((re.compile(pat, lextab._lexreflags | re.VERBOSE), _names_to_funcs(func_name, fdict)))

      File "/home/travis/build/SUSE/kiwi/.tox/3.4/lib/python3.4/re.py", line 223, in compile

        return _compile(pattern, flags)

      File "/home/travis/build/SUSE/kiwi/.tox/3.4/lib/python3.4/re.py", line 294, in _compile

        p = sre_compile.compile(pattern, flags)

      File "/home/travis/build/SUSE/kiwi/.tox/3.4/lib/python3.4/sre_compile.py", line 579, in compile

        "sorry, but this version only supports 100 named groups"

    AssertionError: sorry, but this version only supports 100 named groups



    ----------------------------------------

tests fail on FreeBSD w/ default local

The default local has a fs encoding of US-ASCII which causes the tests to fail. A setting of en_US.UTF-8 makes the tests pass (w/ the changes in issue #59 ). Not sure if setting the local before running tests is best option or not.

`xattr().update()` does not work in Python 3

If you create a file kek.txt and try to add multiple attributes via dict-like xattr() interface, this library would try to use .iteritems(), which is not available on dicts in Python 3:

>>> xattr.xattr('kek.txt').update({'foo': b'FOO', 'bar': b'BAR'})
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File ".../venv/lib/python3.7/site-packages/xattr/__init__.py", line 142, in update
    for k, v in seq.iteritems():
AttributeError: 'dict' object has no attribute 'iteritems'

I am using xattr (0.9.6).

xattr option -x on MacOS 12/2 throws an error when running exiftool

Hi there. Excellent tool. Congrats.

I ran into the following issue:

Is it possible to make this module compatible with the -x option?

Thanks in advance for your support.

unable to install xattr 0.6.4

When I try to upload an app to the app store I get the following error:

Stripping extended attributes failed. "/usr/bin/xattr -crs /var/folders/t2/fjp18t212bdc6kgb3pjzk81m0000gn/T/XcodeDistPipeline.ZBT/Root/Payload/testvgd.app" exited with a non-zero status. The /usr/bin/xattr tool may be damaged.

When I try to run this tool /usr/bin/xattr from command-line I get: "pkg_resources.DistributionNotFound: The 'xattr==0.6.4' distribution was not found and is required by the application"

Where and how can I add this xattr distribution? I downloaded it from: https://pypi.python.org/pypi/xattr/0.6.4, but when I try to install this, with:
$ python .//xattr-0.6.4/setup.py
I get:
error: package directory 'xattr' does not exist.

Is there a fix or workaround for this? Thanks!

`xattr` fails on non-unicode attribute names

On Linux, flag names can be arbitrary strings of bytes:

$ touch /tmp/foo
$ setfattr /tmp/foo -n $'user.b\xffa\xffr' -v $'b\xffa\xffz'
$ getfattr /tmp/foo -n $'user.b\xffa\xffr'
(...)
user.b�a�r="baz"

However, an attempt to list the extended attributes for that file with xattr fails:

>>> from xattr import xattr
>>> xattr('/tmp/foo').list()
(...)
UnicodeDecodeError: 'utf8' codec can't decode byte 0xff in position 6: invalid start byte

Readme file request - why this python xattr rather than attr package's getfattr/setfattr etc?

Hi. I was reinstalling a cmdline tool to manually check the extended filesystem attributes in some datastore thing I was I developing.

I'd forgotten what the command was called however. Googling for "xattr" takes you all over the place. A lot of people who are searching for the right linux man page will end up here instead.

What I wanted, when I finally found them, were the getfattr, setfattr in the attr package. That's the shortest distance between the commandline user (me) and using the setxattr, getxattr, listxattr and removexattr syscalls.

But I'm curious as to what the purpose of this packaged python script is. Is it that getfattr etc. isn't available on OSX even though it also supports extended filesystem attributes? (with quirks?)

And could that please be put in the README.md?

surrogateescape not present on python2

When trying to run the tests on python 2, I get an error that surrogateescape is not present.

I have a fix for this in my branch, py2compat, but I haven't issued a pull request as the main upstream project is broken, and I've submitted a fix for them.

TypeError: initializer for ctype 'void *' must be a cdata pointer, not str

Hi!
When i try add any attr i get message:

  File "/usr/lib64/python3.3/site-packages/xattr/__init__.py", line 112, in __setitem__
    self.set(item, value)
  File "/usr/lib64/python3.3/site-packages/xattr/__init__.py", line 77, in set
    return self._call(_setxattr, _fsetxattr, name, value, 0, options | self.options)
  File "/usr/lib64/python3.3/site-packages/xattr/__init__.py", line 59, in _call
    return name_func(self.value, *args)
  File "/usr/lib64/python3.3/site-packages/xattr/lib.py", line 661, in _setxattr
    res = lib.xattr_setxattr(path, name, value, len(value), position, options)
TypeError: initializer for ctype 'void *' must be a cdata pointer, not str

I use python 3.3.4 and latest version of xattr.

support passing in StringIO instead of file

Currently, passing a file-like object is not really supported.

It would be very useful to be able to pass in the file as a StringIO object. Or the equivalent Python3 equivalent.

package description / README needs an update

if one just reads the description (README) and is not a mac os X / darwin user, one is inclined to search for the next python xattr package (e.g. with linux support).

but, if one digs in changelog, source, etc. it seems like you support more than just darwin, so you likely should tell that right from the beginning.

xattr.get function is not dict-like

This is how a dict's get function works:

D.get(k[,d]) -> D[k] if k in D, else d. d defaults to None.

However, xattr.get will raise an exception if the given name doesn't exist, instead of returning None.

Do you plan to make its behavior more dict-like?

Publish wheels for linux on pypi

https://pypi.org/project/xattr/#files indicates only wheels for macosx, any chance to get some wheels for linux ?

I'm getting compile errors in our CI for trying to install xattr without python-dev

    Running setup.py install for xattr: finished with status 'error'
    ERROR: Command errored out with exit status 1:
     command: /.tox/py27/bin/python -u -c 'import sys, setuptools, tokenize; sys.argv[0] = '"'"'/tmp/pip-install-tq12CM/xattr/setup.py'"'"'; __file__='"'"'/tmp/pip-install-tq12CM/xattr/setup.py'"'"';f=getattr(tokenize, '"'"'open'"'"', open)(__file__);code=f.read().replace('"'"'\r\n'"'"', '"'"'\n'"'"');f.close();exec(compile(code, __file__, '"'"'exec'"'"'))' install --record /tmp/pip-record-jrfrxk/install-record.txt --single-version-externally-managed --compile --install-headers /.tox/py27/include/site/python2.7/xattr
         cwd: /tmp/pip-install-tq12CM/xattr/
    Complete output (24 lines):
    running install
    running build
    running build_py
    creating build
    creating build/lib.linux-x86_64-2.7
    creating build/lib.linux-x86_64-2.7/xattr
    copying xattr/__init__.py -> build/lib.linux-x86_64-2.7/xattr
    copying xattr/lib.py -> build/lib.linux-x86_64-2.7/xattr
    copying xattr/pyxattr_compat.py -> build/lib.linux-x86_64-2.7/xattr
    copying xattr/compat.py -> build/lib.linux-x86_64-2.7/xattr
    copying xattr/lib_build.py -> build/lib.linux-x86_64-2.7/xattr
    copying xattr/tool.py -> build/lib.linux-x86_64-2.7/xattr
    running build_ext
    generating cffi module 'build/temp.linux-x86_64-2.7/_lib.c'
    creating build/temp.linux-x86_64-2.7
    building '_lib' extension
    creating build/temp.linux-x86_64-2.7/build
    creating build/temp.linux-x86_64-2.7/build/temp.linux-x86_64-2.7
    x86_64-linux-gnu-gcc -pthread -DNDEBUG -g -fwrapv -O2 -Wall -Wstrict-prototypes -fno-strict-aliasing -Wdate-time -D_FORTIFY_SOURCE=2 -g -fdebug-prefix-map=/build/python2.7-IbFBHb/python2.7-2.7.16=. -fstack-protector-strong -Wformat -Werror=format-security -fPIC -I/usr/include/python2.7 -c build/temp.linux-x86_64-2.7/_lib.c -o build/temp.linux-x86_64-2.7/build/temp.linux-x86_64-2.7/_lib.o
    build/temp.linux-x86_64-2.7/_lib.c:22:12: fatal error: pyconfig.h: No such file or directory
     #  include <pyconfig.h>
                ^~~~~~~~~~~~
    compilation terminated.
    error: command 'x86_64-linux-gnu-gcc' failed with exit status 1

refuses to work with non-utf8 keys

I'm not sure why xattr explicitly treats keys as utf-8, but clearly that's not necessarily the case.

$ attr -g "$(echo -en 'x\xff')" x
Attribute "x�" had a 8 byte value for x:
asdfjkl;

but python-xattr fails:

>>> xattr.xattr('x').items()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/home/johannes/Projects/bup/xattr/xattr/__init__.py", line 170, in items
    return list(self.iteritems())
  File "/home/johannes/Projects/bup/xattr/xattr/__init__.py", line 166, in iteritems
    for k in self.list():
  File "/home/johannes/Projects/bup/xattr/xattr/__init__.py", line 98, in list
    return [s.decode('utf-8') for s in res]
  File "/usr/lib/python2.7/encodings/utf_8.py", line 16, in decode
    return codecs.utf_8_decode(input, errors, True)
UnicodeDecodeError: 'utf8' codec can't decode byte 0xff in position 6: invalid start byte

I'd suggest to just remove the erroneous utf-8 decoding, but that could make the library backwards incompatible? OTOH, it will make it more compatible with python-pyxattr which supports that.

(this, btw, will mean bup cannot support using python-xattr, as clearly a backup tool must not fail when reading xattrs)

Running tests sometimes fail for xattr 0.9.7

The tests fail sometimes for xattr 0.9.7, no idea about this, could somebody help me?

[ 51s] ============================= test session starts ==============================
[ 51s] platform linux -- Python 3.7.9, pytest-3.6.4, py-1.5.4, pluggy-0.6.0
[ 51s] rootdir: /home/abuild/rpmbuild/BUILD/xattr-0.9.7, inifile:
[ 51s] collected 15 items
[ 51s]
[ 51s] xattr/tests/test_xattr.py FF.sFFF.sFFF.sF [100%]
[ 51s]
[ 51s] =================================== FAILURES ===================================
[ 51s] _____________________ TestFile.test_attr_fs_encoding_ascii _____________________
[ 51s]
[ 51s] self = <xattr.tests.test_xattr.TestFile testMethod=test_attr_fs_encoding_ascii>
[ 51s]
[ 51s] def test_attr_fs_encoding_ascii(self):
[ 51s] xattr.compat.fs_encoding = 'US-ASCII'
[ 51s] if sys.version_info[0] < 3:
[ 51s] with self.assertRaises(UnicodeEncodeError):
[ 51s] self._test_attr()
[ 51s] else:
[ 51s] > self._test_attr()
[ 51s]
[ 51s] xattr/tests/test_xattr.py:29:
[ 51s] _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
[ 51s] xattr/tests/test_xattr.py:60: in _test_attr
[ 51s] x['user.sopal'] = b'foo'
[ 51s] xattr/init.py:112: in setitem
[ 51s] self.set(item, value)
[ 51s] xattr/init.py:78: in set
[ 51s] return self._call(_setxattr, _fsetxattr, name, value, 0, options | self.options)
[ 51s] xattr/init.py:58: in _call
[ 51s] return fd_func(self.value, *args)
[ 51s] xattr/lib.py:93: in _fsetxattr
[ 51s] raise error()
[ 51s] _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
[ 51s]
[ 51s] path = None
[ 51s]
[ 51s] def error(path=None):
[ 51s] errno = ffi.errno
[ 51s] strerror = os.strerror(ffi.errno)
[ 51s] if path:
[ 51s] raise IOError(errno, strerror, path)
[ 51s] else:
[ 51s] > raise IOError(errno, strerror)
[ 51s] E OSError: [Errno 95] Operation not supported
[ 51s]
[ 51s] xattr/lib.py:35: OSError
[ 51s] ____________________ TestFile.test_attr_fs_encoding_unicode ____________________
[ 51s]
[ 51s] self = <xattr.tests.test_xattr.TestFile testMethod=test_attr_fs_encoding_unicode>
[ 51s]
[ 51s] def test_attr_fs_encoding_unicode(self):
[ 51s] # Not using setlocale(LC_ALL, ..) to set locale because
[ 51s] # sys.getfilesystemencoding() implementation falls back
[ 51s] # to user's preferred locale by calling setlocale(LC_ALL, '').
[ 51s] xattr.compat.fs_encoding = 'UTF-8'
[ 51s] > self._test_attr()
[ 51s]
[ 51s] xattr/tests/test_xattr.py:21:
[ 51s] _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
[ 51s] xattr/tests/test_xattr.py:60: in _test_attr
[ 51s] x['user.sopal'] = b'foo'
[ 51s] xattr/init.py:112: in setitem
[ 51s] self.set(item, value)
[ 51s] xattr/init.py:78: in set
[ 51s] return self._call(_setxattr, _fsetxattr, name, value, 0, options | self.options)
[ 51s] xattr/init.py:58: in _call
[ 51s] return fd_func(self.value, *args)
[ 51s] xattr/lib.py:93: in _fsetxattr
[ 51s] raise error()
[ 51s] _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
[ 51s]
[ 51s] path = None
[ 51s]
[ 51s] def error(path=None):
[ 51s] errno = ffi.errno
[ 51s] strerror = os.strerror(ffi.errno)
[ 51s] if path:
[ 51s] raise IOError(errno, strerror, path)
[ 51s] else:
[ 51s] > raise IOError(errno, strerror)
[ 51s] E OSError: [Errno 95] Operation not supported
[ 51s]
[ 51s] xattr/lib.py:35: OSError
[ 51s] _____________________________ TestFile.test_update _____________________________
[ 51s]
[ 51s] self = <xattr.tests.test_xattr.TestFile testMethod=test_update>
[ 51s]
[ 51s] def test_update(self):
[ 51s] x = xattr.xattr(self.tempfile)
[ 51s] attrs = {
[ 51s] 'user.test.key1': b'test_value1',
[ 51s] 'user.test.key2': b'test_value2'
[ 51s] }
[ 51s] > x.update(attrs)
[ 51s]
[ 51s] xattr/tests/test_xattr.py:37:
[ 51s] _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
[ 51s] xattr/init.py:143: in update
[ 51s] self[k] = v
[ 51s] xattr/init.py:112: in setitem
[ 51s] self.set(item, value)
[ 51s] xattr/init.py:78: in set
[ 51s] return self._call(_setxattr, _fsetxattr, name, value, 0, options | self.options)
[ 51s] xattr/init.py:58: in _call
[ 51s] return fd_func(self.value, *args)
[ 51s] xattr/lib.py:93: in _fsetxattr
[ 51s] raise error()
[ 51s] _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
[ 51s]
[ 51s] path = None
[ 51s]
[ 51s] def error(path=None):
[ 51s] errno = ffi.errno
[ 51s] strerror = os.strerror(ffi.errno)
[ 51s] if path:
[ 51s] raise IOError(errno, strerror, path)
[ 51s] else:
[ 51s] > raise IOError(errno, strerror)
[ 51s] E OSError: [Errno 95] Operation not supported
[ 51s]
[ 51s] xattr/lib.py:35: OSError
[ 51s] _____________________ TestDir.test_attr_fs_encoding_ascii ______________________
[ 51s]
[ 51s] self = <xattr.tests.test_xattr.TestDir testMethod=test_attr_fs_encoding_ascii>
[ 51s]
[ 51s] def test_attr_fs_encoding_ascii(self):
[ 51s] xattr.compat.fs_encoding = 'US-ASCII'
[ 51s] if sys.version_info[0] < 3:
[ 51s] with self.assertRaises(UnicodeEncodeError):
[ 51s] self._test_attr()
[ 51s] else:
[ 51s] > self._test_attr()
[ 51s]
[ 51s] xattr/tests/test_xattr.py:29:
[ 51s] _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
[ 51s] xattr/tests/test_xattr.py:60: in _test_attr
[ 51s] x['user.sopal'] = b'foo'
[ 51s] xattr/init.py:112: in setitem
[ 51s] self.set(item, value)
[ 51s] xattr/init.py:78: in set
[ 51s] return self._call(_setxattr, _fsetxattr, name, value, 0, options | self.options)
[ 51s] xattr/init.py:60: in _call
[ 51s] return name_func(self.value, *args)
[ 51s] xattr/lib.py:82: in _setxattr
[ 51s] raise error(path)
[ 51s] _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
[ 51s]
[ 51s] path = b'/tmp/tmpoj3r34hv'
[ 51s]
[ 51s] def error(path=None):
[ 51s] errno = ffi.errno
[ 51s] strerror = os.strerror(ffi.errno)
[ 51s] if path:
[ 51s] > raise IOError(errno, strerror, path)
[ 51s] E OSError: [Errno 95] Operation not supported: b'/tmp/tmpoj3r34hv'
[ 51s]
[ 51s] xattr/lib.py:33: OSError
[ 51s] ____________________ TestDir.test_attr_fs_encoding_unicode _____________________
[ 51s]
[ 51s] self = <xattr.tests.test_xattr.TestDir testMethod=test_attr_fs_encoding_unicode>
[ 51s]
[ 51s] def test_attr_fs_encoding_unicode(self):
[ 51s] # Not using setlocale(LC_ALL, ..) to set locale because
[ 51s] # sys.getfilesystemencoding() implementation falls back
[ 51s] # to user's preferred locale by calling setlocale(LC_ALL, '').
[ 51s] xattr.compat.fs_encoding = 'UTF-8'
[ 51s] > self._test_attr()
[ 51s]
[ 51s] xattr/tests/test_xattr.py:21:
[ 51s] _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
[ 51s] xattr/tests/test_xattr.py:60: in _test_attr
[ 51s] x['user.sopal'] = b'foo'
[ 51s] xattr/init.py:112: in setitem
[ 51s] self.set(item, value)
[ 51s] xattr/init.py:78: in set
[ 51s] return self._call(_setxattr, _fsetxattr, name, value, 0, options | self.options)
[ 51s] xattr/init.py:60: in _call
[ 51s] return name_func(self.value, *args)
[ 51s] xattr/lib.py:82: in _setxattr
[ 51s] raise error(path)
[ 51s] _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
[ 51s]
[ 51s] path = b'/tmp/tmpcd5cj275'
[ 51s]
[ 51s] def error(path=None):
[ 51s] errno = ffi.errno
[ 51s] strerror = os.strerror(ffi.errno)
[ 51s] if path:
[ 51s] > raise IOError(errno, strerror, path)
[ 51s] E OSError: [Errno 95] Operation not supported: b'/tmp/tmpcd5cj275'
[ 51s]
[ 51s] xattr/lib.py:33: OSError
[ 51s] _____________________________ TestDir.test_update ______________________________
[ 51s]
[ 51s] self = <xattr.tests.test_xattr.TestDir testMethod=test_update>
[ 51s]
[ 51s] def test_update(self):
[ 51s] x = xattr.xattr(self.tempfile)
[ 51s] attrs = {
[ 51s] 'user.test.key1': b'test_value1',
[ 51s] 'user.test.key2': b'test_value2'
[ 51s] }
[ 51s] > x.update(attrs)
[ 51s]
[ 51s] xattr/tests/test_xattr.py:37:
[ 51s] _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
[ 51s] xattr/init.py:143: in update
[ 51s] self[k] = v
[ 51s] xattr/init.py:112: in setitem
[ 51s] self.set(item, value)
[ 51s] xattr/init.py:78: in set
[ 51s] return self._call(_setxattr, _fsetxattr, name, value, 0, options | self.options)
[ 51s] xattr/init.py:60: in _call
[ 51s] return name_func(self.value, *args)
[ 51s] xattr/lib.py:82: in _setxattr
[ 51s] raise error(path)
[ 51s] _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
[ 51s]
[ 51s] path = b'/tmp/tmp57mn74fl'
[ 51s]
[ 51s] def error(path=None):
[ 51s] errno = ffi.errno
[ 51s] strerror = os.strerror(ffi.errno)
[ 51s] if path:
[ 51s] > raise IOError(errno, strerror, path)
[ 51s] E OSError: [Errno 95] Operation not supported: b'/tmp/tmp57mn74fl'
[ 51s]
[ 51s] xattr/lib.py:33: OSError
[ 51s] ______________ TestFileWithSurrogates.test_attr_fs_encoding_ascii ______________
[ 51s]
[ 51s] self = <xattr.tests.test_xattr.TestFileWithSurrogates testMethod=test_attr_fs_encoding_ascii>
[ 51s]
[ 51s] def test_attr_fs_encoding_ascii(self):
[ 51s] xattr.compat.fs_encoding = 'US-ASCII'
[ 51s] if sys.version_info[0] < 3:
[ 51s] with self.assertRaises(UnicodeEncodeError):
[ 51s] self._test_attr()
[ 51s] else:
[ 51s] > self._test_attr()
[ 51s]
[ 51s] xattr/tests/test_xattr.py:29:
[ 51s] _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
[ 51s] xattr/tests/test_xattr.py:60: in _test_attr
[ 51s] x['user.sopal'] = b'foo'
[ 51s] xattr/init.py:112: in setitem
[ 51s] self.set(item, value)
[ 51s] xattr/init.py:78: in set
[ 51s] return self._call(_setxattr, _fsetxattr, name, value, 0, options | self.options)
[ 51s] xattr/init.py:58: in _call
[ 51s] return fd_func(self.value, *args)
[ 51s] xattr/lib.py:93: in _fsetxattr
[ 51s] raise error()
[ 51s] _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
[ 51s]
[ 51s] path = None
[ 51s]
[ 51s] def error(path=None):
[ 51s] errno = ffi.errno
[ 51s] strerror = os.strerror(ffi.errno)
[ 51s] if path:
[ 51s] raise IOError(errno, strerror, path)
[ 51s] else:
[ 51s] > raise IOError(errno, strerror)
[ 51s] E OSError: [Errno 95] Operation not supported
[ 51s]
[ 51s] xattr/lib.py:35: OSError
[ 51s] _____________ TestFileWithSurrogates.test_attr_fs_encoding_unicode _____________
[ 51s]
[ 51s] self = <xattr.tests.test_xattr.TestFileWithSurrogates testMethod=test_attr_fs_encoding_unicode>
[ 51s]
[ 51s] def test_attr_fs_encoding_unicode(self):
[ 51s] # Not using setlocale(LC_ALL, ..) to set locale because
[ 51s] # sys.getfilesystemencoding() implementation falls back
[ 51s] # to user's preferred locale by calling setlocale(LC_ALL, '').
[ 51s] xattr.compat.fs_encoding = 'UTF-8'
[ 51s] > self._test_attr()
[ 51s]
[ 51s] xattr/tests/test_xattr.py:21:
[ 51s] _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
[ 51s] xattr/tests/test_xattr.py:60: in _test_attr
[ 51s] x['user.sopal'] = b'foo'
[ 51s] xattr/init.py:112: in setitem
[ 51s] self.set(item, value)
[ 51s] xattr/init.py:78: in set
[ 51s] return self._call(_setxattr, _fsetxattr, name, value, 0, options | self.options)
[ 51s] xattr/init.py:58: in _call
[ 51s] return fd_func(self.value, *args)
[ 51s] xattr/lib.py:93: in _fsetxattr
[ 51s] raise error()
[ 51s] _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
[ 51s]
[ 51s] path = None
[ 51s]
[ 51s] def error(path=None):
[ 51s] errno = ffi.errno
[ 51s] strerror = os.strerror(ffi.errno)
[ 51s] if path:
[ 51s] raise IOError(errno, strerror, path)
[ 51s] else:
[ 51s] > raise IOError(errno, strerror)
[ 51s] E OSError: [Errno 95] Operation not supported
[ 51s]
[ 51s] xattr/lib.py:35: OSError
[ 51s] ______________________ TestFileWithSurrogates.test_update ______________________
[ 51s]
[ 51s] self = <xattr.tests.test_xattr.TestFileWithSurrogates testMethod=test_update>
[ 51s]
[ 51s] def test_update(self):
[ 51s] x = xattr.xattr(self.tempfile)
[ 51s] attrs = {
[ 51s] 'user.test.key1': b'test_value1',
[ 51s] 'user.test.key2': b'test_value2'
[ 51s] }
[ 51s] > x.update(attrs)
[ 51s]
[ 51s] xattr/tests/test_xattr.py:37:
[ 51s] _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
[ 51s] xattr/init.py:143: in update
[ 51s] self[k] = v
[ 51s] xattr/init.py:112: in setitem
[ 51s] self.set(item, value)
[ 51s] xattr/init.py:78: in set
[ 51s] return self._call(_setxattr, _fsetxattr, name, value, 0, options | self.options)
[ 51s] xattr/init.py:58: in _call
[ 51s] return fd_func(self.value, *args)
[ 51s] xattr/lib.py:93: in _fsetxattr
[ 51s] raise error()
[ 51s] _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
[ 51s]
[ 51s] path = None
[ 51s]
[ 51s] def error(path=None):
[ 51s] errno = ffi.errno
[ 51s] strerror = os.strerror(ffi.errno)
[ 51s] if path:
[ 51s] raise IOError(errno, strerror, path)
[ 51s] else:
[ 51s] > raise IOError(errno, strerror)
[ 51s] E OSError: [Errno 95] Operation not supported
[ 51s]
[ 51s] xattr/lib.py:35: OSError
[ 51s] ================ 9 failed, 3 passed, 3 skipped in 0.80 seconds =================

OSX metadata

Hi

I was wondering if this can be used to display/manipulate Metadata values that Spotlight/Finder sets for files,
stuff like kMDItemKeywords or kMDItemFSName

thanks

Python 3 support

Python 3 does not work, because of the print statements in tool.py. I didn't see if there are other incompatibilities as well, though assumedly there aren't many since Python 3 is listed as supported in setup.py.

You should add from __future__ import print_function to the top of every file to avoid this in the future.

xattr -l <file-with-no-attributes> outputs nothing

This makes it difficult to see files that don't have any attributes when listing other files that do. For example, assuming files a, b, and d have attributes while c and e do not:

> xattr -l a b c d e
a: user.attr: a
b: user.attr: b
d: user.attr: d

Note that nothing is printed for c and e. I propose that xattr should instead produce output that looks like this:

a: user.attr: a
b: user.attr: b
c:
d: user.attr: d
e:

I would further suggest using an '=' instead of a ':' for the attribute value ("user.attr = a") to make the output easier to parse. This would then appear as:

a: user.attr=a
b: user.attr=b
c:
d: user.attr=d
e:

Ship tests with the tarball

Currently v0.7.8 release doesn't ship tests in the tarball, which is not ideal since one would want to run them with different cffi versions to test everything works correctly.

xattr has PyInstaller compatibility?

Hi all.
Thank you great and useful library.

I want to build my program with xattr by PyInstaller(3.2)
PyInstaller build success.
But,I have error when my app launched.

Error detail is below:

Failed to execute script RapidPack
Traceback (most recent call last):
File "RapidPack.py", line 16, in
File "", line 2237, in _find_and_load
File "", line 2226, in _find_and_load_unlocked
File "", line 1191, in _load_unlocked
File "", line 1161, in _load_backward_compatible
File "/Library/Frameworks/Python.framework/Versions/3.4/lib/python3.4/site-packages/PyInstaller/loader/pyimod03_importers.py", line 389, in load_module
exec(bytecode, module.dict)
File "site-packages/xattr/init.py", line 12, in
File "", line 2237, in _find_and_load
File "", line 2226, in _find_and_load_unlocked
File "", line 1191, in _load_unlocked
File "", line 1161, in _load_backward_compatible
File "/Library/Frameworks/Python.framework/Versions/3.4/lib/python3.4/site-packages/PyInstaller/loader/pyimod03_importers.py", line 389, in load_module
exec(bytecode, module.dict)
File "site-packages/xattr/lib.py", line 596, in
File "site-packages/cffi/api.py", line 450, in verify
File "site-packages/cffi/verifier.py", line 113, in load_library
File "site-packages/cffi/verifier.py", line 210, in _compile_module
File "site-packages/cffi/ffiplatform.py", line 29, in compile
File "site-packages/cffi/ffiplatform.py", line 55, in _build
File "distutils/dist.py", line 973, in run_command
File "distutils/cmd.py", line 107, in ensure_finalized
File "distutils/command/build_ext.py", line 137, in finalize_options
File "distutils/cmd.py", line 286, in set_undefined_options
File "distutils/dist.py", line 846, in get_command_obj
File "distutils/dist.py", line 832, in get_command_class
distutils.errors.DistutilsModuleError: invalid command 'build'
<

I googled.
This problem is similar "cx_freeze comaptibility" at pyca/cryptography#1323
Anyone Do you know the workaround for this problem?

MyEnvironment:

OSX 10.10.5
Python:3.4
PyInstaller:3.2
xattr:0.8.0
All Library installed by pip8.1.2

Regards

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.