Move usertypes.DownloadTarget to downloads module

This commit is contained in:
Florian Bruhin 2016-11-09 08:15:31 +01:00
parent 80562fbdca
commit cf32aac111
10 changed files with 120 additions and 144 deletions

View File

@ -26,6 +26,7 @@ import posixpath
import zipfile
import fnmatch
from qutebrowser.browser import downloads
from qutebrowser.config import config
from qutebrowser.utils import objreg, standarddir, log, message, usertypes
from qutebrowser.commands import cmdutils, cmdexc
@ -208,7 +209,7 @@ class HostBlocker:
else:
fobj = io.BytesIO()
fobj.name = 'adblock: ' + url.host()
target = usertypes.FileObjDownloadTarget(fobj)
target = downloads.FileObjDownloadTarget(fobj)
download = download_manager.get(url, target=target,
auto_remove=True)
self._in_progress.append(download)

View File

@ -1328,7 +1328,7 @@ class CommandDispatcher:
if dest is None:
target = None
else:
target = usertypes.FileDownloadTarget(dest)
target = downloads.FileDownloadTarget(dest)
download_manager.get(url, target=target)
elif mhtml_:
self._download_mhtml(dest)
@ -1336,7 +1336,7 @@ class CommandDispatcher:
if dest is None:
target = None
else:
target = usertypes.FileDownloadTarget(dest)
target = downloads.FileDownloadTarget(dest)
download_manager.get(self._current_url(), target=target)
def _download_mhtml(self, dest=None):

View File

@ -164,6 +164,77 @@ def get_filename_question(*, suggested_filename, url, parent=None):
return q
class NoFilenameError(Exception):
"""Raised when we can't find out a filename in DownloadTarget."""
# Where a download should be saved
class _DownloadTarget:
"""Abstract base class for different download targets."""
def __init__(self):
raise NotImplementedError
def suggested_filename(self):
"""Get the suggested filename for this download target."""
raise NotImplementedError
class FileDownloadTarget(_DownloadTarget):
"""Save the download to the given file.
Attributes:
filename: Filename where the download should be saved.
"""
def __init__(self, filename):
# pylint: disable=super-init-not-called
self.filename = filename
def suggested_filename(self):
return os.path.basename(self.filename)
class FileObjDownloadTarget(_DownloadTarget):
"""Save the download to the given file-like object.
Attributes:
fileobj: File-like object where the download should be written to.
"""
def __init__(self, fileobj):
# pylint: disable=super-init-not-called
self.fileobj = fileobj
def suggested_filename(self):
try:
return self.fileobj.name
except AttributeError:
raise NoFilenameError
class OpenFileDownloadTarget(_DownloadTarget):
"""Save the download in a temp dir and directly open it.
Attributes:
cmdline: The command to use as string. A `{}` is expanded to the
filename. None means to use the system's default application.
If no `{}` is found, the filename is appended to the cmdline.
"""
def __init__(self, cmdline=None):
# pylint: disable=super-init-not-called
self.cmdline = cmdline
def suggested_filename(self):
raise NoFilenameError
class DownloadItemStats(QObject):
"""Statistics (bytes done, total bytes, time, etc.) about a download.
@ -565,13 +636,13 @@ class AbstractDownloadItem(QObject):
"""Set the target for a given download.
Args:
target: The usertypes.DownloadTarget for this download.
target: The DownloadTarget for this download.
"""
if isinstance(target, usertypes.FileObjDownloadTarget):
if isinstance(target, FileObjDownloadTarget):
self._set_fileobj(target.fileobj, autoclose=False)
elif isinstance(target, usertypes.FileDownloadTarget):
elif isinstance(target, FileDownloadTarget):
self._set_filename(target.filename)
elif isinstance(target, usertypes.OpenFileDownloadTarget):
elif isinstance(target, OpenFileDownloadTarget):
try:
fobj = temp_download_manager.get_tmpfile(self.basename)
except OSError as exc:

View File

@ -372,7 +372,7 @@ class DownloadManager(downloads.AbstractDownloadManager):
Args:
request: The QNetworkRequest to download.
target: Where to save the download as usertypes.DownloadTarget.
target: Where to save the download as downloads.DownloadTarget.
**kwargs: Passed to _fetch_request.
Return:
@ -430,7 +430,7 @@ class DownloadManager(downloads.AbstractDownloadManager):
Args:
reply: The QNetworkReply to download.
target: Where to save the download as usertypes.DownloadTarget.
target: Where to save the download as downloads.DownloadTarget.
auto_remove: Whether to remove the download even if
ui -> remove-finished-downloads is set to -1.
@ -456,7 +456,7 @@ class DownloadManager(downloads.AbstractDownloadManager):
filename = downloads.immediate_download_path(prompt_download_directory)
if filename is not None:
# User doesn't want to be asked, so just use the download_dir
target = usertypes.FileDownloadTarget(filename)
target = downloads.FileDownloadTarget(filename)
download.set_target(target)
return download

View File

@ -143,7 +143,7 @@ class DownloadManager(downloads.AbstractDownloadManager):
filename = downloads.immediate_download_path()
if filename is not None:
# User doesn't want to be asked, so just use the download_dir
target = usertypes.FileDownloadTarget(filename)
target = downloads.FileDownloadTarget(filename)
download.set_target(target)
return

View File

@ -345,7 +345,7 @@ class _Downloader:
download_manager = objreg.get('qtnetwork-download-manager',
scope='window', window=self._win_id)
target = usertypes.FileObjDownloadTarget(_NoCloseBytesIO())
target = downloads.FileObjDownloadTarget(_NoCloseBytesIO())
item = download_manager.get(url, target=target,
auto_remove=True)
self.pending_downloads.add((url, item))

View File

@ -29,6 +29,7 @@ from PyQt5.QtCore import (pyqtSlot, pyqtSignal, Qt, QTimer, QDir, QModelIndex,
from PyQt5.QtWidgets import (QWidget, QGridLayout, QVBoxLayout, QLineEdit,
QLabel, QFileSystemModel, QTreeView, QSizePolicy)
from qutebrowser.browser import downloads
from qutebrowser.config import style
from qutebrowser.utils import usertypes, log, utils, qtutils, objreg, message
from qutebrowser.keyinput import modeman
@ -687,11 +688,11 @@ class DownloadFilenamePrompt(FilenamePrompt):
def accept(self, value=None):
text = value if value is not None else self._lineedit.text()
self.question.answer = usertypes.FileDownloadTarget(text)
self.question.answer = downloads.FileDownloadTarget(text)
return True
def download_open(self, cmdline):
self.question.answer = usertypes.OpenFileDownloadTarget(cmdline)
self.question.answer = downloads.OpenFileDownloadTarget(cmdline)
self.question.done()
message.global_bridge.prompt_done.emit(self.KEY_MODE)

View File

@ -269,77 +269,6 @@ JsWorld = enum('JsWorld', ['main', 'application', 'user', 'jseval'])
MessageLevel = enum('MessageLevel', ['error', 'warning', 'info'])
class NoFilenameError(Exception):
"""Raised when we can't find out a filename in DownloadTarget."""
# Where a download should be saved
class DownloadTarget:
"""Abstract base class for different download targets."""
def __init__(self):
raise NotImplementedError
def suggested_filename(self):
"""Get the suggested filename for this download target."""
raise NotImplementedError
class FileDownloadTarget(DownloadTarget):
"""Save the download to the given file.
Attributes:
filename: Filename where the download should be saved.
"""
def __init__(self, filename):
# pylint: disable=super-init-not-called
self.filename = filename
def suggested_filename(self):
return os.path.basename(self.filename)
class FileObjDownloadTarget(DownloadTarget):
"""Save the download to the given file-like object.
Attributes:
fileobj: File-like object where the download should be written to.
"""
def __init__(self, fileobj):
# pylint: disable=super-init-not-called
self.fileobj = fileobj
def suggested_filename(self):
try:
return self.fileobj.name
except AttributeError:
raise NoFilenameError
class OpenFileDownloadTarget(DownloadTarget):
"""Save the download in a temp dir and directly open it.
Attributes:
cmdline: The command to use as string. A `{}` is expanded to the
filename. None means to use the system's default application.
If no `{}` is found, the filename is appended to the cmdline.
"""
def __init__(self, cmdline=None):
# pylint: disable=super-init-not-called
self.cmdline = cmdline
def suggested_filename(self):
raise NoFilenameError
class Question(QObject):
"""A question asked to the user, e.g. via the status bar.

View File

@ -17,6 +17,7 @@
# You should have received a copy of the GNU General Public License
# along with qutebrowser. If not, see <http://www.gnu.org/licenses/>.
import pytest
from qutebrowser.browser import downloads, qtnetworkdownloads
@ -27,3 +28,35 @@ def test_download_model(qapp, qtmodeltester, config_stub, cookiejar_and_cache):
manager = qtnetworkdownloads.DownloadManager(win_id=0)
model = downloads.DownloadModel(manager)
qtmodeltester.check(model)
class TestDownloadTarget:
def test_base(self):
with pytest.raises(NotImplementedError):
downloads._DownloadTarget()
def test_filename(self):
target = downloads.FileDownloadTarget("/foo/bar")
assert target.filename == "/foo/bar"
def test_fileobj(self):
fobj = object()
target = downloads.FileObjDownloadTarget(fobj)
assert target.fileobj is fobj
def test_openfile(self):
target = downloads.OpenFileDownloadTarget()
assert target.cmdline is None
def test_openfile_custom_command(self):
target = downloads.OpenFileDownloadTarget('echo')
assert target.cmdline == 'echo'
@pytest.mark.parametrize('obj', [
downloads.FileDownloadTarget('foobar'),
downloads.FileObjDownloadTarget(None),
downloads.OpenFileDownloadTarget(),
])
def test_class_hierarchy(self, obj):
assert isinstance(obj, downloads._DownloadTarget)

View File

@ -1,59 +0,0 @@
# vim: ft=python fileencoding=utf-8 sts=4 sw=4 et:
# Copyright 2016 Daniel Schadt
#
# This file is part of qutebrowser.
#
# qutebrowser is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# qutebrowser is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with qutebrowser. If not, see <http://www.gnu.org/licenses/>.
"""Tests for the DownloadTarget class."""
from qutebrowser.utils import usertypes
import pytest
def test_base():
with pytest.raises(NotImplementedError):
usertypes.DownloadTarget()
def test_filename():
target = usertypes.FileDownloadTarget("/foo/bar")
assert target.filename == "/foo/bar"
def test_fileobj():
fobj = object()
target = usertypes.FileObjDownloadTarget(fobj)
assert target.fileobj is fobj
def test_openfile():
target = usertypes.OpenFileDownloadTarget()
assert target.cmdline is None
def test_openfile_custom_command():
target = usertypes.OpenFileDownloadTarget('echo')
assert target.cmdline == 'echo'
@pytest.mark.parametrize('obj', [
usertypes.FileDownloadTarget('foobar'),
usertypes.FileObjDownloadTarget(None),
usertypes.OpenFileDownloadTarget(),
])
def test_class_hierarchy(obj):
assert isinstance(obj, usertypes.DownloadTarget)