diff --git a/.travis.yml b/.travis.yml index 61c4cc3..2a281f0 100644 --- a/.travis.yml +++ b/.travis.yml @@ -5,6 +5,7 @@ python: - "3.6" - "3.7" - "3.8" + - "3.9" install: pip install -r .travis_require script: make test diff --git a/CHANGES.rst b/CHANGES.rst index 125463b..769e88a 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -1,80 +1,172 @@ Changelog ========= + +0.5.1 (2020-12-12) +~~~~~~~~~~~~~~~~~~ + +Bug fixes and minor changes +--------------------------- + ++ `#46`_, `#47`_: `archive-tool` fails with :exc:`NameError` when + trying to emit a warning. + +.. _#46: https://github.com/RKrahl/archive-tools/issues/46 +.. _#47: https://github.com/RKrahl/archive-tools/pull/47 + + 0.5 (2020-05-09) - New features - + #45: The files argument to `archive-tool check` defaults to - the archive's basedir. +~~~~~~~~~~~~~~~~ + +New features +------------ + ++ `#45`_: The files argument to `archive-tool check` defaults to the + archive's basedir. + +Bug fixes and minor changes +--------------------------- + ++ Fix: some test data have not been included in the source + distribution. + +.. _#45: https://github.com/RKrahl/archive-tools/issues/45 - Bug fixes and minor changes - + Fix: some test data have not been included in the source - distribution. 0.4 (2019-12-26) - New features - + #15, #43: Add `archive-tool find` subcommand. - + #38, #39: Add `archive-tool diff` subcommand. - + #40, #44: Add setting tags in the header of the manifest. - + #41: Add a :meth:`Archive.extract` method. - + Add a :meth:`Manifest.sort` method. +~~~~~~~~~~~~~~~~ + +New features +------------ + ++ `#15`_, `#43`_: Add `archive-tool find` subcommand. + ++ `#38`_, `#39`_: Add `archive-tool diff` subcommand. + ++ `#40`_, `#44`_: Add setting tags in the header of the manifest. + ++ `#41`_: Add a :meth:`Archive.extract` method. + ++ Add a :meth:`Manifest.sort` method. + +Internal changes +---------------- + ++ Reorganization of the `archive-tool` script, move the code into + submodules in the new `archive.cli` package. + +.. _#15: https://github.com/RKrahl/archive-tools/issues/15 +.. _#38: https://github.com/RKrahl/archive-tools/issues/38 +.. _#39: https://github.com/RKrahl/archive-tools/pull/39 +.. _#40: https://github.com/RKrahl/archive-tools/issues/40 +.. _#41: https://github.com/RKrahl/archive-tools/pull/41 +.. _#43: https://github.com/RKrahl/archive-tools/pull/43 +.. _#44: https://github.com/RKrahl/archive-tools/pull/44 - Internal changes - + Reorganization of the `archive-tool` script, move the code into - submodules in the new `archive.cli` package. 0.3 (2019-08-06) - New features - + #33: `archive-tool create` should have an option to exclude files. - + #35: :class:`FileInfo` calculates checksums lazily. - + #34: files of unsupported type are ignored when creating an - archive. A warning is emitted instead of raising an error. - - Incompatible changes - + #36: Drop support for strings in the file name arguments - `path`, `paths`, `basedir`, and `workdir` of the methods - :meth:`Archive.create` and :meth:`Archive.open`. These - arguments require :class:`Path` objects now. - - Bug fixes and minor changes - + #37: `archive-tool create` throws an error when trying to - explicitly add a symlink. +~~~~~~~~~~~~~~~~ + +New features +------------ + ++ `#33`_: `archive-tool create` should have an option to exclude files. + ++ `#35`_: :class:`FileInfo` calculates checksums lazily. + ++ `#34`_: files of unsupported type are ignored when creating an + archive. A warning is emitted instead of raising an error. + +Incompatible changes +-------------------- + ++ `#36`_: Drop support for strings in the file name arguments `path`, + `paths`, `basedir`, and `workdir` of the methods + :meth:`Archive.create` and :meth:`Archive.open`. These arguments + require :class:`Path` objects now. + +Bug fixes and minor changes +--------------------------- + ++ `#37`_: `archive-tool create` throws an error when trying to + explicitly add a symlink. + +.. _#33: https://github.com/RKrahl/archive-tools/issues/33 +.. _#34: https://github.com/RKrahl/archive-tools/issues/34 +.. _#35: https://github.com/RKrahl/archive-tools/issues/35 +.. _#36: https://github.com/RKrahl/archive-tools/pull/36 +.. _#37: https://github.com/RKrahl/archive-tools/issues/37 + 0.2 (2019-07-14) - New features - + #28: support deduplication. - + #26 and #30: add support for custom metadata: - - Add methods :meth:`Archive.add_metadata` and - :meth:`Archive.get_metadata` to add and to retrieve custom - metadata to and from archives. - - Add a list of metadata items in the header of the - manifest. - - Bump manifest version to 1.1. - + #4, #32: Add :class:`MailArchive` implementing a special - flavour of an :class:`Archive` for storing mails. - + #27: Add command line flags `--prefix ` and `--stdin` to - `archive-tool check`. - - Incompatible changes - + #23 and #26: review the API of :class:`Archive`: - - Add two methods :meth:`Archive.create` and - :meth:`Archive.open` that create and read archives - respectively. - - The :meth:`Archive.__init__` method does not create or - open archives any longer. - - :meth:`Archive.verify` does not accept the mode argument - any more. - - :class:`Archive` keeps a file object to read the tarfile. - It is opened in :meth:`Archive.open`. - :meth:`Archive.verify` does not reopen the tarfile, but - relies on the internal file object to be left open. - - Add a :meth:`Archive.close` method. - - :class:`Archive` implements the context manager protocol. - - Bug fixes and minor changes - + #20: :meth:`Archive.create` takes a working directory as - optional argument. - + #29: Verfiy fails if archive contains hard links. - + #25: `archive-tool check` should ignore metadata. +~~~~~~~~~~~~~~~~ + +New features +------------ + ++ `#28`_: support deduplication. + ++ `#26`_ and `#30`_: add support for custom metadata: + + - Add methods :meth:`Archive.add_metadata` and + :meth:`Archive.get_metadata` to add and to retrieve custom + metadata to and from archives. + + - Add a list of metadata items in the header of the manifest. + + - Bump manifest version to 1.1. + ++ `#4`_, `#32`_: Add :class:`MailArchive` implementing a special + flavour of an :class:`Archive` for storing mails. + ++ `#27`_: Add command line flags `--prefix ` and `--stdin` to + `archive-tool check`. + +Incompatible changes +-------------------- + ++ `#23`_ and `#26`_: review the API of :class:`Archive`: + + - Add two methods :meth:`Archive.create` and :meth:`Archive.open` + that create and read archives respectively. + + - The :meth:`Archive.__init__` method does not create or open + archives any longer. + + - :meth:`Archive.verify` does not accept the mode argument any more. + + - :class:`Archive` keeps a file object to read the tarfile. It is + opened in :meth:`Archive.open`. :meth:`Archive.verify` does not + reopen the tarfile, but relies on the internal file object to be + left open. + + - Add a :meth:`Archive.close` method. + + - :class:`Archive` implements the context manager protocol. + +Bug fixes and minor changes +--------------------------- + ++ `#20`_: :meth:`Archive.create` takes a working directory as optional + argument. + ++ `#29`_: Verify fails if archive contains hard links. + ++ `#25`_: `archive-tool check` should ignore metadata. + +.. _#4: https://github.com/RKrahl/archive-tools/issues/4 +.. _#20: https://github.com/RKrahl/archive-tools/issues/20 +.. _#23: https://github.com/RKrahl/archive-tools/issues/23 +.. _#25: https://github.com/RKrahl/archive-tools/issues/25 +.. _#26: https://github.com/RKrahl/archive-tools/pull/26 +.. _#27: https://github.com/RKrahl/archive-tools/issues/27 +.. _#28: https://github.com/RKrahl/archive-tools/issues/28 +.. _#29: https://github.com/RKrahl/archive-tools/issues/29 +.. _#30: https://github.com/RKrahl/archive-tools/pull/30 +.. _#32: https://github.com/RKrahl/archive-tools/pull/32 + 0.1 (2019-04-14) - + Initial release. +~~~~~~~~~~~~~~~~ + ++ Initial release. diff --git a/archive/cli/__init__.py b/archive/cli/__init__.py index 56be379..e0f5124 100644 --- a/archive/cli/__init__.py +++ b/archive/cli/__init__.py @@ -9,6 +9,8 @@ subcmds = [ "create", "verify", "ls", "info", "check", "diff", "find", ] +argparser = argparse.ArgumentParser() + def showwarning(message, category, filename, lineno, file=None, line=None): """Display ArchiveWarning in a somewhat more user friendly manner. All other warnings are formatted the standard way. @@ -32,7 +34,6 @@ def showwarning(message, category, filename, lineno, file=None, line=None): def archive_tool(): warnings.showwarning = showwarning - argparser = argparse.ArgumentParser() subparsers = argparser.add_subparsers(title='subcommands', dest='subcmd') for sc in subcmds: m = importlib.import_module('archive.cli.%s' % sc) diff --git a/python-archive-tools.spec b/python-archive-tools.spec index 2522f63..7589767 100644 --- a/python-archive-tools.spec +++ b/python-archive-tools.spec @@ -1,4 +1,4 @@ -%bcond_with tests +%bcond_without tests %global distname archive-tools Name: python3-%{distname} @@ -9,6 +9,7 @@ Summary: $description License: Apache-2.0 Group: Development/Libraries/Python Source: %{distname}-%{version}.tar.gz +BuildRequires: fdupes BuildRequires: python3-base >= 3.4 %if %{with tests} BuildRequires: python3-PyYAML @@ -40,6 +41,7 @@ for f in `ls %{buildroot}%{_bindir}` do mv %{buildroot}%{_bindir}/$$f %{buildroot}%{_bindir}/$${f%%.py} done +%fdupes %{buildroot} %if %{with tests} diff --git a/setup.py b/setup.py index 29f30f6..a587a96 100644 --- a/setup.py +++ b/setup.py @@ -131,6 +131,7 @@ def run(self): "Programming Language :: Python :: 3.6", "Programming Language :: Python :: 3.7", "Programming Language :: Python :: 3.8", + "Programming Language :: Python :: 3.9", "Topic :: System :: Archiving", ], cmdclass = {'build_py': build_py, 'sdist': sdist, 'init_py': init_py}, diff --git a/tests/conftest.py b/tests/conftest.py index 4971982..2420a2b 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -6,7 +6,6 @@ from pathlib import Path from random import getrandbits import shutil -import stat import subprocess import sys import tempfile diff --git a/tests/test_02_create.py b/tests/test_02_create.py index 80ee412..cbc788e 100644 --- a/tests/test_02_create.py +++ b/tests/test_02_create.py @@ -5,7 +5,6 @@ from pathlib import Path import shutil import subprocess -import tarfile import pytest from pytest_dependency import depends from archive import Archive diff --git a/tests/test_03_create_dedup.py b/tests/test_03_create_dedup.py index 6ec6fcc..cae60ad 100644 --- a/tests/test_03_create_dedup.py +++ b/tests/test_03_create_dedup.py @@ -9,7 +9,6 @@ import pytest from pytest_dependency import depends from archive.archive import Archive, DedupMode -from archive.manifest import Manifest from conftest import * diff --git a/tests/test_04_cli_error.py b/tests/test_04_cli_error.py index cd90eeb..9ed8c19 100644 --- a/tests/test_04_cli_error.py +++ b/tests/test_04_cli_error.py @@ -3,8 +3,8 @@ import os from pathlib import Path +import re import stat -import subprocess import tarfile from tempfile import TemporaryFile from archive.manifest import Manifest @@ -114,7 +114,10 @@ def test_cli_create_rel_start_basedir(test_dir, testname, monkeypatch): callscript("archive-tool.py", args, returncode=1, stderr=f) f.seek(0) line = f.readline() - assert "'base/msg.txt' does not start with 'base/data'" in line + # The actual error message differs between Python versions, so + # lets just assert that the error is something about + # 'base/msg.txt' and 'base/data'. + assert re.search(r"'base/msg.txt'.*'base/data'", line) def test_cli_ls_archive_not_found(test_dir, monkeypatch): monkeypatch.chdir(str(test_dir)) diff --git a/tests/test_04_cli_warn.py b/tests/test_04_cli_warn.py new file mode 100644 index 0000000..3f48c1b --- /dev/null +++ b/tests/test_04_cli_warn.py @@ -0,0 +1,61 @@ +"""Test warnings issued by the command line tool. +""" + +from pathlib import Path +import socket +from tempfile import TemporaryFile +import pytest +from archive import Archive +from conftest import * + + +# Setup a directory with some test data to be put into an archive. +# Make sure that we have all kind of different things in there. +testdata = [ + DataDir(Path("base"), 0o755), + DataDir(Path("base", "data"), 0o750), + DataDir(Path("base", "empty"), 0o755), + DataFile(Path("base", "msg.txt"), 0o644), + DataFile(Path("base", "data", "rnd.dat"), 0o600), + DataSymLink(Path("base", "s.dat"), Path("data", "rnd.dat")), +] + +@pytest.fixture(scope="module") +def test_dir(tmpdir): + setup_testdata(tmpdir, testdata) + return tmpdir + +class tmp_socket(): + """A context manager temporarily creating a unix socket. + """ + def __init__(self, path): + self.path = path + self.socket = socket.socket(socket.AF_UNIX) + self.socket.bind(str(self.path)) + def __enter__(self): + return self.socket + def __exit__(self, type, value, tb): + self.socket.close() + self.path.unlink() + +def test_cli_warn_ignore_socket(test_dir, testname, monkeypatch): + """Create an archive from a directory containing a socket. + + archive-tool.py should issue a warning that the socket has been + ignored, but otherwise proceed to create the archive. + """ + monkeypatch.chdir(str(test_dir)) + name = archive_name(tags=[testname]) + basedir = Path("base") + fp = basedir / "socket" + with tmp_socket(fp): + with TemporaryFile(mode="w+t", dir=str(test_dir)) as f: + args = ["create", name, "base"] + callscript("archive-tool.py", args, stderr=f) + f.seek(0) + line = f.readline().strip() + assert line == ("archive-tool.py: %s: socket ignored" % fp) + with Archive().open(name) as archive: + assert archive.basedir == basedir + check_manifest(archive.manifest, testdata) + archive.verify() diff --git a/tests/test_05_mailarchive_create.py b/tests/test_05_mailarchive_create.py index c2acd2a..08950be 100644 --- a/tests/test_05_mailarchive_create.py +++ b/tests/test_05_mailarchive_create.py @@ -2,7 +2,6 @@ """ import email -from pathlib import Path import pytest from pytest_dependency import depends import yaml