Privatize all attributes which aren't needed from the outside.

This commit is contained in:
Florian Bruhin 2014-09-24 22:17:53 +02:00
parent 75da8a7f1b
commit 62e55499eb
23 changed files with 430 additions and 424 deletions

View File

@ -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()

View File

@ -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:]

View File

@ -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(

View File

@ -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)

View File

@ -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!")

View File

@ -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))

View File

@ -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)

View File

@ -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

View File

@ -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()."""

View File

@ -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")

View File

@ -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__':

View File

@ -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

View File

@ -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]

View File

@ -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)

View File

@ -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:

View File

@ -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:

View File

@ -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])

View File

@ -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()

View File

@ -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

View File

@ -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)

View File

@ -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):

View File

@ -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 += ' '

View File

@ -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)