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