Skip to content

Commit

Permalink
feat: Support aria2c input files with options
Browse files Browse the repository at this point in the history
Issue #70: #70
PR #91: #91
  • Loading branch information
jonnieey committed Apr 4, 2021
1 parent 5a4ab65 commit a603961
Show file tree
Hide file tree
Showing 6 changed files with 91 additions and 5 deletions.
56 changes: 52 additions & 4 deletions src/aria2p/api.py
Expand Up @@ -18,7 +18,6 @@
from aria2p.options import Options
from aria2p.stats import Stats
from aria2p.types import OperationResult, OptionsType, PathOrStr
from aria2p.utils import read_lines


class API:
Expand Down Expand Up @@ -74,9 +73,9 @@ def add(self, uri: str) -> List[Download]: # noqa: WPS231 (not that complex)
elif path.suffix == ".metalink":
new_downloads.extend(self.add_metalink(path))
else:
for line in read_lines(path):
if line:
new_downloads.extend(self.add(line))
for uris, options in self.parse_input_file(path):
new_downloads.append(self.add_uris(uris, options=options))

elif uri.startswith("magnet:?"):
new_downloads.append(self.add_magnet(uri))
else:
Expand Down Expand Up @@ -850,3 +849,52 @@ def stop_listening(self) -> None:
if self.listener:
self.listener.join()
self.listener = None

def split_input_file(self, lines):
"""
Helper to split downloads in an input file.
Arguments:
lines: The lines of the input file.
"""
block = []
for line in lines:
if line.lstrip().startswith("#"): # Ignore Comments
continue
if not line.strip(): # Ignore empty line
continue
if not line.startswith(" "): # Read uri
if block:
yield block
block = []
block.append(line.rstrip("\n"))
if block:
yield block

def parse_input_file(self, input_file):
"""
Parse a file with URIs or an aria2c input file.
Arguments:
input_file: Path to file with URIs or aria2c input file.
Returns:
List of tuples containing list of URIs and dictionary with aria2c options.
"""

downloads = []
with Path(input_file).open() as fd:
for download_lines in self.split_input_file(fd):
uris = download_lines[0].split("\t")
options = {}
try:
for option_line in download_lines[1:]:
option_name, option_value = option_line.split("=", 1)
options[option_name.lstrip()] = option_value
downloads.append((uris, options))
except ValueError as error:
logger.error(f"Skipping download because of invalid option line '{option_line}'")
logger.opt(exception=True).trace(error)

return downloads
6 changes: 6 additions & 0 deletions tests/__init__.py
Expand Up @@ -16,3 +16,9 @@
"http://ftp.free.fr/mirrors/ftp.xubuntu.com/releases/18.04/release/xubuntu-18.04.1-desktop-amd64.iso",
"http://mirror.us.leaseweb.net/ubuntu-cdimage/xubuntu/releases/18.04/release/xubuntu-18.04.1-desktop-amd64.iso",
]

INPUT_FILES = [
TESTS_DATA_DIR / "input_files" / "two-valid-downloads",
TESTS_DATA_DIR / "input_files" / "one-valid-one-invalid-downloads",
TESTS_DATA_DIR / "input_files" / "two-invalid-downloads",
]
7 changes: 7 additions & 0 deletions tests/data/input_files/one-valid-one-invalid-downloads
@@ -0,0 +1,7 @@
# A valid aria2c input file.
magnet:?xt=urn:btih:RX46NCATYQRS3MCQNSEXVZGCCDNKTASQ
max-download-limit100000

# Download 2.
magnet:?xt=urn:btih:CVVWTODEHPIRQSNF3DZBELQT7O3BXUCB
max-resume-failure-tries=10
7 changes: 7 additions & 0 deletions tests/data/input_files/two-invalid-downloads
@@ -0,0 +1,7 @@
# An invalid aria2c input file.
magnet:?xt=urn:btih:RX46NCATYQRS3MCQNSEXVZGCCDNKTASQ
max-download-limit 100000

# Download 2.
magnet:?xt=urn:btih:CVVWTODEHPIRQSNF3DZBELQT7O3BXUCB
max-resume-failure-tries10
7 changes: 7 additions & 0 deletions tests/data/input_files/two-valid-downloads
@@ -0,0 +1,7 @@
# A valid aria2c input file.
magnet:?xt=urn:btih:RX46NCATYQRS3MCQNSEXVZGCCDNKTASQ
max-download-limit=100000

# Download 2.
magnet:?xt=urn:btih:CVVWTODEHPIRQSNF3DZBELQT7O3BXUCB
max-resume-failure-tries=10
13 changes: 12 additions & 1 deletion tests/test_api.py
Expand Up @@ -7,7 +7,7 @@

from aria2p import API, Client, ClientException, Download

from . import BUNSENLABS_MAGNET, BUNSENLABS_TORRENT, CONFIGS_DIR, DEBIAN_METALINK, XUBUNTU_MIRRORS
from . import BUNSENLABS_MAGNET, BUNSENLABS_TORRENT, CONFIGS_DIR, DEBIAN_METALINK, INPUT_FILES, XUBUNTU_MIRRORS
from .conftest import Aria2Server


Expand Down Expand Up @@ -346,3 +346,14 @@ def thread_target():
server.client.stop_listening()
time.sleep(1)
server.api.stop_listening()


def test_parse_input_file(server):
downloads = server.api.parse_input_file(INPUT_FILES[0])
assert len(downloads) == 2

downloads = server.api.parse_input_file(INPUT_FILES[1])
assert len(downloads) == 1

downloads = server.api.parse_input_file(INPUT_FILES[2])
assert len(downloads) == 0

0 comments on commit a603961

Please sign in to comment.