diff options
| -rw-r--r-- | setup.py | 11 | ||||
| -rw-r--r-- | src/wikiget/__init__.py | 24 | ||||
| -rw-r--r-- | src/wikiget/client.py | 2 | ||||
| -rw-r--r-- | src/wikiget/dl.py | 2 | ||||
| -rw-r--r-- | src/wikiget/exceptions.py | 2 | ||||
| -rw-r--r-- | src/wikiget/file.py | 2 | ||||
| -rw-r--r-- | src/wikiget/logging.py | 2 | ||||
| -rw-r--r-- | src/wikiget/parse.py | 2 | ||||
| -rw-r--r-- | src/wikiget/validations.py | 2 | ||||
| -rw-r--r-- | src/wikiget/version.py | 2 | ||||
| -rw-r--r-- | src/wikiget/wikiget.py | 11 | ||||
| -rw-r--r-- | tests/test_wikiget_cli.py | 57 |
12 files changed, 98 insertions, 21 deletions
@@ -15,9 +15,14 @@ # You should have received a copy of the GNU General Public License # along with Wikiget. If not, see <https://www.gnu.org/licenses/>. -# This is a stub file for older versions of pip, setuptools, etc. that aren't fully -# compatible with the latest Python packaging standards. -# See <https://setuptools.pypa.io/en/latest/userguide/pyproject_config.html> +"""Configure the program for packaging. + +This is a stub file for older versions of pip, setuptools, etc. that aren't fully +compatible with the latest Python packaging standards. Project metadata and dependencies +have been moved to pyproject.toml. + +See <https://setuptools.pypa.io/en/latest/userguide/pyproject_config.html> for info. +""" from setuptools import setup diff --git a/src/wikiget/__init__.py b/src/wikiget/__init__.py index e0584bb..698fe46 100644 --- a/src/wikiget/__init__.py +++ b/src/wikiget/__init__.py @@ -15,6 +15,30 @@ # You should have received a copy of the GNU General Public License # along with Wikiget. If not, see <https://www.gnu.org/licenses/>. +"""Wikiget is a tool for downloading files from MediaWiki sites. + +It's similar in conception to download tools like wget, but wikiget can use the name of +the file or the URL of its description page to get the actual file's URL and download +it. Additionally, it can download multiple files at once by reading the targets from a +given text file. + +Further documentation can be found in the accompanying README.md file or at +<https://github.com/clpo13/wikiget>. + +Basic usage:: + + wikiget [options] FILE + wikiget [options] [-a|--batch] BATCHFILE + +Examples:: + + wikiget File:Example.jpg + wikiget --site en.wikipedia.org File:Example.jpg + wikiget https://en.wikipedia.org/wiki/File:Example.jpg -o output.jpg + wikiget -a -j4 batch.txt + +""" + from mwclient import __version__ as mwclient_version from wikiget.version import __version__ diff --git a/src/wikiget/client.py b/src/wikiget/client.py index 64c14d9..2729144 100644 --- a/src/wikiget/client.py +++ b/src/wikiget/client.py @@ -15,6 +15,8 @@ # You should have received a copy of the GNU General Public License # along with Wikiget. If not, see <https://www.gnu.org/licenses/>. +"""Handle API calls (via mwclient) for site and image information.""" + from __future__ import annotations import logging diff --git a/src/wikiget/dl.py b/src/wikiget/dl.py index c84935b..d3b42fd 100644 --- a/src/wikiget/dl.py +++ b/src/wikiget/dl.py @@ -15,6 +15,8 @@ # You should have received a copy of the GNU General Public License # along with Wikiget. If not, see <https://www.gnu.org/licenses/>. +"""Prepare and process file downloads.""" + from __future__ import annotations import logging diff --git a/src/wikiget/exceptions.py b/src/wikiget/exceptions.py index c72a589..d9ca8b3 100644 --- a/src/wikiget/exceptions.py +++ b/src/wikiget/exceptions.py @@ -15,6 +15,8 @@ # You should have received a copy of the GNU General Public License # along with Wikiget. If not, see <https://www.gnu.org/licenses/>. +"""Define exceptions specific to the program.""" + class ParseError(Exception): """Raised when some input is unable to be parsed as valid.""" diff --git a/src/wikiget/file.py b/src/wikiget/file.py index 6fc03a1..0b0c1e0 100644 --- a/src/wikiget/file.py +++ b/src/wikiget/file.py @@ -15,6 +15,8 @@ # You should have received a copy of the GNU General Public License # along with Wikiget. If not, see <https://www.gnu.org/licenses/>. +"""Define a File class for representing individual files to be downloaded.""" + from __future__ import annotations from pathlib import Path diff --git a/src/wikiget/logging.py b/src/wikiget/logging.py index 6614a15..e5b955a 100644 --- a/src/wikiget/logging.py +++ b/src/wikiget/logging.py @@ -15,6 +15,8 @@ # You should have received a copy of the GNU General Public License # along with Wikiget. If not, see <https://www.gnu.org/licenses/>. +"""Configure program log configuration and adapters.""" + from __future__ import annotations import logging diff --git a/src/wikiget/parse.py b/src/wikiget/parse.py index 1deaacf..026062e 100644 --- a/src/wikiget/parse.py +++ b/src/wikiget/parse.py @@ -15,6 +15,8 @@ # You should have received a copy of the GNU General Public License # along with Wikiget. If not, see <https://www.gnu.org/licenses/>. +"""Parse download targets and batch files.""" + from __future__ import annotations import fileinput diff --git a/src/wikiget/validations.py b/src/wikiget/validations.py index 7c2b5ae..bde39df 100644 --- a/src/wikiget/validations.py +++ b/src/wikiget/validations.py @@ -15,6 +15,8 @@ # You should have received a copy of the GNU General Public License # along with Wikiget. If not, see <https://www.gnu.org/licenses/>. +"""Validate file and site input and verify file hashes.""" + from __future__ import annotations import hashlib diff --git a/src/wikiget/version.py b/src/wikiget/version.py index 479f200..0fe1802 100644 --- a/src/wikiget/version.py +++ b/src/wikiget/version.py @@ -15,4 +15,6 @@ # You should have received a copy of the GNU General Public License # along with Wikiget. If not, see <https://www.gnu.org/licenses/>. +"""Set the version string of the program.""" + __version__ = "0.8.0.dev0" diff --git a/src/wikiget/wikiget.py b/src/wikiget/wikiget.py index ca211af..870f7a2 100644 --- a/src/wikiget/wikiget.py +++ b/src/wikiget/wikiget.py @@ -15,6 +15,8 @@ # You should have received a copy of the GNU General Public License # along with Wikiget. If not, see <https://www.gnu.org/licenses/>. +"""Set up the command-line interface and handle program start and exit.""" + from __future__ import annotations import argparse @@ -138,5 +140,10 @@ def cli() -> None: logger.info("Starting download session using wikiget %s", wikiget.__version__) logger.debug("User agent: %s", wikiget.USER_AGENT) - exit_code = process_download(args) - sys.exit(exit_code) + try: + exit_code = process_download(args) + except KeyboardInterrupt: + logger.critical("Interrupted by user") + exit_code = 130 + finally: + sys.exit(exit_code) diff --git a/tests/test_wikiget_cli.py b/tests/test_wikiget_cli.py index 87bc069..898ab8e 100644 --- a/tests/test_wikiget_cli.py +++ b/tests/test_wikiget_cli.py @@ -29,7 +29,7 @@ from wikiget.wikiget import cli @patch("wikiget.wikiget.process_download") -class TestCli: +class TestWikigetCli: """Define tests related to wikiget.wikiget.cli.""" def test_cli_no_args(self, monkeypatch: pytest.MonkeyPatch) -> None: @@ -40,7 +40,7 @@ class TestCli: with pytest.raises(SystemExit) as e: cli() - assert e.value.code == 2 + assert e.value.code == 2 def test_cli_completed_successfully( self, mock_process_download: MagicMock, monkeypatch: pytest.MonkeyPatch @@ -54,7 +54,7 @@ class TestCli: with pytest.raises(SystemExit) as e: cli() - assert e.value.code == 0 + assert e.value.code == 0 def test_cli_completed_with_problems( self, mock_process_download: MagicMock, monkeypatch: pytest.MonkeyPatch @@ -68,7 +68,7 @@ class TestCli: with pytest.raises(SystemExit) as e: cli() - assert e.value.code == 1 + assert e.value.code == 1 def test_cli_logs( self, @@ -89,15 +89,40 @@ class TestCli: with pytest.raises(SystemExit): cli() - assert caplog.record_tuples == [ - ( - "wikiget.wikiget", - logging.INFO, - f"Starting download session using wikiget {__version__}", - ), - ( - "wikiget.wikiget", - logging.DEBUG, - f"User agent: {USER_AGENT}", - ), - ] + assert caplog.record_tuples == [ + ( + "wikiget.wikiget", + logging.INFO, + f"Starting download session using wikiget {__version__}", + ), + ( + "wikiget.wikiget", + logging.DEBUG, + f"User agent: {USER_AGENT}", + ), + ] + + def test_cli_interrupt( + self, + mock_process_download: MagicMock, + monkeypatch: pytest.MonkeyPatch, + caplog: pytest.LogCaptureFixture, + ) -> None: + """Test what happens when KeyboardInterrupt is raised during processing. + + A critical log message should be printed and the exit code should be 130. + """ + with monkeypatch.context() as m: + mock_process_download.side_effect = KeyboardInterrupt + m.setattr("sys.argv", ["wikiget", "File:Example.jpg"]) + + with pytest.raises(SystemExit) as e: + cli() + + assert e.value.code == 130 + # ignore the first two messages, since they're tested elsewhere + assert caplog.record_tuples[2] == ( + "wikiget.wikiget", + logging.CRITICAL, + "Interrupted by user", + ) |
