diff --git a/CONTRIBUTING.asciidoc b/CONTRIBUTING.asciidoc index 372fa9ef1..9f65c5d7f 100644 --- a/CONTRIBUTING.asciidoc +++ b/CONTRIBUTING.asciidoc @@ -416,21 +416,17 @@ The types of the function arguments are inferred based on their default values, e.g. an argument `foo=True` will be converted to a flag `-f`/`--foo` in qutebrowser's commandline. -This behavior can be overridden using Python's -http://legacy.python.org/dev/peps/pep-3107/[function annotations]. The -annotation should always be a `dict`, like this: +The type can be overridden using Python's +http://legacy.python.org/dev/peps/pep-3107/[function annotations]: [source,python] ---- @cmdutils.register(...) -def foo(bar: {'type': int}, baz=True): +def foo(bar: int, baz=True): ... ---- -The following keys are supported in the dict: - -* `type`: The type this value should have. The value entered by the user is -then automatically checked. Possible values: +Possible values: - A callable (`int`, `float`, etc.): Gets called to validate/convert the value. - A string: The value must match exactly (mainly useful with tuples to get diff --git a/qutebrowser/browser/commands.py b/qutebrowser/browser/commands.py index ba7f303fb..8ab4614ee 100644 --- a/qutebrowser/browser/commands.py +++ b/qutebrowser/browser/commands.py @@ -455,8 +455,7 @@ class CommandDispatcher: self._open(url, tab, background, window) @cmdutils.register(instance='command-dispatcher', scope='window') - def navigate(self, where: {'type': ('prev', 'next', 'up', 'increment', - 'decrement')}, + def navigate(self, where: ('prev', 'next', 'up', 'increment', 'decrement'), tab=False, bg=False, window=False): """Open typical prev/next links or navigate using the URL path. @@ -505,7 +504,7 @@ class CommandDispatcher: @cmdutils.register(instance='command-dispatcher', hide=True, scope='window') @cmdutils.argument('count', count=True) - def scroll_px(self, dx: {'type': int}, dy: {'type': int}, count=1): + def scroll_px(self, dx: int, dy: int, count=1): """Scroll the current tab by 'count * dx/dy' pixels. Args: @@ -522,7 +521,7 @@ class CommandDispatcher: @cmdutils.register(instance='command-dispatcher', hide=True, scope='window') @cmdutils.argument('count', count=True) - def scroll(self, direction: {'type': (str, int)}, count=1): + def scroll(self, direction: (str, int), count=1): """Scroll the current tab in the given direction. Args: @@ -583,8 +582,7 @@ class CommandDispatcher: scope='window') @cmdutils.argument('count', count=True) @cmdutils.argument('horizontal', flag='x') - def scroll_perc(self, perc: {'type': float}=None, horizontal=False, - count=None): + def scroll_perc(self, perc: float=None, horizontal=False, count=None): """Scroll to a specific percentage of the page. The percentage can be given either as argument or as count. @@ -622,9 +620,9 @@ class CommandDispatcher: @cmdutils.argument('count', count=True) @cmdutils.argument('top_navigate', metavar='ACTION') @cmdutils.argument('bottom_navigate', metavar='ACTION') - def scroll_page(self, x: {'type': float}, y: {'type': float}, *, - top_navigate: {'type': ('prev', 'decrement')}=None, - bottom_navigate: {'type': ('next', 'increment')}=None, + def scroll_page(self, x: float, y: float, *, + top_navigate: ('prev', 'decrement')=None, + bottom_navigate: ('next', 'increment')=None, count=1): """Scroll the frame page-wise. @@ -738,7 +736,7 @@ class CommandDispatcher: @cmdutils.register(instance='command-dispatcher', scope='window') @cmdutils.argument('count', count=True) - def zoom(self, zoom: {'type': int}=None, count=None): + def zoom(self, zoom: int=None, count=None): """Set the zoom level for the current tab. The zoom can be given as argument or as [count]. If neither of both is @@ -921,7 +919,7 @@ class CommandDispatcher: @cmdutils.register(instance='command-dispatcher', scope='window') @cmdutils.argument('count', count=True) - def tab_focus(self, index: {'type': (int, 'last')}=None, count=None): + def tab_focus(self, index: (int, 'last')=None, count=None): """Select the tab given as argument/[count]. If neither count nor index are given, it behaves like tab-next. @@ -954,7 +952,7 @@ class CommandDispatcher: @cmdutils.register(instance='command-dispatcher', scope='window') @cmdutils.argument('count', count=True) - def tab_move(self, direction: {'type': ('+', '-')}=None, count=None): + def tab_move(self, direction: ('+', '-')=None, count=None): """Move the current tab. Args: diff --git a/qutebrowser/commands/command.py b/qutebrowser/commands/command.py index 7245450f6..acec7988e 100644 --- a/qutebrowser/commands/command.py +++ b/qutebrowser/commands/command.py @@ -87,14 +87,8 @@ class Command: _count: The count set for the command. _instance: The object to bind 'self' to. _scope: The scope to get _instance for in the object registry. - - Class attributes: - AnnotationInfo: Named tuple for info from an annotation. """ - AnnotationInfo = collections.namedtuple( - 'AnnotationInfo', ['type']) - def __init__(self, *, handler, name, instance=None, maxsplit=None, hide=False, completion=None, modes=None, not_modes=None, needs_js=False, debug=False, ignore_args=False, @@ -256,14 +250,13 @@ class Command: if not self.ignore_args: for param in signature.parameters.values(): - annotation_info = self._parse_annotation(param) if param.name == 'self': continue if self._inspect_special_param(param): continue - typ = self._get_type(param, annotation_info) - kwargs = self._param_to_argparse_kwargs(param, annotation_info) - args = self._param_to_argparse_args(param, annotation_info) + typ = self._get_type(param) + kwargs = self._param_to_argparse_kwargs(param, typ) + args = self._param_to_argparse_args(param, typ) self._type_conv.update(self._get_typeconv(param, typ)) callsig = debug_utils.format_call( self.parser.add_argument, args, kwargs, @@ -273,18 +266,17 @@ class Command: self.parser.add_argument(*args, **kwargs) return signature.parameters.keys() - def _param_to_argparse_kwargs(self, param, annotation_info): + def _param_to_argparse_kwargs(self, param, typ): """Get argparse keyword arguments for a parameter. Args: param: The inspect.Parameter object to get the args for. - annotation_info: An AnnotationInfo tuple for the parameter. + typ: The type of the parameter Return: A kwargs dict. """ kwargs = {} - typ = self._get_type(param, annotation_info) try: kwargs['help'] = self.docparser.arg_descs[param.name] @@ -314,12 +306,12 @@ class Command: kwargs['nargs'] = '?' return kwargs - def _param_to_argparse_args(self, param, annotation_info): + def _param_to_argparse_args(self, param, typ): """Get argparse positional arguments for a parameter. Args: param: The inspect.Parameter object to get the args for. - annotation_info: An AnnotationInfo tuple for the parameter. + typ: The type of the parameter Return: A list of args. @@ -337,7 +329,6 @@ class Command: raise ValueError("Flag '{}' of parameter {} (command {}) must be " "exactly 1 char!".format(shortname, name, self.name)) - typ = self._get_type(param, annotation_info) if typ is bool or param.kind == inspect.Parameter.KEYWORD_ONLY: long_flag = '--{}'.format(name) short_flag = '-{}'.format(shortname) @@ -351,33 +342,14 @@ class Command: self.pos_args.append((param.name, name)) return args - def _parse_annotation(self, param): - """Get argparse arguments and type from a parameter annotation. - - Args: - param: A inspect.Parameter instance. - - Return: - An AnnotationInfo namedtuple. - typ: The type to use for this argument. - name: The long name if overridden. - """ - info = {'type': None} - if param.annotation is not inspect.Parameter.empty: - log.commands.vdebug("Parsing annotation {}".format( - param.annotation)) - info['type'] = param.annotation['type'] - return self.AnnotationInfo(**info) - - def _get_type(self, param, annotation_info): + def _get_type(self, param): """Get the type of an argument from its default value or annotation. Args: param: The inspect.Parameter to look at. - annotation_info: An AnnotationInfo tuple which overrides the type. """ - if annotation_info.type is not None: - return annotation_info.type + if param.annotation is not inspect.Parameter.empty: + return param.annotation elif param.default is None or param.default is inspect.Parameter.empty: return None else: diff --git a/qutebrowser/misc/sessions.py b/qutebrowser/misc/sessions.py index ecd396be1..4ebee8c44 100644 --- a/qutebrowser/misc/sessions.py +++ b/qutebrowser/misc/sessions.py @@ -388,7 +388,7 @@ class SessionManager(QObject): completion=[usertypes.Completion.sessions], instance='session-manager') @cmdutils.argument('win_id', win_id=True) - def session_save(self, win_id, name: {'type': str}=default, current=False, + def session_save(self, win_id, name: str=default, current=False, quiet=False, force=False): """Save a session. diff --git a/qutebrowser/misc/utilcmds.py b/qutebrowser/misc/utilcmds.py index 35a82d9b2..5025a2c41 100644 --- a/qutebrowser/misc/utilcmds.py +++ b/qutebrowser/misc/utilcmds.py @@ -41,7 +41,7 @@ from PyQt5.QtWidgets import QApplication # pylint: disable=unused-import @cmdutils.register(maxsplit=1, no_cmd_split=True) @cmdutils.argument('win_id', win_id=True) -def later(ms: {'type': int}, command, win_id): +def later(ms: int, command, win_id): """Execute a command after some time. Args: @@ -71,7 +71,7 @@ def later(ms: {'type': int}, command, win_id): @cmdutils.register(maxsplit=1, no_cmd_split=True) @cmdutils.argument('win_id', win_id=True) -def repeat(times: {'type': int}, command, win_id): +def repeat(times: int, command, win_id): """Repeat a given command. Args: @@ -119,7 +119,7 @@ def message_warning(win_id, text): @cmdutils.register(debug=True) -def debug_crash(typ: {'type': ('exception', 'segfault')}='exception'): +def debug_crash(typ: ('exception', 'segfault')='exception'): """Crash for debugging purposes. Args: