diff --git a/coverage.svg b/coverage.svg index d79e240..eb83f3f 100644 --- a/coverage.svg +++ b/coverage.svg @@ -9,13 +9,13 @@ - + coverage coverage - 65% - 65% + 59% + 59% diff --git a/lackey/ImportHandler.py b/lackey/ImportHandler.py new file mode 100644 index 0000000..d48ed9a --- /dev/null +++ b/lackey/ImportHandler.py @@ -0,0 +1,56 @@ +import sys +import os.path + +if sys.version_info[0] == 3: + from importlib.abc import MetaPathFinder + from importlib.util import spec_from_file_location + from importlib.machinery import SourceFileLoader + + class SikuliFinder(MetaPathFinder): + def find_spec(self, fullname, path, target=None): + if "." in fullname: + name = fullname.split(".")[-1] + else: + name = fullname + for entry in sys.path: + if entry == "": + entry = os.getcwd() + sikuli_path = os.path.join(entry, "{}.sikuli".format(name)) + filename = os.path.join(sikuli_path, "{}.py".format(name)) + if not os.path.exists(filename): + continue + + # Found what we're looking for. Add to path. + sys.path.append(sikuli_path) + + return spec_from_file_location(fullname, filename, loader=SourceFileLoader(fullname, filename), + submodule_search_locations=None) + + return None # we don't know how to import this + sys.meta_path.append(SikuliFinder()) +elif sys.version_info[0] == 2: + import imp + + class SikuliFinder(object): + def __init__(self, path): + self.path = path + + @classmethod + def find_module(cls, name, path=None): + for entry in sys.path: + sikuli_path = os.path.join(entry, "{}.sikuli".format(name)) + filename = os.path.join(sikuli_path, "{}.py".format(name)) + if not os.path.exists(filename): + continue + + # Found what we're looking for. Add to path. + sys.path.append(sikuli_path) + return cls(filename) + + def load_module(self, name): + if name in sys.modules: + return sys.modules[name] + with open(self.path, "r") as project: + mod = imp.load_module(name, project, self.path, (".py", "r", imp.PY_SOURCE)) + return mod + sys.meta_path.append(SikuliFinder) \ No newline at end of file diff --git a/lackey/RegionMatching.py b/lackey/RegionMatching.py index e1988b0..2061314 100644 --- a/lackey/RegionMatching.py +++ b/lackey/RegionMatching.py @@ -99,7 +99,7 @@ def setFilename(self, filename): """ Set the filename of the pattern's image (and load it) """ ## Loop through image paths to find the image found = False - for image_path in [Settings.BundlePath, os.getcwd()] + Settings.ImagePaths: + for image_path in sys.path + [Settings.BundlePath, os.getcwd()] + Settings.ImagePaths: full_path = os.path.join(image_path, filename) if os.path.exists(full_path): # Image file not found @@ -1015,33 +1015,38 @@ def write(self, text): def delayType(millisecs): Settings.TypeDelay = millisecs def isRegionValid(self): - """ Returns false if the whole region is outside any screen, otherwise true """ + """ Returns false if the whole region is not even partially inside any screen, otherwise true """ screens = PlatformManager.getScreenDetails() for screen in screens: s_x, s_y, s_w, s_h = screen["rect"] - if (self.x+self.w < s_x or s_x+s_w < self.x or self.y+self.h < s_y or s_y+s_h < self.y): + if self.x+self.w >= s_x and s_x+s_w >= self.x and self.y+self.h >= s_y and s_y+s_h >= self.y: # Rects overlap - return False - return True + return True + return False def clipRegionToScreen(self): """ Returns the part of the region that is visible on a screen + If the region equals to all visible screens, returns Screen(-1). If the region is visible on multiple screens, returns the screen with the smallest ID. Returns None if the region is outside the screen. """ if not self.isRegionValid(): return None screens = PlatformManager.getScreenDetails() + total_x, total_y, total_w, total_h = Screen(-1).getBounds() containing_screen = None for screen in screens: s_x, s_y, s_w, s_h = screen["rect"] if self.x >= s_x and self.x+self.w <= s_x+s_w and self.y >= s_y and self.y+self.h <= s_y+s_h: # Region completely inside screen return self - elif self.x+self.w < s_x or s_x+s_w < self.x or self.y+self.h < s_y or s_y+s_h < self.y: + elif self.x+self.w <= s_x or s_x+s_w <= self.x or self.y+self.h <= s_y or s_y+s_h <= self.y: # Region completely outside screen continue + elif self.x == total_x and self.y == total_y and self.w == total_w and self.h == total_h: + # Region equals all screens, Screen(-1) + return self else: # Region partially inside screen x = max(self.x, s_x) @@ -1903,7 +1908,7 @@ def showMonitors(cls): Debug.info("*** monitor configuration [ {} Screen(s)] ***".format(cls.getNumberScreens())) Debug.info("*** Primary is Screen {}".format(cls.primaryScreen)) for index, screen in enumerate(PlatformManager.getScreenDetails()): - Debug.info("Screen {}: ({}, {}, {}, {})".format(index, *screen[rect])) + Debug.info("Screen {}: ({}, {}, {}, {})".format(index, *screen["rect"])) Debug.info("*** end monitor configuration ***") def resetMonitors(self): """ Recalculates screen based on changed monitor setup """ diff --git a/lackey/__init__.py b/lackey/__init__.py index 7e76eb4..a4ff92f 100644 --- a/lackey/__init__.py +++ b/lackey/__init__.py @@ -38,6 +38,8 @@ from .SikuliGui import PopupInput, PopupList, PopupTextarea from ._version import __version__ +from . import ImportHandler + VALID_PLATFORMS = ["Windows", "Darwin"] ## Define script abort hotkey (Alt+Shift+C) diff --git a/lackey/_version.py b/lackey/_version.py index 39c4d75..7bf37e0 100644 --- a/lackey/_version.py +++ b/lackey/_version.py @@ -2,5 +2,5 @@ """ -__version__ = "0.7.0" +__version__ = "0.7.1" __sikuli_version__ = "1.1.0" diff --git a/tests/preview_open_2.png b/tests/preview_open_2.png new file mode 100644 index 0000000..9c50113 Binary files /dev/null and b/tests/preview_open_2.png differ diff --git a/tests/test_cases.py b/tests/test_cases.py index 4d0a816..9f6df5d 100644 --- a/tests/test_cases.py +++ b/tests/test_cases.py @@ -70,6 +70,15 @@ def setUp(self): lackey.Screen(0).hover() lackey.Screen(0).click() + def testImporter(self): + """ Tries to import the test_cases project file + (ignores FindFailed exception thrown by project) """ + try: + sys.path.append(os.path.join(os.getcwd(), "tests")) + import test_import + except lackey.FindFailed: + pass + def testTypeCopyPaste(self): """ Also tests the log file """ lackey.Debug.setLogFile("logfile.txt") @@ -90,8 +99,8 @@ def testTypeCopyPaste(self): app = lackey.App("+open -e") lackey.sleep(2) #r.debugPreview() - r.wait(lackey.Pattern("preview_open.png"), lackey.FOREVER) - r.click(lackey.Pattern("preview_open.png")) + r.wait(lackey.Pattern("preview_open_2.png")) + r.click(lackey.Pattern("preview_open_2.png")) lackey.type("n", lackey.KeyModifier.CMD) time.sleep(1) app = lackey.App("Untitled") @@ -129,7 +138,7 @@ def test_observer(appear_event): r.doubleClick("notepad.png") elif sys.platform == "darwin": r.doubleClick("textedit.png") - r.wait("preview_open.png") + r.wait("preview_open_2.png") r.type("n", lackey.KeyModifier.CMD) time.sleep(2) r.type("This is a test") @@ -153,7 +162,7 @@ def test_observer(appear_event): r.type("{F4}", lackey.Key.ALT) elif sys.platform == "darwin": r.type("w", lackey.KeyModifier.CMD) - r.click(lackey.Pattern("textedit_save.png").targetOffset(-86, 41)) + r.click(lackey.Pattern("textedit_save_2.png").targetOffset(-86, 25)) lackey.sleep(0.5) r.type("q", lackey.KeyModifier.CMD) diff --git a/tests/test_import.sikuli/1514401659995.png b/tests/test_import.sikuli/1514401659995.png new file mode 100755 index 0000000..5b336fc Binary files /dev/null and b/tests/test_import.sikuli/1514401659995.png differ diff --git a/tests/test_import.sikuli/test.html b/tests/test_import.sikuli/test.html new file mode 100755 index 0000000..89a25ac --- /dev/null +++ b/tests/test_import.sikuli/test.html @@ -0,0 +1,76 @@ + + + + + + +
+

test.sikuli

(Download this script) +
+
+find()
+
+ + diff --git a/tests/test_import.sikuli/test_import.py b/tests/test_import.sikuli/test_import.py new file mode 100755 index 0000000..6431bf1 --- /dev/null +++ b/tests/test_import.sikuli/test_import.py @@ -0,0 +1,4 @@ +import sys +from lackey import * + +find("1514401659995.png") diff --git a/tests/textedit_save_2.png b/tests/textedit_save_2.png new file mode 100644 index 0000000..fcb0a94 Binary files /dev/null and b/tests/textedit_save_2.png differ