Script 'mail_helper' called by obssrc
Hello community,
here is the log from the commit of package python-libarchive-c for
openSUSE:Factory checked in at 2023-12-08 22:32:00
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/python-libarchive-c (Old)
and /work/SRC/openSUSE:Factory/.python-libarchive-c.new.25432 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "python-libarchive-c"
Fri Dec 8 22:32:00 2023 rev:7 rq:1131722 version:5.0
Changes:
--------
--- /work/SRC/openSUSE:Factory/python-libarchive-c/python-libarchive-c.changes
2022-06-04 23:26:57.884751500 +0200
+++
/work/SRC/openSUSE:Factory/.python-libarchive-c.new.25432/python-libarchive-c.changes
2023-12-08 22:32:19.048582807 +0100
@@ -1,0 +2,18 @@
+Thu Dec 7 22:21:33 UTC 2023 - Dirk Müller <[email protected]>
+
+- update to 5.0:
+ * It is now possible to specify a codec for archive entry
+ metadata (`pathname`, `linkpath`, `uname` and `gname`)
+ * **BREAKING:** If you use the `archive_read_class` and
+ `archive_write_class` arguments, the classes you provide will
+ receive a codec name as a second positional argument.
+ * The `timestamp_nsec` arguments of the legacy
+ `ArchiveEntry.set_{a,c,m}time` methods are now optional
+ * Removed obsolete dependencies (`mock` and `six`) from
+ `tox.ini` (#119).
+ * Always use `UTF-8` when reading the `PKG-INFO` and
+ `README.rst` files (#120).
+ * Replaced `pytest-xdist` with `pytest-forked` in `tox.ini`
+- drop python-libarchive-c-no-mock.patch (upstream)
+
+-------------------------------------------------------------------
Old:
----
libarchive-c-4.0.tar.gz
python-libarchive-c-no-mock.patch
New:
----
libarchive-c-5.0.tar.gz
BETA DEBUG BEGIN:
Old: * Replaced `pytest-xdist` with `pytest-forked` in `tox.ini`
- drop python-libarchive-c-no-mock.patch (upstream)
BETA DEBUG END:
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Other differences:
------------------
++++++ python-libarchive-c.spec ++++++
--- /var/tmp/diff_new_pack.8uEuSD/_old 2023-12-08 22:32:19.712607240 +0100
+++ /var/tmp/diff_new_pack.8uEuSD/_new 2023-12-08 22:32:19.724607681 +0100
@@ -1,7 +1,7 @@
#
# spec file for package python-libarchive-c
#
-# Copyright (c) 2022 SUSE LLC
+# Copyright (c) 2023 SUSE LLC
#
# All modifications and additions to the file contributed by third parties
# remain the property of their copyright owners, unless otherwise agreed
@@ -20,15 +20,13 @@
%{?!python_module:%define python_module() python-%{**} python3-%{**}}
Name: python-libarchive-c
-Version: 4.0
+Version: 5.0
Release: 0
Summary: Python interface to libarchive
License: CC0-1.0
Group: Development/Languages/Python
URL: https://github.com/Changaco/python-libarchive-c
Source:
https://files.pythonhosted.org/packages/source/l/libarchive-c/libarchive-c-%{version}.tar.gz
-#
https://github.com/Changaco/python-libarchive-c/commit/13b904e2b046db25a42cd63557d259b3d3998323
-Patch0: python-libarchive-c-no-mock.patch
BuildRequires: %{python_module setuptools}
BuildRequires: fdupes
BuildRequires: python-rpm-macros
@@ -49,8 +47,7 @@
dynamically load and access the C library.
%prep
-%setup -q -n libarchive-c-%{version}
-%patch0 -p1
+%autosetup -p1 -n libarchive-c-%{version}
%build
%python_build
++++++ libarchive-c-4.0.tar.gz -> libarchive-c-5.0.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/libarchive-c-4.0/.github/workflows/main.yml
new/libarchive-c-5.0/.github/workflows/main.yml
--- old/libarchive-c-4.0/.github/workflows/main.yml 2022-01-22
18:28:18.000000000 +0100
+++ new/libarchive-c-5.0/.github/workflows/main.yml 2023-06-29
10:33:58.000000000 +0200
@@ -14,6 +14,14 @@
- uses: actions/checkout@v2
- name: Install libarchive
run: sudo apt-get install -y libarchive13
+ - name: Install Python 3.11
+ uses: actions/setup-python@v2
+ with:
+ python-version: '3.11'
+ - name: Install Python 3.10
+ uses: actions/setup-python@v2
+ with:
+ python-version: '3.10'
- name: Install Python 3.9
uses: actions/setup-python@v2
with:
@@ -22,10 +30,6 @@
uses: actions/setup-python@v2
with:
python-version: '3.8'
- - name: Install Python 3.7
- uses: actions/setup-python@v2
- with:
- python-version: '3.7'
- name: Install tox
run: pip install tox
- name: Run the tests
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/libarchive-c-4.0/PKG-INFO
new/libarchive-c-5.0/PKG-INFO
--- old/libarchive-c-4.0/PKG-INFO 2022-01-22 18:34:08.470586000 +0100
+++ new/libarchive-c-5.0/PKG-INFO 2023-07-04 10:24:25.007115000 +0200
@@ -1,13 +1,12 @@
Metadata-Version: 2.1
Name: libarchive-c
-Version: 4.0
+Version: 5.0
Summary: Python interface to libarchive
Home-page: https://github.com/Changaco/python-libarchive-c
Author: Changaco
Author-email: [email protected]
License: CC0
Keywords: archive libarchive 7z tar bz2 zip gz
-Platform: UNKNOWN
Description-Content-Type: text/x-rst
License-File: LICENSE.md
@@ -27,7 +26,7 @@
python
------
-python-libarchive-c is currently tested with python 3.7, 3.8, and 3.9.
+python-libarchive-c is currently tested with python 3.8, 3.9, 3.10 and 3.11.
If you find an incompatibility with older versions you can send us a small
patch,
but we won't accept big changes.
@@ -127,9 +126,22 @@
libarchive). The acceptable values are listed in
``libarchive.ffi.WRITE_FORMATS``
and ``libarchive.ffi.WRITE_FILTERS``.
+File metadata codecs
+--------------------
+
+By default, UTF-8 is used to read and write file attributes from and to
archives.
+A different codec can be specified through the ``header_codec`` arguments of
the
+``*_reader`` and ``*_writer`` functions. Example::
+
+ with libarchive.file_writer('test.tar', 'ustar', header_codec='cp037') as
archive:
+ ...
+ with file_reader('test.tar', header_codec='cp037') as archive:
+ ...
+
+In addition to file paths (``pathname`` and ``linkpath``), the specified codec
is
+used to encode and decode user and group names (``uname`` and ``gname``).
+
License
=======
`CC0 Public Domain Dedication
<http://creativecommons.org/publicdomain/zero/1.0/>`_
-
-
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/libarchive-c-4.0/README.rst
new/libarchive-c-5.0/README.rst
--- old/libarchive-c-4.0/README.rst 2022-01-22 18:28:18.000000000 +0100
+++ new/libarchive-c-5.0/README.rst 2023-07-04 10:05:38.000000000 +0200
@@ -14,7 +14,7 @@
python
------
-python-libarchive-c is currently tested with python 3.7, 3.8, and 3.9.
+python-libarchive-c is currently tested with python 3.8, 3.9, 3.10 and 3.11.
If you find an incompatibility with older versions you can send us a small
patch,
but we won't accept big changes.
@@ -114,6 +114,21 @@
libarchive). The acceptable values are listed in
``libarchive.ffi.WRITE_FORMATS``
and ``libarchive.ffi.WRITE_FILTERS``.
+File metadata codecs
+--------------------
+
+By default, UTF-8 is used to read and write file attributes from and to
archives.
+A different codec can be specified through the ``header_codec`` arguments of
the
+``*_reader`` and ``*_writer`` functions. Example::
+
+ with libarchive.file_writer('test.tar', 'ustar', header_codec='cp037') as
archive:
+ ...
+ with file_reader('test.tar', header_codec='cp037') as archive:
+ ...
+
+In addition to file paths (``pathname`` and ``linkpath``), the specified codec
is
+used to encode and decode user and group names (``uname`` and ``gname``).
+
License
=======
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/libarchive-c-4.0/libarchive/entry.py
new/libarchive-c-5.0/libarchive/entry.py
--- old/libarchive-c-4.0/libarchive/entry.py 2022-01-22 18:28:18.000000000
+0100
+++ new/libarchive-c-5.0/libarchive/entry.py 2023-07-04 10:05:38.000000000
+0200
@@ -1,5 +1,5 @@
from contextlib import contextmanager
-from ctypes import c_char_p, create_string_buffer
+from ctypes import create_string_buffer
from enum import IntEnum
import math
@@ -34,15 +34,19 @@
class ArchiveEntry:
- __slots__ = ('_archive_p', '_entry_p')
+ __slots__ = ('_archive_p', '_entry_p', 'header_codec')
- def __init__(self, archive_p=None, **attributes):
+ def __init__(self, archive_p=None, header_codec='utf-8', **attributes):
"""Allocate memory for an `archive_entry` struct.
- The attributes are passed to the `modify` method.
+ The `header_codec` is used to decode and encode file paths and other
+ attributes.
+
+ The `**attributes` are passed to the `modify` method.
"""
self._archive_p = archive_p
self._entry_p = ffi.entry_new()
+ self.header_codec = header_codec
if attributes:
self.modify(**attributes)
@@ -54,7 +58,7 @@
"""Returns the file's path"""
return self.pathname
- def modify(self, **attributes):
+ def modify(self, header_codec=None, **attributes):
"""Convenience method to modify the entry's attributes.
Args:
@@ -83,6 +87,8 @@
rdevmajor (int): major part of the device number
rdevminor (int): minor part of the device number
"""
+ if header_codec:
+ self.header_codec = header_codec
for name, value in attributes.items():
setattr(self, name, value)
@@ -112,23 +118,45 @@
@property
def uname(self):
- return ffi.entry_uname_w(self._entry_p)
+ uname = ffi.entry_uname_w(self._entry_p)
+ if not uname:
+ uname = ffi.entry_uname(self._entry_p)
+ if uname is not None:
+ try:
+ uname = uname.decode(self.header_codec)
+ except UnicodeError:
+ pass
+ return uname
@uname.setter
def uname(self, value):
if not isinstance(value, bytes):
- value = value.encode('utf8')
- ffi.entry_update_uname_utf8(self._entry_p, value)
+ value = value.encode(self.header_codec)
+ if self.header_codec == 'utf-8':
+ ffi.entry_update_uname_utf8(self._entry_p, value)
+ else:
+ ffi.entry_copy_uname(self._entry_p, value)
@property
def gname(self):
- return ffi.entry_gname_w(self._entry_p)
+ gname = ffi.entry_gname_w(self._entry_p)
+ if not gname:
+ gname = ffi.entry_gname(self._entry_p)
+ if gname is not None:
+ try:
+ gname = gname.decode(self.header_codec)
+ except UnicodeError:
+ pass
+ return gname
@gname.setter
def gname(self, value):
if not isinstance(value, bytes):
- value = value.encode('utf8')
- ffi.entry_update_gname_utf8(self._entry_p, value)
+ value = value.encode(self.header_codec)
+ if self.header_codec == 'utf-8':
+ ffi.entry_update_gname_utf8(self._entry_p, value)
+ else:
+ ffi.entry_copy_gname(self._entry_p, value)
def get_blocks(self, block_size=ffi.page_size):
"""Read the file's content, keeping only one chunk in memory at a time.
@@ -211,7 +239,7 @@
seconds, fraction = math.modf(value)
self.set_atime(int(seconds), int(fraction * 1_000_000_000))
- def set_atime(self, timestamp_sec, timestamp_nsec):
+ def set_atime(self, timestamp_sec, timestamp_nsec=0):
"Kept for backward compatibility. `entry.atime = ...` is supported
now."
return ffi.entry_set_atime(self._entry_p, timestamp_sec,
timestamp_nsec)
@@ -235,7 +263,7 @@
seconds, fraction = math.modf(value)
self.set_mtime(int(seconds), int(fraction * 1_000_000_000))
- def set_mtime(self, timestamp_sec, timestamp_nsec):
+ def set_mtime(self, timestamp_sec, timestamp_nsec=0):
"Kept for backward compatibility. `entry.mtime = ...` is supported
now."
return ffi.entry_set_mtime(self._entry_p, timestamp_sec,
timestamp_nsec)
@@ -259,7 +287,7 @@
seconds, fraction = math.modf(value)
self.set_ctime(int(seconds), int(fraction * 1_000_000_000))
- def set_ctime(self, timestamp_sec, timestamp_nsec):
+ def set_ctime(self, timestamp_sec, timestamp_nsec=0):
"Kept for backward compatibility. `entry.ctime = ...` is supported
now."
return ffi.entry_set_ctime(self._entry_p, timestamp_sec,
timestamp_nsec)
@@ -294,28 +322,48 @@
path = ffi.entry_pathname_w(self._entry_p)
if not path:
path = ffi.entry_pathname(self._entry_p)
- try:
- path = path.decode()
- except UnicodeError:
- pass
+ if path is not None:
+ try:
+ path = path.decode(self.header_codec)
+ except UnicodeError:
+ pass
return path
@pathname.setter
def pathname(self, value):
if not isinstance(value, bytes):
- value = value.encode('utf8')
- ffi.entry_update_pathname_utf8(self._entry_p, c_char_p(value))
+ value = value.encode(self.header_codec)
+ if self.header_codec == 'utf-8':
+ ffi.entry_update_pathname_utf8(self._entry_p, value)
+ else:
+ ffi.entry_copy_pathname(self._entry_p, value)
@property
def linkpath(self):
- return (ffi.entry_symlink_w(self._entry_p) or
+ path = (
+ (
+ ffi.entry_symlink_w(self._entry_p) or
+ ffi.entry_symlink(self._entry_p)
+ ) if self.issym else (
ffi.entry_hardlink_w(self._entry_p) or
- ffi.entry_symlink(self._entry_p) or
- ffi.entry_hardlink(self._entry_p))
+ ffi.entry_hardlink(self._entry_p)
+ )
+ )
+ if isinstance(path, bytes):
+ try:
+ path = path.decode(self.header_codec)
+ except UnicodeError:
+ pass
+ return path
@linkpath.setter
def linkpath(self, value):
- ffi.entry_update_link_utf8(self._entry_p, value)
+ if not isinstance(value, bytes):
+ value = value.encode(self.header_codec)
+ if self.header_codec == 'utf-8':
+ ffi.entry_update_link_utf8(self._entry_p, value)
+ else:
+ ffi.entry_copy_link(self._entry_p, value)
# aliases for compatibility with the standard `tarfile` module
path = property(pathname.fget, pathname.fset, doc="alias of pathname")
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/libarchive-c-4.0/libarchive/ffi.py
new/libarchive-c-5.0/libarchive/ffi.py
--- old/libarchive-c-4.0/libarchive/ffi.py 2022-01-22 18:28:18.000000000
+0100
+++ new/libarchive-c-5.0/libarchive/ffi.py 2023-07-04 10:05:38.000000000
+0200
@@ -200,6 +200,8 @@
ffi('entry_rdevminor', [c_archive_entry_p], c_uint)
ffi('entry_uid', [c_archive_entry_p], c_longlong)
ffi('entry_gid', [c_archive_entry_p], c_longlong)
+ffi('entry_uname', [c_archive_entry_p], c_char_p)
+ffi('entry_gname', [c_archive_entry_p], c_char_p)
ffi('entry_uname_w', [c_archive_entry_p], c_wchar_p)
ffi('entry_gname_w', [c_archive_entry_p], c_wchar_p)
@@ -222,9 +224,13 @@
ffi('entry_unset_ctime', [c_archive_entry_p], None)
ffi('entry_unset_birthtime', [c_archive_entry_p], None)
+ffi('entry_copy_pathname', [c_archive_entry_p, c_char_p], None)
ffi('entry_update_pathname_utf8', [c_archive_entry_p, c_char_p], c_int,
check_int)
+ffi('entry_copy_link', [c_archive_entry_p, c_char_p], None)
ffi('entry_update_link_utf8', [c_archive_entry_p, c_char_p], c_int, check_int)
+ffi('entry_copy_uname', [c_archive_entry_p, c_char_p], None)
ffi('entry_update_uname_utf8', [c_archive_entry_p, c_char_p], c_int, check_int)
+ffi('entry_copy_gname', [c_archive_entry_p, c_char_p], None)
ffi('entry_update_gname_utf8', [c_archive_entry_p, c_char_p], c_int, check_int)
ffi('entry_clear', [c_archive_entry_p], c_archive_entry_p)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/libarchive-c-4.0/libarchive/read.py
new/libarchive-c-5.0/libarchive/read.py
--- old/libarchive-c-4.0/libarchive/read.py 2022-01-22 18:28:18.000000000
+0100
+++ new/libarchive-c-5.0/libarchive/read.py 2023-07-04 10:05:38.000000000
+0200
@@ -12,16 +12,18 @@
class ArchiveRead:
- def __init__(self, archive_p):
+ def __init__(self, archive_p, header_codec='utf-8'):
self._pointer = archive_p
+ self.header_codec = header_codec
def __iter__(self):
"""Iterates through an archive's entries.
"""
archive_p = self._pointer
+ header_codec = self.header_codec
read_next_header2 = ffi.read_next_header2
while 1:
- entry = ArchiveEntry(archive_p)
+ entry = ArchiveEntry(archive_p, header_codec)
r = read_next_header2(archive_p, entry._entry_p)
if r == ARCHIVE_EOF:
return
@@ -68,6 +70,7 @@
read_func, format_name='all', filter_name='all',
open_func=None, seek_func=None, close_func=None,
block_size=page_size, archive_read_class=ArchiveRead, passphrase=None,
+ header_codec='utf-8',
):
"""Read an archive using a custom function.
"""
@@ -79,12 +82,13 @@
if seek_func:
ffi.read_set_seek_callback(archive_p, seek_cb)
ffi.read_open(archive_p, None, open_cb, read_cb, close_cb)
- yield archive_read_class(archive_p)
+ yield archive_read_class(archive_p, header_codec)
@contextmanager
def fd_reader(
fd, format_name='all', filter_name='all', block_size=4096, passphrase=None,
+ header_codec='utf-8',
):
"""Read an archive from a file descriptor.
"""
@@ -94,12 +98,13 @@
except (OSError, AttributeError): # pragma: no cover
pass
ffi.read_open_fd(archive_p, fd, block_size)
- yield ArchiveRead(archive_p)
+ yield ArchiveRead(archive_p, header_codec)
@contextmanager
def file_reader(
path, format_name='all', filter_name='all', block_size=4096,
passphrase=None,
+ header_codec='utf-8',
):
"""Read an archive from a file.
"""
@@ -109,22 +114,25 @@
except (OSError, AttributeError): # pragma: no cover
pass
ffi.read_open_filename_w(archive_p, path, block_size)
- yield ArchiveRead(archive_p)
+ yield ArchiveRead(archive_p, header_codec)
@contextmanager
-def memory_reader(buf, format_name='all', filter_name='all', passphrase=None):
+def memory_reader(
+ buf, format_name='all', filter_name='all', passphrase=None,
+ header_codec='utf-8',
+):
"""Read an archive from memory.
"""
with new_archive_read(format_name, filter_name, passphrase) as archive_p:
ffi.read_open_memory(archive_p, cast(buf, c_void_p), len(buf))
- yield ArchiveRead(archive_p)
+ yield ArchiveRead(archive_p, header_codec)
@contextmanager
def stream_reader(
stream, format_name='all', filter_name='all', block_size=page_size,
- passphrase=None,
+ passphrase=None, header_codec='utf-8',
):
"""Read an archive from a stream.
@@ -158,7 +166,7 @@
if stream.seekable():
ffi.read_set_seek_callback(archive_p, seek_cb)
ffi.read_open(archive_p, None, open_cb, read_cb, close_cb)
- yield ArchiveRead(archive_p)
+ yield ArchiveRead(archive_p, header_codec)
seekable_stream_reader = stream_reader
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/libarchive-c-4.0/libarchive/write.py
new/libarchive-c-5.0/libarchive/write.py
--- old/libarchive-c-4.0/libarchive/write.py 2022-01-22 18:28:18.000000000
+0100
+++ new/libarchive-c-5.0/libarchive/write.py 2023-07-04 10:05:38.000000000
+0200
@@ -30,8 +30,9 @@
class ArchiveWrite:
- def __init__(self, archive_p):
+ def __init__(self, archive_p, header_codec='utf-8'):
self._pointer = archive_p
+ self.header_codec = header_codec
def add_entries(self, entries):
"""Add the given entries to the archive.
@@ -44,7 +45,8 @@
write_finish_entry(write_p)
def add_files(
- self, *paths, flags=0, lookup=False, pathname=None, **attributes
+ self, *paths, flags=0, lookup=False, pathname=None, recursive=True,
+ **attributes
):
"""Read files through the OS and add them to the archive.
@@ -58,6 +60,9 @@
is called to enable the lookup of user and group names
pathname (str | None):
the path of the file in the archive, defaults to the source
path
+ recursive (bool):
+ when False, if a path in `paths` is a directory,
+ only the directory itself is added.
attributes (dict): passed to `ArchiveEntry.modify()`
Raises:
@@ -70,7 +75,7 @@
if block_size <= 0:
block_size = 10240 # pragma: no cover
- entry = ArchiveEntry()
+ entry = ArchiveEntry(header_codec=self.header_codec)
entry_p = entry._entry_p
destination_path = attributes.pop('pathname', None)
for path in paths:
@@ -103,6 +108,8 @@
write_data(write_p, data, len(data))
write_finish_entry(write_p)
entry_clear(entry_p)
+ if not recursive:
+ break
def add_file(self, path, **kw):
"Single-path alias of `add_files()`"
@@ -116,7 +123,7 @@
""""Add file from memory to archive.
Args:
- entry_path (str): the file's path
+ entry_path (str | bytes): the file's path
entry_size (int): the file's size, in bytes
entry_data (bytes | Iterable[bytes]): the file's content
filetype (int): see `libarchive.entry.ArchiveEntry.modify()`
@@ -134,7 +141,8 @@
entry = ArchiveEntry(
pathname=entry_path, size=entry_size, filetype=filetype,
- perm=permission, **other_attributes
+ perm=permission, header_codec=self.header_codec,
+ **other_attributes
)
write_header(archive_pointer, entry._entry_p)
@@ -194,6 +202,7 @@
write_func, format_name, filter_name=None,
open_func=None, close_func=None, block_size=page_size,
archive_write_class=ArchiveWrite, options='', passphrase=None,
+ header_codec='utf-8',
):
"""Create an archive and send it in chunks to the `write_func` function.
@@ -214,13 +223,14 @@
ffi.write_set_bytes_in_last_block(archive_p, 1)
ffi.write_set_bytes_per_block(archive_p, block_size)
ffi.write_open(archive_p, None, open_cb, write_cb, close_cb)
- yield archive_write_class(archive_p)
+ yield archive_write_class(archive_p, header_codec)
@contextmanager
def fd_writer(
fd, format_name, filter_name=None,
archive_write_class=ArchiveWrite, options='', passphrase=None,
+ header_codec='utf-8',
):
"""Create an archive and write it into a file descriptor.
@@ -230,13 +240,14 @@
with new_archive_write(format_name, filter_name, options,
passphrase) as archive_p:
ffi.write_open_fd(archive_p, fd)
- yield archive_write_class(archive_p)
+ yield archive_write_class(archive_p, header_codec)
@contextmanager
def file_writer(
filepath, format_name, filter_name=None,
archive_write_class=ArchiveWrite, options='', passphrase=None,
+ header_codec='utf-8',
):
"""Create an archive and write it into a file.
@@ -246,13 +257,14 @@
with new_archive_write(format_name, filter_name, options,
passphrase) as archive_p:
ffi.write_open_filename_w(archive_p, filepath)
- yield archive_write_class(archive_p)
+ yield archive_write_class(archive_p, header_codec)
@contextmanager
def memory_writer(
buf, format_name, filter_name=None,
archive_write_class=ArchiveWrite, options='', passphrase=None,
+ header_codec='utf-8',
):
"""Create an archive and write it into a buffer.
@@ -264,4 +276,4 @@
used = byref(c_size_t())
buf_p = cast(buf, c_void_p)
ffi.write_open_memory(archive_p, buf_p, len(buf), used)
- yield archive_write_class(archive_p)
+ yield archive_write_class(archive_p, header_codec)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/libarchive-c-4.0/libarchive_c.egg-info/PKG-INFO
new/libarchive-c-5.0/libarchive_c.egg-info/PKG-INFO
--- old/libarchive-c-4.0/libarchive_c.egg-info/PKG-INFO 2022-01-22
18:34:08.000000000 +0100
+++ new/libarchive-c-5.0/libarchive_c.egg-info/PKG-INFO 2023-07-04
10:24:24.000000000 +0200
@@ -1,13 +1,12 @@
Metadata-Version: 2.1
Name: libarchive-c
-Version: 4.0
+Version: 5.0
Summary: Python interface to libarchive
Home-page: https://github.com/Changaco/python-libarchive-c
Author: Changaco
Author-email: [email protected]
License: CC0
Keywords: archive libarchive 7z tar bz2 zip gz
-Platform: UNKNOWN
Description-Content-Type: text/x-rst
License-File: LICENSE.md
@@ -27,7 +26,7 @@
python
------
-python-libarchive-c is currently tested with python 3.7, 3.8, and 3.9.
+python-libarchive-c is currently tested with python 3.8, 3.9, 3.10 and 3.11.
If you find an incompatibility with older versions you can send us a small
patch,
but we won't accept big changes.
@@ -127,9 +126,22 @@
libarchive). The acceptable values are listed in
``libarchive.ffi.WRITE_FORMATS``
and ``libarchive.ffi.WRITE_FILTERS``.
+File metadata codecs
+--------------------
+
+By default, UTF-8 is used to read and write file attributes from and to
archives.
+A different codec can be specified through the ``header_codec`` arguments of
the
+``*_reader`` and ``*_writer`` functions. Example::
+
+ with libarchive.file_writer('test.tar', 'ustar', header_codec='cp037') as
archive:
+ ...
+ with file_reader('test.tar', header_codec='cp037') as archive:
+ ...
+
+In addition to file paths (``pathname`` and ``linkpath``), the specified codec
is
+used to encode and decode user and group names (``uname`` and ``gname``).
+
License
=======
`CC0 Public Domain Dedication
<http://creativecommons.org/publicdomain/zero/1.0/>`_
-
-
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/libarchive-c-4.0/setup.py
new/libarchive-c-5.0/setup.py
--- old/libarchive-c-4.0/setup.py 2019-11-22 10:30:52.000000000 +0100
+++ new/libarchive-c-5.0/setup.py 2023-06-29 10:33:58.000000000 +0200
@@ -7,6 +7,9 @@
os.umask(0o022)
+with open(join(dirname(__file__), 'README.rst'), encoding="utf-8") as f:
+ README = f.read()
+
setup(
name='libarchive-c',
version=get_version(),
@@ -16,7 +19,7 @@
url='https://github.com/Changaco/python-libarchive-c',
license='CC0',
packages=find_packages(exclude=['tests']),
- long_description=open(join(dirname(__file__), 'README.rst')).read(),
+ long_description=README,
long_description_content_type='text/x-rst',
keywords='archive libarchive 7z tar bz2 zip gz',
)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/libarchive-c-4.0/tests/test_entry.py
new/libarchive-c-5.0/tests/test_entry.py
--- old/libarchive-c-4.0/tests/test_entry.py 2022-01-22 18:28:18.000000000
+0100
+++ new/libarchive-c-5.0/tests/test_entry.py 2023-07-04 10:05:38.000000000
+0200
@@ -106,7 +106,7 @@
def test_the_life_cycle_of_archive_entries():
- """Check that the `get_blocks` method only works on the current entry, and
only once.
+ """Check that `get_blocks` only works on the current entry, and only once.
"""
# Create a test archive in memory
buf = bytes(bytearray(10_000_000))
@@ -135,3 +135,17 @@
assert type(entry3) is ArchiveEntry
assert type(entry2) is PassedArchiveEntry
assert type(entry1) is PassedArchiveEntry
+
+
+def test_non_ASCII_encoding_of_file_metadata():
+ buf = bytes(bytearray(100_000))
+ file_name = 'README.rst'
+ encoded_file_name = 'README.rst'.encode('cp037')
+ with memory_writer(buf, 'ustar', header_codec='cp037') as archive:
+ archive.add_file(file_name)
+ with memory_reader(buf) as archive:
+ entry = next(iter(archive))
+ assert entry.pathname == encoded_file_name
+ with memory_reader(buf, header_codec='cp037') as archive:
+ entry = next(iter(archive))
+ assert entry.pathname == file_name
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/libarchive-c-4.0/tests/test_rwx.py
new/libarchive-c-5.0/tests/test_rwx.py
--- old/libarchive-c-4.0/tests/test_rwx.py 2022-01-22 18:28:18.000000000
+0100
+++ new/libarchive-c-5.0/tests/test_rwx.py 2023-06-29 10:33:58.000000000
+0200
@@ -7,7 +7,7 @@
from libarchive.entry import format_time
from libarchive.extract import EXTRACT_OWNER, EXTRACT_PERM, EXTRACT_TIME
from libarchive.write import memory_writer
-from mock import patch
+from unittest.mock import patch
import pytest
from . import check_archive, in_dir, treestat
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/libarchive-c-4.0/tox.ini new/libarchive-c-5.0/tox.ini
--- old/libarchive-c-4.0/tox.ini 2022-01-22 18:28:18.000000000 +0100
+++ new/libarchive-c-5.0/tox.ini 2023-07-04 10:23:03.000000000 +0200
@@ -1,16 +1,14 @@
[tox]
-envlist=py37,py38,py39
+envlist=py38,py39,py310,py311
skipsdist=True
[testenv]
passenv = LIBARCHIVE
commands=
- python -m pytest -Wd -vv --boxed --cov libarchive --cov-report
term-missing {toxinidir}/tests {posargs}
+ python -m pytest -Wd -vv --forked --cov libarchive --cov-report
term-missing {toxinidir}/tests {posargs}
flake8 {toxinidir}
deps=
flake8
pytest
pytest-cov
- pytest-xdist
- six
- mock
+ pytest-forked
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/libarchive-c-4.0/version.py
new/libarchive-c-5.0/version.py
--- old/libarchive-c-4.0/version.py 2016-11-29 19:03:26.000000000 +0100
+++ new/libarchive-c-5.0/version.py 2023-06-29 10:33:58.000000000 +0200
@@ -35,7 +35,7 @@
else:
# Extract the version from the PKG-INFO file.
- with open(join(d, 'PKG-INFO')) as f:
+ with open(join(d, 'PKG-INFO'), encoding='utf-8', errors='replace') as
f:
version = version_re.search(f.read()).group(1)
return version