Move usertypes.DownloadTarget to downloads module
This commit is contained in:
parent
80562fbdca
commit
cf32aac111
@ -26,6 +26,7 @@ import posixpath
|
|||||||
import zipfile
|
import zipfile
|
||||||
import fnmatch
|
import fnmatch
|
||||||
|
|
||||||
|
from qutebrowser.browser import downloads
|
||||||
from qutebrowser.config import config
|
from qutebrowser.config import config
|
||||||
from qutebrowser.utils import objreg, standarddir, log, message, usertypes
|
from qutebrowser.utils import objreg, standarddir, log, message, usertypes
|
||||||
from qutebrowser.commands import cmdutils, cmdexc
|
from qutebrowser.commands import cmdutils, cmdexc
|
||||||
@ -208,7 +209,7 @@ class HostBlocker:
|
|||||||
else:
|
else:
|
||||||
fobj = io.BytesIO()
|
fobj = io.BytesIO()
|
||||||
fobj.name = 'adblock: ' + url.host()
|
fobj.name = 'adblock: ' + url.host()
|
||||||
target = usertypes.FileObjDownloadTarget(fobj)
|
target = downloads.FileObjDownloadTarget(fobj)
|
||||||
download = download_manager.get(url, target=target,
|
download = download_manager.get(url, target=target,
|
||||||
auto_remove=True)
|
auto_remove=True)
|
||||||
self._in_progress.append(download)
|
self._in_progress.append(download)
|
||||||
|
@ -1328,7 +1328,7 @@ class CommandDispatcher:
|
|||||||
if dest is None:
|
if dest is None:
|
||||||
target = None
|
target = None
|
||||||
else:
|
else:
|
||||||
target = usertypes.FileDownloadTarget(dest)
|
target = downloads.FileDownloadTarget(dest)
|
||||||
download_manager.get(url, target=target)
|
download_manager.get(url, target=target)
|
||||||
elif mhtml_:
|
elif mhtml_:
|
||||||
self._download_mhtml(dest)
|
self._download_mhtml(dest)
|
||||||
@ -1336,7 +1336,7 @@ class CommandDispatcher:
|
|||||||
if dest is None:
|
if dest is None:
|
||||||
target = None
|
target = None
|
||||||
else:
|
else:
|
||||||
target = usertypes.FileDownloadTarget(dest)
|
target = downloads.FileDownloadTarget(dest)
|
||||||
download_manager.get(self._current_url(), target=target)
|
download_manager.get(self._current_url(), target=target)
|
||||||
|
|
||||||
def _download_mhtml(self, dest=None):
|
def _download_mhtml(self, dest=None):
|
||||||
|
@ -164,6 +164,77 @@ def get_filename_question(*, suggested_filename, url, parent=None):
|
|||||||
return q
|
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):
|
class DownloadItemStats(QObject):
|
||||||
|
|
||||||
"""Statistics (bytes done, total bytes, time, etc.) about a download.
|
"""Statistics (bytes done, total bytes, time, etc.) about a download.
|
||||||
@ -565,13 +636,13 @@ class AbstractDownloadItem(QObject):
|
|||||||
"""Set the target for a given download.
|
"""Set the target for a given download.
|
||||||
|
|
||||||
Args:
|
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)
|
self._set_fileobj(target.fileobj, autoclose=False)
|
||||||
elif isinstance(target, usertypes.FileDownloadTarget):
|
elif isinstance(target, FileDownloadTarget):
|
||||||
self._set_filename(target.filename)
|
self._set_filename(target.filename)
|
||||||
elif isinstance(target, usertypes.OpenFileDownloadTarget):
|
elif isinstance(target, OpenFileDownloadTarget):
|
||||||
try:
|
try:
|
||||||
fobj = temp_download_manager.get_tmpfile(self.basename)
|
fobj = temp_download_manager.get_tmpfile(self.basename)
|
||||||
except OSError as exc:
|
except OSError as exc:
|
||||||
|
@ -372,7 +372,7 @@ class DownloadManager(downloads.AbstractDownloadManager):
|
|||||||
|
|
||||||
Args:
|
Args:
|
||||||
request: The QNetworkRequest to download.
|
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.
|
**kwargs: Passed to _fetch_request.
|
||||||
|
|
||||||
Return:
|
Return:
|
||||||
@ -430,7 +430,7 @@ class DownloadManager(downloads.AbstractDownloadManager):
|
|||||||
|
|
||||||
Args:
|
Args:
|
||||||
reply: The QNetworkReply to download.
|
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
|
auto_remove: Whether to remove the download even if
|
||||||
ui -> remove-finished-downloads is set to -1.
|
ui -> remove-finished-downloads is set to -1.
|
||||||
|
|
||||||
@ -456,7 +456,7 @@ class DownloadManager(downloads.AbstractDownloadManager):
|
|||||||
filename = downloads.immediate_download_path(prompt_download_directory)
|
filename = downloads.immediate_download_path(prompt_download_directory)
|
||||||
if filename is not None:
|
if filename is not None:
|
||||||
# User doesn't want to be asked, so just use the download_dir
|
# 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)
|
download.set_target(target)
|
||||||
return download
|
return download
|
||||||
|
|
||||||
|
@ -143,7 +143,7 @@ class DownloadManager(downloads.AbstractDownloadManager):
|
|||||||
filename = downloads.immediate_download_path()
|
filename = downloads.immediate_download_path()
|
||||||
if filename is not None:
|
if filename is not None:
|
||||||
# User doesn't want to be asked, so just use the download_dir
|
# 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)
|
download.set_target(target)
|
||||||
return
|
return
|
||||||
|
|
||||||
|
@ -345,7 +345,7 @@ class _Downloader:
|
|||||||
|
|
||||||
download_manager = objreg.get('qtnetwork-download-manager',
|
download_manager = objreg.get('qtnetwork-download-manager',
|
||||||
scope='window', window=self._win_id)
|
scope='window', window=self._win_id)
|
||||||
target = usertypes.FileObjDownloadTarget(_NoCloseBytesIO())
|
target = downloads.FileObjDownloadTarget(_NoCloseBytesIO())
|
||||||
item = download_manager.get(url, target=target,
|
item = download_manager.get(url, target=target,
|
||||||
auto_remove=True)
|
auto_remove=True)
|
||||||
self.pending_downloads.add((url, item))
|
self.pending_downloads.add((url, item))
|
||||||
|
@ -29,6 +29,7 @@ from PyQt5.QtCore import (pyqtSlot, pyqtSignal, Qt, QTimer, QDir, QModelIndex,
|
|||||||
from PyQt5.QtWidgets import (QWidget, QGridLayout, QVBoxLayout, QLineEdit,
|
from PyQt5.QtWidgets import (QWidget, QGridLayout, QVBoxLayout, QLineEdit,
|
||||||
QLabel, QFileSystemModel, QTreeView, QSizePolicy)
|
QLabel, QFileSystemModel, QTreeView, QSizePolicy)
|
||||||
|
|
||||||
|
from qutebrowser.browser import downloads
|
||||||
from qutebrowser.config import style
|
from qutebrowser.config import style
|
||||||
from qutebrowser.utils import usertypes, log, utils, qtutils, objreg, message
|
from qutebrowser.utils import usertypes, log, utils, qtutils, objreg, message
|
||||||
from qutebrowser.keyinput import modeman
|
from qutebrowser.keyinput import modeman
|
||||||
@ -687,11 +688,11 @@ class DownloadFilenamePrompt(FilenamePrompt):
|
|||||||
|
|
||||||
def accept(self, value=None):
|
def accept(self, value=None):
|
||||||
text = value if value is not None else self._lineedit.text()
|
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
|
return True
|
||||||
|
|
||||||
def download_open(self, cmdline):
|
def download_open(self, cmdline):
|
||||||
self.question.answer = usertypes.OpenFileDownloadTarget(cmdline)
|
self.question.answer = downloads.OpenFileDownloadTarget(cmdline)
|
||||||
self.question.done()
|
self.question.done()
|
||||||
message.global_bridge.prompt_done.emit(self.KEY_MODE)
|
message.global_bridge.prompt_done.emit(self.KEY_MODE)
|
||||||
|
|
||||||
|
@ -269,77 +269,6 @@ JsWorld = enum('JsWorld', ['main', 'application', 'user', 'jseval'])
|
|||||||
MessageLevel = enum('MessageLevel', ['error', 'warning', 'info'])
|
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):
|
class Question(QObject):
|
||||||
|
|
||||||
"""A question asked to the user, e.g. via the status bar.
|
"""A question asked to the user, e.g. via the status bar.
|
||||||
|
@ -17,6 +17,7 @@
|
|||||||
# You should have received a copy of the GNU General Public License
|
# You should have received a copy of the GNU General Public License
|
||||||
# along with qutebrowser. If not, see <http://www.gnu.org/licenses/>.
|
# along with qutebrowser. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
import pytest
|
||||||
|
|
||||||
from qutebrowser.browser import downloads, qtnetworkdownloads
|
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)
|
manager = qtnetworkdownloads.DownloadManager(win_id=0)
|
||||||
model = downloads.DownloadModel(manager)
|
model = downloads.DownloadModel(manager)
|
||||||
qtmodeltester.check(model)
|
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)
|
||||||
|
@ -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)
|
|
Loading…
Reference in New Issue
Block a user