Sikuli wrapper

Asked by Snezhana

I have simple sikuli wrapper to log screenshots of patter in region to robot framework log. Originally copied by http://blog.mykhailo.com/2011/02/how-to-sikuli-and-robot-framework.html but slightly changed.

When I use region, which defined and saved in my regions.sikuli file, this wrapper works.
But if the region is created in code, like
region1.find(capture1).left().click(capture2)
it doesn't go through wrapper.
I've tried to save and print it:
r = region1.find(capture1).left()
print r
r.click(capture2)

print showed that r is a proper region (Region[0,270 254x43]@Screen(0)[0,0 1280x800] E:Y, T:3.0 E:Y, T:3.0), so r.click is a Region.click and it should go through wrapper.. but it didn't

Please help me make wrapper work with such cases as region1.find(capture1).left().click(capture2)

here is log from first case, when it goes through wrapper and I got screenshots, you an see sikuliwrapper is used:
FindFailed:
  Line 370, in file C:\Python27\Lib\site-packages\robot\run.py
 at org.sikuli.script.Region.handleFindFailed(Region.java:421)
 at org.sikuli.script.Region.wait(Region.java:512)
 at sikuli.Region$py.wait$5(C:\Program Files\Sikuli X\sikuli-script.jar\Lib\sikuli\Region.py:102)
 at sikuli.Region$py.call_function(C:\Program Files\Sikuli X\sikuli-script.jar\Lib\sikuli\Region.py)
 at org.sikuli.script.Region.find(Region.java:382)
 at sikuliwrapper$py.find$5(c:\robot\libs\sikuliwrapper.py:46)
 at sikuliwrapper$py.call_function(c:\robot\libs\sikuliwrapper.py)
 at org.sikuli.script.Region.getLocationFromPSRML(Region.java:1134)
 at org.sikuli.script.Region.click(Region.java:607)
 at sikuliwrapper$py.click$4(c:\robot\libs\sikuliwrapper.py:38)
 at sikuliwrapper$py.call_function(c:\robot\libs\sikuliwrapper.py)
 at pvalib$py.select_vt$15(c:\robot\libs\pvalib.sikuli\pvalib.py:136)
 at pvalib$py.call_function(c:\robot\libs\pvalib.sikuli\pvalib.py)
 at robot.utils.application$py._execute$10(C:\Python27\Lib\site-packages\robot\utils\application.py:88)
 at robot.utils.application$py.call_function(C:\Python27\Lib\site-packages\robot\utils\application.py)
 at robot.utils.application$py.execute_cli$5(C:\Python27\Lib\site-packages\robot\utils\application.py:45)
 at robot.utils.application$py.call_function(C:\Python27\Lib\site-packages\robot\utils\application.py)

and here is log of the second case:
FindFailed:
  Line 370, in file C:\Python27\Lib\site-packages\robot\run.py
 at org.sikuli.script.Region.handleFindFailed(Region.java:421)
 at org.sikuli.script.Region.wait(Region.java:512)
 at sikuli.Region$py.wait$5(C:\Program Files\Sikuli X\sikuli-script.jar\Lib\sikuli\Region.py:102)
 at sikuli.Region$py.call_function(C:\Program Files\Sikuli X\sikuli-script.jar\Lib\sikuli\Region.py)
 at org.sikuli.script.Region.find(Region.java:382)
 at org.sikuli.script.Region.getLocationFromPSRML(Region.java:1134)
 at org.sikuli.script.Region.click(Region.java:607)
 at org.sikuli.script.Region.click(Region.java:594)
 at pvalib$py.select_vt$15(c:\robot\libs\pvalib.sikuli\pvalib.py:135)
 at pvalib$py.call_function(c:\robot\libs\pvalib.sikuli\pvalib.py)
 at robot.utils.application$py._execute$10(C:\Python27\Lib\site-packages\robot\utils\application.py:88)
 at robot.utils.application$py.call_function(C:\Python27\Lib\site-packages\robot\utils\application.py)
 at robot.utils.application$py.execute_cli$5(C:\Python27\Lib\site-packages\robot\utils\application.py:45)
 at robot.utils.application$py.call_function(C:\Python27\Lib\site-packages\robot\utils\application.py)

and here is sikuliwrapper.py:

import common
from logger import *
from sikuli.Sikuli import Region as SikuliRegion

# enable slow motion if debug log level enabled
if common.cfgLoggingLevel.lower() == 'debug':
    setShowActions(True)

# =============================================== #
# Overwritten sikuli methods #
# =============================================== #

# function for calling native sikuli methods
def sikuli_method(name, *args, **kwargs):
    return sys.modules['sikuli.Sikuli'].__dict__[name](*args, **kwargs)

# overwritten Screen.exists method
def exists(target, timeout=1):
    addFoundImage(getFilename(target))
    BaseLogger.log.html(getFilename(target))
    return sikuli_method('exists', target, timeout)

# =============================================== #
# Overwritten sikuli classes #
# =============================================== #

# overwriten Sikuli Region class
class Region(SikuliRegion, BaseLogger):

    def click(self, target, modifiers=0):
        try:
            return SikuliRegion.click(self, target, modifiers)
        except FindFailed, e:
            self.log.html_img("Find Failed (click)", common.cfgImageLibrary + '/' + getFilename(target))
            self.log.screenshot(msg="Region", region=(self.getX(), self.getY(), self.getW(), self.getH()))
            raise e

    def find(self, target):
        try:
            return SikuliRegion.find(self, target)
        except FindFailed, e:
            self.log.html_img("Find Failed", common.cfgImageLibrary + '/' + getFilename(target))
            self.log.screenshot(msg="Region", region=(self.getX(), self.getY(), self.getW(), self.getH()))
            raise e

    def exists(self, target, timeout=1):
        img = getFilename(target)
        reg = (self.getX(), self.getY(), self.getW(), self.getH())
        addFoundImage(img, reg)
        return SikuliRegion.exists(self, target, timeout)

Question information

Language:
English Edit question
Status:
Solved
For:
SikuliX Edit question
Assignee:
No assignee Edit question
Solved by:
RaiMan
Solved:
Last query:
Last reply:
Revision history for this message
RaiMan (raimund-hocke) said :
#1

I guess, since you selectively overwrite some methods and find() returns a Match object, that internally inherits from org.sikuli.script.Region (and not from your overwriting class defined on the Python level), you have to cast Match objects to Region objects on the Python level:

in your wrapper the return statements with find and exists:

    def find(self, target):
        try:
            return Region(SikuliRegion.find(self, target))
        except FindFailed, e:
            self.log.html_img("Find Failed", common.cfgImageLibrary + '/' + getFilename(target))
            self.log.screenshot(msg="Region", region=(self.getX(), self.getY(), self.getW(), self.getH()))
            raise e

    def exists(self, target, timeout=1):
        img = getFilename(target)
        reg = (self.getX(), self.getY(), self.getW(), self.getH())
        addFoundImage(img, reg)
        return Region(SikuliRegion.exists(self, target, timeout))

Revision history for this message
Snezhana (tobokeru) said :
#2

Thank you for the fast answer! Unfortunately, I receive an error with your fix T____T:
TypeError: can't convert Region[217,133 59x24]@Screen(0)[0,0 1280x960] E:Y, T:3.0 E:Y, T:3.0 to org.sikuli.script.Match

Traceback (most recent call last):
  File "c:\robot\libs\pvalib.sikuli\pvalib.py", line 118, in new
    upmenu.click(New_button)
  File "c:\robot\libs\sikuliwrapper.py", line 39, in click
    return SikuliRegion.click(self, target, modifiers)
  File "c:\robot\libs\sikuliwrapper.py", line 39, in click
    return SikuliRegion.click(self, target, modifiers)
  File "c:\robot\libs\sikuliwrapper.py", line 35, in getLocationFromPSRML
    return SikuliRegion.getLocationFromPSRML(self, target)

Revision history for this message
Best RaiMan (raimund-hocke) said :
#3

ok, then I have not seen the whole image ;-)

then you have to cast the Match objects in the expressions instead like:

region1.Region(find(capture1)).left().click(capture2)

for all find() and exist() usages.

just revert the other suggested change.

Revision history for this message
Snezhana (tobokeru) said :
#4

Thank you! Finally this works:
Region(region1.find(capture1).left()).click(capture2)

Sad I need to rework all lib =( But now I have my screenshots in logs =) But, somehow, they reported 2 times: for Region.find and for Region.click. Does this means I don't need a part for click in wrapper 0__0?

Revision history for this message
Snezhana (tobokeru) said :
#5

Thanks RaiMan, that solved my question.