diff --git a/.gitignore b/.gitignore index 9efceef63..ceafd9946 100644 --- a/.gitignore +++ b/.gitignore @@ -41,3 +41,4 @@ TODO /scripts/testbrowser/cpp/webengine/.qmake.stash /scripts/dev/pylint_checkers/qute_pylint.egg-info /misc/file_version_info.txt +/doc/extapi/_build diff --git a/doc/extapi/_static/.gitkeep b/doc/extapi/_static/.gitkeep new file mode 100644 index 000000000..e69de29bb diff --git a/doc/extapi/_templates/.gitkeep b/doc/extapi/_templates/.gitkeep new file mode 100644 index 000000000..e69de29bb diff --git a/doc/extapi/api.rst b/doc/extapi/api.rst new file mode 100644 index 000000000..b63db57c3 --- /dev/null +++ b/doc/extapi/api.rst @@ -0,0 +1,48 @@ +API modules +=========== + +cmdutils module +--------------- + +.. automodule:: qutebrowser.api.cmdutils + :members: + :imported-members: + +apitypes module +--------------- + +.. automodule:: qutebrowser.api.apitypes + :members: + :imported-members: + +config module +------------- + +.. automodule:: qutebrowser.api.config + :members: + +downloads module +---------------- + +.. automodule:: qutebrowser.api.downloads + :members: + +hook module +----------- + +.. automodule:: qutebrowser.api.hook + :members: + +interceptor module +------------------ + +.. automodule:: qutebrowser.api.interceptor + :members: + :imported-members: + +message module +-------------- + +.. automodule:: qutebrowser.api.message + :members: + :imported-members: diff --git a/doc/extapi/conf.py b/doc/extapi/conf.py new file mode 100644 index 000000000..4cc5c6803 --- /dev/null +++ b/doc/extapi/conf.py @@ -0,0 +1,179 @@ +# -*- coding: utf-8 -*- +# +# Configuration file for the Sphinx documentation builder. +# +# This file does only contain a selection of the most common options. For a +# full list see the documentation: +# http://www.sphinx-doc.org/en/master/config + +# -- Path setup -------------------------------------------------------------- + +# If extensions (or modules to document with autodoc) are in another directory, +# add these directories to sys.path here. If the directory is relative to the +# documentation root, use os.path.abspath to make it absolute, like shown here. +# +# import os +# import sys +# sys.path.insert(0, os.path.abspath('.')) + + +# -- Project information ----------------------------------------------------- + +project = 'qutebrowser extensions' +copyright = '2018, Florian Bruhin' +author = 'Florian Bruhin' + +# The short X.Y version +version = '' +# The full version, including alpha/beta/rc tags +release = '' + + +# -- General configuration --------------------------------------------------- + +# If your documentation needs a minimal Sphinx version, state it here. +# +# needs_sphinx = '1.0' + +# Add any Sphinx extension module names here, as strings. They can be +# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom +# ones. +extensions = [ + 'sphinx.ext.autodoc', + 'sphinx.ext.napoleon', +] +autodoc_member_order = 'bysource' + +# Add any paths that contain templates here, relative to this directory. +templates_path = ['_templates'] + +# The suffix(es) of source filenames. +# You can specify multiple suffix as a list of string: +# +# source_suffix = ['.rst', '.md'] +source_suffix = '.rst' + +# The master toctree document. +master_doc = 'index' + +# The language for content autogenerated by Sphinx. Refer to documentation +# for a list of supported languages. +# +# This is also used if you do content translation via gettext catalogs. +# Usually you set "language" from the command line for these cases. +language = None + +# List of patterns, relative to source directory, that match files and +# directories to ignore when looking for source files. +# This pattern also affects html_static_path and html_extra_path. +exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store'] + +# The name of the Pygments (syntax highlighting) style to use. +pygments_style = None + + +# -- Options for HTML output ------------------------------------------------- + +# The theme to use for HTML and HTML Help pages. See the documentation for +# a list of builtin themes. +# +html_theme = 'alabaster' + +# Theme options are theme-specific and customize the look and feel of a theme +# further. For a list of options available for each theme, see the +# documentation. +# +# html_theme_options = {} + +# Add any paths that contain custom static files (such as style sheets) here, +# relative to this directory. They are copied after the builtin static files, +# so a file named "default.css" will overwrite the builtin "default.css". +html_static_path = ['_static'] + +# Custom sidebar templates, must be a dictionary that maps document names +# to template names. +# +# The default sidebars (for documents that don't match any pattern) are +# defined by theme itself. Builtin themes are using these templates by +# default: ``['localtoc.html', 'relations.html', 'sourcelink.html', +# 'searchbox.html']``. +# +# html_sidebars = {} + + +# -- Options for HTMLHelp output --------------------------------------------- + +# Output file base name for HTML help builder. +htmlhelp_basename = 'qutebrowserextensionsdoc' + + +# -- Options for LaTeX output ------------------------------------------------ + +latex_elements = { + # The paper size ('letterpaper' or 'a4paper'). + # + # 'papersize': 'letterpaper', + + # The font size ('10pt', '11pt' or '12pt'). + # + # 'pointsize': '10pt', + + # Additional stuff for the LaTeX preamble. + # + # 'preamble': '', + + # Latex figure (float) alignment + # + # 'figure_align': 'htbp', +} + +# Grouping the document tree into LaTeX files. List of tuples +# (source start file, target name, title, +# author, documentclass [howto, manual, or own class]). +latex_documents = [ + (master_doc, 'qutebrowserextensions.tex', 'qutebrowser extensions Documentation', + 'Florian Bruhin', 'manual'), +] + + +# -- Options for manual page output ------------------------------------------ + +# One entry per manual page. List of tuples +# (source start file, name, description, authors, manual section). +man_pages = [ + (master_doc, 'qutebrowserextensions', 'qutebrowser extensions Documentation', + [author], 1) +] + + +# -- Options for Texinfo output ---------------------------------------------- + +# Grouping the document tree into Texinfo files. List of tuples +# (source start file, target name, title, author, +# dir menu entry, description, category) +texinfo_documents = [ + (master_doc, 'qutebrowserextensions', 'qutebrowser extensions Documentation', + author, 'qutebrowserextensions', 'One line description of project.', + 'Miscellaneous'), +] + + +# -- Options for Epub output ------------------------------------------------- + +# Bibliographic Dublin Core info. +epub_title = project + +# The unique identifier of the text. This can be a ISBN number +# or the project homepage. +# +# epub_identifier = '' + +# A unique identification for the text. +# +# epub_uid = '' + +# A list of files that should not be packed into the epub file. +epub_exclude_files = ['search.html'] + + +# -- Extension configuration ------------------------------------------------- diff --git a/doc/extapi/index.rst b/doc/extapi/index.rst new file mode 100644 index 000000000..d181c2ccd --- /dev/null +++ b/doc/extapi/index.rst @@ -0,0 +1,22 @@ +.. qutebrowser extensions documentation master file, created by + sphinx-quickstart on Tue Dec 11 18:59:44 2018. + You can adapt this file completely to your liking, but it should at least + contain the root `toctree` directive. + +Welcome to qutebrowser extensions's documentation! +================================================== + +.. toctree:: + :maxdepth: 2 + :caption: Contents: + + api + tab + + +Indices and tables +================== + +* :ref:`genindex` +* :ref:`modindex` +* :ref:`search` diff --git a/doc/extapi/tab.rst b/doc/extapi/tab.rst new file mode 100644 index 000000000..57a14ac6e --- /dev/null +++ b/doc/extapi/tab.rst @@ -0,0 +1,44 @@ +Tab API +======= + +.. autoclass:: qutebrowser.browser.browsertab.AbstractTab() + :members: + +.. autoclass:: qutebrowser.browser.browsertab.AbstractAction() + :members: + +.. autoclass:: qutebrowser.browser.browsertab.AbstractPrinting() + :members: + +.. autoclass:: qutebrowser.browser.browsertab.AbstractSearch() + :members: + +.. autoclass:: qutebrowser.browser.browsertab.AbstractZoom() + :members: + +.. autoclass:: qutebrowser.browser.browsertab.AbstractCaret() + :members: + +.. autoclass:: qutebrowser.browser.browsertab.AbstractScroller() + :members: + +.. autoclass:: qutebrowser.browser.browsertab.AbstractHistory() + :members: + +.. autoclass:: qutebrowser.browser.browsertab.AbstractElements() + :members: + +.. autoclass:: qutebrowser.browser.browsertab.AbstractAudio() + :members: + +Web element API +=============== + +.. autoclass:: qutebrowser.browser.webelem.AbstractWebElement + :members: + +.. autoclass:: qutebrowser.browser.webelem.Error + :members: + +.. autoclass:: qutebrowser.browser.webelem.OrphanedError + :members: diff --git a/misc/requirements/requirements-sphinx.txt b/misc/requirements/requirements-sphinx.txt new file mode 100644 index 000000000..c0801a48e --- /dev/null +++ b/misc/requirements/requirements-sphinx.txt @@ -0,0 +1,21 @@ +# This file is automatically generated by scripts/dev/recompile_requirements.py + +alabaster==0.7.12 +Babel==2.6.0 +certifi==2018.11.29 +chardet==3.0.4 +docutils==0.14 +idna==2.8 +imagesize==1.1.0 +Jinja2==2.10 +MarkupSafe==1.1.0 +packaging==18.0 +Pygments==2.3.0 +pyparsing==2.3.0 +pytz==2018.7 +requests==2.21.0 +six==1.12.0 +snowballstemmer==1.2.1 +Sphinx==1.8.2 +sphinxcontrib-websupport==1.1.0 +urllib3==1.24.1 diff --git a/misc/requirements/requirements-sphinx.txt-raw b/misc/requirements/requirements-sphinx.txt-raw new file mode 100644 index 000000000..6966869c7 --- /dev/null +++ b/misc/requirements/requirements-sphinx.txt-raw @@ -0,0 +1 @@ +sphinx diff --git a/qutebrowser/api/cmdutils.py b/qutebrowser/api/cmdutils.py index 093244727..f6a6f6da9 100644 --- a/qutebrowser/api/cmdutils.py +++ b/qutebrowser/api/cmdutils.py @@ -17,7 +17,38 @@ # You should have received a copy of the GNU General Public License # along with qutebrowser. If not, see . -"""Utilities for command handlers.""" +""" +qutebrowser has the concept of functions which are exposed to the user as +commands. + +Creating a new command is straightforward:: + + from qutebrowser.api import cmdutils + + @cmdutils.register(...) + def foo(): + ... + +The commands arguments are automatically deduced by inspecting your function. + +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. + +The type can be overridden using Python's function annotations:: + + @cmdutils.register(...) + def foo(bar: int, baz=True): + ... + +Possible values: + +- A callable (``int``, ``float``, etc.): Gets called to validate/convert the value. +- A python enum type: All members of the enum are possible values. +- A ``typing.Union`` of multiple types above: Any of these types are valid + values, e.g., ``typing.Union[str, int]``. +""" + import inspect import typing @@ -33,15 +64,17 @@ class CommandError(cmdexc.Error): """Raised when a command encounters an error while running. If your command handler encounters an error and cannot continue, raise this - exception with an appropriate error message: + exception with an appropriate error message:: raise cmdexc.CommandError("Message") The message will then be shown in the qutebrowser status bar. - Note that you should only raise this exception while a command handler is - run. Raising it at another point causes qutebrowser to crash due to an - unhandled exception. + .. note:: + + You should only raise this exception while a command handler is run. + Raising it at another point causes qutebrowser to crash due to an + unhandled exception. """ @@ -76,13 +109,7 @@ def check_exclusive(flags: typing.Iterable[bool], class register: # noqa: N801,N806 pylint: disable=invalid-name - """Decorator to register a new command handler. - - Attributes: - _instance: The object from the object registry to be used as "self". - _name: The name (as string) or names (as list) of the command. - _kwargs: The arguments to pass to Command. - """ + """Decorator to register a new command handler.""" def __init__(self, *, instance: str = None, @@ -95,8 +122,11 @@ class register: # noqa: N801,N806 pylint: disable=invalid-name Args: See class attributes. """ + # The object from the object registry to be used as "self". self._instance = instance + # The name (as string) or names (as list) of the command. self._name = name + # The arguments to pass to Command. self._kwargs = kwargs def __call__(self, func: typing.Callable) -> typing.Callable: @@ -127,16 +157,47 @@ class register: # noqa: N801,N806 pylint: disable=invalid-name class argument: # noqa: N801,N806 pylint: disable=invalid-name - """Decorator to customize an argument for @cmdutils.register. + """Decorator to customize an argument. - Attributes: - _argname: The name of the argument to handle. - _kwargs: Keyword arguments, valid ArgInfo members + You can customize how an argument is handled using the ``@cmdutils.argument`` + decorator *after* ``@cmdutils.register``. This can, for example, be used to + customize the flag an argument should get:: + + @cmdutils.register(...) + @cmdutils.argument('bar', flag='c') + def foo(bar): + ... + + For a ``str`` argument, you can restrict the allowed strings using ``choices``:: + + @cmdutils.register(...) + @cmdutils.argument('bar', choices=['val1', 'val2']) + def foo(bar: str): + ... + + For ``typing.Union`` types, the given ``choices`` are only checked if other types + (like ``int``) don't match. + + The following arguments are supported for ``@cmdutils.argument``: + + - ``flag``: Customize the short flag (``-x``) the argument will get. + - ``value``: Tell qutebrowser to fill the argument with special values: + + * ``value=cmdutils.Value.count``: The ``count`` given by the user to the command. + * ``value=cmdutils.Value.win_id``: The window ID of the current window. + * ``value=cmdutils.Value.cur_tab``: The tab object which is currently focused. + + - ``completion``: A completion function to use when completing arguments for + the given command. + - ``choices``: The allowed string choices for the argument. + + The name of an argument will always be the parameter name, with any trailing + underscores stripped and underscores replaced by dashes. """ def __init__(self, argname: str, **kwargs: typing.Any) -> None: - self._argname = argname - self._kwargs = kwargs + self._argname = argname # The name of the argument to handle. + self._kwargs = kwargs # Valid ArgInfo members. def __call__(self, func: typing.Callable) -> typing.Callable: funcname = func.__name__ diff --git a/qutebrowser/api/config.py b/qutebrowser/api/config.py index 4a5d73936..0c633e54d 100644 --- a/qutebrowser/api/config.py +++ b/qutebrowser/api/config.py @@ -25,6 +25,16 @@ from PyQt5.QtCore import QUrl from qutebrowser.config import config +#: Simplified access to config values using attribute acccess. +#: For example, to access the ``content.javascript.enabled`` setting, +#: you can do:: +#: +#: if config.val.content.javascript.enabled: +#: ... +#: +#: This also supports setting configuration values:: +#: +#: config.val.content.javascript.enabled = False val = typing.cast('config.ConfigContainer', None) diff --git a/qutebrowser/api/downloads.py b/qutebrowser/api/downloads.py index 82c68d0bd..a2a37d931 100644 --- a/qutebrowser/api/downloads.py +++ b/qutebrowser/api/downloads.py @@ -52,6 +52,21 @@ def download_temp(url: QUrl) -> TempDownload: """Download the given URL into a file object. The download is not saved to disk. + + Returns a ``TempDownload`` object, which triggers a ``finished`` signal + when the download has finished:: + + dl = downloads.download_temp(QUrl("https://www.example.com/")) + dl.finished.connect(functools.partial(on_download_finished, dl)) + + After the download has finished, its ``successful`` attribute can be + checked to make sure it finished successfully. If so, its contents can be + read by accessing the ``fileobj`` attribute:: + + def on_download_finished(download: downloads.TempDownload) -> None: + if download.successful: + print(download.fileobj.read()) + download.fileobj.close() """ fobj = io.BytesIO() fobj.name = 'temporary: ' + url.host() diff --git a/qutebrowser/api/hook.py b/qutebrowser/api/hook.py index 3f06121da..84e103cbd 100644 --- a/qutebrowser/api/hook.py +++ b/qutebrowser/api/hook.py @@ -36,7 +36,17 @@ def _add_module_info(func: typing.Callable) -> loader.ModuleInfo: class init: - """Decorator to mark a function to run when initializing.""" + """Decorator to mark a function to run when initializing. + + The decorated function gets called with a + :class:`qutebrowser.api.apitypes.InitContext` as argument. + + Example:: + + @hook.init() + def init(_context): + message.info("Extension initialized.") + """ def __call__(self, func: typing.Callable) -> typing.Callable: info = _add_module_info(func) @@ -48,7 +58,30 @@ class init: class config_changed: - """Decorator to get notified about changed configs.""" + """Decorator to get notified about changed configs. + + By default, the decorated function is called when any change in the config + occurs:: + + @hook.config_changed() + def on_config_changed(): + ... + + When an option name is passed, it's only called when the given option was + changed:: + + @hook.config_changed('content.javascript.enabled') + def on_config_changed(): + ... + + Alternatively, a part of an option name can be specified. In the following + snippet, ``on_config_changed`` gets called when either + ``bindings.commands`` or ``bindings.key_mappings`` have changed:: + + @hook.config_changed('bindings') + def on_config_changed(): + ... + """ def __init__(self, option_filter: str = None) -> None: self._filter = option_filter diff --git a/qutebrowser/api/interceptor.py b/qutebrowser/api/interceptor.py index a40635fca..634ae1409 100644 --- a/qutebrowser/api/interceptor.py +++ b/qutebrowser/api/interceptor.py @@ -27,7 +27,13 @@ from qutebrowser.extensions.interceptors import Request def register(interceptor: interceptors.InterceptorType) -> None: """Register a request interceptor. - Whenever a request happens, the interceptor gets called with a Request - object. + Whenever a request happens, the interceptor gets called with a + :class:`Request` object. + + Example:: + + def intercept(request: interceptor.Request) -> None: + if request.request_url.host() == 'badhost.example.com': + request.block() """ interceptors.register(interceptor) diff --git a/qutebrowser/browser/browsertab.py b/qutebrowser/browser/browsertab.py index 3bd4c55c3..029394657 100644 --- a/qutebrowser/browser/browsertab.py +++ b/qutebrowser/browser/browsertab.py @@ -141,14 +141,11 @@ class TabData: class AbstractAction: - """Attribute of AbstractTab for Qt WebActions. - - Class attributes (overridden by subclasses): - action_class: The class actions are defined on (QWeb{Engine,}Page) - action_base: The type of the actions (QWeb{Engine,}Page.WebAction) - """ + """Attribute ``action`` of AbstractTab for Qt WebActions.""" + # The class actions are defined on (QWeb{Engine,}Page) action_class = None # type: type + # The type of the actions (QWeb{Engine,}Page.WebAction) action_base = None # type: type def __init__(self, tab: 'AbstractTab') -> None: @@ -200,7 +197,7 @@ class AbstractAction: class AbstractPrinting: - """Attribute of AbstractTab for printing the page.""" + """Attribute ``printing`` of AbstractTab for printing the page.""" def __init__(self, tab: 'AbstractTab') -> None: self._widget = None @@ -271,7 +268,7 @@ class AbstractPrinting: class AbstractSearch(QObject): - """Attribute of AbstractTab for doing searches. + """Attribute ``search`` of AbstractTab for doing searches. Attributes: text: The last thing this view was searched for. @@ -279,15 +276,14 @@ class AbstractSearch(QObject): this view. _flags: The flags of the last search (needs to be set by subclasses). _widget: The underlying WebView widget. - - Signals: - finished: Emitted when a search was finished. - arg: True if the text was found, False otherwise. - cleared: Emitted when an existing search was cleared. """ + #: Signal emitted when a search was finished + #: (True if the text was found, False otherwise) finished = pyqtSignal(bool) + #: Signal emitted when an existing search was cleared. cleared = pyqtSignal() + _Callback = typing.Callable[[bool], None] def __init__(self, tab: 'AbstractTab', parent: QWidget = None): @@ -350,17 +346,13 @@ class AbstractSearch(QObject): class AbstractZoom(QObject): - """Attribute of AbstractTab for controlling zoom. - - Attributes: - _neighborlist: A NeighborList with the zoom levels. - _default_zoom_changed: Whether the zoom was changed from the default. - """ + """Attribute ``zoom`` of AbstractTab for controlling zoom.""" def __init__(self, tab: 'AbstractTab', parent: QWidget = None) -> None: super().__init__(parent) self._tab = tab self._widget = None + # Whether zoom was changed from the default. self._default_zoom_changed = False self._init_neighborlist() config.instance.changed.connect(self._on_config_changed) @@ -375,7 +367,9 @@ class AbstractZoom(QObject): self._init_neighborlist() def _init_neighborlist(self) -> None: - """Initialize self._neighborlist.""" + """Initialize self._neighborlist. + + It is a NeighborList with the zoom levels.""" levels = config.val.zoom.levels self._neighborlist = usertypes.NeighborList( levels, mode=usertypes.NeighborList.Modes.edge) @@ -427,15 +421,12 @@ class AbstractZoom(QObject): class AbstractCaret(QObject): - """Attribute of AbstractTab for caret browsing. - - Signals: - selection_toggled: Emitted when the selection was toggled. - arg: Whether the selection is now active. - follow_selected_done: Emitted when a follow_selection action is done. - """ + """Attribute ``caret`` of AbstractTab for caret browsing.""" + #: Signal emitted when the selection was toggled. + #: (argument - whether the selection is now active) selection_toggled = pyqtSignal(bool) + #: Emitted when a ``follow_selection`` action is done. follow_selected_done = pyqtSignal() def __init__(self, @@ -522,16 +513,12 @@ class AbstractCaret(QObject): class AbstractScroller(QObject): - """Attribute of AbstractTab to manage scroll position. - - Signals: - perc_changed: The scroll position changed. - before_jump_requested: - Emitted by other code when the user requested a jump. - Used to set the special ' mark so the user can return. - """ + """Attribute ``scroller`` of AbstractTab to manage scroll position.""" + #: Signal emitted when the scroll position changed (int, int) perc_changed = pyqtSignal(int, int) + #: Signal emitted before the user requested a jump. + #: Used to set the special ' mark so the user can return. before_jump_requested = pyqtSignal() def __init__(self, tab: 'AbstractTab', parent: QWidget = None): @@ -833,42 +820,46 @@ class AbstractTabPrivate: class AbstractTab(QWidget): - """An adapter for QWebView/QWebEngineView representing a single tab. - - Signals: - See related Qt signals. - - new_tab_requested: Emitted when a new tab should be opened with the - given URL. - load_status_changed: The loading status changed - fullscreen_requested: Fullscreen display was requested by the page. - arg: True if fullscreen should be turned on, - False if it should be turned off. - renderer_process_terminated: Emitted when the underlying renderer - process terminated. - arg 0: A TerminationStatus member. - arg 1: The exit code. - before_load_started: Emitted before we tell Qt to open a URL. - """ + """An adapter for QWebView/QWebEngineView representing a single tab.""" + #: Signal emitted when a website requests to close this tab. window_close_requested = pyqtSignal() + #: Signal emitted when a link is hovered (the hover text) link_hovered = pyqtSignal(str) + #: Signal emitted when a page started loading load_started = pyqtSignal() + #: Signal emitted when a page is loading (progress percentage) load_progress = pyqtSignal(int) + #: Signal emitted when a page finished loading (success as bool) load_finished = pyqtSignal(bool) + #: Signal emitted when a page's favicon changed (icon as QIcon) icon_changed = pyqtSignal(QIcon) + #: Signal emitted when a page's title changed (new title as str) title_changed = pyqtSignal(str) - load_status_changed = pyqtSignal(usertypes.LoadStatus) + #: Signal emitted when a new tab should be opened (url as QUrl) new_tab_requested = pyqtSignal(QUrl) + #: Signal emitted when a page's URL changed (url as QUrl) url_changed = pyqtSignal(QUrl) - shutting_down = pyqtSignal() + #: Signal emitted when a tab's content size changed + #: (new size as QSizeF) contents_size_changed = pyqtSignal(QSizeF) - # url, requested url, title - history_item_triggered = pyqtSignal(QUrl, QUrl, str) + #: Signal emitted when a page requested full-screen (bool) fullscreen_requested = pyqtSignal(bool) - renderer_process_terminated = pyqtSignal(TerminationStatus, int) + #: Signal emitted before load starts (URL as QUrl) before_load_started = pyqtSignal(QUrl) + # Signal emitted when a page's load status changed + # (argument: usertypes.LoadStatus) + load_status_changed = pyqtSignal(usertypes.LoadStatus) + # Signal emitted before shutting down + shutting_down = pyqtSignal() + # Signal emitted when a history item should be added + history_item_triggered = pyqtSignal(QUrl, QUrl, str) + # Signal emitted when the underlying renderer process terminated. + # arg 0: A TerminationStatus member. + # arg 1: The exit code. + renderer_process_terminated = pyqtSignal(TerminationStatus, int) + def __init__(self, *, win_id: int, private: bool, parent: QWidget = None) -> None: self.is_private = private diff --git a/qutebrowser/browser/webelem.py b/qutebrowser/browser/webelem.py index a22facfbd..c00f247f6 100644 --- a/qutebrowser/browser/webelem.py +++ b/qutebrowser/browser/webelem.py @@ -141,20 +141,9 @@ class AbstractWebElement(collections.abc.MutableMapping): def rect_on_view(self, *, elem_geometry=None, no_js=False): """Get the geometry of the element relative to the webview. - Uses the getClientRects() JavaScript method to obtain the collection of - rectangles containing the element and returns the first rectangle which - is large enough (larger than 1px times 1px). If all rectangles returned - by getClientRects() are too small, falls back to elem.rect_on_view(). - - Skipping of small rectangles is due to elements containing other - elements with "display:block" style, see - https://github.com/qutebrowser/qutebrowser/issues/1298 - Args: elem_geometry: The geometry of the element, or None. - Calling QWebElement::geometry is rather expensive so - we want to avoid doing it twice. - no_js: Fall back to the Python implementation + no_js: Fall back to the Python implementation. """ raise NotImplementedError diff --git a/qutebrowser/extensions/interceptors.py b/qutebrowser/extensions/interceptors.py index 4a3ac17d4..269c82ab8 100644 --- a/qutebrowser/extensions/interceptors.py +++ b/qutebrowser/extensions/interceptors.py @@ -34,8 +34,12 @@ class Request: """A request which can be intercepted/blocked.""" + #: The URL of the page being shown. first_party_url = attr.ib() # type: QUrl + + #: The URL of the file being requested. request_url = attr.ib() # type: QUrl + is_blocked = attr.ib(False) # type: bool def block(self) -> None: diff --git a/qutebrowser/utils/message.py b/qutebrowser/utils/message.py index b496273f8..6731721aa 100644 --- a/qutebrowser/utils/message.py +++ b/qutebrowser/utils/message.py @@ -42,12 +42,12 @@ def _log_stack(typ: str, stack: str) -> None: def error(message: str, *, stack: str = None, replace: bool = False) -> None: - """Convenience function to display an error message in the statusbar. + """Display an error message. Args: - message: The message to show - stack: The stack trace to show. - replace: Replace existing messages with replace=True + message: The message to show. + stack: The stack trace to show (if any). + replace: Replace existing messages which are still being shown. """ if stack is None: stack = ''.join(traceback.format_stack()) @@ -60,11 +60,11 @@ def error(message: str, *, stack: str = None, replace: bool = False) -> None: def warning(message: str, *, replace: bool = False) -> None: - """Convenience function to display a warning message in the statusbar. + """Display a warning message. Args: - message: The message to show - replace: Replace existing messages with replace=True + message: The message to show. + replace: Replace existing messages which are still being shown. """ _log_stack('warning', ''.join(traceback.format_stack())) log.message.warning(message) @@ -72,11 +72,11 @@ def warning(message: str, *, replace: bool = False) -> None: def info(message: str, *, replace: bool = False) -> None: - """Convenience function to display an info message in the statusbar. + """Display an info message. Args: - message: The message to show - replace: Replace existing messages with replace=True + message: The message to show. + replace: Replace existing messages which are still being shown. """ log.message.info(message) global_bridge.show(usertypes.MessageLevel.info, message, replace) diff --git a/qutebrowser/utils/usertypes.py b/qutebrowser/utils/usertypes.py index c948df48f..84b7e7f9b 100644 --- a/qutebrowser/utils/usertypes.py +++ b/qutebrowser/utils/usertypes.py @@ -210,15 +210,33 @@ PromptMode = enum.Enum('PromptMode', ['yesno', 'text', 'user_pwd', 'alert', 'download']) -# Where to open a clicked link. -ClickTarget = enum.Enum('ClickTarget', ['normal', 'tab', 'tab_bg', 'window', - 'hover']) +class ClickTarget(enum.Enum): + + """How to open a clicked link.""" + + normal = 0 #: Open the link in the current tab + tab = 1 #: Open the link in a new foreground tab + tab_bg = 2 #: Open the link in a new background tab + window = 3 #: Open the link in a new window + hover = 4 #: Only hover over the link -# Key input modes -KeyMode = enum.Enum('KeyMode', ['normal', 'hint', 'command', 'yesno', 'prompt', - 'insert', 'passthrough', 'caret', 'set_mark', - 'jump_mark', 'record_macro', 'run_macro']) +class KeyMode(enum.Enum): + + """Key input modes.""" + + normal = 1 #: Normal mode (no mode was entered) + hint = 2 #: Hint mode (showing labels for links) + command = 3 #: Command mode (after pressing the colon key) + yesno = 4 #: Yes/No prompts + prompt = 5 #: Text prompts + insert = 6 #: Insert mode (passing through most keys) + passthrough = 7 #: Passthrough mode (passing through all keys) + caret = 8 #: Caret mode (moving cursor with keys) + set_mark = 9 + jump_mark = 10 + record_macro = 11 + run_macro = 12 class Exit(enum.IntEnum): @@ -241,8 +259,14 @@ LoadStatus = enum.Enum('LoadStatus', ['none', 'success', 'success_https', Backend = enum.Enum('Backend', ['QtWebKit', 'QtWebEngine']) -# JS world for QtWebEngine -JsWorld = enum.Enum('JsWorld', ['main', 'application', 'user', 'jseval']) +class JsWorld(enum.Enum): + + """World/context to run JavaScript code in.""" + + main = 1 #: Same world as the web page's JavaScript. + application = 2 #: Application world, used by qutebrowser internally. + user = 3 #: User world, currently not used. + jseval = 4 #: World used for the jseval-command. # Log level of a JS message. This needs to match up with the keys allowed for diff --git a/tox.ini b/tox.ini index 8a4232aaa..bc44df987 100644 --- a/tox.ini +++ b/tox.ini @@ -199,3 +199,14 @@ deps = -r{toxinidir}/misc/requirements/requirements-mypy.txt commands = {envpython} -m mypy qutebrowser {posargs} + +[testenv:sphinx] +basepython = {env:PYTHON:python3} +passenv = +usedevelop = true +deps = + -r{toxinidir}/requirements.txt + -r{toxinidir}/misc/requirements/requirements-pyqt.txt + -r{toxinidir}/misc/requirements/requirements-sphinx.txt +commands = + {envpython} -m sphinx -jauto -W --color {posargs} doc/extapi/ doc/extapi/_build/