diff --git a/sikuli/script/finder.py b/sikuli/script/finder.py index 7784088..4818a41 100644 --- a/sikuli/script/finder.py +++ b/sikuli/script/finder.py @@ -10,7 +10,9 @@ def __init__(self, filename: str): self.filename = filename def find(self, filename: str, similarity: float = 0.7): - raise NotImplementedError("Finder.find(%r, %r) not implemented" % (filename, similarity)) # FIXME + raise NotImplementedError( + "Finder.find(%r, %r) not implemented" % (filename, similarity) + ) # FIXME def hasNext(self) -> bool: raise NotImplementedError("Finder.hasNext() not implemented") # FIXME diff --git a/sikuli/script/match.py b/sikuli/script/match.py index 1d0caf2..6ab73f0 100644 --- a/sikuli/script/match.py +++ b/sikuli/script/match.py @@ -1,6 +1,7 @@ """ http://doc.sikuli.org/match.html """ + import typing as t from .region import Region diff --git a/sikuli/script/rectangle.py b/sikuli/script/rectangle.py index 0bc97da..44da165 100644 --- a/sikuli/script/rectangle.py +++ b/sikuli/script/rectangle.py @@ -23,7 +23,13 @@ def __repr__(self) -> str: ) def __eq__(self, b: object) -> bool: - return isinstance(b, Rectangle) and self.x == b.x and self.y == b.y and self.w == b.w and self.h == b.h + return ( + isinstance(b, Rectangle) + and self.x == b.x + and self.y == b.y + and self.w == b.w + and self.h == b.h + ) def __ne__(self, b: object) -> bool: return not self.__eq__(b) diff --git a/sikuli/script/region.py b/sikuli/script/region.py index 7497fa1..0eef547 100644 --- a/sikuli/script/region.py +++ b/sikuli/script/region.py @@ -51,7 +51,9 @@ def __init__(self, rect, b=None, c=None, d=None): @unofficial def freeze(self) -> None: - self._frozen = Robot.capture((int(self.x), int(self.y), int(self.w), int(self.h))) + self._frozen = Robot.capture( + (int(self.x), int(self.y), int(self.w), int(self.h)) + ) @unofficial def thaw(self) -> None: @@ -139,7 +141,9 @@ def findAll(self, target: t.Union[Pattern, str]) -> List["Match"]: if not isinstance(target, Pattern): target = Pattern(target) - region = self._frozen or Robot.capture((int(self.x), int(self.y), int(self.w), int(self.h))) + region = self._frozen or Robot.capture( + (int(self.x), int(self.y), int(self.w), int(self.h)) + ) matches = [] from .match import Match @@ -200,7 +204,9 @@ def findAll(self, target: t.Union[Pattern, str]) -> List["Match"]: self._last_matches = matches return matches - def wait(self, target: t.Union[Pattern, str], seconds: t.Optional[float] = None) -> "Match": + def wait( + self, target: t.Union[Pattern, str], seconds: t.Optional[float] = None + ) -> "Match": until = time() + (seconds or self.autoWaitTimeout) while True: x = self.find(target) @@ -212,7 +218,9 @@ def wait(self, target: t.Union[Pattern, str], seconds: t.Optional[float] = None) raise FindFailed() - def waitVanish(self, target: t.Union[Pattern, str], seconds: t.Optional[float] = None) -> bool: + def waitVanish( + self, target: t.Union[Pattern, str], seconds: t.Optional[float] = None + ) -> bool: until = time() + (seconds or self.autoWaitTimeout) while True: if not self.find(target): @@ -257,12 +265,16 @@ def stopObserver(self) -> None: # actions - def _targetOrLast(self, target: t.Optional[t.Union[Pattern, str]]) -> t.Union[Pattern, str, Match]: + def _targetOrLast( + self, target: t.Optional[t.Union[Pattern, str]] + ) -> t.Union[Pattern, str, Match]: if target is None: return self.getLastMatch() return target - def _toLocation(self, target: t.Union[Pattern, str, Rectangle, Location]) -> Location: + def _toLocation( + self, target: t.Union[Pattern, str, Rectangle, Location] + ) -> Location: if isinstance(target, str): target = Pattern(target) if isinstance(target, Pattern): @@ -282,7 +294,9 @@ def mouseUp(self, button): Robot.mouseUp(button) def mouseMove( - self, target: t.Optional[t.Union[Pattern, str]], _delay: t.Optional[float] = None + self, + target: t.Optional[t.Union[Pattern, str]], + _delay: t.Optional[float] = None, ) -> Tuple[float, float]: if _delay is None: _delay = Settings.MoveMouseDelay @@ -310,7 +324,11 @@ def wheel(self, target: t.Optional[t.Union[Pattern, str]], button, steps=1): self.mouseUp(button) sleep(0.1) - def click(self, target: t.Optional[t.Union[Pattern, str]] = None, modifiers: t.Optional[int] = None) -> int: + def click( + self, + target: t.Optional[t.Union[Pattern, str]] = None, + modifiers: t.Optional[int] = None, + ) -> int: # FIXME: modifiers self.mouseMove(target) self.mouseDown(Mouse.LEFT) @@ -319,7 +337,9 @@ def click(self, target: t.Optional[t.Union[Pattern, str]] = None, modifiers: t.O return 1 # no. of clicks def doubleClick( - self, target: t.Optional[t.Union[Pattern, str]] = None, modifiers: t.Optional[int] = None + self, + target: t.Optional[t.Union[Pattern, str]] = None, + modifiers: t.Optional[int] = None, ) -> int: # FIXME: modifiers self.mouseMove(target) @@ -333,7 +353,9 @@ def doubleClick( return 1 # no. of double clicks def rightClick( - self, target: t.Optional[t.Union[Pattern, str]] = None, modifiers: t.Optional[int] = None + self, + target: t.Optional[t.Union[Pattern, str]] = None, + modifiers: t.Optional[int] = None, ) -> int: # FIXME: modifiers self.mouseMove(target) @@ -366,7 +388,11 @@ def drag(self, target: t.Optional[t.Union[Pattern, str]] = None) -> None: sleep(Settings.DelayBeforeMouseDown) self.mouseDown(Mouse.LEFT) - def dropAt(self, target: t.Optional[t.Union[Pattern, str]] = None, delay: t.Optional[float] = None) -> None: + def dropAt( + self, + target: t.Optional[t.Union[Pattern, str]] = None, + delay: t.Optional[float] = None, + ) -> None: self.mouseMove(target) if delay is not None: sleep(delay) @@ -403,7 +429,11 @@ def type( Robot.type(text, modifiers) - def paste(self, target: t.Optional[t.Union[Pattern, str]] = None, text: t.Optional[str] = None) -> None: + def paste( + self, + target: t.Optional[t.Union[Pattern, str]] = None, + text: t.Optional[str] = None, + ) -> None: """ Paste the text at a click point. @@ -426,7 +456,9 @@ def text(self) -> str: try: import pytesseract # EXT - pil = Robot.capture((int(self.x), int(self.y), int(self.w), int(self.h))).img + pil = Robot.capture( + (int(self.x), int(self.y), int(self.w), int(self.h)) + ).img cvimg = cv2.cvtColor(np.array(pil.convert("RGB")), cv2.COLOR_RGB2BGR) _, cvimg = cv2.threshold(cvimg, 127, 255, cv2.THRESH_BINARY) # cvimg = cv.adaptiveThreshold( diff --git a/sikuli/script/robot.py b/sikuli/script/robot.py index 27d06ca..84528bf 100644 --- a/sikuli/script/robot.py +++ b/sikuli/script/robot.py @@ -147,9 +147,7 @@ def focus(application: str) -> None: perform action "AXRaise" of (windows whose title is theTitle) end tell end tell -""" % application.encode( - "ascii" - ) +""" % application.encode("ascii") subprocess.run("osascript", input=script, shell=True) elif PLATFORM == Platform.LINUX: p = subprocess.Popen( diff --git a/test/test-osx-grab.py b/test/test-osx-grab.py index d6989cf..62478bf 100644 --- a/test/test-osx-grab.py +++ b/test/test-osx-grab.py @@ -1,11 +1,10 @@ - import Quartz import LaunchServices from Cocoa import NSURL import Quartz.CoreGraphics as CG -def screenshot(path, region = None): +def screenshot(path, region=None): """region should be a CGRect, something like: >>> import Quartz.CoreGraphics as CG @@ -24,38 +23,38 @@ def screenshot(path, region = None): region, CG.kCGWindowListOptionOnScreenOnly, CG.kCGNullWindowID, - CG.kCGWindowImageDefault) + CG.kCGWindowImageDefault, + ) - dpi = 72 # FIXME: Should query this from somewhere, e.g for retina displays + dpi = 72 # FIXME: Should query this from somewhere, e.g for retina displays url = NSURL.fileURLWithPath_(path) dest = Quartz.CGImageDestinationCreateWithURL( url, - LaunchServices.kUTTypePNG, # file type - 1, # 1 image in file - None - ) + LaunchServices.kUTTypePNG, # file type + 1, # 1 image in file + None, + ) properties = { Quartz.kCGImagePropertyDPIWidth: dpi, Quartz.kCGImagePropertyDPIHeight: dpi, - } + } # Add the image to the destination, characterizing the image with # the properties dictionary. Quartz.CGImageDestinationAddImage(dest, image, properties) - # When all the images (only 1 in this example) are added to the destination, - # finalize the CGImageDestination object. + # When all the images (only 1 in this example) are added to the destination, + # finalize the CGImageDestination object. Quartz.CGImageDestinationFinalize(dest) -if __name__ == '__main__': +if __name__ == "__main__": # Capture full screen screenshot("/tmp/testscreenshot_full.png") # Capture region (100x100 box from top-left) region = CG.CGRectMake(0, 0, 100, 100) screenshot("/tmp/testscreenshot_partial.png", region=region) - diff --git a/test/unit/test_rectangle.py b/test/unit/test_rectangle.py index 5a6f6ab..89e3fe2 100644 --- a/test/unit/test_rectangle.py +++ b/test/unit/test_rectangle.py @@ -1,26 +1,17 @@ - import unittest from sikuli import Rectangle, Location + class TestRectangle(unittest.TestCase): def test_rect(self): r = Rectangle(0, 10, 20, 30) - self.assertEqual( - (r.x, r.y, r.w, r.h), - (0, 10, 20, 30) - ) + self.assertEqual((r.x, r.y, r.w, r.h), (0, 10, 20, 30)) def test_moveTo(self): r = Rectangle(0, 10, 20, 30) r.moveTo(Location(5, 15)) - self.assertEqual( - (r.x, r.y, r.w, r.h), - (5, 15, 20, 30) - ) + self.assertEqual((r.x, r.y, r.w, r.h), (5, 15, 20, 30)) def test_getCenter(self): r = Rectangle(0, 10, 20, 30) - self.assertEqual( - r.getCenter(), - Location(10, 25) - ) + self.assertEqual(r.getCenter(), Location(10, 25))