diff --git a/.github/workflows/test-docs-with-edm.yml b/.github/workflows/test-docs-with-edm.yml new file mode 100644 index 000000000..f9733e920 --- /dev/null +++ b/.github/workflows/test-docs-with-edm.yml @@ -0,0 +1,56 @@ +# This workflow targets stable released dependencies from EDM. +# Note that some packages may not actually be installed from EDM but from +# PyPI, see etstool.py implementations. + +name: Build docs with EDM + +on: [pull_request, workflow_dispatch] + +env: + INSTALL_EDM_VERSION: 3.5.0 + QT_MAC_WANTS_LAYER: 1 + +jobs: + + # Build docs using EDM packages + docs-with-edm: + strategy: + matrix: + os: [ubuntu-latest] + toolkit: ['pyside6'] + fail-fast: false + timeout-minutes: 20 # should be plenty, it's usually < 5 + runs-on: ${{ matrix.os }} + env: + # Set root directory, mainly for Windows, so that the EDM Python + # environment lives in the same drive as the cloned source. Otherwise + # 'pip install' raises an error while trying to compute + # relative path between the site-packages and the source directory. + EDM_ROOT_DIRECTORY: ${{ github.workspace }}/.edm + steps: + - uses: actions/checkout@v3 + - name: Install Qt dependencies + uses: ./.github/actions/install-qt-support + if: matrix.toolkit != 'wx' + - name: Cache EDM packages + uses: actions/cache@v3 + with: + path: ~/.cache + key: ${{ runner.os }}-${{ matrix.toolkit }}-${{ hashFiles('etstool.py') }} + - name: Setup EDM + uses: enthought/setup-edm-action@v2 + with: + edm-version: ${{ env.INSTALL_EDM_VERSION }} + - name: Install click to the default EDM environment + run: edm install -y wheel click coverage + - name: Install test environment + run: edm run -- python etstool.py install --toolkit=${{ matrix.toolkit }} + - name: Build docs + run: xvfb-run -a edm run -- python etstool.py docs --toolkit=${{ matrix.toolkit }} + - name: Archive HTML docs + uses: actions/upload-artifact@v3 + with: + name: html-doc-bundle + path: docs/build/html + # don't need these kept for long + retention-days: 7 diff --git a/.github/workflows/test-with-edm.yml b/.github/workflows/test-with-edm.yml index 8f72f1a08..917c71e3d 100644 --- a/.github/workflows/test-with-edm.yml +++ b/.github/workflows/test-with-edm.yml @@ -16,6 +16,8 @@ jobs: test-with-edm: strategy: matrix: + # Note: MacOS support is contingent on not hitting any issues with + # unsupported CPU features such as AVX2 and so may be unstable. os: [ubuntu-latest, macos-latest, windows-latest] toolkit: ['pyside6'] fail-fast: false diff --git a/.gitignore b/.gitignore index 853bfd569..0a46cb31c 100644 --- a/.gitignore +++ b/.gitignore @@ -11,6 +11,7 @@ build/ dist/ docs/build/ +docs/source/api # Auto-generated by setup.py pyface/_version.py diff --git a/CHANGES.txt b/CHANGES.txt index b49dbfa1d..3e6c80236 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -2,6 +2,154 @@ Pyface Changelog ================ +Release 8.0.0 +============= + +Highlights of this release +-------------------------- + +This is a major release which removes a number of things which have been +deprecated for a number of years. The most significant change in this release +is that the Qt toolkit backend has been moved from the ``pyface.ui.qt4`` +package to the ``pyface.ui.qt`` package. The "qt4" namespace had been an +ongoing source of confusion as Qt5 and Qt6 became the most popular versions of +Qt in use. Because this change has the potential to cause significant backwards +compatibility issues, this release includes import hooks to continue to support +imports from ``pyface.ui.qt4...`` which can be enabled by: + +- using "qt4" for the `ETS_TOOLKIT` or `ETSConfig.toolkit` values. +- setting the `ETS_QT4_IMPORT` environment variable to a non-empty value +- explicitly adding the import hooks to `sys.meta_path` + +In particular the environment variables allow users of ETS-based applications +such as Mayavi to continue to use those applications with newer versions of +Pyface until there is time to update their code to the new import locations. + +Additionally this release uses the module-level ``__getattr__`` system +introduced in Python 3.7 to delay imports from the ``api`` modules which have +side-effects, particularly toolkit selection. This means that you can, for +example, import ``pyface.api`` and toolkit selection will be deferred until +you actually request a class or object which is toolkit-dependent. Part of +this included adding formal interfaces for ``ActionManager`` and its subclasses + +In addition this release: + +- adds support for Python 3.11 and drops support for Python 3.6 +- adds support for PySide 6.4+ and the new enum system +- removes code supporting PyQt4, and supports more modern imports from + `pyface.qt`, such as `pyface.qt.QtWidgets`. +- removes many things flagged as deprecated in Pyface 7 +- consistently add interface classes to ``api`` modules. +- adds new Field subclasses, including an ImageField and LabelField +- moves to a pyproject.toml-based packaging solution, removing setup.py + +Detailed changes +---------------- + +Thanks to: + +* Mark Dickinson +* Dominik Gresch +* JaRoSchm +* Rahul Poruri +* Corran Webster + +Features + +* Refactor IField and add IImageField and ILabelField Field classes (#1234) +* Move ``pyface.ui.qt4`` to ``pyface.ui.qt`` (#1223, #1228) +* Delayed imports with side-effects in ``api`` modules; new interfaces for + ``ActionManager`` and its subclasses (#1229) + +Enhancements + +* Better handling of sizes for multiple (or no) screens (#1237) +* More arguments for the ``confirm`` function (#1221) +* Expose interfaces in ``api`` modules and other improvemnts to ``api`` modules + (#1220, #1222, #1229) +* remove deprecated modules and code (#1209, #1215) +* PySide 6.5 support (#1238) +* Python 3.11 and PySide 6.4 support (#1210) + +Fixes + +* Always use a no-delay timer for ``GUI`` ``invoke_later`` and + ``set_trait_later`` on Qt (#1226) +* Work arounds for some end-of-process segfaults on PySide < 6.4.3 (#1214) +* Use ``exec`` instead of ``exec_`` where possible (#1208) +* Emit a warning rather than asserting in SplitTabWidget (#1192) +* Remove required parent argument in Wx StatusBarManager (#1192) +* Use integer division in DockSplitter.draw (#1190) + +Documentation + +* general updates and enhancements (#1238) +* update copyright dates (#1191) + +CI + +* remove ``setup.py`` and use ``pyproject.toml`` (#1203, #1214) + +Release 7.4.4 +============= + +Highlights of this release +-------------------------- + +This is a quick bugfix release that resolves some issues with the 7.4.3 release +on CI for downstream projects. The issues were on testing code, and so +shouldn't impact application code or behaviour. + +Detailed changes +---------------- + +Thanks to: + +* Corran Webster + +Fixes + +* Don't raise ConditionTimeoutError if test doesn't time out (#1182) + +CI + +* get CI working again with ubuntu-current on GitHub (#1186) + +Release 7.4.3 +============= + +Highlights of this release +-------------------------- + +This is a bugfix release that collects a number of additional issues discovered +and fixed since the 7.4.2 release. Among the fixes, this pins PySide6 to less than +6.4.0, as 6.4 has breaking changes in it. + +Detailed changes +---------------- + +Thanks to: + +* Alex Chabot-Leclerc +* Mark Dickinson +* Eric Larson +* Steven Kern +* Corran Webster + +Fixes + +* Fix code editor gutter widget on recent Python versions (#1176) +* fix issues with FileDialog and DirectoryDialog close method on Linux (#1175) +* update setup.py metadata (#1173) +* restrict to PySide versions before 6.4.0 (#1169) +* don't do unneccessary evaluations of conditions in EventLoopHelper (#1168) +* fix a deleted object error in PyQt5 (#1161) +* better reporting of toolkit errors (#1157) + +Documentation + +* fix some Python 2 style print statements in documentation (#1157) + Release 7.4.2 ============= diff --git a/README.rst b/README.rst index 718e977bf..58a70a812 100644 --- a/README.rst +++ b/README.rst @@ -3,10 +3,12 @@ Pyface: Traits-capable Windowing Framework ========================================== The Pyface project contains a toolkit-independent GUI abstraction layer, -which is used to support the "visualization" features of the Traits package. -Thus, you can write code in terms of the Traits API (views, items, editors, -etc.), and let Pyface and your selected toolkit and back-end take care of -the details of displaying them. +which is used to support the "visualization" features of the Enthought Tool +Suite libraries. Pyface contains Traits-aware wrappers of standard GUI +elements such as Windows, Dialogs and Fields, together with the "Tasks" +application framework which provides a rich GUI experience with dock panes, +tabbed editors, and so forth. This permits you to write cross-platform +interactive GUI code without needing to use the underlying GUI backend. The following GUI backends are supported: @@ -14,33 +16,79 @@ The following GUI backends are supported: - PyQt5 (stable) and PyQt6 (in development) - wxPython 4 (experimental) +Example +------- + +The following code creates a window with a simple Python shell: + +.. code-block:: python + + from pyface.api import ApplicationWindow, GUI, IPythonShell + + class MainWindow(ApplicationWindow): + """ The main application window. """ + + #: The PythonShell that forms the contents of the window + shell = Instance(IPythonShell, allow_none=False) + + def _create_contents(self, parent): + """ Create the editor. """ + self.shell.create(parent) + return self.shell.control + + def destroy(self): + self.shell.destroy() + super().destroy() + + def _shell_default(self): + from pyface.api import PythonShell + return PythonShell() + + # Application entry point. + if __name__ == "__main__": + # Create the GUI. + gui = GUI() + + # Create and open the main window. + window = MainWindow(title="Python Shell", size=(640, 480)) + window.open() + + # Start the GUI event loop! + gui.start_event_loop() + +.. image:: https://raw.github.com/enthought/pyface/main/shell_window.png + :alt: A Pyface GUI window containing a Python shell. + Installation ------------ -GUI backends are marked as optional dependencies of Pyface. Some features -or infrastructures may also require additional dependencies. +Pyface is a pure Python package. In most cases Pyface will be installable +using a simple ``pip install`` command. -To install with PySide2 dependencies:: +To install with a backend, choose one of the following, as appropriate: - $ pip install pyface[pyside2] +.. code-block:: console -To install with PySide6 dependencies (experimental):: + $ pip install pyface[pyside2] $ pip install pyface[pyside6] -To install with PyQt5 dependencies:: - $ pip install pyface[pyqt5] -To install with wxPython4 dependencies (experimental):: - $ pip install pyface[wx] -``pillow`` is an optional dependency for the PILImage class:: +Some optional functionality uses ``pillow`` and ``numpy`` and these can be +installed using optional dependencies: + +.. code-block:: console $ pip install pyface[pillow] -To install with additional test dependencies:: + $ pip install pyface[numpy] + +For running tests a few more packages are required: + +.. code-block:: console $ pip install pyface[test] @@ -51,20 +99,6 @@ Documentation * `API Documentation `_. -Prerequisites -------------- - -Pyface depends on: - -* `Traits `_ - -* a GUI toolkit as described above - -* Pygments for syntax highlighting in the Qt code editor widget. - -* some widgets may have additional optional dependencies such as NumPy or - Pillow. - .. end_of_long_description Developing Pyface diff --git a/docs/source/conf.py b/docs/source/conf.py index a16a56067..3cddc233b 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -11,7 +11,10 @@ # All configuration values have a default value; values that are commented out # serve to show the default value. -import importlib.metadata +try: + from importlib.metadata import version as metadata_version +except: + from importlib_metadata import version as metadata_version # General configuration # --------------------- @@ -43,7 +46,7 @@ # The default replacements for |version| and |release|, also used in various # other places throughout the built documents. -version = release = importlib.metadata.version("pyface") +version = release = metadata_version("pyface") # There are two options for replacing |today|: either, you set today to some # non-false value, then it is used: diff --git a/docs/source/index.rst b/docs/source/index.rst index 21281763e..d2c16fd55 100644 --- a/docs/source/index.rst +++ b/docs/source/index.rst @@ -7,26 +7,25 @@ the TraitsUI package. Thus, you can write code in the abstraction of the Pyface API and the selected toolkit and backend take care of the details of displaying them. -Pyface -====== - Pyface enables programmers to interact with generic GUI objects, such as an -"MDI Application Window", rather than with raw GUI widgets. (Pyface is named by -analogy to JFace in Java.) TraitsUI uses Pyface to implement views and editors -for displaying and editing Traits-based objects. +"Application Window", rather than with raw GUI widgets. TraitsUI uses Pyface +to implement views and editors for displaying and editing Traits-based objects. +In addition to wrappers around fields and dialogs, Pyface includes an +application framework called "Tasks" for building full-featured +applications featuring dock panes, tabbed editor areas and so forth. Toolkit Backends ================ -TraitsUI and Pyface define APIs that are independent of any GUI toolkit. -However, in order to actually produce user interfaces with them, you must +Pyface defines APIs that are independent of any GUI toolkit. However, in +order to actually produce user interfaces with them, you must install a supported Python-based GUI toolkit and the appropriate toolkit-specific backend project. Conversely, a "null" backend is automatically used in the absence of a real backend. Currently, the GUI toolkits are -* PySide2 (stable) and PySide6 (experimental) +* PySide2 and PySide6 (stable) * PyQt5 (stable) and PyQt6 (in development) * wxPython 4 (experimental) diff --git a/docs/source/traits.rst b/docs/source/traits.rst index 2be140880..b3391c580 100644 --- a/docs/source/traits.rst +++ b/docs/source/traits.rst @@ -32,13 +32,20 @@ color spaces, such as HSV or HLS:: which allow specification of colors via CSS-style color strings, such as:: Color.from_str("aquamarine") - Color.from_str("#662244") + Color.from_str("#662244cc") -All standard web colors are understood, as well as hexadecimal RGB(A) with -1, 2 or 4 hex digits per channel. +All `standard web colors `_ +are understood, as well as hexadecimal RGB(A) with 1, 2 or 4 hex digits per +channel. |Color| instances are mutable, as their intended use is as values stored -in |PyfaceColor| trait classes which can be modified and listened to. The +in |PyfaceColor| trait classes which can be modified and listened to. This +means that they are comparatively heavyweight objects and should be shared +where possible and aren't particularly suited for situations where large +numbers of distinct and independent colors are needed: NumPy arrays are likely +better suited for this sort of application. + +The |PyfaceColor| validator understands string descriptions of colors, and will accept them as values when initializing or modifying the trait:: @@ -64,8 +71,96 @@ building applications on top of Pyface. It is intended that this trait will eventually replace the ``Color`` trait from TraitsUI. +Fonts +===== + +Just as with colors, it is common to want to be able to specify the font to use +for text in the UI. Each toolkit usually has its own way of representing +fonts, and so the ability to specify a font in a toolkit-independent way that +can be converted to a toolkit-specific representation is important. This is +particularly so when you want to allow the user to specify a font. + +Pyface provides a |Font| class and a corresponding |PyfaceFont| trait-type +that allows this sort of representation. Internally, the |Font| class +stores font attributes such as |Font.weight| or |Font.size| as traits:: + + font = Font(family=["Comic Sans"], size=24, weight="bold") + font.weight + +Some of these attributes are mapped traits, or otherwise convert string +values to numeric values. For example |Font.size| will accept strings like +"12pt", while |Font.weight| holds a numeric weight value in a mapped +attribute:: + +.. code-block:: pycon + + >>> font.weight + "bold" + >>> font.weight_ + 700 + +|Font| instances are mutable, as their intended use is as values stored +in |PyfaceFont| trait classes which can be modified and listened to. + +As a convenience, the |PyfaceFont| validator understands string descriptions +of fonts, and will accept them as values when initializing or modifying the +trait:: + + class Style(HasStrictTraits): + + font = PyfaceFont("24 pt Bold Comic Sans") + + @observe('font.*') + def font_changed(self, event): + print('The font has changed to {}'.format(self.font)) + + style = Style(font='12 italc Helvetica') + style.font.weight = 'light' + style.font = Font( + family=["Helvetica", "Arial", "sans-serif"], + variants={"small-caps"}, + ) + +The parsing of strings to fonts is currently handled by a |simple_parser| that +is modelled on the ``Font`` trait from TraitsUI, but it can be substituted +for a more sophisticated one, if needed. + +For interactions with the toolkit, the |Font.from_toolkit| and +|Font.to_toolkit| methods allow conversion to and from the appropriate +toolkit font objects, such as Qt's :py:class:`QFont` or +:py:class:`wx.Font`. These are most likely to be needed by internal +Pyface functionality, and should not be needed by developers who are +building applications on top of Pyface. + +It is intended that this trait will eventually replace the ``Font`` +trait from TraitsUI. It is also likely that the simple parser will be replaced +with a parser that understands CSS-like font strings. + +Layout Traits +============= + +Pyface also provides a number of classes and traits to assist with +layout-related functionality. These include the convenience Enums |Alignment|, +|Orientation| and |Position| as well as the classes |Margin| and |Border| and +their corresponding traits |HasMargin| and |HasBorder|. + + +.. |Alignment| replace:: :py:attr:`~pyface.ui_traits.Alignment` +.. |Border| replace:: :py:class:`~pyface.ui_traits.Border` .. |Color| replace:: :py:class:`~pyface.color.Color` .. |Color.from_str| replace:: :py:meth:`~pyface.color.Color.from_str` .. |Color.from_toolkit| replace:: :py:meth:`~pyface.color.Color.from_toolkit` .. |Color.to_toolkit| replace:: :py:meth:`~pyface.color.Color.to_toolkit` +.. |Font| replace:: :py:class:`~pyface.font.Font` +.. |Font.size| replace:: :py:attr:`~pyface.font.Font.size` +.. |Font.from_toolkit| replace:: :py:meth:`~pyface.font.Font.from_toolkit` +.. |Font.to_toolkit| replace:: :py:meth:`~pyface.font.Font.to_toolkit` +.. |Font.weight| replace:: :py:attr:`~pyface.font.Font.weight` +.. |HasMargin| replace:: :py:class:`~pyface.ui_traits.HasMargin` +.. |HasBorder| replace:: :py:class:`~pyface.ui_traits.HasBorder` +.. |Margin| replace:: :py:class:`~pyface.ui_traits.Margin` +.. |Orientation| replace:: :py:attr:`~pyface.ui_traits.Orientation` +.. |Position| replace:: :py:attr:`~pyface.ui_traits.Position` .. |PyfaceColor| replace:: :py:class:`~pyface.ui_traits.PyfaceColor` +.. |PyfaceFont| replace:: :py:class:`~pyface.ui_traits.PyfaceFont` +.. |simple_parser| replace:: :py:func:`~pyface.util.font_parser.simple_parser` diff --git a/examples/application/hello_world/hello_application.py b/examples/application/hello_world/hello_application.py index ebe5d36a1..e1cab73c6 100644 --- a/examples/application/hello_world/hello_application.py +++ b/examples/application/hello_world/hello_application.py @@ -17,9 +17,9 @@ computation. """ - import argparse -from pyface.application import Application + +from pyface.api import Application from traits.api import Str diff --git a/pyface/action/action.py b/pyface/action/action.py index 2542ac982..526c07f32 100644 --- a/pyface/action/action.py +++ b/pyface/action/action.py @@ -124,7 +124,7 @@ def perform(self, event): Parameters ---------- - event : ActionEvent instance + event : ActionEvent The event which triggered the action. """ if self.on_perform is not None: diff --git a/pyface/action/action_controller.py b/pyface/action/action_controller.py index d8ddf9379..b2c926df9 100644 --- a/pyface/action/action_controller.py +++ b/pyface/action/action_controller.py @@ -25,14 +25,14 @@ def perform(self, action, event): Parameters ---------- - action : Action instance + action : Action The action to perform. - event : ActionEvent instance + event : ActionEvent The event that triggered the action. Returns ------- - result : any + result : Any The result of the action's perform method (usually None). """ return action.perform(event) @@ -42,7 +42,7 @@ def can_add_to_menu(self, action): Parameters ---------- - action : Action instance + action : Action The action to consider. Returns @@ -57,7 +57,7 @@ def add_to_menu(self, action): Parameters ---------- - action : Action instance + action : Action The action added to the menu. """ pass @@ -67,7 +67,7 @@ def can_add_to_toolbar(self, action): Parameters ---------- - action : Action instance + action : Action The action to consider. Returns @@ -82,7 +82,7 @@ def add_to_toolbar(self, action): Parameters ---------- - action : Action instance + action : Action The action added to the toolbar. """ pass diff --git a/pyface/action/action_item.py b/pyface/action/action_item.py index 987ab1b02..d9744383c 100644 --- a/pyface/action/action_item.py +++ b/pyface/action/action_item.py @@ -93,7 +93,7 @@ def add_to_menu(self, parent, menu, controller): The parent of the new menu item control. menu : toolkit menu The menu to add the action item to. - controller : ActionController instance or None + controller : pyface.action.action_controller.ActionController or None The controller to use. """ if (controller is None) or controller.can_add_to_menu(self.action): @@ -117,9 +117,9 @@ def add_to_toolbar( The parent of the new menu item control. tool_bar : toolkit toolbar The toolbar to add the action item to. - image_cache : ImageCache instance + image_cache : ImageCache The image cache for resized images. - controller : ActionController instance or None + controller : pyface.action.action_controller.ActionController or None The controller to use. show_labels : bool Should the toolbar item show a label. @@ -145,7 +145,7 @@ def add_to_palette(self, tool_palette, image_cache, show_labels=True): The parent of the new menu item control. tool_palette : toolkit tool palette The tool palette to add the action item to. - image_cache : ImageCache instance + image_cache : ImageCache The image cache for resized images. show_labels : bool Should the toolbar item show a label. diff --git a/pyface/action/action_manager.py b/pyface/action/action_manager.py index d5d0de280..4f2ef2703 100644 --- a/pyface/action/action_manager.py +++ b/pyface/action/action_manager.py @@ -72,7 +72,7 @@ def __init__(self, *args, **traits): Parameters ---------- - args : collection of strings, Group instances, or ActionManagerItem instances + args : collection of strings, Group instances, or ActionManagerItem s Positional arguments are interpreted as Items or Groups managed by the action manager. @@ -142,7 +142,7 @@ def append(self, item): Parameters ---------- - item : string, Group instance or ActionManagerItem instance + item : string, Group instance or ActionManagerItem The item to append. Notes @@ -180,7 +180,7 @@ def insert(self, index, item): ---------- index : int The position at which to insert the object - item : string, Group instance or ActionManagerItem instance + item : string, Group instance or ActionManagerItem The item to insert. Notes @@ -213,7 +213,7 @@ def find_group(self, id): Returns ------- - group : Group instance + group : Group The group which matches the id, or None if no such group exists. """ for group in self._groups: @@ -256,7 +256,7 @@ def walk(self, fn): Parameters ---------- - fn : callable + fn : Callable A callable to apply to the tree of groups and items, starting with the manager. """ @@ -274,7 +274,7 @@ def walk_group(self, group, fn): ---------- group : Group The group to walk. - fn : callable + fn : Callable A callable to apply to the tree of groups and items. """ fn(group) @@ -295,7 +295,7 @@ def walk_item(self, item, fn): item : item The item to walk. This may be a submenu or similar in addition to simple Action items. - fn : callable + fn : Callable A callable to apply to the tree of items and subgroups. """ if hasattr(item, "groups"): @@ -314,7 +314,7 @@ def _get_default_group(self): Returns ------- - group : Group instance + group : Group The manager's default group. """ group = self.find_group(self.DEFAULT_GROUP) @@ -329,7 +329,7 @@ def _prepare_item(self, item): Parameters ---------- - item : string, Group instance or ActionManagerItem instance + item : string, Group instance or ActionManagerItem The item to be added to this ActionManager Returns diff --git a/pyface/action/action_manager_item.py b/pyface/action/action_manager_item.py index a407b99e5..a6297ed17 100644 --- a/pyface/action/action_manager_item.py +++ b/pyface/action/action_manager_item.py @@ -53,7 +53,7 @@ def add_to_menu(self, parent, menu, controller): The parent of the new menu item control. menu : toolkit menu The menu to add the action item to. - controller : ActionController instance or None + controller : pyface.action.action_controller.ActionController or None The controller to use. """ raise NotImplementedError() @@ -67,9 +67,9 @@ def add_to_toolbar(self, parent, tool_bar, image_cache, controller): The parent of the new menu item control. tool_bar : toolkit toolbar The toolbar to add the action item to. - image_cache : ImageCache instance + image_cache : ImageCache The image cache for resized images. - controller : ActionController instance or None + controller : pyface.action.action_controller.ActionController or None The controller to use. show_labels : bool Should the toolbar item show a label. diff --git a/pyface/action/field_action.py b/pyface/action/field_action.py index 830223f72..f9848ac1e 100644 --- a/pyface/action/field_action.py +++ b/pyface/action/field_action.py @@ -70,7 +70,7 @@ def perform(self, event): Parameters ---------- - event : ActionEvent instance + event : ActionEvent The event which triggered the action. """ if self.on_perform is not None: diff --git a/pyface/action/i_action_manager.py b/pyface/action/i_action_manager.py index f813cd051..3a4f98de7 100644 --- a/pyface/action/i_action_manager.py +++ b/pyface/action/i_action_manager.py @@ -65,7 +65,7 @@ def __init__(self, *items, **traits): Parameters ---------- - items : collection of strings, Group, or ActionManagerItem instances + items : collection of strings, Group, or ActionManagerItem s Positional arguments are interpreted as Items or Groups managed by the action manager. traits : additional traits @@ -90,7 +90,7 @@ def append(self, item): Parameters ---------- - item : string, Group instance or ActionManagerItem instance + item : string, Group instance or ActionManagerItem The item to append. Notes @@ -117,7 +117,7 @@ def insert(self, index, item): ---------- index : int The position at which to insert the object - item : string, Group instance or ActionManagerItem instance + item : string, Group instance or ActionManagerItem The item to insert. Notes @@ -140,7 +140,7 @@ def find_group(self, id): Returns ------- - group : Group instance + group : Group The group which matches the id, or None if no such group exists. """ @@ -166,7 +166,7 @@ def walk(self, fn): Parameters ---------- - fn : callable + fn : Callable A callable to apply to the tree of groups and items, starting with the manager. """ @@ -180,7 +180,7 @@ def walk_group(self, group, fn): ---------- group : Group The group to walk. - fn : callable + fn : Callable A callable to apply to the tree of groups and items. """ @@ -194,6 +194,6 @@ def walk_item(self, item, fn): item : item The item to walk. This may be a submenu or similar in addition to simple Action items. - fn : callable + fn : Callable A callable to apply to the tree of items and subgroups. """ diff --git a/pyface/action/i_menu_bar_manager.py b/pyface/action/i_menu_bar_manager.py index 33b08ee11..7a23a7fb8 100644 --- a/pyface/action/i_menu_bar_manager.py +++ b/pyface/action/i_menu_bar_manager.py @@ -28,6 +28,6 @@ def create_menu_bar(self, parent, controller=None): ---------- parent : toolkit control The toolkit control that owns the menubar. - controller : ActionController + controller : pyface.action.action_controller.ActionController An optional ActionController for all items in the menubar. """ diff --git a/pyface/action/i_menu_manager.py b/pyface/action/i_menu_manager.py index 9469fa7d9..cd1132562 100644 --- a/pyface/action/i_menu_manager.py +++ b/pyface/action/i_menu_manager.py @@ -40,6 +40,6 @@ def create_menu(self, parent, controller=None): ---------- parent : toolkit control The toolkit control that owns the menu. - controller : ActionController + controller : pyface.action.action_controller.ActionController An optional ActionController for all items in the menu. """ diff --git a/pyface/action/i_tool_bar_manager.py b/pyface/action/i_tool_bar_manager.py index f98863c13..08e536036 100644 --- a/pyface/action/i_tool_bar_manager.py +++ b/pyface/action/i_tool_bar_manager.py @@ -45,6 +45,6 @@ def create_tool_bar(self, parent, controller=None): ---------- parent : toolkit control The toolkit control that owns the toolbar. - controller : ActionController + controller : pyface.action.action_controller.ActionController An optional ActionController for all items in the toolbar. """ diff --git a/pyface/base_toolkit.py b/pyface/base_toolkit.py index 657e1e984..0bc1fff9b 100644 --- a/pyface/base_toolkit.py +++ b/pyface/base_toolkit.py @@ -179,7 +179,7 @@ def import_toolkit(toolkit_name, entry_point="pyface.toolkits"): Returns ------- - toolkit_object : callable + toolkit_object : Callable A callable object that implements the Toolkit interface. Raises @@ -251,12 +251,12 @@ def find_toolkit( toolkits : collection of strings Only consider toolkits which match the given strings, ignore other ones. - priorities : callable + priorities : Callable A callable function that returns an priority for each plugin. Returns ------- - toolkit : Toolkit instance + toolkit : Toolkit A callable object that implements the Toolkit interface. Raises diff --git a/pyface/data_view/abstract_data_exporter.py b/pyface/data_view/abstract_data_exporter.py index 8602cfad6..6d1e31d44 100644 --- a/pyface/data_view/abstract_data_exporter.py +++ b/pyface/data_view/abstract_data_exporter.py @@ -36,9 +36,9 @@ def add_data(self, data_wrapper, model, indices): Parameters ---------- - data_wrapper : DataWrapper instance + data_wrapper : DataWrapper The data wrapper that will be used to export data. - model : AbstractDataModel instance + model : AbstractDataModel The data model holding the data. indices : list of (row, column) index pairs The indices where the data is to be stored. @@ -55,14 +55,14 @@ def get_data(self, model, indices): Parameters ---------- - model : AbstractDataModel instance + model : AbstractDataModel The data model holding the data. indices : list of (row, column) index pairs The indices where the data is to be stored. Returns ------- - data : any + data : Any The data, of a type that can be serialized by the format. """ raise NotImplementedError() diff --git a/pyface/data_view/abstract_data_model.py b/pyface/data_view/abstract_data_model.py index 6a6d10aac..2690ad861 100644 --- a/pyface/data_view/abstract_data_model.py +++ b/pyface/data_view/abstract_data_model.py @@ -150,7 +150,7 @@ def get_value(self, row, column): Returns ------- - value : any + value : Any The value represented by the given row and column. Raises @@ -202,7 +202,7 @@ def set_value(self, row, column, value): The indices of the row as a sequence from root to leaf. column : sequence of int The indices of the column as a sequence of length 0 or 1. - value : any + value : Any The new value for the given row and column. Raises diff --git a/pyface/data_view/abstract_value_type.py b/pyface/data_view/abstract_value_type.py index 47cd23640..697007f8f 100644 --- a/pyface/data_view/abstract_value_type.py +++ b/pyface/data_view/abstract_value_type.py @@ -94,7 +94,7 @@ def get_editor_value(self, model, row, column): Returns ------- - value : any + value : Any The value to edit. """ return model.get_value(row, column) @@ -113,7 +113,7 @@ def set_editor_value(self, model, row, column, value): The row in the data model being queried. column : sequence of int The column in the data model being queried. - value : any + value : Any The value to set. Raises @@ -228,7 +228,7 @@ def get_color(self, model, row, column): Returns ------- - color : Color instance + color : Color The color associated with the cell. """ return Color(rgba=(1.0, 1.0, 1.0, 1.0)) diff --git a/pyface/data_view/data_formats.py b/pyface/data_view/data_formats.py index e2f1f0d69..a5f315404 100644 --- a/pyface/data_view/data_formats.py +++ b/pyface/data_view/data_formats.py @@ -23,9 +23,9 @@ def to_json(data, default=None): Parameters ---------- - data : any + data : Any The data to be serialized. - default : callable or None + default : Callable or None Callable that takes a Python object and returns a JSON-serializable data structure. @@ -45,13 +45,13 @@ def from_json(raw_data, object_hook=None): ---------- raw_data : bytes The serialized JSON data as a byte string. - object_hook : callable + object_hook : Callable Callable that takes a dictionary and returns an corresponding Python object. Returns ------- - data : any + data : Any The data extracted. """ return json.loads(raw_data.decode('utf-8'), object_hook=object_hook) diff --git a/pyface/data_view/data_models/array_data_model.py b/pyface/data_view/data_models/array_data_model.py index dce74f47a..3b48afd72 100644 --- a/pyface/data_view/data_models/array_data_model.py +++ b/pyface/data_view/data_models/array_data_model.py @@ -205,7 +205,7 @@ def set_value(self, row, column, value): Returns ------- - value : any + value : Any The value represented by the given row and column. """ if self.can_set_value(row, column): diff --git a/pyface/data_view/data_models/data_accessors.py b/pyface/data_view/data_models/data_accessors.py index cb23ee0da..4b375c40e 100644 --- a/pyface/data_view/data_models/data_accessors.py +++ b/pyface/data_view/data_models/data_accessors.py @@ -52,12 +52,12 @@ def get_value(self, obj): Parameters ---------- - obj : any + obj : Any The object that contains the data. Returns ------- - value : any + value : Any The data value contained in the object. """ raise NotImplementedError() @@ -67,7 +67,7 @@ def can_set_value(self, obj): Parameters ---------- - obj : any + obj : Any The object that contains the data. Returns @@ -82,9 +82,9 @@ def set_value(self, obj, value): Parameters ---------- - obj : any + obj : Any The object that contains the data. - value : any + value : Any The data value to set. Raises @@ -119,12 +119,12 @@ def get_value(self, obj): Parameters ---------- - obj : any + obj : Any An object. Returns ------- - value : any + value : Any The data value contained in this class' value trait. """ return self.value @@ -149,12 +149,12 @@ def get_value(self, obj): Parameters ---------- - obj : any + obj : Any The object that contains the data. Returns ------- - value : any + value : Any The data value contained in the object's attribute. """ return xgetattr(obj, self.attr) @@ -164,7 +164,7 @@ def can_set_value(self, obj): Parameters ---------- - obj : any + obj : Any The object that contains the data. Returns @@ -211,7 +211,7 @@ def get_value(self, obj): Returns ------- - value : any + value : Any The data value contained in the object at the index. """ return obj[self.index] @@ -221,7 +221,7 @@ def can_set_value(self, obj): Parameters ---------- - obj : any + obj : Any The object that contains the data. Returns @@ -236,9 +236,9 @@ def set_value(self, obj, value): Parameters ---------- - obj : any + obj : Any The object that contains the data. - value : any + value : Any The data value to set. Raises @@ -280,7 +280,7 @@ def get_value(self, obj): Returns ------- - value : any + value : Any The data value contained in the given key of the object. """ return obj[self.key] @@ -292,7 +292,7 @@ def can_set_value(self, obj): ---------- obj : mapping The object that contains the data. - value : any + value : Any The data value to set. Raises @@ -307,9 +307,9 @@ def set_value(self, obj, value): Parameters ---------- - obj : any + obj : Any The object that contains the data. - value : any + value : Any The data value to set. Raises diff --git a/pyface/data_view/data_models/row_table_data_model.py b/pyface/data_view/data_models/row_table_data_model.py index e9abf39eb..f9899055e 100644 --- a/pyface/data_view/data_models/row_table_data_model.py +++ b/pyface/data_view/data_models/row_table_data_model.py @@ -111,7 +111,7 @@ def get_value(self, row, column): Returns ------- - value : any + value : Any The value represented by the given row and column. """ if len(column) == 0: @@ -162,7 +162,7 @@ def set_value(self, row, column, value): The indices of the row as a sequence from root to leaf. column : sequence of int The indices of the column as a sequence of length 0 or 1. - value : any + value : Any The new value for the given row and column. Raises diff --git a/pyface/data_view/exporters/item_exporter.py b/pyface/data_view/exporters/item_exporter.py index 12b5bf2ec..d648afdd7 100644 --- a/pyface/data_view/exporters/item_exporter.py +++ b/pyface/data_view/exporters/item_exporter.py @@ -26,9 +26,9 @@ def add_data(self, data_wrapper, model, indices): Parameters ---------- - data_wrapper : DataWrapper instance + data_wrapper : DataWrapper The data wrapper that will be used to export data. - model : AbstractDataModel instance + model : AbstractDataModel The data model holding the data. indices : list of (row, column) index pairs The indices where the data is to be stored. @@ -42,14 +42,14 @@ def get_data(self, model, indices): Parameters ---------- - model : AbstractDataModel instance + model : AbstractDataModel The data model holding the data. indices : list of (row, column) index pairs The indices where the data is to be stored. Returns ------- - data : any + data : Any The data, of a type that can be serialized by the format. """ if len(indices) != 1: diff --git a/pyface/data_view/exporters/row_exporter.py b/pyface/data_view/exporters/row_exporter.py index f5cd9accb..e1bcd8e95 100644 --- a/pyface/data_view/exporters/row_exporter.py +++ b/pyface/data_view/exporters/row_exporter.py @@ -44,14 +44,14 @@ def get_data(self, model, indices): Parameters ---------- - model : AbstractDataModel instance + model : AbstractDataModel The data model holding the data. indices : list of (row, column) index pairs The indices where the data is to be stored. Returns ------- - data : any + data : Any The data, of a type that can be serialized by the format. """ rows = sorted({row for row, column in indices}) diff --git a/pyface/data_view/i_data_wrapper.py b/pyface/data_view/i_data_wrapper.py index 5152a95ed..ed5bba885 100644 --- a/pyface/data_view/i_data_wrapper.py +++ b/pyface/data_view/i_data_wrapper.py @@ -93,7 +93,7 @@ def get_format(self, format): Returns ------- - data : any + data : Any The data decoded for the given format. """ raise NotImplementedError() @@ -105,7 +105,7 @@ def set_format(self, format, data): ---------- format : DataFormat A data format object. - data : any + data : Any The data to be encoded and stored. """ raise NotImplementedError() @@ -171,7 +171,7 @@ def get_format(self, format): Returns ------- - data : any + data : Any The data decoded for the given format. """ return format.deserialize(self.get_mimedata(format.mimetype)) @@ -183,7 +183,7 @@ def set_format(self, format, data): ---------- format : DataFormat A data format object. - data : any + data : Any The data to be encoded and stored. """ self.set_mimedata(format.mimetype, format.serialize(data)) diff --git a/pyface/data_view/value_types/color_value.py b/pyface/data_view/value_types/color_value.py index e8f4dae12..900500c44 100644 --- a/pyface/data_view/value_types/color_value.py +++ b/pyface/data_view/value_types/color_value.py @@ -34,7 +34,7 @@ def is_valid(self, model, row, column, value): The row in the data model being queried. column : sequence of int The column in the data model being queried. - value : any + value : Any The value to test. Returns @@ -168,7 +168,7 @@ def get_color(self, model, row, column): Returns ------- - color : Color instance + color : Color The color associated with the cell. """ return model.get_value(row, column) diff --git a/pyface/data_view/value_types/constant_value.py b/pyface/data_view/value_types/constant_value.py index 855a24e95..1d6bc4133 100644 --- a/pyface/data_view/value_types/constant_value.py +++ b/pyface/data_view/value_types/constant_value.py @@ -79,7 +79,7 @@ def get_color(self, model, row, column): Returns ------- - color : Color instance + color : Color The color associated with the cell. """ return self.color diff --git a/pyface/data_view/value_types/editable_value.py b/pyface/data_view/value_types/editable_value.py index 918cdf961..f03b29425 100644 --- a/pyface/data_view/value_types/editable_value.py +++ b/pyface/data_view/value_types/editable_value.py @@ -40,7 +40,7 @@ def is_valid(self, model, row, column, value): The row in the data model being queried. column : sequence of int The column in the data model being queried. - value : any + value : Any The value to validate. Returns @@ -85,7 +85,7 @@ def set_editor_value(self, model, row, column, value): The row in the data model being set. column : sequence of int The column in the data model being set. - value : any + value : Any The value being set. Raises diff --git a/pyface/data_view/value_types/enum_value.py b/pyface/data_view/value_types/enum_value.py index 45a634347..3ff260ab2 100644 --- a/pyface/data_view/value_types/enum_value.py +++ b/pyface/data_view/value_types/enum_value.py @@ -43,7 +43,7 @@ def is_valid(self, model, row, column, value): The row in the data model being queried. column : sequence of int The column in the data model being queried. - value : any + value : Any The value to validate. Returns @@ -127,7 +127,7 @@ def get_color(self, model, row, column): Returns ------- - color : Color instance + color : Color The color associated with the cell. """ return self.colors(model.get_value(row, column)) diff --git a/pyface/data_view/value_types/numeric_value.py b/pyface/data_view/value_types/numeric_value.py index 447f0e989..b13d46317 100644 --- a/pyface/data_view/value_types/numeric_value.py +++ b/pyface/data_view/value_types/numeric_value.py @@ -51,7 +51,7 @@ def is_valid(self, model, row, column, value): The row in the data model being queried. column : sequence of int The column in the data model being queried. - value : any + value : Any The value to validate. Returns diff --git a/pyface/dock/dock_window_feature.py b/pyface/dock/dock_window_feature.py index 82f5a6528..34fff4500 100644 --- a/pyface/dock/dock_window_feature.py +++ b/pyface/dock/dock_window_feature.py @@ -302,7 +302,7 @@ def drop(self, object): Parameters ---------- - object : any object + object : Any object The object being dropped onto the feature image Returns @@ -329,7 +329,7 @@ def can_drop(self, object): Parameters ---------- - object : any object + object : Any object The object being dragged onto the feature image Returns diff --git a/pyface/font.py b/pyface/font.py index 5d4434930..7d287f00e 100644 --- a/pyface/font.py +++ b/pyface/font.py @@ -247,6 +247,11 @@ def __init__(self, default_value=NoDefaultSpecified, **metadata): super().__init__(default_value, **metadata) def validate(self, object, name, value): + """Validate the trait + + This is a CFloat trait that also accepts percentage strings. Values + must be in the range 50 to 200 inclusive + """ if isinstance(value, str) and value.endswith('%'): value = value[:-1] value = STRETCHES.get(value, value) @@ -256,6 +261,7 @@ def validate(self, object, name, value): return value def info(self): + """Describe the trait""" info = ( "a float from 50 to 200, " "a value that can convert to a float from 50 to 200, " @@ -284,6 +290,11 @@ def __init__(self, default_value=NoDefaultSpecified, **metadata): super().__init__(default_value, **metadata) def validate(self, object, name, value): + """Validate the trait + + This is a CFloat trait that also accepts strings with 'pt' or 'px' + suffixes. Values must be positive. + """ if ( isinstance(value, str) and (value.endswith('pt') or value.endswith('px')) @@ -296,6 +307,7 @@ def validate(self, object, name, value): return value def info(self): + """Describe the trait""" info = ( "a positive float, a value that can convert to a positive float, " ) @@ -343,7 +355,7 @@ def from_toolkit(cls, toolkit_font): Parameters ---------- - toolkit_font : any + toolkit_font : Any A toolkit font to be converted to a corresponding class instance, within the limitations of the options supported by the class. """ @@ -358,7 +370,7 @@ def to_toolkit(self): Returns ------- - toolkit_font : any + toolkit_font : Any A toolkit font which matches the property of the font as closely as possible given the constraints of the toolkit. """ diff --git a/pyface/gui_application.py b/pyface/gui_application.py index 1f285c948..ee4e9a46c 100644 --- a/pyface/gui_application.py +++ b/pyface/gui_application.py @@ -116,7 +116,7 @@ def create_window(self, **kwargs): Returns ------- - window : IWindow instance or None + window : IWindow or None The new IWindow instance. """ window = self.window_factory(application=self, **kwargs) diff --git a/pyface/i_application_window.py b/pyface/i_application_window.py index ee8061853..5f32ddae1 100644 --- a/pyface/i_application_window.py +++ b/pyface/i_application_window.py @@ -26,10 +26,10 @@ class IApplicationWindow(IWindow): The application window has support for a menu bar, tool bar and a status bar (all of which are optional). - Usage + Notes ----- - Create a sub-class of this class and override the + To use, create a sub-class of this class and override the :py:meth:`._create_contents` method. """ diff --git a/pyface/i_gui.py b/pyface/i_gui.py index b950b617f..9b5fa6771 100644 --- a/pyface/i_gui.py +++ b/pyface/i_gui.py @@ -49,7 +49,7 @@ def __init__(self, splash_screen=None): Parameters ---------- - splash_screen : ISplashScreen instance or None + splash_screen : ISplashScreen or None An optional splash screen that will be displayed until the event loop is started. """ @@ -78,7 +78,7 @@ def invoke_after(cls, millisecs, callable, *args, **kw): ---------- millisecs : float Delay in milliseconds - callable : callable + callable : Callable Callable to be called after the delay args, kwargs : Arguments and keyword arguments to be used when calling. @@ -90,7 +90,7 @@ def invoke_later(cls, callable, *args, **kw): Parameters ---------- - callable : callable + callable : Callable Callable to be called after the delay args, kwargs : Arguments and keyword arguments to be used when calling. @@ -104,11 +104,11 @@ def set_trait_after(cls, millisecs, obj, trait_name, new): ---------- millisecs : float Delay in milliseconds - obj : HasTraits instance + obj : traits.has_traits.HasTraits Object on which the trait is to be set trait_name : str The name of the trait to set - new : any + new : Any The value to set. """ @@ -118,11 +118,11 @@ def set_trait_later(cls, obj, trait_name, new): Parameters ---------- - obj : HasTraits instance + obj : traits.has_traits.HasTraits Object on which the trait is to be set trait_name : str The name of the trait to set - new : any + new : Any The value to set. """ diff --git a/pyface/i_image_resource.py b/pyface/i_image_resource.py index 5df954c05..b1874198b 100644 --- a/pyface/i_image_resource.py +++ b/pyface/i_image_resource.py @@ -124,7 +124,7 @@ def _get_ref(self, size=None): Returns ------- - ref : ImageReference instance + ref : ImageReference The reference to the requested image. """ @@ -162,7 +162,7 @@ def _get_image_not_found(cls): Returns ------- - not_found : ImageResource instance + not_found : ImageResource An image resource for the the 'not found' image. """ diff --git a/pyface/i_python_shell.py b/pyface/i_python_shell.py index e98582f9c..039f72f64 100644 --- a/pyface/i_python_shell.py +++ b/pyface/i_python_shell.py @@ -38,7 +38,7 @@ def interpreter(self): Returns ------- - interpreter : InteractiveInterpreter instance + interpreter : InteractiveInterpreter Returns the InteractiveInterpreter instance. """ @@ -49,7 +49,7 @@ def bind(self, name, value): ---------- name : str The python idetifier to bind the value to. - value : any + value : Any The python object to be bound into the interpreter's namespace. """ @@ -118,7 +118,7 @@ def bind(self, name, value): ---------- name : str The python idetifier to bind the value to. - value : any + value : Any The python object to be bound into the interpreter's namespace. """ self.interpreter().locals[name] = value diff --git a/pyface/i_widget.py b/pyface/i_widget.py index 0cd6ad7ad..dd71465cd 100644 --- a/pyface/i_widget.py +++ b/pyface/i_widget.py @@ -77,7 +77,7 @@ def create(self, parent=None): """ Creates the toolkit specific control. This method should create the control and assign it to the - :py:attr:``control`` trait. + :py:attr:`control` trait. """ def destroy(self): diff --git a/pyface/single_choice_dialog.py b/pyface/single_choice_dialog.py index c7f8d278c..e187e6475 100644 --- a/pyface/single_choice_dialog.py +++ b/pyface/single_choice_dialog.py @@ -38,7 +38,7 @@ def choose_one(parent, message, choices, title="Choose", cancel=True): Returns ------- - choice : any + choice : Any The selected object, or None if cancelled. """ dialog = SingleChoiceDialog( diff --git a/pyface/splash_screen_log_handler.py b/pyface/splash_screen_log_handler.py index 4ccf4dc78..50ec28c0f 100644 --- a/pyface/splash_screen_log_handler.py +++ b/pyface/splash_screen_log_handler.py @@ -22,7 +22,7 @@ def __init__(self, splash_screen): Parameters ---------- - splash_screen : ISplashScreen instance + splash_screen : ISplashScreen The splash screen being used to display the log messages """ # Base class constructor. @@ -36,7 +36,7 @@ def emit(self, record): Parameters ---------- - record : logging record instance + record : logging record The log record to be displayed. """ self._splash_screen.text = str(record.getMessage()) + "..." diff --git a/pyface/tasks/tasks_application.py b/pyface/tasks/tasks_application.py index 9f14443d9..510445098 100644 --- a/pyface/tasks/tasks_application.py +++ b/pyface/tasks/tasks_application.py @@ -121,7 +121,7 @@ def create_window(self, layout=None, **kwargs): Parameters ---------- - layout : TaskLayout instance or None + layout : TaskLayout or None The pane layout for the window. **kwargs : dict Additional keyword arguments to pass to the window factory. @@ -129,7 +129,7 @@ def create_window(self, layout=None, **kwargs): Returns ------- - window : ITaskWindow instance or None + window : ITaskWindow or None The new TaskWindow. """ from pyface.tasks.task_window_layout import TaskWindowLayout diff --git a/pyface/timer/do_later.py b/pyface/timer/do_later.py index 92e996e88..07f5cc69a 100644 --- a/pyface/timer/do_later.py +++ b/pyface/timer/do_later.py @@ -34,7 +34,7 @@ def do_later(callable, *args, **kwargs): Parameters ---------- - callable : callable + callable : Callable The callable to call in 50ms time. args, kwargs : tuple, dict Arguments to be passed through to the callable. @@ -51,7 +51,7 @@ def do_after(interval, callable, *args, **kwargs): ---------- interval : float The time interval in milliseconds to wait before calling. - callable : callable + callable : Callable The callable to call. args Positional arguments to be passed through to the callable. diff --git a/pyface/ui/__init__.py b/pyface/ui/__init__.py index 5cc66c880..002e3d564 100644 --- a/pyface/ui/__init__.py +++ b/pyface/ui/__init__.py @@ -37,7 +37,7 @@ class ShadowedModuleLoader(Loader): new_name : str The full name of the corresponding "real" module. Eg. "pyface.ui.qt.foo" - new_spec : ModuleSpec instance + new_spec : ModuleSpec The spec object for the corresponding "real" module. """ diff --git a/pyface/ui/qt/application_window.py b/pyface/ui/qt/application_window.py index 2efb0e8a6..bd2d64961 100644 --- a/pyface/ui/qt/application_window.py +++ b/pyface/ui/qt/application_window.py @@ -141,6 +141,7 @@ def _menu_bar_manager_updated(self, event): def _status_bar_manager_updated(self, event): if self.control is not None: if event.old is not None: + self.control.setStatusBar(None) event.old.destroy() self._create_status_bar(self.control) @@ -154,7 +155,8 @@ def _update_tool_bar_managers(self, event): child.deleteLater() # Add the new toolbars. - self._create_tool_bar(self.control) + if event.new is not None: + self._create_status_bar(self.control) @observe("icon") def _icon_updated(self, event): diff --git a/pyface/ui/qt/console/console_widget.py b/pyface/ui/qt/console/console_widget.py index 746aca8fc..9508d24fc 100644 --- a/pyface/ui/qt/console/console_widget.py +++ b/pyface/ui/qt/console/console_widget.py @@ -1874,7 +1874,7 @@ def _readline(self, prompt="", callback=None): prompt : str, optional The prompt to print before reading the line. - callback : callable, optional + callback : Callable, optional A callback to execute with the read line. If not specified, input is read *synchronously* and this method does not return until it has been read. diff --git a/pyface/ui/qt/font.py b/pyface/ui/qt/font.py index 1c0b2a20f..beb21e789 100644 --- a/pyface/ui/qt/font.py +++ b/pyface/ui/qt/font.py @@ -187,7 +187,7 @@ def map_to_nearest(target, mapping): Returns ------- - value : any + value : Any The value corresponding to the nearest key. In the case of a tie, the first value is returned. """ diff --git a/pyface/ui/qt/tasks/split_editor_area_pane.py b/pyface/ui/qt/tasks/split_editor_area_pane.py index 9baf03687..889857fc8 100644 --- a/pyface/ui/qt/tasks/split_editor_area_pane.py +++ b/pyface/ui/qt/tasks/split_editor_area_pane.py @@ -472,7 +472,7 @@ class EditorAreaWidget(QtGui.QSplitter): def __init__(self, editor_area, parent=None, tabwidget=None): """ Creates an EditorAreaWidget object. - editor_area : global SplitEditorAreaPane instance + editor_area : global SplitEditorAreaPane parent : parent splitter tabwidget : tabwidget object contained by this splitter @@ -759,7 +759,7 @@ class DraggableTabWidget(QtGui.QTabWidget): def __init__(self, editor_area, parent): """ - editor_area : global SplitEditorAreaPane instance + editor_area : global SplitEditorAreaPane parent : parent of the tabwidget """ super().__init__(parent) diff --git a/pyface/ui/qt/util/event_loop_helper.py b/pyface/ui/qt/util/event_loop_helper.py index a863bf7ac..18676ce08 100644 --- a/pyface/ui/qt/util/event_loop_helper.py +++ b/pyface/ui/qt/util/event_loop_helper.py @@ -110,7 +110,7 @@ def event_loop_until_condition(self, condition, timeout=10.0): Parameters ---------- - condition : callable + condition : Callable A callable to determine if the stop criteria have been met. This should accept no arguments. diff --git a/pyface/ui/qt/util/gui_test_assistant.py b/pyface/ui/qt/util/gui_test_assistant.py index 12e3bdcec..620cc05b9 100644 --- a/pyface/ui/qt/util/gui_test_assistant.py +++ b/pyface/ui/qt/util/gui_test_assistant.py @@ -159,7 +159,7 @@ def event_loop_until_condition(self, condition, timeout=10.0): Parameters ---------- - condition : callable + condition : Callable A callable to determine if the stop criteria have been met. This should accept no arguments. timeout : float @@ -197,7 +197,7 @@ def assertEventuallyTrueInGui(self, condition, timeout=10.0): Parameters ---------- - condition : callable() -> bool + condition : Callable() -> bool Callable accepting no arguments and returning a bool. timeout : float Maximum length of time to wait for the condition to become @@ -224,11 +224,11 @@ def assertTraitChangesInEventLoop( Parameters ---------- - obj : HasTraits + obj : traits.has_traits.HasTraits The HasTraits instance whose trait will change. trait : str The extended trait name of trait changes to listen to. - condition : callable + condition : Callable A callable to determine if the stop criteria have been met. This takes obj as the only argument. count : int @@ -269,7 +269,7 @@ def event_loop_until_traits_change(self, traits_object, *traits, **kw): Paramaters ---------- - traits_object : HasTraits instance + traits_object : traits.has_traits.HasTraits The object on which to listen for a trait events traits : one or more str The names of the traits to listen to for events @@ -345,7 +345,7 @@ def find_qt_widget(self, start, type_, test=None): type_ : type A subclass of QWidget to use for an initial type filter while walking the tree - test : callable + test : Callable A filter function that takes one argument (the current widget being evaluated) and returns either True or False to determine if the widget matches the required criteria. diff --git a/pyface/ui/qt/util/modal_dialog_tester.py b/pyface/ui/qt/util/modal_dialog_tester.py index 00782fde3..b4fbf0cdb 100644 --- a/pyface/ui/qt/util/modal_dialog_tester.py +++ b/pyface/ui/qt/util/modal_dialog_tester.py @@ -28,7 +28,7 @@ class ModalDialogTester(object): """ Test helper for code that open a traits ui or QDialog window. - Usage + Notes ----- :: @@ -86,7 +86,7 @@ def open_and_run(self, when_opened, *args, **kwargs): Parameters ---------- - when_opened : callable + when_opened : Callable A callable to be called when the dialog has been created and opened. The callable with be called with the tester instance as argument. @@ -142,7 +142,7 @@ def open_and_wait(self, when_opened, *args, **kwargs): Parameters ---------- - when_opened : callable + when_opened : Callable A callable to be called when the dialog has been created and opened. The callable with be called with the tester instance as argument. diff --git a/pyface/ui/qt/util/testing.py b/pyface/ui/qt/util/testing.py index cfdf36368..c35276d97 100644 --- a/pyface/ui/qt/util/testing.py +++ b/pyface/ui/qt/util/testing.py @@ -128,7 +128,7 @@ def find_qt_widget(start, type_, test=None): type_ : type A subclass of QWidget to use for an initial type filter while walking the tree - test : callable + test : Callable A filter function that takes one argument (the current widget being evaluated) and returns either True or False to determine if the widget matches the required criteria. diff --git a/pyface/ui/wx/layout_widget.py b/pyface/ui/wx/layout_widget.py index 665fa44e0..dce282f31 100644 --- a/pyface/ui/wx/layout_widget.py +++ b/pyface/ui/wx/layout_widget.py @@ -94,7 +94,7 @@ def _size_to_wx_size(size): Returns ------- - wx_size : wx.Size instance + wx_size : wx.Size A corresponding wx Size instance. """ return wx.Size(*( @@ -108,7 +108,7 @@ def _wx_size_to_size(wx_size): Parameters ---------- - wx_size : wx.Size instance + wx_size : wx.Size A wx Size instance. Returns diff --git a/pyface/ui_traits.py b/pyface/ui_traits.py index e78274123..a968e8ad8 100644 --- a/pyface/ui_traits.py +++ b/pyface/ui_traits.py @@ -149,7 +149,7 @@ class PyfaceColor(TraitType): """ A Trait which casts strings and tuples to a Pyface Color value. """ - #: The default value should be a tuple (factory, args, kwargs) + #: The default value should be a tuple (factory, args, kwargs). default_value_type = DefaultValue.callable_and_args def __init__(self, value=None, **metadata): @@ -161,6 +161,11 @@ def __init__(self, value=None, **metadata): super().__init__(default_value, **metadata) def validate(self, object, name, value): + """Validate the trait + + This accepts, Color values, parseable strings and RGB(A) sequences + (including numpy arrays). + """ if isinstance(value, Color): return value if isinstance(value, str): @@ -182,6 +187,7 @@ def validate(self, object, name, value): self.error(object, name, value) def info(self): + """Describe the trait""" return ( "a Pyface Color, a #-hexadecimal rgb or rgba string, a standard " "color name, or a sequence of RGBA or RGB values between 0 and 1" @@ -225,6 +231,10 @@ def __init__(self, value=None, *, parser=simple_parser, **metadata): super().__init__(default_value, **metadata) def validate(self, object, name, value): + """Validate the trait + + This accepts, Font values and parseable strings. + """ if isinstance(value, Font): return value if isinstance(value, str): @@ -236,6 +246,7 @@ def validate(self, object, name, value): self.error(object, name, value) def info(self): + """Describe the trait""" return ( "a Pyface Font, or a string describing a Pyface Font" ) @@ -247,15 +258,18 @@ def info(self): class BaseMB(ABCHasStrictTraits): - def __init__(self, *args, **traits): - """ Map posiitonal arguments to traits. + """ Base class for Margins and Borders - If one value is provided it is taken as the value for all sides. - If two values are provided, then the first argument is used for - left and right, while the second is used for top and bottom. - If 4 values are provided, then the arguments are mapped to - left, right, top, and bottom, respectively. - """ + The constructor of this class maps posiitonal arguments to traits. + + - If one value is provided it is taken as the value for all sides. + - If two values are provided, then the first argument is used for + left and right, while the second is used for top and bottom. + - If 4 values are provided, then the arguments are mapped to + left, right, top, and bottom, respectively. + """ + + def __init__(self, *args, **traits): n = len(args) if n > 0: if n == 1: @@ -277,32 +291,34 @@ def __init__(self, *args, **traits): class Margin(BaseMB): + """A HasTraits class that holds margin sizes.""" - # The amount of padding/margin at the top: + #: The amount of padding/margin at the top. top = Range(-32, 32, 0) - # The amount of padding/margin at the bottom: + #: The amount of padding/margin at the bottom. bottom = Range(-32, 32, 0) - # The amount of padding/margin on the left: + #: The amount of padding/margin on the left. left = Range(-32, 32, 0) - # The amount of padding/margin on the right: + #: The amount of padding/margin on the right. right = Range(-32, 32, 0) class Border(BaseMB): + """A HasTraits class that holds border thicknesses.""" - # The amount of border at the top: + #: The amount of border at the top. top = Range(0, 32, 0) - # The amount of border at the bottom: + #: The amount of border at the bottom. bottom = Range(0, 32, 0) - # The amount of border on the left: + #: The amount of border on the left. left = Range(0, 32, 0) - # The amount of border on the right: + #: The amount of border on the right. right = Range(0, 32, 0) @@ -311,13 +327,13 @@ class HasMargin(TraitType): tuple value that can be converted to one. """ - # The desired value class: + #: The desired value class. klass = Margin - # Define the default value for the trait: + #: Define the default value for the trait. default_value = Margin(0) - # A description of the type of value this trait accepts: + #: A description of the type of value this trait accepts. info_text = ( "a Margin instance, or an integer in the range from -32 to 32 " "or a tuple with 1, 2 or 4 integers in that range that can be " @@ -371,13 +387,13 @@ class HasBorder(HasMargin): or tuple value that can be converted to one. """ - # The desired value class: + #: The desired value class. klass = Border - # Define the default value for the trait: + #: Define the default value for the trait. default_value = Border(0) - # A description of the type of value this trait accepts: + #: A description of the type of value this trait accepts. info_text = ( "a Border instance, or an integer in the range from 0 to 32 " "or a tuple with 1, 2 or 4 integers in that range that can be " diff --git a/pyface/util/testing.py b/pyface/util/testing.py index ce154809f..d55069e8f 100644 --- a/pyface/util/testing.py +++ b/pyface/util/testing.py @@ -11,9 +11,15 @@ import re from unittest import TestSuite +try: + from importlib.metadata import version +except: + from importlib_metadata import version + from packaging.version import Version -from traits import __version__ as TRAITS_VERSION + +TRAITS_VERSION = version("traits") def filter_tests(test_suite, exclusion_pattern): diff --git a/pyface/workbench/action/action_controller.py b/pyface/workbench/action/action_controller.py index 0d03c8e07..28620553d 100644 --- a/pyface/workbench/action/action_controller.py +++ b/pyface/workbench/action/action_controller.py @@ -10,12 +10,12 @@ """ The action controller for workbench menu and tool bars. """ -from pyface.action.api import ActionController +from pyface.action.api import ActionController as PyfaceActionController from pyface.workbench.api import WorkbenchWindow from traits.api import Instance -class ActionController(ActionController): +class ActionController(PyfaceActionController): """ The action controller for workbench menu and tool bars. The controller is used to 'hook' the invocation of every action on the menu diff --git a/pyproject.toml b/pyproject.toml index b0687a01f..b91cc3c31 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -17,7 +17,7 @@ dependencies = [ 'importlib-resources>=1.1.0; python_version<"3.9"', 'traits>=6.2', ] -version = '8.0.0.dev0' +version = '8.0.0' license = {file = "LICENSE.txt"} [project.entry-points.'pyface.toolkits'] diff --git a/shell_window.png b/shell_window.png new file mode 100644 index 000000000..12b18a063 Binary files /dev/null and b/shell_window.png differ