diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml
index a5626c0b..5b2f0ff4 100644
--- a/.github/workflows/lint.yml
+++ b/.github/workflows/lint.yml
@@ -17,9 +17,12 @@ jobs:
- name: Install dependencies
run: |
python -m pip install --upgrade pip
- pip install mypy black
+ pip install mypy black pycodestyle pydocstyle
- name: Run linters
run: |
mypy guibot
black --check --diff --color guibot
+ # only excluded checks are conflicts with black and within pycodestyle
+ pycodestyle --ignore=E203,E501,W503 guibot
+ pydocstyle guibot
diff --git a/guibot/__init__.py b/guibot/__init__.py
index 1219a921..15d7fc1a 100644
--- a/guibot/__init__.py
+++ b/guibot/__init__.py
@@ -14,10 +14,10 @@
# along with guibot. If not, see .
"""
+Package with the complete guibot modules and functionality.
SUMMARY
------------------------------------------------------
-Package with the complete guibot modules and functionality.
INTERFACE
diff --git a/guibot/calibrator.py b/guibot/calibrator.py
index c0c0919a..529b432f 100644
--- a/guibot/calibrator.py
+++ b/guibot/calibrator.py
@@ -14,10 +14,10 @@
# along with guibot. If not, see .
"""
+Calibration and benchmarking for all CV backends on a given matching target.
SUMMARY
------------------------------------------------------
-Calibration and benchmarking for all CV backends on a given matching target.
INTERFACE
@@ -29,6 +29,7 @@
import math
import copy
from typing import Generator
+import logging
from .finder import *
from .target import Target, Image
@@ -36,7 +37,6 @@
from .errors import *
from .location import Location
-import logging
log = logging.getLogger("guibot.calibrator")
@@ -51,9 +51,9 @@
class Calibrator(object):
"""
- Provides with a group of methods to facilitate and automate the selection
- of algorithms and parameters that are most suitable for a given preselected
- image matching pair.
+ Provides with a group of methods to facilitate and automate the selection of algorithms and parameters.
+
+ This is most suitable for a given preselected image matching pair.
Use the benchmarking method to choose the best algorithm to find your image.
Use the calibration method to find the best parameters if you have already
@@ -108,8 +108,7 @@ def benchmark(
**kwargs: dict[str, type]
) -> list[tuple[str, float, float]]:
"""
- Perform benchmarking on all available algorithms of a finder
- for a given needle and haystack.
+ Perform benchmarking on all available algorithms of a finder for a given needle and haystack.
:param finder: CV backend whose backend algorithms will be benchmarked
:param random_starts: number of random starts to try with (0 for nonrandom)
@@ -205,8 +204,10 @@ def search(
**kwargs: dict[str, type]
) -> float:
"""
- Search for the best match configuration for a given needle and haystack
- using calibration from random initial conditions.
+ Search for best match configuration via random initial condition calibration.
+
+ Find the best match configuration for a given needle and haystack using
+ calibration from random initial conditions.
:param finder: CV backend to use in order to determine deltas, fixed, and free
parameters and ultimately tweak to minimize error
@@ -291,8 +292,9 @@ def calibrate(
self, finder: Finder, max_attempts: int = 3, **kwargs: dict[str, type]
) -> float:
"""
- Calibrate the available match configuration for a given needle
- and haystack minimizing the matchign error.
+ Calibrate the available match configuration for a given needle and haystack.
+
+ The calibration minimizes the matching error.
:param finder: configuration for the CV backend to calibrate
:param max_attempts: maximal number of refinements to reach
@@ -530,8 +532,7 @@ def run_default(self, finder: Finder, **_kwargs: dict[str, type]) -> float:
def run_performance(self, finder: Finder, **kwargs: dict[str, type]) -> float:
"""
- Run a match case and return error from the match as dissimilarity
- and linear performance penalty.
+ Run a match case and return error from the match as dissimilarity and linear performance penalty.
:param finder: finder with match configuration to use for the run
:returns: error obtained as unity minus similarity
@@ -561,8 +562,9 @@ def run_performance(self, finder: Finder, **kwargs: dict[str, type]) -> float:
def run_peak(self, finder: Finder, **kwargs: dict[str, type]) -> float:
"""
- Run a match case and return error from the match as failure to obtain
- high similarity of one match and low similarity of all others.
+ Run match case and return a peak error from the match.
+
+ A peak error is a failure to obtain high similarity of one match and low similarity of all others.
:param finder: finder with match configuration to use for the run
:returns: error obtained as unity minus similarity
diff --git a/guibot/config.py b/guibot/config.py
index 4dd5a4ae..b0bd439e 100644
--- a/guibot/config.py
+++ b/guibot/config.py
@@ -14,10 +14,10 @@
# along with guibot. If not, see .
"""
+Global and local (per target or region instance) configuration.
SUMMARY
------------------------------------------------------
-Global and local (per target or region instance) configuration.
INTERFACE
@@ -30,6 +30,7 @@
from .errors import *
+
log = logging.getLogger("guibot.config")
@@ -81,10 +82,10 @@ class GlobalConfig(type):
def toggle_delay(self, value: float = None) -> float | None:
"""
- Getter/setter for property attribute.
+ Get or set property attribute.
:param value: time interval between mouse down and up in a click
- :returns: current value if no argument was passed otherwise only sets it
+ :returns: current value if no argument was passed otherwise None
"""
if value is None:
return GlobalConfig._toggle_delay
@@ -97,9 +98,10 @@ def toggle_delay(self, value: float = None) -> float | None:
def click_delay(self, value: float = None) -> float | None:
"""
- Same as :py:func:`GlobalConfig.toggle_delay` but with
+ Get or set property attribute.
:param value: time interval after a click (in a double or n-click)
+ :returns: current value if no argument was passed otherwise None
"""
if value is None:
return GlobalConfig._click_delay
@@ -112,9 +114,10 @@ def click_delay(self, value: float = None) -> float | None:
def delay_after_drag(self, value: float = None) -> float | None:
"""
- Same as :py:func:`GlobalConfig.toggle_delay` but with
+ Get or set property attribute.
:param value: timeout before drag operation
+ :returns: current value if no argument was passed otherwise None
"""
if value is None:
return GlobalConfig._drag_delay
@@ -127,9 +130,10 @@ def delay_after_drag(self, value: float = None) -> float | None:
def delay_before_drop(self, value: float = None) -> float | None:
"""
- Same as :py:func:`GlobalConfig.toggle_delay` but with
+ Get or set property attribute.
:param value: timeout before drop operation
+ :returns: current value if no argument was passed otherwise None
"""
if value is None:
return GlobalConfig._drop_delay
@@ -142,9 +146,10 @@ def delay_before_drop(self, value: float = None) -> float | None:
def delay_before_keys(self, value: float = None) -> float | None:
"""
- Same as :py:func:`GlobalConfig.toggle_delay` but with
+ Get or set property attribute.
:param value: timeout before key press operation
+ :returns: current value if no argument was passed otherwise None
"""
if value is None:
return GlobalConfig._keys_delay
@@ -157,9 +162,10 @@ def delay_before_keys(self, value: float = None) -> float | None:
def delay_between_keys(self, value: float = None) -> float | None:
"""
- Same as :py:func:`GlobalConfig.toggle_delay` but with
+ Get or set property attribute.
:param value: time interval between two consecutively typed keys
+ :returns: current value if no argument was passed otherwise None
"""
if value is None:
return GlobalConfig._type_delay
@@ -172,10 +178,11 @@ def delay_between_keys(self, value: float = None) -> float | None:
def rescan_speed_on_find(self, value: float = None) -> float | None:
"""
- Same as :py:func:`GlobalConfig.toggle_delay` but with
+ Get or set property attribute.
:param value: time interval between two image matching attempts
(used to reduce overhead on the CPU)
+ :returns: current value if no argument was passed otherwise None
"""
if value is None:
return GlobalConfig._rescan_speed_on_find
@@ -193,7 +200,7 @@ def wait_for_animations(self, value: bool = None) -> bool | None:
Getter/setter for property attribute.
:param value: whether to wait for animations to complete and match only static (not moving) targets
- :returns: current value if no argument was passed otherwise only sets it
+ :returns: current value if no argument was passed otherwise None
:raises: :py:class:`ValueError` if value is not boolean or None
This is useful to handle highly animated environments with lots of moving
@@ -216,7 +223,7 @@ def smooth_mouse_drag(self, value: bool = None) -> bool | None:
Getter/setter for property attribute.
:param value: whether to move the mouse cursor to a location instantly or smoothly
- :returns: current value if no argument was passed otherwise only sets it
+ :returns: current value if no argument was passed otherwise None
:raises: :py:class:`ValueError` if value is not boolean or None
This is useful if a routine task has to be executed faster without
@@ -235,10 +242,11 @@ def smooth_mouse_drag(self, value: bool = None) -> bool | None:
def preprocess_special_chars(self, value: bool = None) -> bool | None:
"""
- Same as :py:func:`GlobalConfig.smooth_mouse_drag` but with
+ Getter/setter for property attribute.
:param value: whether to preprocess capital and special characters and
handle them internally
+ :returns: current value if no argument was passed otherwise None
.. warning:: The characters will be forcefully preprocessed for the
autopy on linux (capital and special) and vncdotool (capital) backends.
@@ -258,9 +266,10 @@ def preprocess_special_chars(self, value: bool = None) -> bool | None:
def save_needle_on_error(self, value: bool = None) -> bool | None:
"""
- Same as :py:func:`GlobalConfig.smooth_mouse_drag` but with
+ Getter/setter for property attribute.
:param value: whether to perform an extra needle dump on matching error
+ :returns: current value if no argument was passed otherwise None
"""
if value is None:
return GlobalConfig._save_needle_on_error
@@ -280,7 +289,7 @@ def image_logging_level(self, value: int = None) -> int | None:
Getter/setter for property attribute.
:param value: logging level similar to the python logging module
- :returns: current value if no argument was passed otherwise only sets it
+ :returns: current value if no argument was passed otherwise None
.. seealso:: See the image logging documentation for more details.
"""
@@ -295,10 +304,11 @@ def image_logging_level(self, value: int = None) -> int | None:
def image_logging_step_width(self, value: int = None) -> int | None:
"""
- Same as :py:func:`GlobalConfig.image_logging_level` but with
+ Getter/setter for property attribute.
:param value: number of digits when enumerating the image
logging steps, e.g. value=3 for 001, 002, etc.
+ :returns: current value if no argument was passed otherwise None
"""
if value is None:
return GlobalConfig._image_logging_step_width
@@ -313,11 +323,12 @@ def image_logging_step_width(self, value: int = None) -> int | None:
def image_quality(self, value: int = None) -> int | None:
"""
- Same as :py:func:`GlobalConfig.image_logging_level` but with
+ Getter/setter for property attribute.
:param value: quality of the image dumps ranging from 0 for no compression
to 9 for maximum compression (used to save space and reduce
the disk space needed for image logging)
+ :returns: current value if no argument was passed otherwise None
"""
if value is None:
return GlobalConfig._image_quality
@@ -334,7 +345,7 @@ def image_logging_destination(self, value: str = None) -> str | None:
Getter/setter for property attribute.
:param value: relative path of the image logging steps
- :returns: current value if no argument was passed otherwise only sets it
+ :returns: current value if no argument was passed otherwise None
"""
if value is None:
return GlobalConfig._image_logging_destination
@@ -349,9 +360,10 @@ def image_logging_destination(self, value: str = None) -> str | None:
def display_control_backend(self, value: str = None) -> str | None:
"""
- Same as :py:func:`GlobalConfig.image_logging_destination` but with
+ Getter/setter for property attribute.
:param value: name of the display control backend
+ :returns: current value if no argument was passed otherwise None
:raises: :py:class:`ValueError` if value is not among the supported backends
Supported backends:
@@ -388,9 +400,10 @@ def display_control_backend(self, value: str = None) -> str | None:
# is already done during region and target initialization
def find_backend(self, value: str = None) -> str | None:
"""
- Same as :py:func:`GlobalConfig.image_logging_destination` but with
+ Getter/setter for property attribute.
:param value: name of the computer vision backend
+ :returns: current value if no argument was passed otherwise None
Supported backends:
* autopy - simple bitmap matching provided by AutoPy
@@ -423,9 +436,10 @@ def find_backend(self, value: str = None) -> str | None:
def contour_threshold_backend(self, value: str = None) -> str | None:
"""
- Same as :py:func:`GlobalConfig.image_logging_destination` but with
+ Getter/setter for property attribute.
:param value: name of the contour threshold backend
+ :returns: current value if no argument was passed otherwise None
Supported backends: normal, adaptive, canny.
"""
@@ -442,9 +456,10 @@ def contour_threshold_backend(self, value: str = None) -> str | None:
def template_match_backend(self, value: str = None) -> str | None:
"""
- Same as :py:func:`GlobalConfig.image_logging_destination` but with
+ Getter/setter for property attribute.
:param value: name of the template matching backend
+ :returns: current value if no argument was passed otherwise None
Supported backends: autopy, sqdiff, ccorr, ccoeff, sqdiff_normed,
ccorr_normed, ccoeff_normed.
@@ -462,9 +477,10 @@ def template_match_backend(self, value: str = None) -> str | None:
def feature_detect_backend(self, value: str = None) -> str | None:
"""
- Same as :py:func:`GlobalConfig.image_logging_destination` but with
+ Getter/setter for property attribute.
:param value: name of the feature detection backend
+ :returns: current value if no argument was passed otherwise None
Supported backends: BruteForce, BruteForce-L1, BruteForce-Hamming,
BruteForce-Hamming(2), in-house-raw, in-house-region.
@@ -482,9 +498,10 @@ def feature_detect_backend(self, value: str = None) -> str | None:
def feature_extract_backend(self, value: str = None) -> str | None:
"""
- Same as :py:func:`GlobalConfig.image_logging_destination` but with
+ Getter/setter for property attribute.
:param value: name of the feature extraction backend
+ :returns: current value if no argument was passed otherwise None
Supported backends: ORB, FAST, STAR, GFTT, HARRIS, Dense, oldSURF.
"""
@@ -501,9 +518,10 @@ def feature_extract_backend(self, value: str = None) -> str | None:
def feature_match_backend(self, value: str = None) -> str | None:
"""
- Same as :py:func:`GlobalConfig.image_logging_destination` but with
+ Getter/setter for property attribute.
:param value: name of the feature matching backend
+ :returns: current value if no argument was passed otherwise None
Supported backends: ORB, BRIEF, FREAK.
"""
@@ -520,9 +538,10 @@ def feature_match_backend(self, value: str = None) -> str | None:
def text_detect_backend(self, value: str = None) -> str | None:
"""
- Same as :py:func:`GlobalConfig.image_logging_destination` but with
+ Getter/setter for property attribute.
:param value: name of the text detection backend
+ :returns: current value if no argument was passed otherwise None
Supported backends: east, erstat, contours, components.
"""
@@ -537,9 +556,10 @@ def text_detect_backend(self, value: str = None) -> str | None:
def text_ocr_backend(self, value: str = None) -> str | None:
"""
- Same as :py:func:`GlobalConfig.image_logging_destination` but with
+ Getter/setter for property attribute.
:param value: name of the optical character recognition backend
+ :returns: current value if no argument was passed otherwise None
Supported backends: pytesseract, tesserocr, tesseract (OpenCV), hmm, beamSearch.
"""
@@ -554,9 +574,10 @@ def text_ocr_backend(self, value: str = None) -> str | None:
def deep_learn_backend(self, value: str = None) -> str | None:
"""
- Same as :py:func:`GlobalConfig.image_logging_destination` but with
+ Getter/setter for property attribute.
:param value: name of the deep learning backend
+ :returns: current value if no argument was passed otherwise None
Supported backends: pytorch, tensorflow (partial).
"""
@@ -571,9 +592,10 @@ def deep_learn_backend(self, value: str = None) -> str | None:
def hybrid_match_backend(self, value: str = None) -> str | None:
"""
- Same as :py:func:`GlobalConfig.image_logging_destination` but with
+ Getter/setter for property attribute.
:param value: name of the hybrid matching backend for unconfigured one-step targets
+ :returns: current value if no argument was passed otherwise None
Supported backends: all nonhybrid backends of :py:func:`GlobalConfig.find_backend`.
"""
@@ -591,8 +613,7 @@ def hybrid_match_backend(self, value: str = None) -> str | None:
class GlobalConfig(object, metaclass=GlobalConfig): # type: ignore
"""
- Handler for default configuration present in all
- cases where no specific value is set.
+ Handler for default configuration present in all cases where no specific value is set.
The methods of this class are shared among
all of its instances.
@@ -603,9 +624,10 @@ class GlobalConfig(object, metaclass=GlobalConfig): # type: ignore
class TemporaryConfig(object):
"""
- Proxies a GlobalConfig instance extending it to add context
- support, such that once this context ends the changes to the
- wrapped config object are restored.
+ Proxy a GlobalConfig instance extending it to add context support.
+
+ The context support is such that once this context ends the changes
+ to the wrapped config object are restored.
This is useful when we have a global config instance and need to
change it only for a few operations.
@@ -630,10 +652,12 @@ def __init__(self) -> None:
object.__setattr__(self, "_original_values", {})
def __getattribute__(self, name: Any) -> Any:
+ """Get attribute given a name."""
# fallback to GlobalConfig
return getattr(GlobalConfig, name)
def __setattr__(self, name: Any, value: Any) -> None:
+ """Set attribute given a name and a value."""
original_values = object.__getattribute__(self, "_original_values")
# store the original value only at the first set operation,
# so further changes won't overwrite the history
@@ -642,10 +666,12 @@ def __setattr__(self, name: Any, value: Any) -> None:
setattr(GlobalConfig, name, value)
def __enter__(self) -> "TemporaryConfig":
+ """Set up context manager upon entry."""
# our temporary config object
return self
def __exit__(self, *_: tuple[type, ...]) -> None:
+ """Clean up context manager upon exit."""
original_values = object.__getattribute__(self, "_original_values")
# restore original configuration values
for name, value in original_values.items():
@@ -656,10 +682,10 @@ def __exit__(self, *_: tuple[type, ...]) -> None:
class LocalConfig(object):
"""
- Container for the configuration of all display control and
- computer vision backends, responsible for making them behave
- according to the selected parameters as well as for providing
- information about them and the current parameters.
+ Contain locally the configuration of all display control and computer vision backends.
+
+ The local container is reponsible for making them behave according to the selected
+ parameters as well as for providing information about them and the current parameters.
"""
def __init__(self, configure: bool = True, synchronize: bool = True) -> None:
diff --git a/guibot/controller.py b/guibot/controller.py
index a3824b40..061d3ed8 100644
--- a/guibot/controller.py
+++ b/guibot/controller.py
@@ -14,10 +14,10 @@
# along with guibot. If not, see .
"""
+Display controllers (DC backends) to perform user operations.
SUMMARY
------------------------------------------------------
-Display controllers (DC backends) to perform user operations.
INTERFACE
@@ -52,8 +52,10 @@
class Controller(LocalConfig):
"""
- Screen control backend, responsible for performing desktop operations
- like mouse clicking, key pressing, text typing, etc.
+ Screen control backend, responsible for performing display operations.
+
+ Examples of display operations include mouse clicking mouse clicking,
+ key pressing, text typing, etc.
"""
def __init__(self, configure: bool = True, synchronize: bool = True) -> None:
@@ -171,6 +173,8 @@ def configure_backend(
self, backend: str = None, category: str = "control", reset: bool = False
) -> None:
"""
+ Generate configuration dictionary for a given backend.
+
Custom implementation of the base method.
See base method for details.
@@ -195,6 +199,8 @@ def synchronize_backend(
self, backend: str = None, category: str = "control", reset: bool = False
) -> None:
"""
+ Synchronize a category backend with the equalizer configuration.
+
Custom implementation of the base method.
See base method for details.
@@ -358,8 +364,9 @@ def keys_type(self, text: list[str] | str, modifiers: list[str] = None) -> None:
class AutoPyController(Controller):
"""
- Screen control backend implemented through AutoPy which is a small
- python library portable to Windows and Linux operating systems.
+ Screen control backend implemented through AutoPy.
+
+ AutoPy is a small python library portable to Windows and Linux operating systems.
"""
def __init__(self, configure: bool = True, synchronize: bool = True) -> None:
@@ -372,6 +379,8 @@ def __init__(self, configure: bool = True, synchronize: bool = True) -> None:
def get_mouse_location(self) -> Location:
"""
+ Getter for readonly attribute.
+
Custom implementation of the base method.
See base method for details.
@@ -406,6 +415,8 @@ def configure_backend(
self, backend: str = None, category: str = "autopy", reset: bool = False
) -> None:
"""
+ Generate configuration dictionary for a given backend.
+
Custom implementation of the base method.
See base method for details.
@@ -443,6 +454,8 @@ def synchronize_backend(
self, backend: str = None, category: str = "autopy", reset: bool = False
) -> None:
"""
+ Synchronize a category backend with the equalizer configuration.
+
Custom implementation of the base method.
See base method for details.
@@ -451,6 +464,8 @@ def synchronize_backend(
def capture_screen(self, *args: "list[int] | Region | None") -> Image:
"""
+ Get the current screen as image.
+
Custom implementation of the base method.
See base method for details.
@@ -485,6 +500,8 @@ def capture_screen(self, *args: "list[int] | Region | None") -> Image:
def mouse_move(self, location: Location, smooth: bool = True) -> None:
"""
+ Move the mouse to a desired location.
+
Custom implementation of the base method.
See base method for details.
@@ -500,6 +517,8 @@ def mouse_click(
self, button: int = None, count: int = 1, modifiers: list[str] = None
) -> None:
"""
+ Click the selected mouse button N times at the current mouse location.
+
Custom implementation of the base method.
See base method for details.
@@ -520,6 +539,8 @@ def mouse_click(
def mouse_down(self, button: int) -> None:
"""
+ Hold down a mouse button.
+
Custom implementation of the base method.
See base method for details.
@@ -528,6 +549,8 @@ def mouse_down(self, button: int) -> None:
def mouse_up(self, button: int) -> None:
"""
+ Release a mouse button.
+
Custom implementation of the base method.
See base method for details.
@@ -536,6 +559,8 @@ def mouse_up(self, button: int) -> None:
def keys_toggle(self, keys: list[str] | str, up_down: bool) -> None:
"""
+ Hold down or release together all provided keys.
+
Custom implementation of the base method.
See base method for details.
@@ -545,6 +570,8 @@ def keys_toggle(self, keys: list[str] | str, up_down: bool) -> None:
def keys_type(self, text: list[str] | str, modifiers: list[str] = None) -> None:
"""
+ Type (press consecutively) all provided keys.
+
Custom implementation of the base method.
See base method for details.
@@ -564,10 +591,7 @@ def keys_type(self, text: list[str] | str, modifiers: list[str] = None) -> None:
class XDoToolController(Controller):
- """
- Screen control backend implemented through the xdotool client and
- thus portable to Linux operating systems.
- """
+ """Screen control backend implemented through the xdotool client and thus portable to Linux operating systems."""
def __init__(self, configure: bool = True, synchronize: bool = True) -> None:
"""Build a DC backend using XDoTool."""
@@ -579,6 +603,8 @@ def __init__(self, configure: bool = True, synchronize: bool = True) -> None:
def get_mouse_location(self) -> Location:
"""
+ Getter for readonly attribute.
+
Custom implementation of the base method.
See base method for details.
@@ -608,6 +634,8 @@ def configure_backend(
self, backend: str = None, category: str = "xdotool", reset: bool = False
) -> None:
"""
+ Generate configuration dictionary for a given backend.
+
Custom implementation of the base method.
See base method for details.
@@ -653,6 +681,8 @@ def synchronize_backend(
self, backend: str = None, category: str = "xdotool", reset: bool = False
) -> None:
"""
+ Synchronize a category backend with the equalizer configuration.
+
Custom implementation of the base method.
See base method for details.
@@ -661,6 +691,8 @@ def synchronize_backend(
def capture_screen(self, *args: "list[int] | Region | None") -> Image:
"""
+ Get the current screen as image.
+
Custom implementation of the base method.
See base method for details.
@@ -688,6 +720,8 @@ def capture_screen(self, *args: "list[int] | Region | None") -> Image:
def mouse_move(self, location: Location, smooth: bool = True) -> None:
"""
+ Move the mouse to a desired location.
+
Custom implementation of the base method.
See base method for details.
@@ -708,6 +742,8 @@ def mouse_click(
self, button: int = None, count: int = 1, modifiers: list[str] = None
) -> None:
"""
+ Click the selected mouse button N times at the current mouse location.
+
Custom implementation of the base method.
See base method for details.
@@ -729,6 +765,8 @@ def mouse_click(
def mouse_down(self, button: int) -> None:
"""
+ Hold down a mouse button.
+
Custom implementation of the base method.
See base method for details.
@@ -737,6 +775,8 @@ def mouse_down(self, button: int) -> None:
def mouse_up(self, button: int) -> None:
"""
+ Release a mouse button.
+
Custom implementation of the base method.
See base method for details.
@@ -745,6 +785,8 @@ def mouse_up(self, button: int) -> None:
def keys_toggle(self, keys: list[str] | str, up_down: bool) -> None:
"""
+ Hold down or release together all provided keys.
+
Custom implementation of the base method.
See base method for details.
@@ -757,6 +799,8 @@ def keys_toggle(self, keys: list[str] | str, up_down: bool) -> None:
def keys_type(self, text: list[str] | str, modifiers: list[str] = None) -> None:
"""
+ Type (press consecutively) all provided keys.
+
Custom implementation of the base method.
See base method for details.
@@ -773,8 +817,9 @@ def keys_type(self, text: list[str] | str, modifiers: list[str] = None) -> None:
class VNCDoToolController(Controller):
"""
- Screen control backend implemented through the VNCDoTool client and
- thus portable to any guest OS that is accessible through a VNC/RFB protocol.
+ Screen control backend implemented through the VNCDoTool client.
+
+ This backend is thus portable to any guest OS that is accessible through a VNC/RFB protocol.
"""
def __init__(self, configure: bool = True, synchronize: bool = True) -> None:
@@ -808,6 +853,8 @@ def configure_backend(
self, backend: str = None, category: str = "vncdotool", reset: bool = False
) -> None:
"""
+ Generate configuration dictionary for a given backend.
+
Custom implementation of the base method.
See base method for details.
@@ -873,6 +920,8 @@ def synchronize_backend(
self, backend: str = None, category: str = "vncdotool", reset: bool = False
) -> None:
"""
+ Synchronize a category backend with the equalizer configuration.
+
Custom implementation of the base method.
See base method for details.
@@ -881,6 +930,8 @@ def synchronize_backend(
def capture_screen(self, *args: "list[int] | Region | None") -> Image:
"""
+ Get the current screen as image.
+
Custom implementation of the base method.
See base method for details.
@@ -895,6 +946,8 @@ def capture_screen(self, *args: "list[int] | Region | None") -> Image:
def mouse_move(self, location: Location, smooth: bool = True) -> None:
"""
+ Move the mouse to a desired location.
+
Custom implementation of the base method.
See base method for details.
@@ -909,6 +962,8 @@ def mouse_click(
self, button: int = None, count: int = 1, modifiers: list[str] = None
) -> None:
"""
+ Click the selected mouse button N times at the current mouse location.
+
Custom implementation of the base method.
See base method for details.
@@ -931,6 +986,8 @@ def mouse_click(
def mouse_down(self, button: int) -> None:
"""
+ Hold down a mouse button.
+
Custom implementation of the base method.
See base method for details.
@@ -939,6 +996,8 @@ def mouse_down(self, button: int) -> None:
def mouse_up(self, button: int) -> None:
"""
+ Release a mouse button.
+
Custom implementation of the base method.
See base method for details.
@@ -947,6 +1006,8 @@ def mouse_up(self, button: int) -> None:
def keys_toggle(self, keys: list[str] | str, up_down: bool) -> None:
"""
+ Hold down or release together all provided keys.
+
Custom implementation of the base method.
See base method for details.
@@ -965,6 +1026,8 @@ def keys_toggle(self, keys: list[str] | str, up_down: bool) -> None:
def keys_type(self, text: list[str] | str, modifiers: list[str] = None) -> None:
"""
+ Type (press consecutively) all provided keys.
+
Custom implementation of the base method.
See base method for details.
@@ -991,8 +1054,9 @@ def keys_type(self, text: list[str] | str, modifiers: list[str] = None) -> None:
class PyAutoGUIController(Controller):
"""
- Screen control backend implemented through PyAutoGUI which is a python
- library portable to MacOS, Windows, and Linux operating systems.
+ Screen control backend implemented through PyAutoGUI.
+
+ PyAutoGUI is a python library portable to MacOS, Windows, and Linux operating systems.
"""
def __init__(self, configure: bool = True, synchronize: bool = True) -> None:
@@ -1005,6 +1069,8 @@ def __init__(self, configure: bool = True, synchronize: bool = True) -> None:
def get_mouse_location(self) -> Location:
"""
+ Getter for readonly attribute.
+
Custom implementation of the base method.
See base method for details.
@@ -1031,6 +1097,8 @@ def configure_backend(
self, backend: str = None, category: str = "pyautogui", reset: bool = False
) -> None:
"""
+ Generate configuration dictionary for a given backend.
+
Custom implementation of the base method.
See base method for details.
@@ -1069,6 +1137,8 @@ def synchronize_backend(
self, backend: str = None, category: str = "pyautogui", reset: bool = False
) -> None:
"""
+ Synchronize a category backend with the equalizer configuration.
+
Custom implementation of the base method.
See base method for details.
@@ -1077,6 +1147,8 @@ def synchronize_backend(
def capture_screen(self, *args: "list[int] | Region | None") -> Image:
"""
+ Get the current screen as image.
+
Custom implementation of the base method.
See base method for details.
@@ -1088,6 +1160,8 @@ def capture_screen(self, *args: "list[int] | Region | None") -> Image:
def mouse_move(self, location: Location, smooth: bool = True) -> None:
"""
+ Move the mouse to a desired location.
+
Custom implementation of the base method.
See base method for details.
@@ -1102,6 +1176,8 @@ def mouse_click(
self, button: int = None, count: int = 1, modifiers: list[str] = None
) -> None:
"""
+ Click the selected mouse button N times at the current mouse location.
+
Custom implementation of the base method.
See base method for details.
@@ -1124,6 +1200,8 @@ def mouse_click(
def mouse_down(self, button: int) -> None:
"""
+ Hold down a mouse button.
+
Custom implementation of the base method.
See base method for details.
@@ -1132,6 +1210,8 @@ def mouse_down(self, button: int) -> None:
def mouse_up(self, button: int) -> None:
"""
+ Release a mouse button.
+
Custom implementation of the base method.
See base method for details.
@@ -1140,6 +1220,8 @@ def mouse_up(self, button: int) -> None:
def mouse_scroll(self, clicks: int = 10, horizontal: bool = False) -> None:
"""
+ Scroll the mouse for a number of clicks.
+
Custom implementation of the base method.
See base method for details.
@@ -1151,6 +1233,8 @@ def mouse_scroll(self, clicks: int = 10, horizontal: bool = False) -> None:
def keys_toggle(self, keys: list[str] | str, up_down: bool) -> None:
"""
+ Hold down or release together all provided keys.
+
Custom implementation of the base method.
See base method for details.
@@ -1163,6 +1247,8 @@ def keys_toggle(self, keys: list[str] | str, up_down: bool) -> None:
def keys_type(self, text: list[str] | str, modifiers: list[str] = None) -> None:
"""
+ Type (press consecutively) all provided keys.
+
Custom implementation of the base method.
See base method for details.
diff --git a/guibot/desktopcontrol.py b/guibot/desktopcontrol.py
index 0e41e286..1875e426 100644
--- a/guibot/desktopcontrol.py
+++ b/guibot/desktopcontrol.py
@@ -14,10 +14,10 @@
# along with guibot. If not, see .
"""
+Old module for display controllers (DC backends) - to be deprecated.
SUMMARY
------------------------------------------------------
-Old module for display controllers (DC backends) - to be deprecated.
INTERFACE
diff --git a/guibot/errors.py b/guibot/errors.py
index 391a9617..fc6130f1 100644
--- a/guibot/errors.py
+++ b/guibot/errors.py
@@ -14,10 +14,10 @@
# along with guibot. If not, see .
"""
+Exceptions used by all guibot interfaces and modules.
SUMMARY
------------------------------------------------------
-Exceptions used by all guibot interfaces and modules.
INTERFACE
@@ -40,23 +40,23 @@
class GuiBotError(Exception):
- """GuiBot exception base class"""
+ """GuiBot exception base class."""
class FileNotFoundError(GuiBotError):
- """Exception raised when a picture file cannot be found on disc"""
+ """Exception raised when a picture file cannot be found on disc."""
class IncompatibleTargetError(GuiBotError):
- """Exception raised when a matched target is of type that cannot be handled by the finder"""
+ """Exception raised when a matched target is of type that cannot be handled by the finder."""
class IncompatibleTargetFileError(GuiBotError):
- """Exception raised when a matched target is restored from a file of unsupported type"""
+ """Exception raised when a matched target is restored from a file of unsupported type."""
class FindError(GuiBotError):
- """Exception raised when an Image cannot be found on the screen"""
+ """Exception raised when an Image cannot be found on the screen."""
def __init__(self, failed_target: "Target" = None) -> None:
"""
@@ -72,7 +72,7 @@ def __init__(self, failed_target: "Target" = None) -> None:
class NotFindError(GuiBotError):
- """Exception raised when an Image can be found on the screen but should not be"""
+ """Exception raised when an Image can be found on the screen but should not be."""
def __init__(self, failed_target: "Target" = None) -> None:
"""
@@ -91,12 +91,12 @@ def __init__(self, failed_target: "Target" = None) -> None:
class UnsupportedBackendError(GuiBotError):
- """Exception raised when a non-existent method is used for finding a target"""
+ """Exception raised when a non-existent method is used for finding a target."""
class MissingHotmapError(GuiBotError):
- """Exception raised when an attempt to access a non-existent hotmap in the image logger is made"""
+ """Exception raised when an attempt to access a non-existent hotmap in the image logger is made."""
class UninitializedBackendError(GuiBotError):
- """Exception raised when a region is created within an empty screen (a disconnected display control backend)"""
+ """Exception raised when a region is created within an empty screen (a disconnected display control backend)."""
diff --git a/guibot/fileresolver.py b/guibot/fileresolver.py
index 0549e351..29ec0e62 100644
--- a/guibot/fileresolver.py
+++ b/guibot/fileresolver.py
@@ -14,10 +14,10 @@
# along with guibot. If not, see .
"""
+Cached and reused paths for target files to search in and load target data from.
SUMMARY
------------------------------------------------------
-Cached and reused paths for target files to search in and load target data from.
INTERFACE
@@ -28,7 +28,6 @@
import os
from .errors import *
from typing import Generator
-
import logging
@@ -37,8 +36,7 @@
class FileResolver(object):
"""
- Handler for currently used target paths or
- sources of targets with a desired name.
+ Handler for currently used target paths or sources of targets with a desired name.
The methods of this class are shared among
all of its instances.
@@ -49,8 +47,7 @@ class FileResolver(object):
def add_path(self, directory: str) -> None:
"""
- Add a path to the list of currently accessible paths
- if it wasn't already added.
+ Add a path to the list of currently accessible paths if it wasn't already added.
:param directory: path to add
"""
@@ -129,10 +126,12 @@ def search(
return None
def __iter__(self) -> Generator[str, None, None]:
+ """Iterate over the target paths."""
for p in self._target_paths:
yield p
def __len__(self) -> int:
+ """Return total number of target paths."""
return len(self._target_paths)
@@ -149,8 +148,7 @@ class CustomFileResolver(object):
def __init__(self, *paths: tuple[type, ...]) -> None:
"""
- Create the class with the paths that the search will be
- restricted to.
+ Create the class with the paths that the search will be restricted to.
:param paths: list of paths that the search will use
"""
diff --git a/guibot/finder.py b/guibot/finder.py
index c4c9c58e..f3ff3d7d 100644
--- a/guibot/finder.py
+++ b/guibot/finder.py
@@ -14,10 +14,10 @@
# along with guibot. If not, see .
"""
+Computer vision finders (CV backends) to perform find targets on screen.
SUMMARY
------------------------------------------------------
-Computer vision finders (CV backends) to perform find targets on screen.
INTERFACE
@@ -34,6 +34,7 @@
import PIL.Image
from typing import Callable
from typing import Any
+import logging
from .config import GlobalConfig, LocalConfig
from .imagelogger import ImageLogger
@@ -41,7 +42,6 @@
from .errors import *
from .location import Location
-import logging
log = logging.getLogger("guibot.finder")
@@ -146,7 +146,7 @@ def __repr__(self) -> str:
def __eq__(self, other: "CVParameter") -> bool:
"""
- Custom implementation for equality check.
+ Check equality for CV parameters.
:returns: whether this instance is equal to another
"""
@@ -395,6 +395,8 @@ def configure_backend(
self, backend: str = None, category: str = "find", reset: bool = False
) -> None:
"""
+ Generate configuration dictionary for a given backend.
+
Custom implementation of the base method.
See base method for details.
@@ -420,6 +422,8 @@ def synchronize_backend(
self, backend: str = None, category: str = "find", reset: bool = False
) -> None:
"""
+ Synchronize a category backend with the equalizer configuration.
+
Custom implementation of the base method.
See base method for details.
@@ -428,8 +432,9 @@ def synchronize_backend(
def can_calibrate(self, category: str, mark: bool) -> None:
"""
- Fix the parameters for a given category backend algorithm,
- i.e. disallow the calibrator to change them.
+ Fix the parameters for a given category backend algorithm.
+
+ "Fix" as in disallow the calibrator from changing them.
:param category: backend category whose parameters are marked
:param mark: whether to mark for calibration
@@ -560,6 +565,8 @@ def configure_backend(
self, backend: str = None, category: str = "autopy", reset: bool = False
) -> None:
"""
+ Generate configuration dictionary for a given backend.
+
Custom implementation of the base method.
See base method for details.
@@ -568,6 +575,8 @@ def configure_backend(
def find(self, needle: "Image", haystack: "Image") -> "list[Match]":
"""
+ Find all needle targets in a haystack image.
+
Custom implementation of the base method.
:param needle: target iamge to search for
@@ -663,11 +672,6 @@ def __init__(self, configure: bool = True, synchronize: bool = True) -> None:
def __configure_backend(
self, backend: str = None, category: str = "contour", reset: bool = False
) -> None:
- """
- Custom implementation of the base method.
-
- See base method for details.
- """
if category not in ["contour", "threshold"]:
raise UnsupportedBackendError(
"Backend category '%s' is not supported" % category
@@ -743,6 +747,8 @@ def configure_backend(
self, backend: str = None, category: str = "contour", reset: bool = False
) -> None:
"""
+ Generate configuration dictionary for a given backend.
+
Custom implementation of the base method.
See base method for details.
@@ -765,6 +771,8 @@ def configure(
**kwargs: dict[str, type]
) -> None:
"""
+ Generate configuration dictionary for all backends.
+
Custom implementation of the base method.
:param threshold_filter: name of a preselected backend
@@ -774,6 +782,8 @@ def configure(
def find(self, needle: "Image", haystack: "Image") -> "list[Match]":
"""
+ Find all needle targets in a haystack image.
+
Custom implementation of the base method.
:param needle: target iamge to search for
@@ -971,6 +981,8 @@ def _extract_contours(
def log(self, lvl: int) -> None:
"""
+ Log images with an arbitrary logging level.
+
Custom implementation of the base method.
See base method for details.
@@ -1032,11 +1044,6 @@ def __init__(self, configure: bool = True, synchronize: bool = True) -> None:
def __configure_backend(
self, backend: str = None, category: str = "template", reset: bool = False
) -> None:
- """
- Custom implementation of the base method.
-
- See base method for details.
- """
if category != "template":
raise UnsupportedBackendError(
"Backend category '%s' is not supported" % category
@@ -1061,6 +1068,8 @@ def configure_backend(
self, backend: str = None, category: str = "template", reset: bool = False
) -> None:
"""
+ Generate configuration dictionary for a given backend.
+
Custom implementation of the base method.
See base method for details.
@@ -1069,6 +1078,8 @@ def configure_backend(
def find(self, needle: "Image", haystack: "Image") -> "list[Match]":
"""
+ Find all needle targets in a haystack image.
+
Custom implementation of the base method.
:param needle: target iamge to search for
@@ -1256,6 +1267,8 @@ def _match_template(
def log(self, lvl: int) -> None:
"""
+ Log images with an arbitrary logging level.
+
Custom implementation of the base method.
See base method for details.
@@ -1468,6 +1481,8 @@ def configure_backend(
self, backend: str = None, category: str = "feature", reset: bool = False
) -> None:
"""
+ Generate configuration dictionary for a given backend.
+
Custom implementation of the base method.
Some relevant parameters are:
@@ -1508,6 +1523,8 @@ def configure(
**kwargs: dict[str, type]
) -> None:
"""
+ Generate configuration dictionary for all backends.
+
Custom implementation of the base method.
:param feature_detect: name of a preselected backend
@@ -1584,6 +1601,8 @@ def synchronize_backend(
self, backend: str = None, category: str = "feature", reset: bool = False
) -> None:
"""
+ Synchronize a category backend with the equalizer configuration.
+
Custom implementation of the base method.
See base method for details.
@@ -1610,6 +1629,8 @@ def synchronize(
reset: bool = True,
) -> None:
"""
+ Synchronize all backends with the current configuration dictionary.
+
Custom implementation of the base method.
:param feature_detect: name of a preselected backend
@@ -1621,6 +1642,8 @@ def synchronize(
def find(self, needle: "Image", haystack: "Image") -> "list[Match]":
"""
+ Find all needle targets in a haystack image.
+
Custom implementation of the base method.
:param needle: target iamge to search for
@@ -1834,8 +1857,11 @@ def _match_features(
def ratio_test(matches: list[Any]) -> list[Any]:
"""
- The ratio test checks the first and second best match. If their
- ratio is close to 1.0, there are both good candidates for the
+ Perform a ratio test.
+
+ The ratio test checks the first and second best match.
+
+ If their ratio is close to 1.0, there are both good candidates for the
match and the probabilty of error when choosing one is greater.
Therefore these matches are ignored and thus only matches of
greater probabilty are returned.
@@ -1861,11 +1887,13 @@ def ratio_test(matches: list[Any]) -> list[Any]:
def symmetry_test(nmatches: list[Any], hmatches: list[Any]) -> list[Any]:
"""
- Refines the matches with a symmetry test which extracts
- only the matches in agreement with both the haystack and needle
- sets of keypoints. The two keypoints must be best feature
- matching of each other to ensure the error by accepting the
- match is not too large.
+ Perform a symmetry test.
+
+ The symmetry test refines the matches with a symmetry test which extracts
+ only in agreement with haystack and needle sets of keypoints.
+
+ The two keypoints must be best feature matching of each other
+ to ensure the error by accepting the match is not too large.
"""
import cv2
@@ -2030,6 +2058,8 @@ def _project_locations(
def log(self, lvl: int) -> None:
"""
+ Log images with an arbitrary logging level.
+
Custom implementation of the base method.
See base method for details.
@@ -2118,11 +2148,6 @@ def __init__(
def __configure_backend(
self, backend: str = None, category: str = "cascade", reset: bool = False
) -> None:
- """
- Custom implementation of the base method.
-
- See base method for details.
- """
if category != "cascade":
raise UnsupportedBackendError(
"Backend category '%s' is not supported" % category
@@ -2143,6 +2168,8 @@ def configure_backend(
self, backend: str = None, category: str = "cascade", reset: bool = False
) -> None:
"""
+ Generate configuration dictionary for a given backend.
+
Custom implementation of the base method.
See base method for details.
@@ -2151,6 +2178,8 @@ def configure_backend(
def find(self, needle: "Pattern", haystack: "Image") -> "list[Match]":
"""
+ Find all needle targets in a haystack image.
+
Custom implementation of the base method.
:param needle: target pattern (cascade) to search for
@@ -2266,11 +2295,6 @@ def __init__(self, configure: bool = True, synchronize: bool = True) -> None:
def __configure_backend(
self, backend: str = None, category: str = "text", reset: bool = False
) -> None:
- """
- Custom implementation of the base method.
-
- See base method for details.
- """
if category not in [
"text",
"tdetect",
@@ -2467,6 +2491,8 @@ def configure_backend(
self, backend: str = None, category: str = "text", reset: bool = False
) -> None:
"""
+ Generate configuration dictionary for a given backend.
+
Custom implementation of the base method.
See base method for details.
@@ -2501,6 +2527,8 @@ def configure(
**kwargs: dict[str, type]
) -> None:
"""
+ Generate configuration dictionary for all backends.
+
Custom implementation of the base method.
:param text_detector: name of a preselected backend
@@ -2701,6 +2729,8 @@ def synchronize_backend(
self, backend: str = None, category: str = "text", reset: bool = False
) -> None:
"""
+ Synchronize a category backend with the equalizer configuration.
+
Custom implementation of the base method.
See base method for details.
@@ -2734,6 +2764,8 @@ def synchronize(
reset: bool = True,
) -> None:
"""
+ Synchronize all backends with the current configuration dictionary.
+
Custom implementation of the base method.
:param text_detector: name of a preselected backend
@@ -2754,6 +2786,8 @@ def synchronize(
def find(self, needle: "Text", haystack: "Image") -> "list[Match]":
"""
+ Find all needle targets in a haystack image.
+
Custom implementation of the base method.
:param needle: target text to search for
@@ -3010,8 +3044,8 @@ def _detect_text_boxes(self, haystack: "Image") -> list[list[int]]:
return text_regions
def _detect_text_east(self, haystack: "Image") -> list[tuple[int, int, int, int]]:
- #:.. note:: source implementation by Adrian Rosebrock from his post:
- #: https://www.pyimagesearch.com/2018/08/20/opencv-text-detection-east-text-detector/
+ # :.. note:: source implementation by Adrian Rosebrock from his post:
+ # : https://www.pyimagesearch.com/2018/08/20/opencv-text-detection-east-text-detector/
import cv2
import numpy
@@ -3421,6 +3455,8 @@ def _detect_text_components(
def log(self, lvl: int) -> None:
"""
+ Log images with an arbitrary logging level.
+
Custom implementation of the base method.
See base method for details.
@@ -3533,6 +3569,8 @@ def configure_backend(
self, backend: str = None, category: str = "tempfeat", reset: bool = False
) -> None:
"""
+ Generate configuration dictionary for a given backend.
+
Custom implementation of the base method.
See base method for details.
@@ -3564,7 +3602,9 @@ def configure(
**kwargs: dict[str, type]
) -> None:
"""
- Custom implementation of the base methods.
+ Generate configuration dictionary for all backends.
+
+ Custom implementation of the base method.
See base methods for details.
"""
@@ -3580,6 +3620,8 @@ def synchronize(
reset: bool = True,
) -> None:
"""
+ Synchronize all backends with the current configuration dictionary.
+
Custom implementation of the base method.
See base method for details.
@@ -3595,6 +3637,8 @@ def synchronize(
def find(self, needle: "Image", haystack: "Image") -> "list[Match]":
"""
+ Find all needle targets in a haystack image.
+
Custom implementation of the base method.
See base method for details.
@@ -3766,6 +3810,8 @@ def find(self, needle: "Image", haystack: "Image") -> "list[Match]":
def log(self, lvl: int) -> None:
"""
+ Log images with an arbitrary logging level.
+
Custom implementation of the base method.
See base method for details.
@@ -3851,11 +3897,6 @@ def __init__(
def __configure_backend(
self, backend: str = None, category: str = "deep", reset: bool = False
) -> None:
- """
- Custom implementation of the base method.
-
- See base method for details.
- """
if category != "deep":
raise UnsupportedBackendError(
"Backend category '%s' is not supported" % category
@@ -3886,6 +3927,8 @@ def configure_backend(
self, backend: str = None, category: str = "deep", reset: bool = False
) -> None:
"""
+ Generate configuration dictionary for a given backend.
+
Custom implementation of the base method.
See base method for details.
@@ -3974,6 +4017,8 @@ def synchronize_backend(
self, backend: str = None, category: str = "deep", reset: bool = False
) -> None:
"""
+ Synchronize a category backend with the equalizer configuration.
+
Custom implementation of the base method.
See base method for details.
@@ -3982,6 +4027,8 @@ def synchronize_backend(
def find(self, needle: "Pattern", haystack: "Image") -> "list[Match]":
"""
+ Find all needle targets in a haystack image.
+
Custom implementation of the base method.
:param needle: target pattern (cascade) to search for
@@ -4008,14 +4055,17 @@ def find(self, needle: "Pattern", haystack: "Image") -> "list[Match]":
assert backend == "pytorch", "Only PyTorch model zoo/garden is supported"
import torch
- classes: Callable[[Any], str] = None
if needle.data_file is not None:
with open(needle.data_file, "rt") as f:
classes_list = [line.rstrip() for line in f.readlines()]
- classes = lambda x: classes_list[x]
+
+ def classes(x: int) -> str:
+ return classes_list[x]
+
else:
# an infinite list as a string identity map
- classes = lambda x: str(x)
+ def classes(x: Any) -> str:
+ return str(x)
# set the module in evaluation mode
self.net.eval()
@@ -4080,6 +4130,8 @@ def find(self, needle: "Pattern", haystack: "Image") -> "list[Match]":
def log(self, lvl: int) -> None:
"""
+ Log images with an arbitrary logging level.
+
Custom implementation of the base method.
See base method for details.
@@ -4174,6 +4226,8 @@ def configure_backend(
self, backend: str = None, category: str = "hybrid", reset: bool = False
) -> None:
"""
+ Generate configuration dictionary for a given backend.
+
Custom implementation of the base method.
See base method for details.
@@ -4217,6 +4271,8 @@ def synchronize_backend(
self, backend: str = None, category: str = "hybrid", reset: bool = False
) -> None:
"""
+ Synchronize a category backend with the equalizer configuration.
+
Custom implementation of the base method.
See base method for details.
@@ -4225,6 +4281,8 @@ def synchronize_backend(
def find(self, needle: "Image", haystack: "Image") -> "list[Match]":
"""
+ Find all needle targets in a haystack image.
+
Custom implementation of the base method.
See base method for details.
diff --git a/guibot/guibot.py b/guibot/guibot.py
index b4da4005..ce89282d 100644
--- a/guibot/guibot.py
+++ b/guibot/guibot.py
@@ -14,14 +14,13 @@
# along with guibot. If not, see .
"""
+Main guibot interface for GUI automation.
SUMMARY
------------------------------------------------------
-Main guibot interface for GUI automation.
This frontend is recommended for use in most normal cases.
-
INTERFACE
------------------------------------------------------
@@ -41,8 +40,7 @@
class GuiBot(Region):
"""
- The main guibot object is the root (first and screen wide) region
- with some convenience functions added.
+ The main guibot object is the root (first and screen wide) region with some convenience functions added.
.. seealso:: Real API is inherited from :py:class:`region.Region`.
"""
@@ -63,8 +61,7 @@ def __init__(self, dc: Controller = None, cv: Finder = None) -> None:
def add_path(self, directory: str) -> None:
"""
- Add a path to the list of currently accessible paths
- if it wasn't already added.
+ Add a path to the list of currently accessible paths if it wasn't already added.
:param directory: path to add
"""
diff --git a/guibot/guibot_proxy.py b/guibot/guibot_proxy.py
index ab1a1e0a..0a986e89 100644
--- a/guibot/guibot_proxy.py
+++ b/guibot/guibot_proxy.py
@@ -14,10 +14,10 @@
# along with guibot. If not, see .
"""
+Remote guibot interface for proxy operations using remote visual objects.
SUMMARY
------------------------------------------------------
-Remote guibot interface for proxy operations using remote visual objects.
Frontend with serialization compatible API allowing the use of PyRO modified
:py:class:`guibot.GuiBot` object (creating and running the same object
@@ -25,7 +25,6 @@
this object with some additional postprocessing to make the execution remote so
for information about the API please refer to it and :py:class:`region.Region`.
-
INTERFACE
------------------------------------------------------
@@ -49,8 +48,7 @@ def serialize_custom_error(
class_obj: type,
) -> dict[str, "str | getset_descriptor | dictproxy"]:
"""
- Serialization method for the :py:class:`errors.UnsupportedBackendError`
- which was chosen just as a sample.
+ Serialize the :py:class:`errors.UnsupportedBackendError` which was chosen just as a sample.
:param class_obj: class object for the serialized error class
:returns: serialization dictionary with the class name, arguments, and attributes
@@ -64,8 +62,7 @@ def serialize_custom_error(
def register_exception_serialization() -> None:
"""
- We put here any exceptions that are too complicated for the default serialization
- and define their serialization methods.
+ Register exceptions that are too complicated for the default serialization via own serialization methods.
.. note:: This would not be needed if we were using the Pickle serializer but its
security problems at the moment made us prefer the serpent serializer paying
@@ -79,8 +76,11 @@ def register_exception_serialization() -> None:
class GuiBotProxy(GuiBot):
"""
- The proxy guibot object is just a wrapper around the actual guibot
- object that takes care of returning easily serializable PyRO proxy objects
+ The proxy guibot object takes care of returning easily serializable PyRO proxy objects.
+
+ It is just a wrapper around the actual guibot object that replaces its real resulting objects with proxy ones.
+
+ This takes care of returning easily serializable PyRO proxy objects
instead of the real ones or their serialized copies.
It allows you to move the mouse, type text and do any other GuiBot action
diff --git a/guibot/guibot_simple.py b/guibot/guibot_simple.py
index 42678460..2f3ca0a1 100644
--- a/guibot/guibot_simple.py
+++ b/guibot/guibot_simple.py
@@ -14,17 +14,16 @@
# along with guibot. If not, see .
"""
+Simple guibot interface for short scripts, examples, and basic GUI automation.
SUMMARY
------------------------------------------------------
-Simple guibot interface for short scripts, examples, and basic GUI automation.
Frontend with simple procedural API allowing the use of a module instead of
the :py:class:`guibot.GuiBot` object (creating and running this same
object internally). All the methods delegate their calls to this object so
for information about the API please refer to it and :py:class:`region.Region`.
-
INTERFACE
------------------------------------------------------
diff --git a/guibot/imagelogger.py b/guibot/imagelogger.py
index 2a9f4702..f8ebc167 100644
--- a/guibot/imagelogger.py
+++ b/guibot/imagelogger.py
@@ -14,10 +14,10 @@
# along with guibot. If not, see .
"""
+Image logging for enhanced debugging and verbosity of guibot's operation.
SUMMARY
------------------------------------------------------
-Image logging for enhanced debugging and verbosity of guibot's operation.
INTERFACE
diff --git a/guibot/inputmap.py b/guibot/inputmap.py
index 8e7e5c8a..2a65741a 100644
--- a/guibot/inputmap.py
+++ b/guibot/inputmap.py
@@ -14,10 +14,10 @@
# along with guibot. If not, see .
"""
+Key mappings, modifiers, and mouse buttons.
SUMMARY
------------------------------------------------------
-Key mappings, modifiers, and mouse buttons.
INTERFACE
@@ -111,8 +111,7 @@ def __init__(self) -> None:
def to_string(self, key: str) -> str:
"""
- Provide with a text representation of a desired key
- according to the custom BC backend.
+ Provide with a text representation of a desired key according to the custom BC backend.
:param key: selected key name according to the custom backend
:returns: text representation of the selected key
@@ -556,8 +555,7 @@ def __init__(self) -> None:
def to_string(self, key: str) -> str:
"""
- Provide with a text representation of a desired modifier key
- according to the custom BC backend.
+ Provide with a text representation of a desired modifier key according to the custom BC backend.
:param key: selected modifier name according to the current backend
:returns: text representation of the selected modifier
@@ -650,8 +648,7 @@ def __init__(self) -> None:
def to_string(self, key: str) -> str:
"""
- Provide with a text representation of a desired mouse button
- according to the custom BC backend.
+ Provide with a text representation of a desired mouse button according to the custom BC backend.
:param key: selected mouse button according to the current backend
:returns: text representation of the selected mouse button
diff --git a/guibot/location.py b/guibot/location.py
index be75fb30..bdf92443 100644
--- a/guibot/location.py
+++ b/guibot/location.py
@@ -14,15 +14,14 @@
# along with guibot. If not, see .
"""
+Simple class to hold screen location data.
SUMMARY
------------------------------------------------------
-Simple class to hold screen location data.
..note:: Unless this class becomes more useful for the extra OOP abstraction
it might get deprecated in favor of a simple (x, y) tuple.
-
INTERFACE
------------------------------------------------------
diff --git a/guibot/match.py b/guibot/match.py
index 1864fe4e..8050035b 100644
--- a/guibot/match.py
+++ b/guibot/match.py
@@ -14,10 +14,10 @@
# along with guibot. If not, see .
"""
+Class and functionality related to target matches on screen.
SUMMARY
------------------------------------------------------
-Class and functionality related to target matches on screen.
INTERFACE
@@ -32,10 +32,7 @@
class Match(Region):
- """
- Wrapper around image which adds data necessary for manipulation
- of matches on a screen.
- """
+ """Wrapper around region which adds data necessary for manipulation of matches on a screen."""
def __init__(
self,
diff --git a/guibot/path.py b/guibot/path.py
index c865a2d7..33dee520 100644
--- a/guibot/path.py
+++ b/guibot/path.py
@@ -14,10 +14,10 @@
# along with guibot. If not, see .
"""
+Old module for path resolution - to be deprecated.
SUMMARY
------------------------------------------------------
-Old module for path resolution - to be deprecated.
INTERFACE
diff --git a/guibot/region.py b/guibot/region.py
index da5d0a60..6c63ff6a 100644
--- a/guibot/region.py
+++ b/guibot/region.py
@@ -14,17 +14,16 @@
# along with guibot. If not, see .
"""
+Secondary (and more advanced) interface for generic screen regions.
SUMMARY
------------------------------------------------------
-Secondary (and more advanced) interface for generic screen regions.
The main guibot interface is just a specialized region where we could match
and work with subregions. Any region instance can also be a complete screen,
hence the increased generality of using this as an interface and calling it
directly.
-
INTERFACE
------------------------------------------------------
@@ -32,6 +31,7 @@
import time
import os
+import logging
# interconnected classes - carefully avoid circular reference
from .config import GlobalConfig
@@ -42,15 +42,15 @@
from .finder import *
from .controller import *
-import logging
log = logging.getLogger("guibot.region")
class Region(object):
"""
- Region of the screen supporting vertex and nearby region selection,
- validation of expected images, and mouse and keyboard control.
+ Region of the screen at a given position and with a given size.
+
+ It supports vertex and nearby region selection, validation of expected images, and mouse and keyboard control.
"""
def __init__(
@@ -293,8 +293,7 @@ def get_mouse_location(self) -> Location:
def nearby(self, rrange: int = 50) -> "Region":
"""
- Obtain a region containing the previous one but enlarged
- by a number of pixels on each side.
+ Obtain a region containing the previous one but enlarged by a number of pixels on each side.
:param rrange: number of pixels to add
:returns: new region enlarged by `rrange` on all sides
@@ -318,8 +317,7 @@ def nearby(self, rrange: int = 50) -> "Region":
def above(self, rrange: int = 0) -> "Region":
"""
- Obtain a region containing the previous one but enlarged
- by a number of pixels on the upper side.
+ Obtain an enlarged region by a number of pixels on the upper side.
:param rrange: number of pixels to add
:returns: new region enlarged by `rrange` on upper side
@@ -347,8 +345,7 @@ def above(self, rrange: int = 0) -> "Region":
def below(self, rrange: int = 0) -> "Region":
"""
- Obtain a region containing the previous one but enlarged
- by a number of pixels on the lower side.
+ Obtain an enlarged region by a number of pixels on the lower side.
:param rrange: number of pixels to add
:returns: new region enlarged by `rrange` on lower side
@@ -371,8 +368,7 @@ def below(self, rrange: int = 0) -> "Region":
def left(self, rrange: int = 0) -> "Region":
"""
- Obtain a region containing the previous one but enlarged
- by a number of pixels on the left side.
+ Obtain an enlarged region by a number of pixels on the left side..
:param rrange: number of pixels to add
:returns: new region enlarged by `rrange` on left side
@@ -400,8 +396,7 @@ def left(self, rrange: int = 0) -> "Region":
def right(self, rrange: int = 0) -> "Region":
"""
- Obtain a region containing the previous one but enlarged
- by a number of pixels on the right side.
+ Obtain an enlarged region by a number of pixels on the right side.
:param rrange: number of pixels to add
:returns: new region enlarged by `rrange` on right side
@@ -495,14 +490,14 @@ def find_all(
moving_targets = True
last_matches.append(new_match)
self._last_match = last_matches[-1]
- if not GlobalConfig.wait_for_animations == True or not moving_targets:
+ if GlobalConfig.wait_for_animations is not True or not moving_targets:
return last_matches
elif time.time() > timeout_limit:
if allow_zero:
return last_matches
else:
- if GlobalConfig.save_needle_on_error == True:
+ if GlobalConfig.save_needle_on_error is True:
if not os.path.exists(ImageLogger.logging_destination):
os.mkdir(ImageLogger.logging_destination)
dump_path = GlobalConfig.image_logging_destination
@@ -555,8 +550,9 @@ def _determine_cv_backend(self, target: Target) -> "Match":
def sample(self, target: str | Target) -> float:
"""
- Sample the similarity between a target and the screen,
- i.e. an empirical probability that the target is on the screen.
+ Sample the similarity between a target and the screen.
+
+ Similarity here means an empirical probability that the target is on the screen.
:param target: target to look for
:returns: similarity with best match on the screen
@@ -577,8 +573,7 @@ def sample(self, target: str | Target) -> float:
def exists(self, target: str | Target, timeout: int = 0) -> "Match | None":
"""
- Check if a target exists on the screen using the matching
- success as a threshold for the existence.
+ Check if a target exists on the screen using similarity as a threshold.
:param target: target to look for
:param timeout: timeout before giving up
@@ -594,8 +589,7 @@ def exists(self, target: str | Target, timeout: int = 0) -> "Match | None":
def wait(self, target: str | Target, timeout: int = 30) -> "Match":
"""
- Wait for a target to appear (be matched) with a given timeout
- as failing tolerance.
+ Wait for a target to appear (be matched) with a given timeout as failing tolerance.
:param target: target to look for
:param timeout: timeout before giving up
@@ -607,8 +601,7 @@ def wait(self, target: str | Target, timeout: int = 30) -> "Match":
def wait_vanish(self, target: str | Target, timeout: int = 30) -> "Region":
"""
- Wait for a target to disappear (be unmatched, i.e. matched
- without success) with a given timeout as failing tolerance.
+ Wait for a target to disappear (be unmatched) with a given timeout as failing tolerance.
:param target: target to look for
:param timeout: timeout before giving up
@@ -683,8 +676,9 @@ def click(
modifiers: list[str] = None,
) -> "Match | None":
"""
- Click on a target or location using the left mouse button and
- optionally holding special keys.
+ Click on a target or location using the left mouse button.
+
+ Optionally we can hold some special keys.
:param target_or_location: target or location to click on
:param modifiers: special keys to hold during clicking
@@ -708,8 +702,9 @@ def right_click(
modifiers: list[str] = None,
) -> "Match | None":
"""
- Click on a target or location using the right mouse button and
- optionally holding special keys.
+ Click on a target or location using the right mouse button.
+
+ Optionally we can hold some special keys.
Arguments and return values are analogical to :py:func:`Region.click`.
"""
@@ -726,8 +721,9 @@ def middle_click(
modifiers: list[str] = None,
) -> "Match | None":
"""
- Click on a target or location using the middle mouse button and
- optionally holding special keys.
+ Click on a target or location using the middle mouse button.
+
+ Optionally we can hold some special keys.
Arguments and return values are analogical to :py:func:`Region.click`.
"""
@@ -744,8 +740,7 @@ def double_click(
modifiers: list[str] = None,
) -> "Match | None":
"""
- Double click on a target or location using the left mouse button
- and optionally holding special keys.
+ Double click on a target or location using the left mouse button special keys.
Arguments and return values are analogical to :py:func:`Region.click`.
"""
@@ -763,8 +758,9 @@ def multi_click(
modifiers: list[str] = None,
) -> "Match | None":
"""
- Click N times on a target or location using the left mouse button
- and optionally holding special keys.
+ Click N times on a target or location using the left mouse button.
+
+ Optionally we can hold some special keys.
Arguments and return values are analogical to :py:func:`Region.click`.
"""
@@ -843,8 +839,7 @@ def click_at_index(
timeout: int = 10,
) -> "Match":
"""
- Find all instances of an anchor image and click on the one with the
- desired index given that they are horizontally then vertically sorted.
+ Find and click on a specific instance of an anchor image indexed by horizontal and vertical sorting.
:param anchor: image to find all matches of
:param index: index of the match to click on (assuming >=1 matches),
@@ -1048,8 +1043,7 @@ def press_at(
target_or_location: "Match | Location | str | Target",
) -> "Match":
"""
- Press a single key or a list of keys simultaneously
- at a specified target or location.
+ Press a single key or a list of keys simultaneously at a specified target or location.
This method is similar to :py:func:`Region.press_keys` but
with an extra argument like :py:func:`Region.click`.
@@ -1192,8 +1186,9 @@ def type_at(
modifiers: list[str] = None,
) -> "Match":
"""
- Type a list of consecutive character keys (without special keys)
- at a specified target or location.
+ Type a list of consecutive keys at a specified target or location.
+
+ These are meant to be characters and not special keys.
This method is similar to :py:func:`Region.type_text` but
with an extra argument like :py:func:`Region.click`.
@@ -1277,7 +1272,7 @@ def fill_at(
mark_clicks: int = 1,
) -> "Region":
"""
- Fills a new text at a text box using a displacement from an anchor.
+ Fill a new text at a text box using a displacement from an anchor.
:param anchor: target of reference for the input field
:param text: text to fill in
@@ -1336,8 +1331,10 @@ def select_at(
tries: int = 3,
) -> "Region":
"""
- Select an option at a dropdown list using either an integer index
- or an option image if the order cannot be easily inferred.
+ Select an option at a dropdown list using an index or an image.
+
+ The caller can use either integer index or an option image if the
+ order cannot be easily inferred.
:param anchor: target of reference for the input dropdown menu
:param image_or_index: item image or item index
diff --git a/guibot/target.py b/guibot/target.py
index d89cad46..93c9227f 100644
--- a/guibot/target.py
+++ b/guibot/target.py
@@ -14,10 +14,10 @@
# along with guibot. If not, see .
"""
+Classes and functionality related to sought targets on screen.
SUMMARY
------------------------------------------------------
-Classes and functionality related to sought targets on screen.
INTERFACE
@@ -42,10 +42,7 @@
class Target(object):
- """
- Target used to obtain screen location for clicking, typing,
- validation of expected visual output, etc.
- """
+ """Target used to obtain screen location for clicking, typing, validation of expected visual output, etc."""
@staticmethod
def from_data_file(filename: str) -> "Target":
@@ -212,8 +209,7 @@ def copy(self) -> "Target":
def with_center_offset(self, xpos: int, ypos: int) -> "Target":
"""
- Perform a copy of the target data with new match settings
- and with a newly defined center offset.
+ Perform a copy of the target data with new match settings and with a newly defined center offset.
:param xpos: new offset in the x direction
:param ypos: new offset in the y direction
@@ -225,8 +221,7 @@ def with_center_offset(self, xpos: int, ypos: int) -> "Target":
def with_similarity(self, new_similarity: float) -> "Target":
"""
- Perform a copy of the target data with new match settings
- and with a newly defined required similarity.
+ Perform a copy of the target data with new match settings and with a newly defined required similarity.
:param new_similarity: new required similarity
:returns: copy of the current target with new similarity
@@ -237,10 +232,7 @@ def with_similarity(self, new_similarity: float) -> "Target":
class Image(Target):
- """
- Container for image data supporting caching, clicking target,
- file operations, and preprocessing.
- """
+ """Container for image data supporting caching, clicking target, file operations, and preprocessing."""
_cache = {}
@@ -371,10 +363,7 @@ def save(self, filename: str) -> "Image":
class Text(Target):
- """
- Container for text data which is visually identified
- using OCR or general text detection methods.
- """
+ """Container for text data which is visually identified using OCR or general text detection methods."""
def __init__(
self,
@@ -454,10 +443,7 @@ def distance_to(self, str2: str) -> float:
class Pattern(Target):
- """
- Container for abstracted data which is obtained from
- training of a classifier in order to recognize a target.
- """
+ """Container for abstracted data which is obtained from training of a classifier in order to recognize a target."""
def __init__(self, id: str, match_settings: "Finder" = None) -> None:
"""