Privatize all attributes which aren't needed from the outside.
This commit is contained in:
parent
75da8a7f1b
commit
62e55499eb
@ -43,15 +43,15 @@ class DownloadItem(QObject):
|
||||
estimate the remaining time.
|
||||
|
||||
Attributes:
|
||||
reply: The QNetworkReply associated with this download.
|
||||
bytes_done: How many bytes there are already downloaded.
|
||||
bytes_total: The total count of bytes.
|
||||
None if the total is unknown.
|
||||
speed: The current download speed, in bytes per second.
|
||||
fileobj: The file object to download the file to.
|
||||
filename: The filename of the download.
|
||||
is_cancelled: Whether the download was cancelled.
|
||||
speed_avg: A rolling average of speeds.
|
||||
_bytes_done: How many bytes there are already downloaded.
|
||||
_bytes_total: The total count of bytes.
|
||||
None if the total is unknown.
|
||||
_speed: The current download speed, in bytes per second.
|
||||
_fileobj: The file object to download the file to.
|
||||
_filename: The filename of the download.
|
||||
_is_cancelled: Whether the download was cancelled.
|
||||
_speed_avg: A rolling average of speeds.
|
||||
_reply: The QNetworkReply associated with this download.
|
||||
_last_done: The count of bytes which where downloaded when calculating
|
||||
the speed the last time.
|
||||
|
||||
@ -77,18 +77,18 @@ class DownloadItem(QObject):
|
||||
reply: The QNetworkReply to download.
|
||||
"""
|
||||
super().__init__(parent)
|
||||
self.reply = reply
|
||||
self.bytes_total = None
|
||||
self.speed = 0
|
||||
self._reply = reply
|
||||
self._bytes_total = None
|
||||
self._speed = 0
|
||||
self.basename = '???'
|
||||
samples = int(self.SPEED_AVG_WINDOW *
|
||||
(1000 / self.SPEED_REFRESH_INTERVAL))
|
||||
self.speed_avg = collections.deque(maxlen=samples)
|
||||
self.fileobj = None
|
||||
self.filename = None
|
||||
self.is_cancelled = False
|
||||
self._speed_avg = collections.deque(maxlen=samples)
|
||||
self._fileobj = None
|
||||
self._filename = None
|
||||
self._is_cancelled = False
|
||||
self._do_delayed_write = False
|
||||
self.bytes_done = 0
|
||||
self._bytes_done = 0
|
||||
self._last_done = 0
|
||||
reply.setReadBufferSize(16 * 1024 * 1024)
|
||||
reply.downloadProgress.connect(self.on_download_progress)
|
||||
@ -115,11 +115,11 @@ class DownloadItem(QObject):
|
||||
|
||||
Example: foo.pdf [699.2kB/s|0.34|16%|4.253/25.124]
|
||||
"""
|
||||
speed = utils.format_size(self.speed, suffix='B/s')
|
||||
down = utils.format_size(self.bytes_done, suffix='B')
|
||||
speed = utils.format_size(self._speed, suffix='B/s')
|
||||
down = utils.format_size(self._bytes_done, suffix='B')
|
||||
perc = self._percentage()
|
||||
remaining = self._remaining_time()
|
||||
if all(e is None for e in (perc, remaining, self.bytes_total)):
|
||||
if all(e is None for e in (perc, remaining, self._bytes_total)):
|
||||
return ('{name} [{speed:>10}|{down}]'.format(
|
||||
name=self.basename, speed=speed, down=down))
|
||||
if perc is None:
|
||||
@ -130,7 +130,7 @@ class DownloadItem(QObject):
|
||||
remaining = '?'
|
||||
else:
|
||||
remaining = utils.format_seconds(remaining)
|
||||
total = utils.format_size(self.bytes_total, suffix='B')
|
||||
total = utils.format_size(self._bytes_total, suffix='B')
|
||||
return ('{name} [{speed:>10}|{remaining:>5}|{perc:>2}%|'
|
||||
'{down}/{total}]'.format(name=self.basename, speed=speed,
|
||||
remaining=remaining, perc=perc,
|
||||
@ -138,36 +138,36 @@ class DownloadItem(QObject):
|
||||
|
||||
def _die(self, msg):
|
||||
"""Abort the download and emit an error."""
|
||||
self.reply.downloadProgress.disconnect()
|
||||
self.reply.finished.disconnect()
|
||||
self.reply.error.disconnect()
|
||||
self.reply.readyRead.disconnect()
|
||||
self.bytes_done = self.bytes_total
|
||||
self._reply.downloadProgress.disconnect()
|
||||
self._reply.finished.disconnect()
|
||||
self._reply.error.disconnect()
|
||||
self._reply.readyRead.disconnect()
|
||||
self._bytes_done = self._bytes_total
|
||||
self.timer.stop()
|
||||
self.error.emit(msg)
|
||||
self.reply.abort()
|
||||
self.reply.deleteLater()
|
||||
if self.fileobj is not None:
|
||||
self._reply.abort()
|
||||
self._reply.deleteLater()
|
||||
if self._fileobj is not None:
|
||||
try:
|
||||
self.fileobj.close()
|
||||
self._fileobj.close()
|
||||
except OSError as e:
|
||||
self.error.emit(e.strerror)
|
||||
self.finished.emit()
|
||||
|
||||
def _percentage(self):
|
||||
"""The current download percentage, or None if unknown."""
|
||||
if self.bytes_total == 0 or self.bytes_total is None:
|
||||
if self._bytes_total == 0 or self._bytes_total is None:
|
||||
return None
|
||||
else:
|
||||
return 100 * self.bytes_done / self.bytes_total
|
||||
return 100 * self._bytes_done / self._bytes_total
|
||||
|
||||
def _remaining_time(self):
|
||||
"""The remaining download time in seconds, or None."""
|
||||
if self.bytes_total is None or not self.speed_avg:
|
||||
if self._bytes_total is None or not self._speed_avg:
|
||||
# No average yet or we don't know the total size.
|
||||
return None
|
||||
remaining_bytes = self.bytes_total - self.bytes_done
|
||||
avg = sum(self.speed_avg) / len(self.speed_avg)
|
||||
remaining_bytes = self._bytes_total - self._bytes_done
|
||||
avg = sum(self._speed_avg) / len(self._speed_avg)
|
||||
if avg == 0:
|
||||
# Download stalled
|
||||
return None
|
||||
@ -189,13 +189,13 @@ class DownloadItem(QObject):
|
||||
"""Cancel the download."""
|
||||
log.downloads.debug("cancelled")
|
||||
self.cancelled.emit()
|
||||
self.is_cancelled = True
|
||||
self.reply.abort()
|
||||
self.reply.deleteLater()
|
||||
if self.fileobj is not None:
|
||||
self.fileobj.close()
|
||||
if self.filename is not None and os.path.exists(self.filename):
|
||||
os.remove(self.filename)
|
||||
self._is_cancelled = True
|
||||
self._reply.abort()
|
||||
self._reply.deleteLater()
|
||||
if self._fileobj is not None:
|
||||
self._fileobj.close()
|
||||
if self._filename is not None and os.path.exists(self._filename):
|
||||
os.remove(self._filename)
|
||||
self.finished.emit()
|
||||
|
||||
def set_filename(self, filename):
|
||||
@ -205,19 +205,19 @@ class DownloadItem(QObject):
|
||||
filename: The full filename to save the download to.
|
||||
None: special value to stop the download.
|
||||
"""
|
||||
if self.filename is not None:
|
||||
if self._filename is not None:
|
||||
raise ValueError("Filename was already set! filename: {}, "
|
||||
"existing: {}".format(filename, self.filename))
|
||||
"existing: {}".format(filename, self._filename))
|
||||
filename = os.path.expanduser(filename)
|
||||
if os.path.isabs(filename) and os.path.isdir(filename):
|
||||
# We got an absolute directory from the user, so we save it under
|
||||
# the default filename in that directory.
|
||||
self.filename = os.path.join(filename, self.basename)
|
||||
self._filename = os.path.join(filename, self.basename)
|
||||
elif os.path.isabs(filename):
|
||||
# We got an absolute filename from the user, so we save it under
|
||||
# that filename.
|
||||
self.filename = filename
|
||||
self.basename = os.path.basename(self.filename)
|
||||
self._filename = filename
|
||||
self.basename = os.path.basename(self._filename)
|
||||
else:
|
||||
# We only got a filename (without directory) from the user, so we
|
||||
# save it under that filename in the default directory.
|
||||
@ -225,11 +225,11 @@ class DownloadItem(QObject):
|
||||
if download_dir is None:
|
||||
download_dir = utils.get_standard_dir(
|
||||
QStandardPaths.DownloadLocation)
|
||||
self.filename = os.path.join(download_dir, filename)
|
||||
self._filename = os.path.join(download_dir, filename)
|
||||
self.basename = filename
|
||||
log.downloads.debug("Setting filename to {}".format(filename))
|
||||
try:
|
||||
self.fileobj = open(self.filename, 'wb')
|
||||
self._fileobj = open(self._filename, 'wb')
|
||||
if self._do_delayed_write:
|
||||
# Downloading to the buffer in RAM has already finished so we
|
||||
# write out the data and clean up now.
|
||||
@ -246,10 +246,10 @@ class DownloadItem(QObject):
|
||||
"""Write buffered data to disk and finish the QNetworkReply."""
|
||||
log.downloads.debug("Doing delayed write...")
|
||||
self._do_delayed_write = False
|
||||
self.fileobj.write(self.reply.readAll())
|
||||
self.fileobj.close()
|
||||
self.reply.close()
|
||||
self.reply.deleteLater()
|
||||
self._fileobj.write(self._reply.readAll())
|
||||
self._fileobj.close()
|
||||
self._reply.close()
|
||||
self._reply.deleteLater()
|
||||
self.finished.emit()
|
||||
log.downloads.debug("Download finished")
|
||||
|
||||
@ -263,8 +263,8 @@ class DownloadItem(QObject):
|
||||
"""
|
||||
if bytes_total == -1:
|
||||
bytes_total = None
|
||||
self.bytes_done = bytes_done
|
||||
self.bytes_total = bytes_total
|
||||
self._bytes_done = bytes_done
|
||||
self._bytes_total = bytes_total
|
||||
self.data_changed.emit()
|
||||
|
||||
@pyqtSlot()
|
||||
@ -275,12 +275,12 @@ class DownloadItem(QObject):
|
||||
doesn't mean the download (i.e. writing data to the disk) is finished
|
||||
as well. Therefore, we can't close() the QNetworkReply in here yet.
|
||||
"""
|
||||
self.bytes_done = self.bytes_total
|
||||
self._bytes_done = self._bytes_total
|
||||
self.timer.stop()
|
||||
if self.is_cancelled:
|
||||
if self._is_cancelled:
|
||||
return
|
||||
log.downloads.debug("Reply finished, fileobj {}".format(self.fileobj))
|
||||
if self.fileobj is None:
|
||||
log.downloads.debug("Reply finished, fileobj {}".format(self._fileobj))
|
||||
if self._fileobj is None:
|
||||
# We'll handle emptying the buffer and cleaning up as soon as the
|
||||
# filename is set.
|
||||
self._do_delayed_write = True
|
||||
@ -292,11 +292,11 @@ class DownloadItem(QObject):
|
||||
@pyqtSlot()
|
||||
def on_ready_read(self):
|
||||
"""Read available data and save file when ready to read."""
|
||||
if self.fileobj is None:
|
||||
if self._fileobj is None:
|
||||
# No filename has been set yet, so we don't empty the buffer.
|
||||
return
|
||||
try:
|
||||
self.fileobj.write(self.reply.readAll())
|
||||
self._fileobj.write(self._reply.readAll())
|
||||
except OSError as e:
|
||||
self._die(e.strerror)
|
||||
|
||||
@ -306,15 +306,15 @@ class DownloadItem(QObject):
|
||||
if code == QNetworkReply.OperationCanceledError:
|
||||
return
|
||||
else:
|
||||
self.error.emit(self.reply.errorString())
|
||||
self.error.emit(self._reply.errorString())
|
||||
|
||||
@pyqtSlot()
|
||||
def update_speed(self):
|
||||
"""Recalculate the current download speed."""
|
||||
delta = self.bytes_done - self._last_done
|
||||
self.speed = delta * 1000 / self.SPEED_REFRESH_INTERVAL
|
||||
self.speed_avg.append(self.speed)
|
||||
self._last_done = self.bytes_done
|
||||
delta = self._bytes_done - self._last_done
|
||||
self._speed = delta * 1000 / self.SPEED_REFRESH_INTERVAL
|
||||
self._speed_avg.append(self._speed)
|
||||
self._last_done = self._bytes_done
|
||||
self.data_changed.emit()
|
||||
|
||||
|
||||
|
@ -91,16 +91,16 @@ class register: # pylint: disable=invalid-name
|
||||
much cleaner to implement.
|
||||
|
||||
Attributes:
|
||||
instance: The instance to be used as "self", as a dotted string.
|
||||
name: The name (as string) or names (as list) of the command.
|
||||
split: Whether to split the arguments.
|
||||
hide: Whether to hide the command or not.
|
||||
completion: Which completion to use for arguments, as a list of
|
||||
strings.
|
||||
modes/not_modes: List of modes to use/not use.
|
||||
needs_js: If javascript is needed for this command.
|
||||
debug: Whether this is a debugging command (only shown with --debug).
|
||||
ignore_args: Whether to ignore the arguments of the function.
|
||||
_instance: The instance to be used as "self", as a dotted string.
|
||||
_name: The name (as string) or names (as list) of the command.
|
||||
_split: Whether to split the arguments.
|
||||
_hide: Whether to hide the command or not.
|
||||
_completion: Which completion to use for arguments, as a list of
|
||||
strings.
|
||||
_modes/_not_modes: List of modes to use/not use.
|
||||
_needs_js: If javascript is needed for this command.
|
||||
_debug: Whether this is a debugging command (only shown with --debug).
|
||||
_ignore_args: Whether to ignore the arguments of the function.
|
||||
"""
|
||||
|
||||
def __init__(self, instance=None, name=None, split=True, hide=False,
|
||||
@ -116,16 +116,16 @@ class register: # pylint: disable=invalid-name
|
||||
# pylint: disable=too-many-arguments
|
||||
if modes is not None and not_modes is not None:
|
||||
raise ValueError("Only modes or not_modes can be given!")
|
||||
self.name = name
|
||||
self.split = split
|
||||
self.hide = hide
|
||||
self.instance = instance
|
||||
self.completion = completion
|
||||
self.modes = modes
|
||||
self.not_modes = not_modes
|
||||
self.needs_js = needs_js
|
||||
self.debug = debug
|
||||
self.ignore_args = ignore_args
|
||||
self._name = name
|
||||
self._split = split
|
||||
self._hide = hide
|
||||
self._instance = instance
|
||||
self._completion = completion
|
||||
self._modes = modes
|
||||
self._not_modes = not_modes
|
||||
self._needs_js = needs_js
|
||||
self._debug = debug
|
||||
self._ignore_args = ignore_args
|
||||
if modes is not None:
|
||||
for m in modes:
|
||||
if not isinstance(m, usertypes.KeyMode):
|
||||
@ -150,12 +150,12 @@ class register: # pylint: disable=invalid-name
|
||||
Return:
|
||||
A list of names, with the main name being the first item.
|
||||
"""
|
||||
if self.name is None:
|
||||
if self._name is None:
|
||||
return [func.__name__.lower().replace('_', '-')]
|
||||
elif isinstance(self.name, str):
|
||||
return [self.name]
|
||||
elif isinstance(self._name, str):
|
||||
return [self._name]
|
||||
else:
|
||||
return self.name
|
||||
return self._name
|
||||
|
||||
def __call__(self, func):
|
||||
"""Register the command before running the function.
|
||||
@ -178,10 +178,11 @@ class register: # pylint: disable=invalid-name
|
||||
if name in cmd_dict:
|
||||
raise ValueError("{} is already registered!".format(name))
|
||||
cmd = command.Command(
|
||||
name=names[0], split=self.split, hide=self.hide,
|
||||
instance=self.instance, completion=self.completion,
|
||||
modes=self.modes, not_modes=self.not_modes, needs_js=self.needs_js,
|
||||
is_debug=self.debug, ignore_args=self.ignore_args, handler=func)
|
||||
name=names[0], split=self._split, hide=self._hide,
|
||||
instance=self._instance, completion=self._completion,
|
||||
modes=self._modes, not_modes=self._not_modes,
|
||||
needs_js=self._needs_js, is_debug=self._debug,
|
||||
ignore_args=self._ignore_args, handler=func)
|
||||
for name in names:
|
||||
cmd_dict[name] = cmd
|
||||
aliases += names[1:]
|
||||
|
@ -37,17 +37,18 @@ class Command:
|
||||
name: The main name of the command.
|
||||
split: Whether to split the arguments.
|
||||
hide: Whether to hide the arguments or not.
|
||||
count: Whether the command supports a count, or not.
|
||||
desc: The description of the command.
|
||||
instance: How to get to the "self" argument of the handler.
|
||||
A dotted string as viewed from app.py, or None.
|
||||
handler: The handler function to call.
|
||||
completion: Completions to use for arguments, as a list of strings.
|
||||
needs_js: Whether the command needs javascript enabled
|
||||
debug: Whether this is a debugging command (only shown with --debug).
|
||||
parser: The ArgumentParser to use to parse this command.
|
||||
type_conv: A mapping of conversion functions for arguments.
|
||||
name_conv: A mapping of argument names to parameter names.
|
||||
_type_conv: A mapping of conversion functions for arguments.
|
||||
_name_conv: A mapping of argument names to parameter names.
|
||||
_needs_js: Whether the command needs javascript enabled
|
||||
_modes: The modes the command can be executed in.
|
||||
_not_modes: The modes the command can not be executed in.
|
||||
_count: Whether the command supports a count, or not.
|
||||
_instance: The object to bind 'self' to.
|
||||
|
||||
Class attributes:
|
||||
AnnotationInfo: Named tuple for info from an annotation.
|
||||
@ -66,11 +67,11 @@ class Command:
|
||||
self.name = name
|
||||
self.split = split
|
||||
self.hide = hide
|
||||
self.instance = instance
|
||||
self._instance = instance
|
||||
self.completion = completion
|
||||
self.modes = modes
|
||||
self.not_modes = not_modes
|
||||
self.needs_js = needs_js
|
||||
self._modes = modes
|
||||
self._not_modes = not_modes
|
||||
self._needs_js = needs_js
|
||||
self.debug = is_debug
|
||||
self.ignore_args = ignore_args
|
||||
self.handler = handler
|
||||
@ -84,13 +85,13 @@ class Command:
|
||||
self._check_func()
|
||||
self.opt_args = collections.OrderedDict()
|
||||
self.namespace = None
|
||||
self.count = None
|
||||
self._count = None
|
||||
self.pos_args = []
|
||||
has_count, desc, type_conv, name_conv = self._inspect_func()
|
||||
self.has_count = has_count
|
||||
self.desc = desc
|
||||
self.type_conv = type_conv
|
||||
self.name_conv = name_conv
|
||||
self._type_conv = type_conv
|
||||
self._name_conv = name_conv
|
||||
|
||||
def _check_prerequisites(self):
|
||||
"""Check if the command is permitted to run currently.
|
||||
@ -99,17 +100,17 @@ class Command:
|
||||
PrerequisitesError if the command can't be called currently.
|
||||
"""
|
||||
curmode = objreg.get('mode-manager').mode()
|
||||
if self.modes is not None and curmode not in self.modes:
|
||||
mode_names = '/'.join(mode.name for mode in self.modes)
|
||||
if self._modes is not None and curmode not in self._modes:
|
||||
mode_names = '/'.join(mode.name for mode in self._modes)
|
||||
raise cmdexc.PrerequisitesError(
|
||||
"{}: This command is only allowed in {} mode.".format(
|
||||
self.name, mode_names))
|
||||
elif self.not_modes is not None and curmode in self.not_modes:
|
||||
mode_names = '/'.join(mode.name for mode in self.not_modes)
|
||||
elif self._not_modes is not None and curmode in self._not_modes:
|
||||
mode_names = '/'.join(mode.name for mode in self._not_modes)
|
||||
raise cmdexc.PrerequisitesError(
|
||||
"{}: This command is not allowed in {} mode.".format(
|
||||
self.name, mode_names))
|
||||
if self.needs_js and not QWebSettings.globalSettings().testAttribute(
|
||||
if self._needs_js and not QWebSettings.globalSettings().testAttribute(
|
||||
QWebSettings.JavascriptEnabled):
|
||||
raise cmdexc.PrerequisitesError(
|
||||
"{}: This command needs javascript enabled.".format(self.name))
|
||||
@ -117,10 +118,10 @@ class Command:
|
||||
def _check_func(self):
|
||||
"""Make sure the function parameters don't violate any rules."""
|
||||
signature = inspect.signature(self.handler)
|
||||
if 'self' in signature.parameters and self.instance is None:
|
||||
if 'self' in signature.parameters and self._instance is None:
|
||||
raise TypeError("{} is a class method, but instance was not "
|
||||
"given!".format(self.name[0]))
|
||||
elif 'self' not in signature.parameters and self.instance is not None:
|
||||
elif 'self' not in signature.parameters and self._instance is not None:
|
||||
raise TypeError("{} is not a class method, but instance was "
|
||||
"given!".format(self.name[0]))
|
||||
elif inspect.getfullargspec(self.handler).varkw is not None:
|
||||
@ -299,7 +300,7 @@ class Command:
|
||||
args: The positional argument list. Gets modified directly.
|
||||
"""
|
||||
assert param.kind == inspect.Parameter.POSITIONAL_OR_KEYWORD
|
||||
obj = objreg.get(self.instance)
|
||||
obj = objreg.get(self._instance)
|
||||
args.append(obj)
|
||||
|
||||
def _get_count_arg(self, param, args, kwargs):
|
||||
@ -314,27 +315,27 @@ class Command:
|
||||
raise TypeError("{}: count argument given with a command which "
|
||||
"does not support count!".format(self.name))
|
||||
if param.kind == inspect.Parameter.POSITIONAL_OR_KEYWORD:
|
||||
if self.count is not None:
|
||||
args.append(self.count)
|
||||
if self._count is not None:
|
||||
args.append(self._count)
|
||||
else:
|
||||
args.append(param.default)
|
||||
elif param.kind == inspect.Parameter.KEYWORD_ONLY:
|
||||
if self.count is not None:
|
||||
kwargs['count'] = self.count
|
||||
if self._count is not None:
|
||||
kwargs['count'] = self._count
|
||||
else:
|
||||
raise TypeError("{}: invalid parameter type {} for argument "
|
||||
"'count'!".format(self.name, param.kind))
|
||||
|
||||
def _get_param_name_and_value(self, param):
|
||||
"""Get the converted name and value for an inspect.Parameter."""
|
||||
name = self.name_conv.get(param.name, param.name)
|
||||
name = self._name_conv.get(param.name, param.name)
|
||||
value = getattr(self.namespace, name)
|
||||
if param.name in self.type_conv:
|
||||
if param.name in self._type_conv:
|
||||
# We convert enum types after getting the values from
|
||||
# argparse, because argparse's choices argument is
|
||||
# processed after type conversation, which is not what we
|
||||
# want.
|
||||
value = self.type_conv[param.name](value)
|
||||
value = self._type_conv[param.name](value)
|
||||
return name, value
|
||||
|
||||
def _get_call_args(self):
|
||||
@ -349,13 +350,13 @@ class Command:
|
||||
signature = inspect.signature(self.handler)
|
||||
|
||||
if self.ignore_args:
|
||||
if self.instance is not None:
|
||||
if self._instance is not None:
|
||||
param = list(signature.parameters.values())[0]
|
||||
self._get_self_arg(param, args)
|
||||
return args, kwargs
|
||||
|
||||
for i, param in enumerate(signature.parameters.values()):
|
||||
if i == 0 and self.instance is not None:
|
||||
if i == 0 and self._instance is not None:
|
||||
# Special case for 'self'.
|
||||
self._get_self_arg(param, args)
|
||||
continue
|
||||
@ -401,7 +402,7 @@ class Command:
|
||||
log.commands.debug("argparser exited with status {}: {}".format(
|
||||
e.status, e))
|
||||
return
|
||||
self.count = count
|
||||
self._count = count
|
||||
posargs, kwargs = self._get_call_args()
|
||||
self._check_prerequisites()
|
||||
log.commands.debug('Calling {}'.format(
|
||||
|
@ -51,7 +51,7 @@ class _BlockingFIFOReader(QObject):
|
||||
was requested.
|
||||
|
||||
Attributes:
|
||||
filepath: The filename of the FIFO to read.
|
||||
_filepath: The filename of the FIFO to read.
|
||||
fifo: The file object which is being read.
|
||||
|
||||
Signals:
|
||||
@ -65,7 +65,7 @@ class _BlockingFIFOReader(QObject):
|
||||
|
||||
def __init__(self, filepath, parent=None):
|
||||
super().__init__(parent)
|
||||
self.filepath = filepath
|
||||
self._filepath = filepath
|
||||
self.fifo = None
|
||||
|
||||
def read(self):
|
||||
@ -74,7 +74,7 @@ class _BlockingFIFOReader(QObject):
|
||||
# See http://www.outflux.net/blog/archives/2008/03/09/using-select-on-a-fifo/
|
||||
# We also use os.open and os.fdopen rather than built-in open so we can
|
||||
# add O_NONBLOCK.
|
||||
fd = os.open(self.filepath, os.O_RDWR |
|
||||
fd = os.open(self._filepath, os.O_RDWR |
|
||||
os.O_NONBLOCK, # pylint: disable=no-member
|
||||
encoding='utf-8')
|
||||
self.fifo = os.fdopen(fd, 'r')
|
||||
@ -96,8 +96,8 @@ class _BaseUserscriptRunner(QObject):
|
||||
"""Common part between the Windows and the POSIX userscript runners.
|
||||
|
||||
Attributes:
|
||||
filepath: The path of the file/FIFO which is being read.
|
||||
proc: The QProcess which is being executed.
|
||||
_filepath: The path of the file/FIFO which is being read.
|
||||
_proc: The QProcess which is being executed.
|
||||
|
||||
Class attributes:
|
||||
PROCESS_MESSAGES: A mapping of QProcess::ProcessError members to
|
||||
@ -124,8 +124,8 @@ class _BaseUserscriptRunner(QObject):
|
||||
|
||||
def __init__(self, parent=None):
|
||||
super().__init__(parent)
|
||||
self.filepath = None
|
||||
self.proc = None
|
||||
self._filepath = None
|
||||
self._proc = None
|
||||
|
||||
def _run_process(self, cmd, *args, env):
|
||||
"""Start the given command via QProcess.
|
||||
@ -135,27 +135,27 @@ class _BaseUserscriptRunner(QObject):
|
||||
*args: The arguments to hand to the command
|
||||
env: A dictionary of environment variables to add.
|
||||
"""
|
||||
self.proc = QProcess(self)
|
||||
self._proc = QProcess(self)
|
||||
procenv = QProcessEnvironment.systemEnvironment()
|
||||
procenv.insert('QUTE_FIFO', self.filepath)
|
||||
procenv.insert('QUTE_FIFO', self._filepath)
|
||||
if env is not None:
|
||||
for k, v in env.items():
|
||||
procenv.insert(k, v)
|
||||
self.proc.setProcessEnvironment(procenv)
|
||||
self.proc.error.connect(self.on_proc_error)
|
||||
self.proc.finished.connect(self.on_proc_finished)
|
||||
self.proc.start(cmd, args)
|
||||
self._proc.setProcessEnvironment(procenv)
|
||||
self._proc.error.connect(self.on_proc_error)
|
||||
self._proc.finished.connect(self.on_proc_finished)
|
||||
self._proc.start(cmd, args)
|
||||
|
||||
def _cleanup(self):
|
||||
"""Clean up the temporary file."""
|
||||
try:
|
||||
os.remove(self.filepath)
|
||||
os.remove(self._filepath)
|
||||
except PermissionError as e:
|
||||
# NOTE: Do not replace this with "raise CommandError" as it's
|
||||
# executed async.
|
||||
message.error("Failed to delete tempfile... ({})".format(e))
|
||||
self.filepath = None
|
||||
self.proc = None
|
||||
self._filepath = None
|
||||
self._proc = None
|
||||
|
||||
def run(self, cmd, *args, env=None):
|
||||
"""Run the userscript given.
|
||||
@ -192,14 +192,14 @@ class _POSIXUserscriptRunner(_BaseUserscriptRunner):
|
||||
executed immediately when they arrive in the FIFO.
|
||||
|
||||
Attributes:
|
||||
reader: The _BlockingFIFOReader instance.
|
||||
thread: The QThread where reader runs.
|
||||
_reader: The _BlockingFIFOReader instance.
|
||||
_thread: The QThread where reader runs.
|
||||
"""
|
||||
|
||||
def __init__(self, parent=None):
|
||||
super().__init__(parent)
|
||||
self.reader = None
|
||||
self.thread = None
|
||||
self._reader = None
|
||||
self._thread = None
|
||||
|
||||
def run(self, cmd, *args, env=None):
|
||||
rundir = utils.get_standard_dir(QStandardPaths.RuntimeLocation)
|
||||
@ -208,43 +208,43 @@ class _POSIXUserscriptRunner(_BaseUserscriptRunner):
|
||||
# directory and place the FIFO there, which sucks. Since os.kfifo will
|
||||
# raise an exception anyways when the path doesn't exist, it shouldn't
|
||||
# be a big issue.
|
||||
self.filepath = tempfile.mktemp(prefix='userscript-', dir=rundir)
|
||||
os.mkfifo(self.filepath) # pylint: disable=no-member
|
||||
self._filepath = tempfile.mktemp(prefix='userscript-', dir=rundir)
|
||||
os.mkfifo(self._filepath) # pylint: disable=no-member
|
||||
|
||||
self.reader = _BlockingFIFOReader(self.filepath)
|
||||
self.thread = QThread(self)
|
||||
self.reader.moveToThread(self.thread)
|
||||
self.reader.got_line.connect(self.got_cmd)
|
||||
self.thread.started.connect(self.reader.read)
|
||||
self.reader.finished.connect(self.on_reader_finished)
|
||||
self.thread.finished.connect(self.on_thread_finished)
|
||||
self._reader = _BlockingFIFOReader(self._filepath)
|
||||
self._thread = QThread(self)
|
||||
self._reader.moveToThread(self._thread)
|
||||
self._reader.got_line.connect(self.got_cmd)
|
||||
self._thread.started.connect(self._reader.read)
|
||||
self._reader.finished.connect(self.on_reader_finished)
|
||||
self._thread.finished.connect(self.on_thread_finished)
|
||||
|
||||
self._run_process(cmd, *args, env=env)
|
||||
self.thread.start()
|
||||
self._thread.start()
|
||||
|
||||
def on_proc_finished(self):
|
||||
"""Interrupt the reader when the process finished."""
|
||||
log.procs.debug("proc finished")
|
||||
self.thread.requestInterruption()
|
||||
self._thread.requestInterruption()
|
||||
|
||||
def on_proc_error(self, error):
|
||||
"""Interrupt the reader when the process had an error."""
|
||||
super().on_proc_error(error)
|
||||
self.thread.requestInterruption()
|
||||
self._thread.requestInterruption()
|
||||
|
||||
def on_reader_finished(self):
|
||||
"""Quit the thread and clean up when the reader finished."""
|
||||
log.procs.debug("reader finished")
|
||||
self.thread.quit()
|
||||
self.reader.fifo.close()
|
||||
self.reader.deleteLater()
|
||||
self._thread.quit()
|
||||
self._reader.fifo.close()
|
||||
self._reader.deleteLater()
|
||||
super()._cleanup()
|
||||
self.finished.emit()
|
||||
|
||||
def on_thread_finished(self):
|
||||
"""Clean up the QThread object when the thread finished."""
|
||||
log.procs.debug("thread finished")
|
||||
self.thread.deleteLater()
|
||||
self._thread.deleteLater()
|
||||
|
||||
|
||||
class _WindowsUserscriptRunner(_BaseUserscriptRunner):
|
||||
@ -262,13 +262,13 @@ class _WindowsUserscriptRunner(_BaseUserscriptRunner):
|
||||
|
||||
def __init__(self, parent=None):
|
||||
super().__init__(parent)
|
||||
self.oshandle = None
|
||||
self._oshandle = None
|
||||
|
||||
def _cleanup(self):
|
||||
"""Clean up temporary files after the userscript finished."""
|
||||
os.close(self.oshandle)
|
||||
os.close(self._oshandle)
|
||||
super()._cleanup()
|
||||
self.oshandle = None
|
||||
self._oshandle = None
|
||||
|
||||
def on_proc_finished(self):
|
||||
"""Read back the commands when the process finished.
|
||||
@ -277,7 +277,7 @@ class _WindowsUserscriptRunner(_BaseUserscriptRunner):
|
||||
got_cmd: Emitted for every command in the file.
|
||||
"""
|
||||
log.procs.debug("proc finished")
|
||||
with open(self.filepath, 'r', encoding='utf-8') as f:
|
||||
with open(self._filepath, 'r', encoding='utf-8') as f:
|
||||
for line in f:
|
||||
self.got_cmd.emit(line.rstrip())
|
||||
self._cleanup()
|
||||
@ -290,7 +290,7 @@ class _WindowsUserscriptRunner(_BaseUserscriptRunner):
|
||||
self.finished.emit()
|
||||
|
||||
def run(self, cmd, *args, env=None):
|
||||
self.oshandle, self.filepath = tempfile.mkstemp(text=True)
|
||||
self._oshandle, self._filepath = tempfile.mkstemp(text=True)
|
||||
self._run_process(cmd, *args, env=env)
|
||||
|
||||
|
||||
|
@ -86,7 +86,7 @@ class BaseType:
|
||||
"""A type used for a setting value.
|
||||
|
||||
Attributes:
|
||||
none_ok: Whether to convert to None for an empty string.
|
||||
_none_ok: Whether to convert to None for an empty string.
|
||||
|
||||
Class attributes:
|
||||
valid_values: Possible values if they can be expressed as a fixed
|
||||
@ -98,7 +98,7 @@ class BaseType:
|
||||
valid_values = None
|
||||
|
||||
def __init__(self, none_ok=False):
|
||||
self.none_ok = none_ok
|
||||
self._none_ok = none_ok
|
||||
|
||||
def transform(self, value):
|
||||
"""Transform the setting value.
|
||||
@ -132,7 +132,7 @@ class BaseType:
|
||||
NotImplementedError if self.valid_values is not defined and this
|
||||
method should be overridden.
|
||||
"""
|
||||
if not value and self.none_ok:
|
||||
if not value and self._none_ok:
|
||||
return
|
||||
if self.valid_values is not None:
|
||||
if value not in self.valid_values:
|
||||
@ -196,7 +196,7 @@ class String(BaseType):
|
||||
|
||||
def validate(self, value):
|
||||
if not value:
|
||||
if self.none_ok:
|
||||
if self._none_ok:
|
||||
return
|
||||
else:
|
||||
raise ValidationError(value, "may not be empty!")
|
||||
@ -224,7 +224,7 @@ class List(BaseType):
|
||||
def validate(self, value):
|
||||
vals = self.transform(value)
|
||||
if None in vals:
|
||||
if self.none_ok:
|
||||
if self._none_ok:
|
||||
pass
|
||||
else:
|
||||
raise ValidationError(value, "items may not be empty!")
|
||||
@ -252,7 +252,7 @@ class Bool(BaseType):
|
||||
|
||||
def validate(self, value):
|
||||
if not value:
|
||||
if self.none_ok:
|
||||
if self._none_ok:
|
||||
return
|
||||
else:
|
||||
raise ValidationError(value, "may not be empty!")
|
||||
@ -290,7 +290,7 @@ class Int(BaseType):
|
||||
|
||||
def validate(self, value):
|
||||
if not value:
|
||||
if self.none_ok:
|
||||
if self._none_ok:
|
||||
return
|
||||
else:
|
||||
raise ValidationError(value, "may not be empty!")
|
||||
@ -321,7 +321,7 @@ class IntList(List):
|
||||
vals = self.transform(value)
|
||||
except ValueError:
|
||||
raise ValidationError(value, "must be a list of integers!")
|
||||
if None in vals and not self.none_ok:
|
||||
if None in vals and not self._none_ok:
|
||||
raise ValidationError(value, "items may not be empty!")
|
||||
|
||||
|
||||
@ -352,7 +352,7 @@ class Float(BaseType):
|
||||
|
||||
def validate(self, value):
|
||||
if not value:
|
||||
if self.none_ok:
|
||||
if self._none_ok:
|
||||
return
|
||||
else:
|
||||
raise ValidationError(value, "may not be empty!")
|
||||
@ -395,7 +395,7 @@ class Perc(BaseType):
|
||||
|
||||
def validate(self, value):
|
||||
if not value:
|
||||
if self.none_ok:
|
||||
if self._none_ok:
|
||||
return
|
||||
else:
|
||||
raise ValidationError(value, "may not be empty")
|
||||
@ -442,7 +442,7 @@ class PercList(List):
|
||||
try:
|
||||
for val in vals:
|
||||
if val is None:
|
||||
if self.none_ok:
|
||||
if self._none_ok:
|
||||
continue
|
||||
else:
|
||||
raise ValidationError(value, "items may not be empty!")
|
||||
@ -481,7 +481,7 @@ class PercOrInt(BaseType):
|
||||
|
||||
def validate(self, value):
|
||||
if not value:
|
||||
if self.none_ok:
|
||||
if self._none_ok:
|
||||
return
|
||||
else:
|
||||
raise ValidationError(value, "may not be empty!")
|
||||
@ -517,7 +517,7 @@ class Command(BaseType):
|
||||
|
||||
def validate(self, value):
|
||||
if not value:
|
||||
if self.none_ok:
|
||||
if self._none_ok:
|
||||
return
|
||||
else:
|
||||
raise ValidationError(value, "may not be empty!")
|
||||
@ -541,7 +541,7 @@ class ColorSystem(BaseType):
|
||||
|
||||
def validate(self, value):
|
||||
if not value:
|
||||
if self.none_ok:
|
||||
if self._none_ok:
|
||||
return
|
||||
else:
|
||||
raise ValidationError(value, "may not be empty!")
|
||||
@ -567,7 +567,7 @@ class QtColor(BaseType):
|
||||
|
||||
def validate(self, value):
|
||||
if not value:
|
||||
if self.none_ok:
|
||||
if self._none_ok:
|
||||
return
|
||||
else:
|
||||
raise ValidationError(value, "may not be empty!")
|
||||
@ -591,7 +591,7 @@ class CssColor(BaseType):
|
||||
|
||||
def validate(self, value):
|
||||
if not value:
|
||||
if self.none_ok:
|
||||
if self._none_ok:
|
||||
return
|
||||
else:
|
||||
raise ValidationError(value, "may not be empty!")
|
||||
@ -626,7 +626,7 @@ class QssColor(CssColor):
|
||||
|
||||
def validate(self, value):
|
||||
if not value:
|
||||
if self.none_ok:
|
||||
if self._none_ok:
|
||||
return
|
||||
else:
|
||||
raise ValidationError(value, "may not be empty!")
|
||||
@ -662,7 +662,7 @@ class Font(BaseType):
|
||||
|
||||
def validate(self, value):
|
||||
if not value:
|
||||
if self.none_ok:
|
||||
if self._none_ok:
|
||||
return
|
||||
else:
|
||||
raise ValidationError(value, "may not be empty!")
|
||||
@ -729,7 +729,7 @@ class Regex(BaseType):
|
||||
|
||||
def validate(self, value):
|
||||
if not value:
|
||||
if self.none_ok:
|
||||
if self._none_ok:
|
||||
return
|
||||
else:
|
||||
raise ValidationError(value, "may not be empty!")
|
||||
@ -766,7 +766,7 @@ class RegexList(List):
|
||||
except sre_constants.error as e:
|
||||
raise ValidationError(value, "must be a list valid regexes - " +
|
||||
str(e))
|
||||
if not self.none_ok and None in vals:
|
||||
if not self._none_ok and None in vals:
|
||||
raise ValidationError(value, "items may not be empty!")
|
||||
|
||||
|
||||
@ -778,7 +778,7 @@ class File(BaseType):
|
||||
|
||||
def validate(self, value):
|
||||
if not value:
|
||||
if self.none_ok:
|
||||
if self._none_ok:
|
||||
return
|
||||
else:
|
||||
raise ValidationError(value, "may not be empty!")
|
||||
@ -802,7 +802,7 @@ class Directory(BaseType):
|
||||
|
||||
def validate(self, value):
|
||||
if not value:
|
||||
if self.none_ok:
|
||||
if self._none_ok:
|
||||
return
|
||||
else:
|
||||
raise ValidationError(value, "may not be empty!")
|
||||
@ -903,7 +903,7 @@ class WebKitBytesList(List):
|
||||
vals = super().transform(value)
|
||||
for val in vals:
|
||||
self.bytestype.validate(val)
|
||||
if None in vals and not self.none_ok:
|
||||
if None in vals and not self._none_ok:
|
||||
raise ValidationError(value, "items may not be empty!")
|
||||
if self.length is not None and len(vals) != self.length:
|
||||
raise ValidationError(value, "exactly {} values need to be "
|
||||
@ -926,7 +926,7 @@ class ShellCommand(BaseType):
|
||||
|
||||
def validate(self, value):
|
||||
if not value:
|
||||
if self.none_ok:
|
||||
if self._none_ok:
|
||||
return
|
||||
else:
|
||||
raise ValidationError(value, "may not be empty!")
|
||||
@ -975,7 +975,7 @@ class Proxy(BaseType):
|
||||
|
||||
def validate(self, value):
|
||||
if not value:
|
||||
if self.none_ok:
|
||||
if self._none_ok:
|
||||
return
|
||||
else:
|
||||
raise ValidationError(value, "may not be empty!")
|
||||
@ -1022,7 +1022,7 @@ class SearchEngineName(BaseType):
|
||||
|
||||
def validate(self, value):
|
||||
if not value:
|
||||
if self.none_ok:
|
||||
if self._none_ok:
|
||||
return
|
||||
else:
|
||||
raise ValidationError(value, "may not be empty!")
|
||||
@ -1034,7 +1034,7 @@ class SearchEngineUrl(BaseType):
|
||||
|
||||
def validate(self, value):
|
||||
if not value:
|
||||
if self.none_ok:
|
||||
if self._none_ok:
|
||||
return
|
||||
else:
|
||||
raise ValidationError(value, "may not be empty!")
|
||||
@ -1054,7 +1054,7 @@ class Encoding(BaseType):
|
||||
|
||||
def validate(self, value):
|
||||
if not value:
|
||||
if self.none_ok:
|
||||
if self._none_ok:
|
||||
return
|
||||
else:
|
||||
raise ValidationError(value, "may not be empty!")
|
||||
@ -1075,7 +1075,7 @@ class UserStyleSheet(File):
|
||||
|
||||
def validate(self, value):
|
||||
if not value:
|
||||
if self.none_ok:
|
||||
if self._none_ok:
|
||||
return
|
||||
else:
|
||||
raise ValidationError(value, "may not be empty!")
|
||||
@ -1117,7 +1117,7 @@ class AutoSearch(BaseType):
|
||||
|
||||
def validate(self, value):
|
||||
if not value:
|
||||
if self.none_ok:
|
||||
if self._none_ok:
|
||||
return
|
||||
else:
|
||||
raise ValidationError(value, "may not be empty!")
|
||||
|
@ -53,8 +53,8 @@ class BaseKeyParser(QObject):
|
||||
Attributes:
|
||||
bindings: Bound keybindings
|
||||
special_bindings: Bound special bindings (<Foo>).
|
||||
warn_on_keychains: Whether a warning should be logged when binding
|
||||
keychains in a section which does not support them.
|
||||
_warn_on_keychains: Whether a warning should be logged when binding
|
||||
keychains in a section which does not support them.
|
||||
_keystring: The currently entered key sequence
|
||||
_timer: Timer for delayed execution.
|
||||
_modename: The name of the input mode associated with this keyparser.
|
||||
@ -83,7 +83,7 @@ class BaseKeyParser(QObject):
|
||||
supports_count = supports_chains
|
||||
self._supports_count = supports_count
|
||||
self._supports_chains = supports_chains
|
||||
self.warn_on_keychains = True
|
||||
self._warn_on_keychains = True
|
||||
self.bindings = {}
|
||||
self.special_bindings = {}
|
||||
|
||||
@ -330,7 +330,7 @@ class BaseKeyParser(QObject):
|
||||
self.special_bindings[keystr] = cmd
|
||||
elif self._supports_chains:
|
||||
self.bindings[key] = cmd
|
||||
elif self.warn_on_keychains:
|
||||
elif self._warn_on_keychains:
|
||||
log.keyboard.warning(
|
||||
"Ignoring keychain '{}' in mode '{}' because "
|
||||
"keychains are not supported there.".format(key, modename))
|
||||
|
@ -29,17 +29,17 @@ class CommandKeyParser(BaseKeyParser):
|
||||
"""KeyChainParser for command bindings.
|
||||
|
||||
Attributes:
|
||||
commandrunner: CommandRunner instance.
|
||||
_commandrunner: CommandRunner instance.
|
||||
"""
|
||||
|
||||
def __init__(self, parent=None, supports_count=None,
|
||||
supports_chains=False):
|
||||
super().__init__(parent, supports_count, supports_chains)
|
||||
self.commandrunner = runners.CommandRunner()
|
||||
self._commandrunner = runners.CommandRunner()
|
||||
|
||||
def execute(self, cmdstr, _keytype, count=None):
|
||||
try:
|
||||
self.commandrunner.run(cmdstr, count)
|
||||
self._commandrunner.run(cmdstr, count)
|
||||
except (cmdexc.CommandMetaError, cmdexc.CommandError) as e:
|
||||
message.error(e, immediately=True)
|
||||
|
||||
@ -66,10 +66,10 @@ class PassthroughKeyParser(CommandKeyParser):
|
||||
"""
|
||||
super().__init__(parent, supports_chains=False)
|
||||
self.log = False
|
||||
self.warn_on_keychains = warn
|
||||
self._warn_on_keychains = warn
|
||||
self.read_config(mode)
|
||||
self._mode = mode
|
||||
|
||||
def __repr__(self):
|
||||
return '<{} mode={}, warn={})'.format(
|
||||
self.__class__.__name__, self._mode, self.warn_on_keychains)
|
||||
self.__class__.__name__, self._mode, self._warn_on_keychains)
|
||||
|
@ -19,6 +19,8 @@
|
||||
|
||||
"""Tests for qutebrowser.utils.editor."""
|
||||
|
||||
# pylint: disable=protected-access
|
||||
|
||||
import os
|
||||
import os.path
|
||||
import unittest
|
||||
@ -59,7 +61,7 @@ class ArgTests(unittest.TestCase):
|
||||
editor.config = stubs.ConfigStub(
|
||||
{'general': {'editor': ['bin'], 'editor-encoding': 'utf-8'}})
|
||||
self.editor.edit("")
|
||||
self.editor.proc.start.assert_called_with("bin", [])
|
||||
self.editor._proc.start.assert_called_with("bin", [])
|
||||
|
||||
def test_start_args(self):
|
||||
"""Test starting editor with static arguments."""
|
||||
@ -67,7 +69,7 @@ class ArgTests(unittest.TestCase):
|
||||
{'general': {'editor': ['bin', 'foo', 'bar'],
|
||||
'editor-encoding': 'utf-8'}})
|
||||
self.editor.edit("")
|
||||
self.editor.proc.start.assert_called_with("bin", ["foo", "bar"])
|
||||
self.editor._proc.start.assert_called_with("bin", ["foo", "bar"])
|
||||
|
||||
def test_placeholder(self):
|
||||
"""Test starting editor with placeholder argument."""
|
||||
@ -75,9 +77,9 @@ class ArgTests(unittest.TestCase):
|
||||
{'general': {'editor': ['bin', 'foo', '{}', 'bar'],
|
||||
'editor-encoding': 'utf-8'}})
|
||||
self.editor.edit("")
|
||||
filename = self.editor.filename
|
||||
self.editor.proc.start.assert_called_with("bin",
|
||||
["foo", filename, "bar"])
|
||||
filename = self.editor._filename
|
||||
self.editor._proc.start.assert_called_with("bin",
|
||||
["foo", filename, "bar"])
|
||||
|
||||
def test_in_arg_placeholder(self):
|
||||
"""Test starting editor with placeholder argument inside argument."""
|
||||
@ -85,7 +87,7 @@ class ArgTests(unittest.TestCase):
|
||||
{'general': {'editor': ['bin', 'foo{}bar'],
|
||||
'editor-encoding': 'utf-8'}})
|
||||
self.editor.edit("")
|
||||
self.editor.proc.start.assert_called_with("bin", ["foo{}bar"])
|
||||
self.editor._proc.start.assert_called_with("bin", ["foo{}bar"])
|
||||
|
||||
def tearDown(self):
|
||||
self.editor._cleanup() # pylint: disable=protected-access
|
||||
@ -107,7 +109,7 @@ class FileHandlingTests(unittest.TestCase):
|
||||
def test_file_handling_closed_ok(self):
|
||||
"""Test file handling when closing with an exitstatus == 0."""
|
||||
self.editor.edit("")
|
||||
filename = self.editor.filename
|
||||
filename = self.editor._filename
|
||||
self.assertTrue(os.path.exists(filename))
|
||||
self.editor.on_proc_closed(0, QProcess.NormalExit)
|
||||
self.assertFalse(os.path.exists(filename))
|
||||
@ -115,7 +117,7 @@ class FileHandlingTests(unittest.TestCase):
|
||||
def test_file_handling_closed_error(self):
|
||||
"""Test file handling when closing with an exitstatus != 0."""
|
||||
self.editor.edit("")
|
||||
filename = self.editor.filename
|
||||
filename = self.editor._filename
|
||||
self.assertTrue(os.path.exists(filename))
|
||||
self.editor.on_proc_closed(1, QProcess.NormalExit)
|
||||
self.assertFalse(os.path.exists(filename))
|
||||
@ -123,7 +125,7 @@ class FileHandlingTests(unittest.TestCase):
|
||||
def test_file_handling_closed_crash(self):
|
||||
"""Test file handling when closing with a crash."""
|
||||
self.editor.edit("")
|
||||
filename = self.editor.filename
|
||||
filename = self.editor._filename
|
||||
self.assertTrue(os.path.exists(filename))
|
||||
self.editor.on_proc_error(QProcess.Crashed)
|
||||
self.editor.on_proc_closed(0, QProcess.CrashExit)
|
||||
@ -150,7 +152,7 @@ class TextModifyTests(unittest.TestCase):
|
||||
Args:
|
||||
text: The text to write to the file.
|
||||
"""
|
||||
filename = self.editor.filename
|
||||
filename = self.editor._filename
|
||||
with open(filename, 'w', encoding='utf-8') as f:
|
||||
f.write(text)
|
||||
|
||||
@ -160,7 +162,7 @@ class TextModifyTests(unittest.TestCase):
|
||||
Return:
|
||||
The text which was read.
|
||||
"""
|
||||
filename = self.editor.filename
|
||||
filename = self.editor._filename
|
||||
with open(filename, 'r', encoding='utf-8') as f:
|
||||
data = f.read()
|
||||
return data
|
||||
|
@ -171,18 +171,18 @@ class RAMHandlerTests(BaseTest):
|
||||
"""Test handler with exactly as much records as it can hold."""
|
||||
self.logger.debug("One")
|
||||
self.logger.debug("Two")
|
||||
self.assertEqual(len(self.handler.data), 2)
|
||||
self.assertEqual(self.handler.data[0].msg, "One")
|
||||
self.assertEqual(self.handler.data[1].msg, "Two")
|
||||
self.assertEqual(len(self.handler._data), 2)
|
||||
self.assertEqual(self.handler._data[0].msg, "One")
|
||||
self.assertEqual(self.handler._data[1].msg, "Two")
|
||||
|
||||
def test_overflow(self):
|
||||
"""Test handler with more records as it can hold."""
|
||||
self.logger.debug("One")
|
||||
self.logger.debug("Two")
|
||||
self.logger.debug("Three")
|
||||
self.assertEqual(len(self.handler.data), 2)
|
||||
self.assertEqual(self.handler.data[0].msg, "Two")
|
||||
self.assertEqual(self.handler.data[1].msg, "Three")
|
||||
self.assertEqual(len(self.handler._data), 2)
|
||||
self.assertEqual(self.handler._data[0].msg, "Two")
|
||||
self.assertEqual(self.handler._data[1].msg, "Three")
|
||||
|
||||
def test_dump_log(self):
|
||||
"""Test dump_log()."""
|
||||
|
@ -19,6 +19,8 @@
|
||||
|
||||
"""Tests for qutebrowser.utils.readline."""
|
||||
|
||||
# pylint: disable=protected-access
|
||||
|
||||
import inspect
|
||||
import unittest
|
||||
from unittest import mock
|
||||
@ -105,7 +107,7 @@ class ReadlineBridgeTest(unittest.TestCase):
|
||||
self._set_selected_text("delete test")
|
||||
self.bridge.rl_unix_line_discard()
|
||||
self.qle.home.assert_called_with(True)
|
||||
self.assertEqual(self.bridge.deleted[self.qle], "delete test")
|
||||
self.assertEqual(self.bridge._deleted[self.qle], "delete test")
|
||||
self.qle.del_.assert_called_with()
|
||||
self.bridge.rl_yank()
|
||||
self.qle.insert.assert_called_with("delete test")
|
||||
@ -115,7 +117,7 @@ class ReadlineBridgeTest(unittest.TestCase):
|
||||
self._set_selected_text("delete test")
|
||||
self.bridge.rl_kill_line()
|
||||
self.qle.end.assert_called_with(True)
|
||||
self.assertEqual(self.bridge.deleted[self.qle], "delete test")
|
||||
self.assertEqual(self.bridge._deleted[self.qle], "delete test")
|
||||
self.qle.del_.assert_called_with()
|
||||
self.bridge.rl_yank()
|
||||
self.qle.insert.assert_called_with("delete test")
|
||||
@ -125,7 +127,7 @@ class ReadlineBridgeTest(unittest.TestCase):
|
||||
self._set_selected_text("delete test")
|
||||
self.bridge.rl_unix_word_rubout()
|
||||
self.qle.cursorWordBackward.assert_called_with(True)
|
||||
self.assertEqual(self.bridge.deleted[self.qle], "delete test")
|
||||
self.assertEqual(self.bridge._deleted[self.qle], "delete test")
|
||||
self.qle.del_.assert_called_with()
|
||||
self.bridge.rl_yank()
|
||||
self.qle.insert.assert_called_with("delete test")
|
||||
@ -135,7 +137,7 @@ class ReadlineBridgeTest(unittest.TestCase):
|
||||
self._set_selected_text("delete test")
|
||||
self.bridge.rl_kill_word()
|
||||
self.qle.cursorWordForward.assert_called_with(True)
|
||||
self.assertEqual(self.bridge.deleted[self.qle], "delete test")
|
||||
self.assertEqual(self.bridge._deleted[self.qle], "delete test")
|
||||
self.qle.del_.assert_called_with()
|
||||
self.bridge.rl_yank()
|
||||
self.qle.insert.assert_called_with("delete test")
|
||||
|
@ -72,17 +72,17 @@ class DefaultTests(unittest.TestCase):
|
||||
def test_simple(self):
|
||||
"""Test default with a numeric argument."""
|
||||
nl = usertypes.NeighborList([1, 2, 3], default=2)
|
||||
self.assertEqual(nl.idx, 1)
|
||||
self.assertEqual(nl._idx, 1)
|
||||
|
||||
def test_none(self):
|
||||
"""Test default 'None'."""
|
||||
nl = usertypes.NeighborList([1, 2, None], default=None)
|
||||
self.assertEqual(nl.idx, 2)
|
||||
self.assertEqual(nl._idx, 2)
|
||||
|
||||
def test_unset(self):
|
||||
"""Test unset default value."""
|
||||
nl = usertypes.NeighborList([1, 2, 3])
|
||||
self.assertIsNone(nl.idx)
|
||||
self.assertIsNone(nl._idx)
|
||||
|
||||
|
||||
class EmptyTests(unittest.TestCase):
|
||||
@ -130,48 +130,48 @@ class ItemTests(unittest.TestCase):
|
||||
|
||||
def test_curitem(self):
|
||||
"""Test curitem()."""
|
||||
self.assertEqual(self.nl.idx, 2)
|
||||
self.assertEqual(self.nl._idx, 2)
|
||||
self.assertEqual(self.nl.curitem(), 3)
|
||||
self.assertEqual(self.nl.idx, 2)
|
||||
self.assertEqual(self.nl._idx, 2)
|
||||
|
||||
def test_nextitem(self):
|
||||
"""Test nextitem()."""
|
||||
self.assertEqual(self.nl.nextitem(), 4)
|
||||
self.assertEqual(self.nl.idx, 3)
|
||||
self.assertEqual(self.nl._idx, 3)
|
||||
self.assertEqual(self.nl.nextitem(), 5)
|
||||
self.assertEqual(self.nl.idx, 4)
|
||||
self.assertEqual(self.nl._idx, 4)
|
||||
|
||||
def test_previtem(self):
|
||||
"""Test previtem()."""
|
||||
self.assertEqual(self.nl.previtem(), 2)
|
||||
self.assertEqual(self.nl.idx, 1)
|
||||
self.assertEqual(self.nl._idx, 1)
|
||||
self.assertEqual(self.nl.previtem(), 1)
|
||||
self.assertEqual(self.nl.idx, 0)
|
||||
self.assertEqual(self.nl._idx, 0)
|
||||
|
||||
def test_firstitem(self):
|
||||
"""Test firstitem()."""
|
||||
self.assertEqual(self.nl.firstitem(), 1)
|
||||
self.assertEqual(self.nl.idx, 0)
|
||||
self.assertEqual(self.nl._idx, 0)
|
||||
|
||||
def test_lastitem(self):
|
||||
"""Test lastitem()."""
|
||||
self.assertEqual(self.nl.lastitem(), 5)
|
||||
self.assertEqual(self.nl.idx, 4)
|
||||
self.assertEqual(self.nl._idx, 4)
|
||||
|
||||
def test_reset(self):
|
||||
"""Test reset()."""
|
||||
self.nl.nextitem()
|
||||
self.assertEqual(self.nl.idx, 3)
|
||||
self.assertEqual(self.nl._idx, 3)
|
||||
self.nl.reset()
|
||||
self.assertEqual(self.nl.idx, 2)
|
||||
self.assertEqual(self.nl._idx, 2)
|
||||
|
||||
def test_getitem(self):
|
||||
"""Test getitem()."""
|
||||
self.assertEqual(self.nl.getitem(2), 5)
|
||||
self.assertEqual(self.nl.idx, 4)
|
||||
self.assertEqual(self.nl._idx, 4)
|
||||
self.nl.reset()
|
||||
self.assertEqual(self.nl.getitem(-2), 1)
|
||||
self.assertEqual(self.nl.idx, 0)
|
||||
self.assertEqual(self.nl._idx, 0)
|
||||
|
||||
|
||||
class OneTests(unittest.TestCase):
|
||||
@ -189,51 +189,51 @@ class OneTests(unittest.TestCase):
|
||||
"""Test out of bounds previtem() with mode=wrap."""
|
||||
self.nl._mode = usertypes.NeighborList.Modes.wrap
|
||||
self.nl.firstitem()
|
||||
self.assertEqual(self.nl.idx, 0)
|
||||
self.assertEqual(self.nl._idx, 0)
|
||||
self.assertEqual(self.nl.previtem(), 1)
|
||||
self.assertEqual(self.nl.idx, 0)
|
||||
self.assertEqual(self.nl._idx, 0)
|
||||
|
||||
def test_first_block(self):
|
||||
"""Test out of bounds previtem() with mode=block."""
|
||||
self.nl._mode = usertypes.NeighborList.Modes.block
|
||||
self.nl.firstitem()
|
||||
self.assertEqual(self.nl.idx, 0)
|
||||
self.assertEqual(self.nl._idx, 0)
|
||||
self.assertEqual(self.nl.previtem(), 1)
|
||||
self.assertEqual(self.nl.idx, 0)
|
||||
self.assertEqual(self.nl._idx, 0)
|
||||
|
||||
def test_first_raise(self):
|
||||
"""Test out of bounds previtem() with mode=raise."""
|
||||
self.nl._mode = usertypes.NeighborList.Modes.exception
|
||||
self.nl.firstitem()
|
||||
self.assertEqual(self.nl.idx, 0)
|
||||
self.assertEqual(self.nl._idx, 0)
|
||||
with self.assertRaises(IndexError):
|
||||
self.nl.previtem()
|
||||
self.assertEqual(self.nl.idx, 0)
|
||||
self.assertEqual(self.nl._idx, 0)
|
||||
|
||||
def test_last_wrap(self):
|
||||
"""Test out of bounds nextitem() with mode=wrap."""
|
||||
self.nl._mode = usertypes.NeighborList.Modes.wrap
|
||||
self.nl.lastitem()
|
||||
self.assertEqual(self.nl.idx, 0)
|
||||
self.assertEqual(self.nl._idx, 0)
|
||||
self.assertEqual(self.nl.nextitem(), 1)
|
||||
self.assertEqual(self.nl.idx, 0)
|
||||
self.assertEqual(self.nl._idx, 0)
|
||||
|
||||
def test_last_block(self):
|
||||
"""Test out of bounds nextitem() with mode=block."""
|
||||
self.nl._mode = usertypes.NeighborList.Modes.block
|
||||
self.nl.lastitem()
|
||||
self.assertEqual(self.nl.idx, 0)
|
||||
self.assertEqual(self.nl._idx, 0)
|
||||
self.assertEqual(self.nl.nextitem(), 1)
|
||||
self.assertEqual(self.nl.idx, 0)
|
||||
self.assertEqual(self.nl._idx, 0)
|
||||
|
||||
def test_last_raise(self):
|
||||
"""Test out of bounds nextitem() with mode=raise."""
|
||||
self.nl._mode = usertypes.NeighborList.Modes.exception
|
||||
self.nl.lastitem()
|
||||
self.assertEqual(self.nl.idx, 0)
|
||||
self.assertEqual(self.nl._idx, 0)
|
||||
with self.assertRaises(IndexError):
|
||||
self.nl.nextitem()
|
||||
self.assertEqual(self.nl.idx, 0)
|
||||
self.assertEqual(self.nl._idx, 0)
|
||||
|
||||
|
||||
class BlockTests(unittest.TestCase):
|
||||
@ -252,16 +252,16 @@ class BlockTests(unittest.TestCase):
|
||||
def test_first(self):
|
||||
"""Test ouf of bounds previtem()."""
|
||||
self.nl.firstitem()
|
||||
self.assertEqual(self.nl.idx, 0)
|
||||
self.assertEqual(self.nl._idx, 0)
|
||||
self.assertEqual(self.nl.previtem(), 1)
|
||||
self.assertEqual(self.nl.idx, 0)
|
||||
self.assertEqual(self.nl._idx, 0)
|
||||
|
||||
def test_last(self):
|
||||
"""Test ouf of bounds nextitem()."""
|
||||
self.nl.lastitem()
|
||||
self.assertEqual(self.nl.idx, 4)
|
||||
self.assertEqual(self.nl._idx, 4)
|
||||
self.assertEqual(self.nl.nextitem(), 5)
|
||||
self.assertEqual(self.nl.idx, 4)
|
||||
self.assertEqual(self.nl._idx, 4)
|
||||
|
||||
|
||||
class WrapTests(unittest.TestCase):
|
||||
@ -279,16 +279,16 @@ class WrapTests(unittest.TestCase):
|
||||
def test_first(self):
|
||||
"""Test ouf of bounds previtem()."""
|
||||
self.nl.firstitem()
|
||||
self.assertEqual(self.nl.idx, 0)
|
||||
self.assertEqual(self.nl._idx, 0)
|
||||
self.assertEqual(self.nl.previtem(), 5)
|
||||
self.assertEqual(self.nl.idx, 4)
|
||||
self.assertEqual(self.nl._idx, 4)
|
||||
|
||||
def test_last(self):
|
||||
"""Test ouf of bounds nextitem()."""
|
||||
self.nl.lastitem()
|
||||
self.assertEqual(self.nl.idx, 4)
|
||||
self.assertEqual(self.nl._idx, 4)
|
||||
self.assertEqual(self.nl.nextitem(), 1)
|
||||
self.assertEqual(self.nl.idx, 0)
|
||||
self.assertEqual(self.nl._idx, 0)
|
||||
|
||||
|
||||
class RaiseTests(unittest.TestCase):
|
||||
@ -307,18 +307,18 @@ class RaiseTests(unittest.TestCase):
|
||||
def test_first(self):
|
||||
"""Test ouf of bounds previtem()."""
|
||||
self.nl.firstitem()
|
||||
self.assertEqual(self.nl.idx, 0)
|
||||
self.assertEqual(self.nl._idx, 0)
|
||||
with self.assertRaises(IndexError):
|
||||
self.nl.previtem()
|
||||
self.assertEqual(self.nl.idx, 0)
|
||||
self.assertEqual(self.nl._idx, 0)
|
||||
|
||||
def test_last(self):
|
||||
"""Test ouf of bounds nextitem()."""
|
||||
self.nl.lastitem()
|
||||
self.assertEqual(self.nl.idx, 4)
|
||||
self.assertEqual(self.nl._idx, 4)
|
||||
with self.assertRaises(IndexError):
|
||||
self.nl.nextitem()
|
||||
self.assertEqual(self.nl.idx, 4)
|
||||
self.assertEqual(self.nl._idx, 4)
|
||||
|
||||
|
||||
class SnapInTests(unittest.TestCase):
|
||||
@ -336,29 +336,29 @@ class SnapInTests(unittest.TestCase):
|
||||
"""Test fuzzyval with snapping to a bigger value."""
|
||||
self.nl.fuzzyval = 7
|
||||
self.assertEqual(self.nl.nextitem(), 9)
|
||||
self.assertEqual(self.nl.idx, 1)
|
||||
self.assertEqual(self.nl._idx, 1)
|
||||
self.assertEqual(self.nl.nextitem(), 1)
|
||||
self.assertEqual(self.nl.idx, 2)
|
||||
self.assertEqual(self.nl._idx, 2)
|
||||
|
||||
def test_smaller(self):
|
||||
"""Test fuzzyval with snapping to a smaller value."""
|
||||
self.nl.fuzzyval = 7
|
||||
self.assertEqual(self.nl.previtem(), 5)
|
||||
self.assertEqual(self.nl.idx, 3)
|
||||
self.assertEqual(self.nl._idx, 3)
|
||||
self.assertEqual(self.nl.previtem(), 1)
|
||||
self.assertEqual(self.nl.idx, 2)
|
||||
self.assertEqual(self.nl._idx, 2)
|
||||
|
||||
def test_equal_bigger(self):
|
||||
"""Test fuzzyval with matching value, snapping to a bigger value."""
|
||||
self.nl.fuzzyval = 20
|
||||
self.assertEqual(self.nl.nextitem(), 9)
|
||||
self.assertEqual(self.nl.idx, 1)
|
||||
self.assertEqual(self.nl._idx, 1)
|
||||
|
||||
def test_equal_smaller(self):
|
||||
"""Test fuzzyval with matching value, snapping to a smaller value."""
|
||||
self.nl.fuzzyval = 5
|
||||
self.assertEqual(self.nl.previtem(), 1)
|
||||
self.assertEqual(self.nl.idx, 2)
|
||||
self.assertEqual(self.nl._idx, 2)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
@ -33,7 +33,7 @@ class Completer(QObject):
|
||||
"""Completer which manages completions in a CompletionView.
|
||||
|
||||
Attributes:
|
||||
ignore_change: Whether to ignore the next completion update.
|
||||
_ignore_change: Whether to ignore the next completion update.
|
||||
_models: dict of available completion models.
|
||||
|
||||
Signals:
|
||||
@ -48,8 +48,8 @@ class Completer(QObject):
|
||||
change_completed_part = pyqtSignal(str, bool)
|
||||
|
||||
def __init__(self, parent=None):
|
||||
super().__init__()
|
||||
self.ignore_change = False
|
||||
super().__init__(parent)
|
||||
self._ignore_change = False
|
||||
|
||||
self._models = {
|
||||
usertypes.Completion.option: {},
|
||||
@ -177,9 +177,9 @@ class Completer(QObject):
|
||||
# and go on to the next part.
|
||||
self.change_completed_part.emit(data, True)
|
||||
else:
|
||||
self.ignore_change = True
|
||||
self._ignore_change = True
|
||||
self.change_completed_part.emit(data, False)
|
||||
self.ignore_change = False
|
||||
self._ignore_change = False
|
||||
|
||||
@pyqtSlot(str, list, int)
|
||||
def on_update_completion(self, prefix, parts, cursor_part):
|
||||
@ -191,7 +191,7 @@ class Completer(QObject):
|
||||
text: The new text
|
||||
cursor_part: The part the cursor is currently over.
|
||||
"""
|
||||
if self.ignore_change:
|
||||
if self._ignore_change:
|
||||
log.completion.debug("Ignoring completion update")
|
||||
return
|
||||
|
||||
|
@ -75,12 +75,13 @@ class DocstringParser:
|
||||
Args:
|
||||
func: The function to parse the docstring for.
|
||||
"""
|
||||
self.state = self.State.short
|
||||
self._state = self.State.short
|
||||
self._cur_arg_name = None
|
||||
self.short_desc = []
|
||||
self.long_desc = []
|
||||
self.arg_descs = collections.OrderedDict()
|
||||
self.cur_arg_name = None
|
||||
self.handlers = {
|
||||
doc = inspect.getdoc(func)
|
||||
handlers = {
|
||||
self.State.short: self._parse_short,
|
||||
self.State.desc: self._parse_desc,
|
||||
self.State.desc_hidden: self._skip,
|
||||
@ -88,9 +89,8 @@ class DocstringParser:
|
||||
self.State.arg_inside: self._parse_arg_inside,
|
||||
self.State.misc: self._skip,
|
||||
}
|
||||
doc = inspect.getdoc(func)
|
||||
for line in doc.splitlines():
|
||||
handler = self.handlers[self.state]
|
||||
handler = handlers[self._state]
|
||||
stop = handler(line)
|
||||
if stop:
|
||||
break
|
||||
@ -101,41 +101,41 @@ class DocstringParser:
|
||||
|
||||
def _process_arg(self, line):
|
||||
"""Helper method to process a line like 'fooarg: Blah blub'."""
|
||||
self.cur_arg_name, argdesc = line.split(':', maxsplit=1)
|
||||
self.cur_arg_name = self.cur_arg_name.strip().lstrip('*')
|
||||
self.arg_descs[self.cur_arg_name] = [argdesc.strip()]
|
||||
self._cur_arg_name, argdesc = line.split(':', maxsplit=1)
|
||||
self._cur_arg_name = self._cur_arg_name.strip().lstrip('*')
|
||||
self.arg_descs[self._cur_arg_name] = [argdesc.strip()]
|
||||
|
||||
def _skip(self, line):
|
||||
"""Handler to ignore everything until we get 'Args:'."""
|
||||
if line.startswith('Args:'):
|
||||
self.state = self.State.arg_start
|
||||
self._state = self.State.arg_start
|
||||
|
||||
def _parse_short(self, line):
|
||||
"""Parse the short description (first block) in the docstring."""
|
||||
if not line:
|
||||
self.state = self.State.desc
|
||||
self._state = self.State.desc
|
||||
else:
|
||||
self.short_desc.append(line.strip())
|
||||
|
||||
def _parse_desc(self, line):
|
||||
"""Parse the long description in the docstring."""
|
||||
if line.startswith('Args:'):
|
||||
self.state = self.State.arg_start
|
||||
self._state = self.State.arg_start
|
||||
elif line.startswith('Emit:') or line.startswith('Raise:'):
|
||||
self.state = self.State.misc
|
||||
self._state = self.State.misc
|
||||
elif line.strip() == '//':
|
||||
self.state = self.State.desc_hidden
|
||||
self._state = self.State.desc_hidden
|
||||
elif line.strip():
|
||||
self.long_desc.append(line.strip())
|
||||
|
||||
def _parse_arg_start(self, line):
|
||||
"""Parse first argument line."""
|
||||
self._process_arg(line)
|
||||
self.state = self.State.arg_inside
|
||||
self._state = self.State.arg_inside
|
||||
|
||||
def _parse_arg_inside(self, line):
|
||||
"""Parse subsequent argument lines."""
|
||||
argname = self.cur_arg_name
|
||||
argname = self._cur_arg_name
|
||||
if re.match(r'^[A-Z][a-z]+:$', line):
|
||||
if not self.arg_descs[argname][-1].strip():
|
||||
self.arg_descs[argname] = self.arg_descs[argname][:-1]
|
||||
|
@ -36,16 +36,16 @@ class ExternalEditor(QObject):
|
||||
|
||||
def __init__(self, parent=None):
|
||||
super().__init__(parent)
|
||||
self.text = None
|
||||
self.oshandle = None
|
||||
self.filename = None
|
||||
self.proc = None
|
||||
self._text = None
|
||||
self._oshandle = None
|
||||
self._filename = None
|
||||
self._proc = None
|
||||
|
||||
def _cleanup(self):
|
||||
"""Clean up temporary files after the editor closed."""
|
||||
os.close(self.oshandle)
|
||||
os.close(self._oshandle)
|
||||
try:
|
||||
os.remove(self.filename)
|
||||
os.remove(self._filename)
|
||||
except PermissionError as e:
|
||||
# NOTE: Do not replace this with "raise CommandError" as it's
|
||||
# executed async.
|
||||
@ -72,7 +72,7 @@ class ExternalEditor(QObject):
|
||||
exitcode))
|
||||
return
|
||||
encoding = config.get('general', 'editor-encoding')
|
||||
with open(self.filename, 'r', encoding=encoding) as f:
|
||||
with open(self._filename, 'r', encoding=encoding) as f:
|
||||
text = ''.join(f.readlines())
|
||||
log.procs.debug("Read back: {}".format(text))
|
||||
self.editing_finished.emit(text)
|
||||
@ -105,19 +105,19 @@ class ExternalEditor(QObject):
|
||||
Emit:
|
||||
editing_finished with the new text if editing finshed successfully.
|
||||
"""
|
||||
if self.text is not None:
|
||||
if self._text is not None:
|
||||
raise ValueError("Already editing a file!")
|
||||
self.text = text
|
||||
self.oshandle, self.filename = tempfile.mkstemp(text=True)
|
||||
self._text = text
|
||||
self._oshandle, self._filename = tempfile.mkstemp(text=True)
|
||||
if text:
|
||||
encoding = config.get('general', 'editor-encoding')
|
||||
with open(self.filename, 'w', encoding=encoding) as f:
|
||||
with open(self._filename, 'w', encoding=encoding) as f:
|
||||
f.write(text)
|
||||
self.proc = QProcess(self)
|
||||
self.proc.finished.connect(self.on_proc_closed)
|
||||
self.proc.error.connect(self.on_proc_error)
|
||||
self._proc = QProcess(self)
|
||||
self._proc.finished.connect(self.on_proc_closed)
|
||||
self._proc.error.connect(self.on_proc_error)
|
||||
editor = config.get('general', 'editor')
|
||||
executable = editor[0]
|
||||
args = [self.filename if arg == '{}' else arg for arg in editor[1:]]
|
||||
args = [self._filename if arg == '{}' else arg for arg in editor[1:]]
|
||||
log.procs.debug("Calling \"{}\" with args {}".format(executable, args))
|
||||
self.proc.start(executable, args)
|
||||
self._proc.start(executable, args)
|
||||
|
@ -31,10 +31,10 @@ class Loader(jinja2.BaseLoader):
|
||||
"""Jinja loader which uses utils.read_file to load templates."""
|
||||
|
||||
def __init__(self, subdir):
|
||||
self.subdir = subdir
|
||||
self._subdir = subdir
|
||||
|
||||
def get_source(self, _env, template):
|
||||
path = os.path.join(self.subdir, template)
|
||||
path = os.path.join(self._subdir, template)
|
||||
try:
|
||||
source = utils.read_file(path)
|
||||
except FileNotFoundError:
|
||||
|
@ -295,21 +295,21 @@ class LogFilter(logging.Filter):
|
||||
comma-separated list instead.
|
||||
|
||||
Attributes:
|
||||
names: A list of names that should be logged.
|
||||
_names: A list of names that should be logged.
|
||||
"""
|
||||
|
||||
def __init__(self, names):
|
||||
super().__init__()
|
||||
self.names = names
|
||||
self._names = names
|
||||
|
||||
def filter(self, record):
|
||||
"""Determine if the specified record is to be logged."""
|
||||
if self.names is None:
|
||||
if self._names is None:
|
||||
return True
|
||||
if record.levelno > logging.DEBUG:
|
||||
# More important than DEBUG, so we won't filter at all
|
||||
return True
|
||||
for name in self.names:
|
||||
for name in self._names:
|
||||
if record.name == name:
|
||||
return True
|
||||
elif not record.name.startswith(name):
|
||||
@ -327,21 +327,21 @@ class RAMHandler(logging.Handler):
|
||||
uses a simple list rather than a deque.
|
||||
|
||||
Attributes:
|
||||
data: A deque containing the logging records.
|
||||
_data: A deque containing the logging records.
|
||||
"""
|
||||
|
||||
def __init__(self, capacity):
|
||||
super().__init__()
|
||||
self.html_formatter = None
|
||||
if capacity != -1:
|
||||
self.data = collections.deque(maxlen=capacity)
|
||||
self._data = collections.deque(maxlen=capacity)
|
||||
else:
|
||||
self.data = collections.deque()
|
||||
self._data = collections.deque()
|
||||
|
||||
def emit(self, record):
|
||||
if record.levelno >= logging.DEBUG:
|
||||
# We don't log VDEBUG to RAM.
|
||||
self.data.append(record)
|
||||
self._data.append(record)
|
||||
|
||||
def dump_log(self, html=False):
|
||||
"""Dump the complete formatted log data as as string.
|
||||
@ -352,7 +352,7 @@ class RAMHandler(logging.Handler):
|
||||
fmt = self.html_formatter.format if html else self.format
|
||||
self.acquire()
|
||||
try:
|
||||
records = list(self.data)
|
||||
records = list(self._data)
|
||||
finally:
|
||||
self.release()
|
||||
for record in records:
|
||||
|
@ -30,11 +30,11 @@ class ReadlineBridge:
|
||||
"""Bridge which provides readline-like commands for the current QLineEdit.
|
||||
|
||||
Attributes:
|
||||
deleted: Mapping from widgets to their last deleted text.
|
||||
_deleted: Mapping from widgets to their last deleted text.
|
||||
"""
|
||||
|
||||
def __init__(self):
|
||||
self.deleted = {}
|
||||
self._deleted = {}
|
||||
|
||||
def __repr__(self):
|
||||
return '<{}>'.format(self.__class__.__name__)
|
||||
@ -130,7 +130,7 @@ class ReadlineBridge:
|
||||
if widget is None:
|
||||
return
|
||||
widget.home(True)
|
||||
self.deleted[widget] = widget.selectedText()
|
||||
self._deleted[widget] = widget.selectedText()
|
||||
widget.del_()
|
||||
|
||||
@cmdutils.register(instance='readline-bridge', hide=True,
|
||||
@ -144,7 +144,7 @@ class ReadlineBridge:
|
||||
if widget is None:
|
||||
return
|
||||
widget.end(True)
|
||||
self.deleted[widget] = widget.selectedText()
|
||||
self._deleted[widget] = widget.selectedText()
|
||||
widget.del_()
|
||||
|
||||
@cmdutils.register(instance='readline-bridge', hide=True,
|
||||
@ -158,7 +158,7 @@ class ReadlineBridge:
|
||||
if widget is None:
|
||||
return
|
||||
widget.cursorWordBackward(True)
|
||||
self.deleted[widget] = widget.selectedText()
|
||||
self._deleted[widget] = widget.selectedText()
|
||||
widget.del_()
|
||||
|
||||
@cmdutils.register(instance='readline-bridge', hide=True,
|
||||
@ -172,7 +172,7 @@ class ReadlineBridge:
|
||||
if widget is None:
|
||||
return
|
||||
widget.cursorWordForward(True)
|
||||
self.deleted[widget] = widget.selectedText()
|
||||
self._deleted[widget] = widget.selectedText()
|
||||
widget.del_()
|
||||
|
||||
@cmdutils.register(instance='readline-bridge', hide=True,
|
||||
@ -183,9 +183,9 @@ class ReadlineBridge:
|
||||
This acts like readline's yank.
|
||||
"""
|
||||
widget = self._widget()
|
||||
if widget is None or widget not in self.deleted:
|
||||
if widget is None or widget not in self._deleted:
|
||||
return
|
||||
widget.insert(self.deleted[widget])
|
||||
widget.insert(self._deleted[widget])
|
||||
|
||||
@cmdutils.register(instance='readline-bridge', hide=True,
|
||||
modes=[typ.KeyMode.command, typ.KeyMode.prompt])
|
||||
|
@ -71,8 +71,8 @@ class NeighborList(collections.abc.Sequence):
|
||||
Modes: Different modes, see constructor documentation.
|
||||
|
||||
Attributes:
|
||||
idx: The current position in the list.
|
||||
fuzzyval: The value which is currently set but not in the list.
|
||||
_idx: The current position in the list.
|
||||
_items: A list of all items, accessed through item property.
|
||||
_mode: The current mode.
|
||||
"""
|
||||
@ -98,9 +98,9 @@ class NeighborList(collections.abc.Sequence):
|
||||
self._items = list(items)
|
||||
self._default = default
|
||||
if default is not _UNSET:
|
||||
self.idx = self._items.index(default)
|
||||
self._idx = self._items.index(default)
|
||||
else:
|
||||
self.idx = None
|
||||
self._idx = None
|
||||
self._mode = mode
|
||||
self.fuzzyval = None
|
||||
|
||||
@ -128,7 +128,7 @@ class NeighborList(collections.abc.Sequence):
|
||||
items = [(idx, e) for (idx, e) in enumerate(self._items)
|
||||
if op(e, self.fuzzyval)]
|
||||
close_item = min(items, key=lambda tpl: abs(self.fuzzyval - tpl[1]))
|
||||
self.idx = close_item[0]
|
||||
self._idx = close_item[0]
|
||||
return self.fuzzyval not in self._items
|
||||
|
||||
def _get_new_item(self, offset):
|
||||
@ -145,21 +145,21 @@ class NeighborList(collections.abc.Sequence):
|
||||
exception.
|
||||
"""
|
||||
try:
|
||||
if self.idx + offset >= 0:
|
||||
new = self._items[self.idx + offset]
|
||||
if self._idx + offset >= 0:
|
||||
new = self._items[self._idx + offset]
|
||||
else:
|
||||
raise IndexError
|
||||
except IndexError:
|
||||
if self._mode == self.Modes.block:
|
||||
new = self.curitem()
|
||||
elif self._mode == self.Modes.wrap:
|
||||
self.idx += offset
|
||||
self.idx %= len(self.items)
|
||||
self._idx += offset
|
||||
self._idx %= len(self.items)
|
||||
new = self.curitem()
|
||||
elif self._mode == self.Modes.exception:
|
||||
raise
|
||||
else:
|
||||
self.idx += offset
|
||||
self._idx += offset
|
||||
return new
|
||||
|
||||
@property
|
||||
@ -181,7 +181,7 @@ class NeighborList(collections.abc.Sequence):
|
||||
exception.
|
||||
"""
|
||||
log.misc.debug("{} items, idx {}, offset {}".format(
|
||||
len(self._items), self.idx, offset))
|
||||
len(self._items), self._idx, offset))
|
||||
if not self._items:
|
||||
raise IndexError("No items found!")
|
||||
if self.fuzzyval is not None:
|
||||
@ -198,8 +198,8 @@ class NeighborList(collections.abc.Sequence):
|
||||
|
||||
def curitem(self):
|
||||
"""Get the current item in the list."""
|
||||
if self.idx is not None:
|
||||
return self._items[self.idx]
|
||||
if self._idx is not None:
|
||||
return self._items[self._idx]
|
||||
else:
|
||||
raise IndexError("No current item!")
|
||||
|
||||
@ -215,14 +215,14 @@ class NeighborList(collections.abc.Sequence):
|
||||
"""Get the first item in the list."""
|
||||
if not self._items:
|
||||
raise IndexError("No items found!")
|
||||
self.idx = 0
|
||||
self._idx = 0
|
||||
return self.curitem()
|
||||
|
||||
def lastitem(self):
|
||||
"""Get the last item in the list."""
|
||||
if not self._items:
|
||||
raise IndexError("No items found!")
|
||||
self.idx = len(self._items) - 1
|
||||
self._idx = len(self._items) - 1
|
||||
return self.curitem()
|
||||
|
||||
def reset(self):
|
||||
@ -230,7 +230,7 @@ class NeighborList(collections.abc.Sequence):
|
||||
if self._default is _UNSET:
|
||||
raise ValueError("No default set!")
|
||||
else:
|
||||
self.idx = self._items.index(self._default)
|
||||
self._idx = self._items.index(self._default)
|
||||
return self.curitem()
|
||||
|
||||
|
||||
|
@ -532,8 +532,8 @@ class prevent_exceptions: # pylint: disable=invalid-name
|
||||
much cleaner to implement.
|
||||
|
||||
Attributes:
|
||||
retval: The value to return in case of an exception.
|
||||
predicate: The condition which needs to be True to prevent exceptions
|
||||
_retval: The value to return in case of an exception.
|
||||
_predicate: The condition which needs to be True to prevent exceptions
|
||||
"""
|
||||
|
||||
def __init__(self, retval, predicate=True):
|
||||
@ -544,8 +544,8 @@ class prevent_exceptions: # pylint: disable=invalid-name
|
||||
Args:
|
||||
See class attributes.
|
||||
"""
|
||||
self.retval = retval
|
||||
self.predicate = predicate
|
||||
self._retval = retval
|
||||
self._predicate = predicate
|
||||
|
||||
def __call__(self, func):
|
||||
"""Gets called when a function should be decorated.
|
||||
@ -556,10 +556,10 @@ class prevent_exceptions: # pylint: disable=invalid-name
|
||||
Return:
|
||||
The decorated function.
|
||||
"""
|
||||
if not self.predicate:
|
||||
if not self._predicate:
|
||||
return func
|
||||
|
||||
retval = self.retval
|
||||
retval = self._retval
|
||||
|
||||
@functools.wraps(func)
|
||||
def wrapper(*args, **kwargs): # pylint: disable=missing-docstring
|
||||
|
@ -56,7 +56,7 @@ class ConsoleLineEdit(misc.CommandLineEdit):
|
||||
'self': parent,
|
||||
}
|
||||
self._interpreter = code.InteractiveInterpreter(interpreter_locals)
|
||||
self.history = cmdhistory.History()
|
||||
self._history = cmdhistory.History()
|
||||
self.returnPressed.connect(self.execute)
|
||||
self.setText('')
|
||||
|
||||
@ -67,10 +67,10 @@ class ConsoleLineEdit(misc.CommandLineEdit):
|
||||
@pyqtSlot(str)
|
||||
def execute(self):
|
||||
"""Execute the line of code which was entered."""
|
||||
self.history.stop()
|
||||
self._history.stop()
|
||||
text = self.text()
|
||||
if text:
|
||||
self.history.append(text)
|
||||
self._history.append(text)
|
||||
self.push(text)
|
||||
self.setText('')
|
||||
|
||||
@ -95,10 +95,10 @@ class ConsoleLineEdit(misc.CommandLineEdit):
|
||||
def history_prev(self):
|
||||
"""Go back in the history."""
|
||||
try:
|
||||
if not self.history.is_browsing():
|
||||
item = self.history.start(self.text().strip())
|
||||
if not self._history.is_browsing():
|
||||
item = self._history.start(self.text().strip())
|
||||
else:
|
||||
item = self.history.previtem()
|
||||
item = self._history.previtem()
|
||||
except (cmdhistory.HistoryEmptyError,
|
||||
cmdhistory.HistoryEndReachedError):
|
||||
return
|
||||
@ -106,10 +106,10 @@ class ConsoleLineEdit(misc.CommandLineEdit):
|
||||
|
||||
def history_next(self):
|
||||
"""Go forward in the history."""
|
||||
if not self.history.is_browsing():
|
||||
if not self._history.is_browsing():
|
||||
return
|
||||
try:
|
||||
item = self.history.nextitem()
|
||||
item = self._history.nextitem()
|
||||
except cmdhistory.HistoryEndReachedError:
|
||||
return
|
||||
self.setText(item)
|
||||
@ -166,15 +166,15 @@ class ConsoleWidget(QWidget):
|
||||
|
||||
def __init__(self, parent=None):
|
||||
super().__init__(parent)
|
||||
self.lineedit = ConsoleLineEdit(self)
|
||||
self.output = ConsoleTextEdit()
|
||||
self.lineedit.write.connect(self.output.append)
|
||||
self.vbox = QVBoxLayout()
|
||||
self.vbox.setSpacing(0)
|
||||
self.vbox.addWidget(self.output)
|
||||
self.vbox.addWidget(self.lineedit)
|
||||
self.setLayout(self.vbox)
|
||||
self.lineedit.setFocus()
|
||||
self._lineedit = ConsoleLineEdit(self)
|
||||
self._output = ConsoleTextEdit()
|
||||
self._lineedit.write.connect(self._output.append)
|
||||
self._vbox = QVBoxLayout()
|
||||
self._vbox.setSpacing(0)
|
||||
self._vbox.addWidget(self._output)
|
||||
self._vbox.addWidget(self._lineedit)
|
||||
self.setLayout(self._vbox)
|
||||
self._lineedit.setFocus()
|
||||
|
||||
def __repr__(self):
|
||||
return '<{}, visible={}>'.format(
|
||||
@ -183,5 +183,5 @@ class ConsoleWidget(QWidget):
|
||||
@pyqtSlot(str, str)
|
||||
def on_config_changed(self, section, option):
|
||||
"""Update font when config changed."""
|
||||
self.lineedit.on_config_changed(section, option)
|
||||
self.output.on_config_changed(section, option)
|
||||
self._lineedit.on_config_changed(section, option)
|
||||
self._output.on_config_changed(section, option)
|
||||
|
@ -41,7 +41,7 @@ class MainWindow(QWidget):
|
||||
|
||||
Attributes:
|
||||
status: The StatusBar widget.
|
||||
downloadview: The DownloadView widget.
|
||||
_downloadview: The DownloadView widget.
|
||||
_tabbed_browser: The TabbedBrowser widget.
|
||||
_vbox: The main QVBoxLayout.
|
||||
"""
|
||||
@ -77,9 +77,9 @@ class MainWindow(QWidget):
|
||||
self._vbox.setContentsMargins(0, 0, 0, 0)
|
||||
self._vbox.setSpacing(0)
|
||||
|
||||
self.downloadview = downloads.DownloadView()
|
||||
self._vbox.addWidget(self.downloadview)
|
||||
self.downloadview.show()
|
||||
self._downloadview = downloads.DownloadView()
|
||||
self._vbox.addWidget(self._downloadview)
|
||||
self._downloadview.show()
|
||||
|
||||
self._tabbed_browser = tabbedbrowser.TabbedBrowser()
|
||||
self._tabbed_browser.title_changed.connect(self.setWindowTitle)
|
||||
@ -164,7 +164,7 @@ class MainWindow(QWidget):
|
||||
"""
|
||||
super().resizeEvent(e)
|
||||
self.resize_completion()
|
||||
self.downloadview.updateGeometry()
|
||||
self._downloadview.updateGeometry()
|
||||
self._tabbed_browser.tabBar().refresh()
|
||||
|
||||
def closeEvent(self, e):
|
||||
|
@ -73,7 +73,7 @@ class Command(misc.MinimalLineEditMixin, misc.CommandLineEdit):
|
||||
def __init__(self, parent=None):
|
||||
misc.CommandLineEdit.__init__(self, parent)
|
||||
misc.MinimalLineEditMixin.__init__(self)
|
||||
self.cursor_part = 0
|
||||
self._cursor_part = 0
|
||||
self.history.history = objreg.get('command-history').data
|
||||
self._empty_item_idx = None
|
||||
self.textEdited.connect(self.on_text_edited)
|
||||
@ -124,7 +124,7 @@ class Command(misc.MinimalLineEditMixin, misc.CommandLineEdit):
|
||||
for i, part in enumerate(self.split()):
|
||||
if cursor_pos <= len(part):
|
||||
# foo| bar
|
||||
self.cursor_part = i
|
||||
self._cursor_part = i
|
||||
if spaces:
|
||||
self._empty_item_idx = i
|
||||
else:
|
||||
@ -132,14 +132,14 @@ class Command(misc.MinimalLineEditMixin, misc.CommandLineEdit):
|
||||
break
|
||||
cursor_pos -= (len(part) + 1) # FIXME are spaces always 1 char?
|
||||
log.completion.debug("cursor_part {}, spaces {}".format(
|
||||
self.cursor_part, spaces))
|
||||
self._cursor_part, spaces))
|
||||
return
|
||||
|
||||
@pyqtSlot()
|
||||
def on_cursor_position_changed(self):
|
||||
"""Update completion when the cursor position changed."""
|
||||
self.update_completion.emit(self.prefix(), self.split(),
|
||||
self.cursor_part)
|
||||
self._cursor_part)
|
||||
|
||||
@pyqtSlot(str)
|
||||
def set_cmd_text(self, text):
|
||||
@ -156,7 +156,7 @@ class Command(misc.MinimalLineEditMixin, misc.CommandLineEdit):
|
||||
if old_text != text:
|
||||
# We want the completion to pop out here.
|
||||
self.update_completion.emit(self.prefix(), self.split(),
|
||||
self.cursor_part)
|
||||
self._cursor_part)
|
||||
self.setFocus()
|
||||
self.show_cmd.emit()
|
||||
|
||||
@ -196,16 +196,16 @@ class Command(misc.MinimalLineEditMixin, misc.CommandLineEdit):
|
||||
"""
|
||||
parts = self.split()
|
||||
log.completion.debug("changing part {} to '{}'".format(
|
||||
self.cursor_part, newtext))
|
||||
parts[self.cursor_part] = newtext
|
||||
self._cursor_part, newtext))
|
||||
parts[self._cursor_part] = newtext
|
||||
# We want to place the cursor directly after the part we just changed.
|
||||
cursor_str = self.prefix() + ' '.join(parts[:self.cursor_part + 1])
|
||||
cursor_str = self.prefix() + ' '.join(parts[:self._cursor_part + 1])
|
||||
if immediate:
|
||||
# If we should complete immediately, we want to move the cursor by
|
||||
# one more char, to get to the next field.
|
||||
cursor_str += ' '
|
||||
text = self.prefix() + ' '.join(parts)
|
||||
if immediate and self.cursor_part == len(parts) - 1:
|
||||
if immediate and self._cursor_part == len(parts) - 1:
|
||||
# If we should complete immediately and we're completing the last
|
||||
# part in the commandline, we automatically add a space.
|
||||
text += ' '
|
||||
|
@ -57,7 +57,7 @@ class Prompter:
|
||||
up the *new* question.
|
||||
|
||||
Attributes:
|
||||
question: A Question object with the question to be asked to the user.
|
||||
_question: A Question object with the question to be asked to the user.
|
||||
_loops: A list of local EventLoops to spin in when blocking.
|
||||
_queue: A deque of waiting questions.
|
||||
"""
|
||||
@ -86,7 +86,7 @@ class Prompter:
|
||||
if not self._busy:
|
||||
return None
|
||||
prompt = objreg.get('prompt')
|
||||
ctx = PromptContext(question=self.question,
|
||||
ctx = PromptContext(question=self._question,
|
||||
text=prompt.txt.text(),
|
||||
input_text=prompt.lineedit.text(),
|
||||
echo_mode=prompt.lineedit.echoMode(),
|
||||
@ -107,7 +107,7 @@ class Prompter:
|
||||
prompt.hide_prompt.emit()
|
||||
self._busy = False
|
||||
return False
|
||||
self.question = ctx.question
|
||||
self._question = ctx.question
|
||||
prompt.txt.setText(ctx.text)
|
||||
prompt.lineedit.setText(ctx.input_text)
|
||||
prompt.lineedit.setEchoMode(ctx.echo_mode)
|
||||
@ -115,7 +115,7 @@ class Prompter:
|
||||
return True
|
||||
|
||||
def _display_question(self):
|
||||
"""Display the question saved in self.question.
|
||||
"""Display the question saved in self._question.
|
||||
|
||||
Return:
|
||||
The mode which should be entered.
|
||||
@ -124,30 +124,30 @@ class Prompter:
|
||||
ValueError if the set PromptMode is invalid.
|
||||
"""
|
||||
prompt = objreg.get('prompt')
|
||||
if self.question.mode == usertypes.PromptMode.yesno:
|
||||
if self.question.default is None:
|
||||
if self._question.mode == usertypes.PromptMode.yesno:
|
||||
if self._question.default is None:
|
||||
suffix = ""
|
||||
elif self.question.default:
|
||||
elif self._question.default:
|
||||
suffix = " (yes)"
|
||||
else:
|
||||
suffix = " (no)"
|
||||
prompt.txt.setText(self.question.text + suffix)
|
||||
prompt.txt.setText(self._question.text + suffix)
|
||||
prompt.lineedit.hide()
|
||||
mode = usertypes.KeyMode.yesno
|
||||
elif self.question.mode == usertypes.PromptMode.text:
|
||||
prompt.txt.setText(self.question.text)
|
||||
if self.question.default:
|
||||
prompt.lineedit.setText(self.question.default)
|
||||
elif self._question.mode == usertypes.PromptMode.text:
|
||||
prompt.txt.setText(self._question.text)
|
||||
if self._question.default:
|
||||
prompt.lineedit.setText(self._question.default)
|
||||
prompt.lineedit.show()
|
||||
mode = usertypes.KeyMode.prompt
|
||||
elif self.question.mode == usertypes.PromptMode.user_pwd:
|
||||
prompt.txt.setText(self.question.text)
|
||||
if self.question.default:
|
||||
prompt.lineedit.setText(self.question.default)
|
||||
elif self._question.mode == usertypes.PromptMode.user_pwd:
|
||||
prompt.txt.setText(self._question.text)
|
||||
if self._question.default:
|
||||
prompt.lineedit.setText(self._question.default)
|
||||
prompt.lineedit.show()
|
||||
mode = usertypes.KeyMode.prompt
|
||||
elif self.question.mode == usertypes.PromptMode.alert:
|
||||
prompt.txt.setText(self.question.text + ' (ok)')
|
||||
elif self._question.mode == usertypes.PromptMode.alert:
|
||||
prompt.txt.setText(self._question.text + ' (ok)')
|
||||
prompt.lineedit.hide()
|
||||
mode = usertypes.KeyMode.prompt
|
||||
else:
|
||||
@ -184,8 +184,8 @@ class Prompter:
|
||||
prompt.lineedit.setEchoMode(QLineEdit.Normal)
|
||||
prompt.hide_prompt.emit()
|
||||
self._busy = False
|
||||
if self.question.answer is None and not self.question.is_aborted:
|
||||
self.question.cancel()
|
||||
if self._question.answer is None and not self._question.is_aborted:
|
||||
self._question.cancel()
|
||||
|
||||
@cmdutils.register(instance='prompter', hide=True,
|
||||
modes=[usertypes.KeyMode.prompt,
|
||||
@ -199,34 +199,34 @@ class Prompter:
|
||||
for the password or leaves the mode.
|
||||
"""
|
||||
prompt = objreg.get('prompt')
|
||||
if (self.question.mode == usertypes.PromptMode.user_pwd and
|
||||
self.question.user is None):
|
||||
if (self._question.mode == usertypes.PromptMode.user_pwd and
|
||||
self._question.user is None):
|
||||
# User just entered an username
|
||||
self.question.user = prompt.lineedit.text()
|
||||
self._question.user = prompt.lineedit.text()
|
||||
prompt.txt.setText("Password:")
|
||||
prompt.lineedit.clear()
|
||||
prompt.lineedit.setEchoMode(QLineEdit.Password)
|
||||
elif self.question.mode == usertypes.PromptMode.user_pwd:
|
||||
elif self._question.mode == usertypes.PromptMode.user_pwd:
|
||||
# User just entered a password
|
||||
password = prompt.lineedit.text()
|
||||
self.question.answer = (self.question.user, password)
|
||||
self._question.answer = (self._question.user, password)
|
||||
modeman.leave(usertypes.KeyMode.prompt, 'prompt accept')
|
||||
self.question.done()
|
||||
elif self.question.mode == usertypes.PromptMode.text:
|
||||
self._question.done()
|
||||
elif self._question.mode == usertypes.PromptMode.text:
|
||||
# User just entered text.
|
||||
self.question.answer = prompt.lineedit.text()
|
||||
self._question.answer = prompt.lineedit.text()
|
||||
modeman.leave(usertypes.KeyMode.prompt, 'prompt accept')
|
||||
self.question.done()
|
||||
elif self.question.mode == usertypes.PromptMode.yesno:
|
||||
self._question.done()
|
||||
elif self._question.mode == usertypes.PromptMode.yesno:
|
||||
# User wants to accept the default of a yes/no question.
|
||||
self.question.answer = self.question.default
|
||||
self._question.answer = self._question.default
|
||||
modeman.leave(usertypes.KeyMode.yesno, 'yesno accept')
|
||||
self.question.done()
|
||||
elif self.question.mode == usertypes.PromptMode.alert:
|
||||
self._question.done()
|
||||
elif self._question.mode == usertypes.PromptMode.alert:
|
||||
# User acknowledged an alert
|
||||
self.question.answer = None
|
||||
self._question.answer = None
|
||||
modeman.leave(usertypes.KeyMode.prompt, 'alert accept')
|
||||
self.question.done()
|
||||
self._question.done()
|
||||
else:
|
||||
raise ValueError("Invalid question mode!")
|
||||
|
||||
@ -234,23 +234,23 @@ class Prompter:
|
||||
modes=[usertypes.KeyMode.yesno])
|
||||
def prompt_yes(self):
|
||||
"""Answer yes to a yes/no prompt."""
|
||||
if self.question.mode != usertypes.PromptMode.yesno:
|
||||
if self._question.mode != usertypes.PromptMode.yesno:
|
||||
# We just ignore this if we don't have a yes/no question.
|
||||
return
|
||||
self.question.answer = True
|
||||
self._question.answer = True
|
||||
modeman.leave(usertypes.KeyMode.yesno, 'yesno accept')
|
||||
self.question.done()
|
||||
self._question.done()
|
||||
|
||||
@cmdutils.register(instance='prompter', hide=True,
|
||||
modes=[usertypes.KeyMode.yesno])
|
||||
def prompt_no(self):
|
||||
"""Answer no to a yes/no prompt."""
|
||||
if self.question.mode != usertypes.PromptMode.yesno:
|
||||
if self._question.mode != usertypes.PromptMode.yesno:
|
||||
# We just ignore this if we don't have a yes/no question.
|
||||
return
|
||||
self.question.answer = False
|
||||
self._question.answer = False
|
||||
modeman.leave(usertypes.KeyMode.yesno, 'prompt accept')
|
||||
self.question.done()
|
||||
self._question.done()
|
||||
|
||||
@pyqtSlot(usertypes.Question, bool)
|
||||
def ask_question(self, question, blocking):
|
||||
@ -280,7 +280,7 @@ class Prompter:
|
||||
# restore it after exec, if exec gets called multiple times.
|
||||
context = self._get_ctx()
|
||||
|
||||
self.question = question
|
||||
self._question = question
|
||||
mode = self._display_question()
|
||||
question.aborted.connect(lambda: modeman.maybe_leave(mode, 'aborted'))
|
||||
mode_manager = objreg.get('mode-manager')
|
||||
@ -303,6 +303,6 @@ class Prompter:
|
||||
# questions.
|
||||
if self._queue:
|
||||
self._pop_later()
|
||||
return self.question.answer
|
||||
return self._question.answer
|
||||
else:
|
||||
question.completed.connect(self._pop_later)
|
||||
|
Loading…
Reference in New Issue
Block a user