def moveImagesToCommonFolder(source = sikuli.getParentFolder(), destination = ""):
    if destination == "":
        destination = _myImagesPath
    for foldername, subfolders, filenames in os.walk(source):
        for filename in filenames:
            file = os.path.join(foldername,filename)
            if source == sikuli.getBundleFolder():
                folderFilter = True
            else:
                folderFilter = foldername.endswith(".sikuli")
            if file.endswith(".png") and folderFilter:
                #print file
                myfilename = os.path.basename(file)
                myhash = getHash(file)
                newFile = os.path.join(destination, myfilename)
                newHash = getHash(file)
                if not os.path.exists(newFile):
                    shutil.move(file, destination)
                else:
                    print "----------", myfilename," is in ", destination
                    if newHash == myhash:
                        #print "duplicate found, removing it"
                        os.remove(file)
                    else:
                        print "cannot move :", file
 def user(message):
     if SikuliSettings.UserLogs:
         if Debug.printoutuser == None:
             if SikuliSettings.isMacApp:
                 Debug.printoutuser = "******"
             else:
                 Debug.printoutuser = sikuli.getBundleFolder()+ "UserLog.txt"
         with open(Debug.printoutuser, "a") as f:
             if SikuliSettings.UserLogTime:
                 text = '[{} ({})] {}'.format(SikuliSettings.UserLogPrefix,'{:%m/%d/%y %I:%M:%S %p}'.format(datetime.datetime.now()).lstrip("0").replace(" 0", " "), message)
             else:
                 text = '[{}] {}'.format(SikuliSettings.UserLogPrefix, message)
             f.write(text+"\n")
def _recapture_image_prompt(original_path, message):
    global _myEvent
    badKey = False
    na_path = os.path.join(_sitePackages, "image_not_captured_yet.png")
    temp_path = na_path
    three_buttons = ["Instant Capture", "User-Initiated Capture (CTRL+SHIFT+2)", "Show Capture", "Show Original", ]
    four_buttons = ["Instant Capture", "User-Initiated Capture (CTRL+SHIFT+2)", "Show Capture", "Show Original", "Move On"]
    icon = ImageIcon(original_path)
    while True:
        if temp_path == na_path:
            buttons = three_buttons
        else:
            buttons = four_buttons
        choice = JOptionPane().showOptionDialog(None, message , "Capture new image or close this window to retry the code.",  JOptionPane.PLAIN_MESSAGE, 0, icon, buttons, buttons[0])
        if choice == -1:
            #print "Image updater closed without doing anything."
            break #with this included the while loop will quit and the _screen_logger loop will retry the original image
        elif choice == 0:
            temp_path = sikuli.capture()
            if temp_path == None:
                temp_path = na_path
                icon = ImageIcon(original_path)
            else:
                icon = ImageIcon(temp_path)
        elif choice == 1:
            if not sikuli.Env.addHotkey("2", sikuli.KeyModifier.SHIFT + sikuli.KeyModifier.CTRL, _capture_wait):
                badKey = True
                sikuli.Env.addHotkey(Key.F2, sikuli.KeyModifier.SHIFT + sikuli.KeyModifier.CTRL, _capture_wait)
            _myEvent.clear()
            _myEvent.wait()
            temp_path = sikuli.SCREEN.capture()
            if temp_path == None:
                temp_path = na_path
                icon = ImageIcon(original_path)
            else:
                icon = ImageIcon(temp_path)
            if badKey:
                sikuli.Env.removeHotkey(Key.F2, sikuli.KeyModifier.SHIFT + sikuli.KeyModifier.CTRL)
            else:
                sikuli.Env.removeHotkey("2", sikuli.KeyModifier.SHIFT + sikuli.KeyModifier.CTRL)
        elif choice == 2:
            icon = ImageIcon(temp_path)
        elif choice == 3:
            icon = ImageIcon(original_path)
        elif choice == 4:
            shutil.copyfile(temp_path, original_path)
            break
        else:
            #print "You added an extra button and it doesn't do anything."
            break
def _find_valid_image(img):
    if isinstance(img, sikuli.Pattern):
        img = img.getFilename()
    valid_extensions = ["png", "jpg", "jpeg"]
    split_result = img.split('.')

    # If no '.': not a file
    if len(split_result) <= 1:
        return ""
    # If there is only one '.' and nothing before it, not a file
    elif len(split_result) == 2 and  split_result[0] == "":
        return ""
    # If it doesn't end in a valid extension, not an image file
    elif split_result[-1] not in valid_extensions:
        return ""
    # If it's an absolute path (that passed the file extension
    # tests), return it
    elif os.path.isfile(img):
        return img

    # Look in all the SIKULI_IMAGE_PATH dirs to see if it's there
    image_dirs = list(sikuli.getImagePath())
    #image_dirs.insert(0, sikuli.getBundlePath())
    my_frames = inspect.getouterframes(inspect.currentframe())
    image_path = os.path.dirname(my_frames[-1][1])
    image_dirs.insert(0, image_path)

    for dir in image_dirs:
        if not dir.endswith('/'):
            dir = dir + '/'
        if dir.startswith('/') and myOS == "W":
            dir = dir[1:]
        # If found, return the full path
        if os.path.isfile(os.path.join(dir, img)):
            return dir + img
    #No file handling
    if _imageUpdating:
        missing_file = os.path.join(_myImagesPath, img) #put in common imagepath
        print missing_file
        return missing_file
    return ""
    def setUserLogFile(fileName, premake=True):
        if fileName == None:
            fileName = ""
            return False
        else:
            if "" == fileName:
                if SikuliSettings.isMacApp:
                    Debug.printoutuser = "******"
                else:
                    Debug.printoutuser = sikuli.getBundleFolder()+ "UserLog.txt"
            else:
                Debug.printoutuser = fileName

            if premake:
                try:
                    with open(Debug.printoutuser, "a") as f:
                        f.write("")
                    return True
                except:
                    Debug.printoutuser = None
                    print "[Error] User logfile %s not accessible - check given path"% fileName
                    return False
from __future__ import with_statement
import org.sikuli.basics.SikuliXforJython
from sikuli import *
from sikuliwrapper import *
from org.sikuli.script import App, Env
from sikuli import Sikuli

#add custom image library
Sikuli.addImagePath(common.cfgImageLibrary)

class Calculator(BaseLogger):
	
	ROBOT_LIBRARY_SCOPE = 'TEST SUITE'
	
	def __init__(self):
		self.appCoordinates = (0, 0, 1024, 768)
	
	def startApp(self):
		calcApp = App("Calculator")
		if not calcApp.window():
				App.open("calc.exe"); wait(2)
		calcApp.focus(); wait(1)

	def verifyApp(self):
		# check application
		if exists("CalcApp.png"):
			self.log.passed("Calculator window appeared")
		else:
			self.log.failed("No calculator window")

	def performAction(self, *args):
def _init():
    SikuliSettings.ActionLogs = False
    SikuliSettings.InfoLogs = False
    #SikuliSettings.DebugLogs = False

    #print "initializing"
    global myOS
    global _sitePackages
    global _logToFolder
    global _imageUpdating
    global _errorFile
    global _artifactFolder
    global _partialHTML
    global _myImagesPath
    global _showHeader
    global _textLog
    global _myEvent
    _myEvent = threading.Event()
    _myEvent.set()

    #OS-specific variables section
    my_OS = sikuli.Env.getOS()
    splitOSVersion = sikuli.Env.getOSVersion().split('.')
    my_OSVersion = splitOSVersion[0]+"."+splitOSVersion[1]
    if my_OS == sikuli.OS.LINUX:
        myOS = "L"
        _sikuliRepo = os.path.join(os.path.expanduser('~'),".Sikulix/")
        _vagrantFolder = "/vagrant/"
        _homeFolder = os.path.expanduser('~')+"/"
        os_options = {
        "3.2": "UbuntuPrecise",
        "3.13": "UbuntuTrusty",
        "4.4" : "UbuntuXenial",
        "3.8" : "Wasta12",
        "3.16": "Wasta14"
        }
    elif my_OS == sikuli.OS.WINDOWS:
        myOS = "W"
        _sikuliRepo = os.path.join(os.getenv('APPDATA'),"Sikulix\\")
        _vagrantFolder = "C:/vagrant/"
        _homeFolder = os.getenv('USERPROFILE')+"\\"
        os_options = {
        "6.0": "WindowsVista",
        "6.1":"Windows7",
        "6.2":"Windows8",
        "6.3":"Windows8.1",
        "10.0": "Windows10",
        }
    elif my_OS == OS.MAC:
        myOS = "M"
        _sikuliRepo = os.path.join(os.path.expanduser('~'),"Library/Application Support/Sikulix/")
        _homeFolder = os.path.expanduser('~')+"/"
    else:
        myOS = "N"
        print "Unsupported OS."
        exit(1)
    _sitePackages = os.path.join(_sikuliRepo, "Lib/site-packages")

    # Determine Logging Folder
    # A non-existent, empty, invalid logFolder.txt or one with "image_updater" keeps all logs in the .sikuli folder of each test.
    # A logFolder.txt with a valid path keeps all logs in one log in that folder.
    # A logFolder.txt with "vagrant" keeps all logs in the default vagrant folder.
    # Helper scripts logs are kept in the top level folder.
    try:
        with open(os.path.join(_sitePackages, "logFolder.txt"), "r") as f:
            rawLogFolder = os.path.normpath((f.readline()).strip())
    except IOError:
        rawLogFolder = "."

    if "image_updater" in rawLogFolder:
        _logToFolder = sikuli.getBundleFolder()
        updateImages()
        #setFindFailedResponse(PROMPT) #Native support for capturing in 1.1.1
    elif "vagrant" in rawLogFolder:
        _logToFolder = _vagrantFolder
    else:
        if rawLogFolder != "." and os.path.exists(rawLogFolder):
            _logToFolder = rawLogFolder
        else:
            if len(rawLogFolder)>1:
                print "ERROR: LogFolder.txt contents not usable. Using default behavior."
            _logToFolder = sikuli.getBundleFolder()
    Debug.setUserLogFile(os.path.join(_logToFolder, "UserLog.txt"), premake=False)

    try:
        myImagesFolder = os_options[my_OSVersion]
    except:
        sikuli.popup("The version of "+str(my_OS)+" is not supported yet.")

    #Determing where the common immage folders are and make them (default) if they are missing.
    parentPath = sikuli.getParentPath()
    parentFolder = os.path.basename(parentPath)
    if os.path.basename(parentPath) == "helpers":
        _myImagesPath = os.path.join(os.path.dirname(parentPath), "images", myImagesFolder)
    else:
        _myImagesPath = os.path.join(parentPath, "images", myImagesFolder)
    if not os.path.exists(_myImagesPath):
        error_message = "WARNING: The following Common Image Path is missing: "+_myImagesPath
        print error_message
        #sikuli.popup(error_message)
        if sikuli.Sikulix.prefLoad("cib") == "ASK":
            buttons = ["Make", "Cancel","Exit Program"]
            choice = JOptionPane().showOptionDialog(None, error_message , "Common Image Path Does Not Exist.",  JOptionPane.PLAIN_MESSAGE, 0, None, buttons, buttons[0])
        elif sikuli.Sikulix.prefLoad("cib") == "MAKE":
            choice = 0
        elif sikuli.Sikulix.prefLoad("cib") == "SKIP":
            choice = 1
        else:
            print "Common Image Behavior not correct."

        if choice == -1:
            pass #Window Closed
        elif choice == 0:
            #creat path
            try:
                os.makedirs(_myImagesPath)
                sikuli.addImagePath(_myImagesPath)
            except:
                sikuli.popup(_myImagesPath+" could not be created.")
        elif choice == 1:
            pass
        elif choice == 2:
            exit(1)
        else:
            #print "You added an extra button and it doesn't do anything."
            pass
    else:
        sikuli.addImagePath(_myImagesPath)

    #myProjectsPath = os.path.join(parentPath, "projects")

    # If a file with the given filename already exists, the Logger will
    # just keep writing to the end of that file.
    # *_errorFile* is the path to the text log.
    # *_logToFolder* is the path to the directory which stores the
    # html log and its assiocated images.
    _artifactFolder = os.path.join(_logToFolder, "log")
    _errorFile = os.path.join(_artifactFolder,"error_log")
    #with open(_errorFile, "a") as f:
    #    f.write("")

    # Create the log folder if it doesn't exist
    if not os.path.exists(_artifactFolder):
        os.makedirs(_artifactFolder)
        _partialHTML = os.path.join(_artifactFolder, "mylog.log")
    # Otherwise, see if there's already a log file
    else:
        glob_result = glob.glob(_artifactFolder + "/*.log")
        if len(glob_result) == 1:
            _partialHTML = glob_result[0]
        else:
            _partialHTML = os.path.join(_artifactFolder, "mylog.log")

    # Add the CSS stylesheet to the log folder, if it's not there already.
    if not os.path.exists(os.path.join(_artifactFolder, "log.css")):
        shutil.copyfile(os.path.join(_sitePackages,"log.css"),
                        os.path.join(_artifactFolder, "log.css"))
    if _showHeader:
        #if imported this header shows the filepath of the main script
        #if runScript this header shows the filepath of the helper script
        doc, tag, text = Doc().tagtext()
        with tag("tr"):
            with tag("td", style="text-align: center; background-color:lightskyblue", colspan="7"):
                text(time.strftime("%x %H:%M:%S")+": "+sikuli.getBundleFolder())
        with open(_partialHTML, "a") as f:
            f.write(doc.getvalue())
        _registerHTMLgenerator()
    def _screen_logger_wrapper(*args, **kwargs):
        #print "Arguments were: %s %s | %s" % (func.__name__, args, kwargs)
        frames = inspect.getouterframes(inspect.currentframe())
        scriptname = os.path.basename(frames[1][1])[:-3]
        count = 0

        for frame in frames:
            if frame[3] == '_screen_logger_wrapper':
                count = count +1

        # Sikuli uses find and wait internally, so the only versions of the
        # sikuli commands that should be decorated are those that are at the
        # highest level (i.e. those that are only wrapped once).
        if count == 1:
            fname = func.__name__
            #frame = frames[1][0]
            #filename = frames[1][1]
            lineno = frames[1][2]
            #function = frames[1][3]
            code_context = frames[1][4][0]
            #index = frames[1][5]
            output = "[Line "+str(lineno)+"] "+str(code_context).rstrip()
            number_of_screens = sikuli.getNumberScreens()
            if isinstance(args[0],SikuliRegion):
                specific_area = True
                area = args[0]
                image = args[1]
                if fname == "wait" and _imageUpdating:
                    targs = list(args)
                    if len(args)==1:
                        targs.append(0)
                    elif len(args)>1:
                        targs[2] = 0
                        args = targs

                elif fname == "dragDrop":
                    extraImage = args[2]
            else:
                specific_area = False
                area = sikuli.SCREEN
                image = args[0]
                if fname == "wait" and _imageUpdating:
                    targs = list(args)
                    if len(args)==1:
                        targs.append(0)
                    elif len(args)>1:
                        targs[1] = 0
                        args = targs
                elif fname == "dragDrop":
                    extraImage = args[1]

            if fname == "dragDrop":
                display_order = "[start]"
            else:
                display_order = ""

            if isinstance(image, float) or isinstance(image, int):
                _textLog = True
            elif isinstance(image, sikuli.Pattern):
                _textLog = False
                imageName = os.path.basename(image.getFilename())
            else:
                _textLog = False
                imageName = image
            if fname == "dragDrop":
                if isinstance(extraImage, sikuli.Pattern):
                    extraImageName = os.path.basename(extraImage.getFilename())
                else:
                    extraImageName = extraImage

            ### TODO replace image in code_context with image for HTML log, consolidate columns
            while True:
                try:
                    screenshot = sikuli.capture(area)
                    if specific_area or fname == "type" or fname == "paste" or fname == "onChange" or fname == "observe" or _textLog:
                        result = func(*args, **kwargs)
                    else:
                        failures = 0
                        for screen_id in range(number_of_screens):
                            try:
                                my_screen = sikuli.Screen(screen_id)
                                screen_check_func = getattr(my_screen,func.__name__)
                                result = screen_check_func(*args, **kwargs)
                                break
                            except sikuli.FindFailed:
                                failures = failures +1
                            except:
                                #print "base exception"
                                raise
                        if failures == number_of_screens:
                            #print "both screens FindFailed"
                            raise sikuli.FindFailed("Find Failed on both Screens")
                    if fname =="exists" and result == None and _imageUpdating:
                        raise sikuli.FindFailed("Exists() did not find anything.")
                    if _logType == "SUCCESS" or _logType == "ALL":
                        if _textLog:
                            similarity ="N/A"
                        else:
                            similarity = str(simpleCompare(screenshot, image, 4))
                        _write_error("+++",scriptname, output+display_order+"[S:"+similarity+"]")
                        _write_html_row(scriptname,func.__name__+display_order, image, "Success", screenshot, similarity)
                    #if _imageUpdating:
                    #    if fname == "type" or fname == "paste" or fname == "onChange" or fname == "observe" or fname == "onVanish" or fname == "onAppear":
                    #        pass
                    #    elif specific_area:
                    #        specific_area.getLastMatch().highlight(1)
                    #    else:
                    #        my_screen.getLastMatch().highlight(1)
                    return result
                except sikuli.FindFailed:
                    if _textLog:
                        similarity ="N/A"
                    else:
                        screenshot = area.getLastScreenImageFile(tempfile.gettempdir(), str(int(time.time()*1000)))
                    similarity = str(simpleCompare(screenshot, image, 4))
                    error_text = traceback.format_exc()
                    if fname == "dragDrop" and extraImageName in error_text:
                        if _logType == "SUCCESS" or _logType == "ALL":
                            _write_error("+++",scriptname, output+display_order+"[S:"+similarity+"]")
                            _write_html_row(scriptname,func.__name__+display_order, image, "Success", screenshot, similarity)
                        display_order = "[end]"
                        image = extraImage
                        similarity = str(simpleCompare(screenshot, image, 4))
                    if _imageUpdating:
                        line_data = "\n"+frames[1][1]+"\nCurrent Similarity is: "+str(similarity)+"\n"+output+display_order
                        if specific_area:
                            area.highlight(1)
                        _recapture_image_prompt(_find_valid_image(image), line_data)
                        continue
                    else:
                        if _logType == "FAIL" or _logType == "ALL":
                            _write_error("---",scriptname, output+display_order+"[S:"+similarity+"]")
                            _write_html_row(scriptname,func.__name__+display_order, image, "Fail", screenshot, similarity)
                        raise
                except:
                    raise
        else:
            return func(*args, **kwargs)
def _write_html_row(script_name, action_type, expected, result_type, screenshot, similarity):
    doc, tag, text = Doc().tagtext()
    # Create the row
    # Status, Time and Date, Test name, Action, Expected, Screenshot, Similarity
    with tag("tr"):
        if result_type == "Success":
            with tag("td", ('bgcolor', 'green')):
                text("+++")
        elif result_type == "Fail":
            with tag("td", ('bgcolor', 'red')):
                text("---")
        else:
            with tag("td"):
                text("???")
        with tag("td"):
            text(time.strftime("%H:%M:%S %x"))
        with tag("td"):
            text(script_name)
        with tag("td"):
            text(action_type)
        with tag("td"):
            # If 'expected' is given, figure out what kind
            # of thing it is
            if expected:
                expected_path = ""
                # If it's a pattern, get the image
                if isinstance(expected, sikuli.Pattern):
                    full_path = _find_valid_image(expected.getFilename())
                    expected_path = _copy_testfile(full_path)
                # If it's a match or a region, take a
                # screenshot of the area
                elif (isinstance(expected, sikuli.Match) or
                      isinstance(expected, sikuli.Region)):
                    screencap = sikuli.capture(expected)
                    expected_path = _copy_testfile(screencap)
                elif isinstance(expected, sikuli.Location):
                    # Create an area 50px around the location
                    r = sikuli.Region(expected.getX(), expected.getY(), 0, 0)
                    r = r.nearby()
                    # take a screenshot
                    screencap = sikuli.capture(r)
                    expected_path = _copy_testfile(screencap)
                elif isinstance(expected, str):
                    full_path = _find_valid_image(expected)

                    # If a path was found, add a clickable image.
                    # If not, add text.
                    if full_path:
                        expected_path = _copy_testfile(full_path)

                if expected_path == "":
                    text(str(expected))
                else:
                    with tag("a", href="./log/"+expected_path):
                        doc.stag("img", src="./log/"+expected_path)

        with tag("td"):
            screenshot_path = _copy_testfile(screenshot)
            with tag("a", href="./log/"+screenshot_path):
                doc.stag("img", src="./log/"+screenshot_path)
        with tag("td"):
            text(similarity)

    # Write the row to the partial html file
    with open(_partialHTML, "a") as f:
        f.write(doc.getvalue())