Lib.sikuli.Sikuli.py Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of sikulixapi Show documentation
Show all versions of sikulixapi Show documentation
... for visual testing and automation
# Copyright 2010-2014, Sikuli.org, sikulix.com
# Released under the MIT License.
# modified RaiMan 2013
from __future__ import with_statement
from org.sikuli.basics import Debug
from org.sikuli.script import RunTime
RUNTIME = RunTime.get()
Debug.log(3, "Jython: sikuli: Sikuli: starting init")
import time
import __builtin__
#import __main__
import types
import sys
import os
import inspect
Debug.log(4, "Jython: sikuli: Sikuli: constants")
import org.sikuli.script.FindFailed as FindFailed
from org.sikuli.script.FindFailedResponse import *
from org.sikuli.script.Constants import *
import org.sikuli.script.Button as Button
from org.sikuli.script.Button import WHEEL_UP, WHEEL_DOWN
from org.sikuli.basics import OS
Debug.log(4, "Jython: sikuli: Sikuli: import Region")
from org.sikuli.script import Region as JRegion
from Region import *
from org.sikuli.script import Observing
Debug.log(4, "Jython: sikuli: Sikuli: import Screen")
from org.sikuli.script import Screen as JScreen
from Screen import *
Debug.log(4, "Jython: sikuli: Sikuli: Env.addHotkey")
from Env import *
Debug.log(4, "Jython: sikuli: Sikuli: import Match")
from org.sikuli.script import Match
Debug.log(4, "Jython: sikuli: Sikuli: import Pattern")
from org.sikuli.script import Pattern
Debug.log(4, "Jython: sikuli: Sikuli: import Location")
from org.sikuli.script import Location
Debug.log(4, "Jython: sikuli: Sikuli: import ScreenUnion")
from org.sikuli.script import ScreenUnion
Debug.log(4, "Jython: sikuli: Sikuli: import Finder")
from org.sikuli.script import Finder
from org.sikuli.script import ImageFinder
from org.sikuli.script import ImageFind
Debug.log(4, "Jython: sikuli: Sikuli: import Image")
from org.sikuli.script import Image
from org.sikuli.script import ImageGroup
Debug.log(4, "Jython: sikuli: Sikuli: import ImagePath")
from org.sikuli.script import ImagePath
Debug.log(4, "Jython: sikuli: Sikuli: import App")
from org.sikuli.script import App
Debug.log(4, "Jython: sikuli: Sikuli: import KeyBoard/Mouse")
from org.sikuli.script import Key
from org.sikuli.script import KeyModifier
from org.sikuli.script.KeyModifier import KEY_CTRL, KEY_SHIFT, KEY_META, KEY_CMD, KEY_WIN, KEY_ALT
from org.sikuli.script import Device
from org.sikuli.script import Mouse
from org.sikuli.script import Keys
Debug.log(4, "Jython: sikuli: Sikuli: import from Basics")
from org.sikuli.basics import Settings
from org.sikuli.basics import ExtensionManager
Debug.log(4, "Jython: sikuli: Sikuli: import from compare")
from org.sikuli.script.compare import DistanceComparator
from org.sikuli.script.compare import VerticalComparator
from org.sikuli.script.compare import HorizontalComparator
Debug.log(4, "Jython: sikuli: Sikuli: init SikuliImporter")
import SikuliImporter
Debug.log(4, "Jython: sikuli: Sikuli: import Sikulix")
from org.sikuli.script import Sikulix
Debug.log(4, "Jython: sikuli: Sikuli: import ScriptingSupport")
SCRIPT_SUPPORT = True
try:
from org.sikuli.scriptrunner import ScriptingSupport
except:
SCRIPT_SUPPORT = False
from org.sikuli.script import Runner
from org.sikuli.util import JythonHelper
RUNTIME = RunTime.get()
def show():
RUNTIME.show()
##
# a token to check the availability
#
SIKULIX_IS_WORKING = sys.version.split("(")[0]
##
# some support for handling unicode and strings
#
## use instead of print if unicode strings present
# usage: uprint(s1, u1, u2, u3, s3, ...)
#
def uprint(*args):
for e in args[:-1]:
if isinstance(e, str): print e,
else: print e.encode("utf8"),
if isinstance(args[-1], str): print args[-1]
else: print args[-1].encode("utf8")
##
# to make an utf8-encoded string from a str object
#
def unicd(s):
return ucode(s)
def ucode(s):
return (unicode(s, "utf8"))
##
# loads a Sikuli extension (.jar) from
# 1. user's sikuli data path
# 2. bundle path
#
def load(jar):
return JythonHelper.get().load(jar)
##
# unzips the given input (string) to the given folder (string)
# relative paths are resolved against the working folder
#
def unzip(zip, target):
import org.sikuli.basics.FileManager as FM
return FM.unzip(str(zip), str(target))
## ----------------------------------------------------------------------
# append the given path sys.path if not yet contained
#
def addImportPath(path):
_addModPath(path)
##
# append the given path image path list if not yet contained
#
def addImagePath(path):
ImagePath.add(path)
##
# return the current image path list
#
def getImagePath():
return [e for e in ImagePath.get()]
##
# remove the given path from the image path
#
def removeImagePath(path):
ImagePath.remove(path)
##
# reset the image path, so it only contains the bundlepath
#
def resetImagePath(path = None):
if not path:
path = getBundlePath();
ImagePath.reset(path)
## ----------------------------------------------------------------------
# Sets the path for searching images in all Sikuli Script methods.
# Sikuli IDE sets this to the path of the bundle of source code (.sikuli)
# automatically. If you write Sikuli scripts using Sikuli IDE, you should
# know what you are doing.
# returns true if path is valid and exists, false otherwise (no changes)
#
def setBundlePath(path):
return ImagePath.setBundlePath(path)
##
# return the current bundlepath (usually the folder .sikuli)
# or None if no bundlepath is defined
# no trailing path sep
#
def getBundlePath():
return ImagePath.getBundlePath()
##
# return the current bundlepath (usually the folder .sikuli)
# or None if no bundlepath is defined
# with a trailing path separator (for string concatenation)
#
def getBundleFolder():
path = ImagePath.getBundlePath()
if not path: return None
return path + Settings.getFilePathSeperator();
##
# return the parent folder of the current bundlepath
# (usually the folder containing the current script folder.sikuli)
# or None if no bundlepath is defined
# no trailing path sep
#
def getParentPath():
path = ImagePath.getBundlePath()
if not path: return None
return os.path.dirname(makePath(getBundlePath()));
##
# return the parent folder of the current bundlepath
# (usually the folder containing the current script folder.sikuli)
# or None if no bundlepath is defined
# no trailing path sep
#
def getParentFolder():
path = getParentPath()
if not path: return None
return path + Settings.getFilePathSeperator();
##
# make a valid path by by using os.path.join() with the given elements
# always without a trailing path separator
#
def makePath(*paths):
if len(paths) == 0: return None
path = paths[0]
if len(paths) > 1:
for p in paths[1:]:
path = os.path.join(path, p)
if path[-1] == Settings.getFilePathSeperator():
return os.path.dirname(path)
return path
##
# make a valid path by by using os.path.join() with the given elements
# with a trailing path separator (for string concatenation)
#
def makeFolder(*paths):
path = makePath(*paths)
if not path: return None
path = path + Settings.getFilePathSeperator()
return path
## ----------------------------------------------------------------------
# Sikuli shows actions (click, dragDrop, ... etc.) if this flag is set to True.
# The default setting is False.
#
def setShowActions(flag):
Settings.setShowActions(flag)
def highlightOff():
import org.sikuli.util.ScreenHighlighter as SH
SH.closeAll()
## ----------------------------------------------------------------------
# Shows a message dialog containing the given message.
# @param msg The given message string.
# @param title gets the window title.
def popup(msg, title="Sikuli Info"):
Sikulix.popup(msg, title)
# Show error popup (special icon) containing the given message.
# @param msg The given message string.
# @param title gets the window title.
def popError(msg, title="Sikuli Error"):
Sikulix.popError(msg, title)
# Show a popup containing the given message asking for yes or no
# @param msg The given message string.
# @param title gets the window title.
# @return True if answered Yes, else False
def popAsk(msg, title="Sikuli Decision"):
return Sikulix.popAsk(msg, title)
##
# Shows a question-message dialog requesting input from the user.
# @param msg The message to display.
# @param default The preset text of the input field (default empty).
# @param title the title for the dialog (default: Sikuli input request)
# @param hidden =true makes the dialog run as a password input (input hidden with bullets)
# @return The user's input string.
#
def input(msg="", default="", title="Sikuli Input", hidden=False):
if (hidden):
default = ""
return Sikulix.input(msg, default, title, hidden)
##
# Shows a dialog request to enter text in a multiline text field
# Though not all text might be visible, everything entered is delivered with the returned text
# The main purpose for this feature is to allow pasting text from somewhere
# @param msg the message to display.
# @param title the title for the dialog (default: Sikuli input request)
# @param lines the maximum number of lines visible in the text field (default 9)
# @param width the maximum number of characters visible in one line (default 20)
# @return The user's input including the line breaks.
def inputText(msg="", title="Sikuli Text", lines=0, width=0):
return Sikulix.inputText(msg, title, width, lines)
##
# Shows a dialog requesting to select an entry from the drop down list
# @param msg the message to display.
# @param title the title for the dialog
def select(msg="", title="Sikuli Selection", options=(), default=None):
if len(options) == 0:
return ""
if default:
if not __builtin__.type(default) is types.StringType:
try:
default = options[default]
except:
default = None
return Sikulix.popSelect(msg, title, options, default)
## ----------------------------------------------------------------------
def capture(*args):
scr = ScreenUnion()
if len(args) == 0:
simg = scr.userCapture()
if simg:
return simg.getFilename()
else:
return None
elif len(args) == 1:
if __builtin__.type(args[0]) is types.StringType or __builtin__.type(args[0]) is types.UnicodeType:
simg = scr.userCapture(args[0])
if simg:
return simg.getFilename()
else:
return None
else:
return scr.capture(args[0]).getFilename()
elif len(args) == 4:
return scr.capture(args[0], args[1], args[2], args[3]).getFilename()
else:
return None
def saveCapture(*args):
scr = ScreenUnion()
if len(args) == 1:
return scr.saveCapture(args[0])
elif len(args) == 2:
return scr.saveCapture(args[0], args[1])
elif len(args) == 5:
return scr.saveCapture(args[0], Region.create(args[1], args[2], args[3], args[4]))
else:
return None
def selectRegion(msg=None):
if msg:
r = ScreenUnion().selectRegion(msg)
else:
r = ScreenUnion().selectRegion()
if r:
return Region(r)
else:
return None
## ----------------------------------------------------------------------
# set the default screen to given or primary screen
#
# TODO where else to remember an opened remote screen?
remoteScreen = None
def use(scr = None, remote = False):
if remote:
theGlobals = inspect.currentframe().f_back.f_back.f_globals
else:
theGlobals = inspect.currentframe().f_back.f_globals
global remoteScreen
if remoteScreen:
remoteScreen.close()
remoteScreen = None
if not scr:
SCREEN = Screen()
else:
SCREEN = scr
Debug.log(3, "Jython: requested to use as default region: " + SCREEN.toStringShort())
globals()['SIKULISAVED'] = _exposeAllMethods(SCREEN, globals().get('SIKULISAVED'), theGlobals, None)
theGlobals['SCREEN'] = SCREEN
if remote:
remoteScreen = SCREEN
return SCREEN
##
# set the default screen to given remote screen
#
def useRemote(adr, port = 0):
global remoteScreen
import org.sikuli.script.ScreenRemote as SR
SCREEN = SR(adr, str(port))
if SCREEN.isValid():
return use(SCREEN, True)
else:
return None
## ----------------------------------------------------------------------
# Switches the frontmost application to the given application.
# If the given application is not running, it will be launched by openApp()
# automatically.
# Note: On Windows, Sikule searches in the text on the title bar
# instead of the application name.
# @param app The name of the application. (case-insensitive)
#
def switchApp(app):
return App.focus(app)
##
# Opens the given application.
# @param app The name of an application if it is in the environment variable PATH, or the full path to an application.
#
def openApp(app):
return App.open(app)
##
# Closes the given application.
# @param app The name of the application. (case-insensitive)
#
def closeApp(app):
return App.close(app)
##
# Sleeps until the given amount of time in seconds has elapsed.
# @param sec The amount of sleeping time in seconds.
def sleep(sec):
time.sleep(sec)
## ----------------------------------------------------------------------
def reset():
JScreen.resetMonitors();
use();
ALL = SCREEN.all().getRegion()
##
# shutdown and return given exit code
#
def exit(code=0):
global remoteScreen
if remoteScreen:
remoteScreen.close()
remoteScreen = None
Sikulix.cleanUp(code)
sys.exit(code)
## ----------------------------------------------------------------------
# Runs the given string command.
# @param cmd The given string command.
# @return Returns the output from the executed command.
def run(cmd):
return Sikulix.run(cmd)
# Runs the script given by absolute or relative path (./ same folder as calling script)
# @param script The given script path.
# @args the parameters for the called script (sys.argv)
# @return returns the scripts return code given with exit(n)
def runScript(script, *args):
if SCRIPT_SUPPORT:
return ScriptingSupport.run(script, args)
else:
return Runner.run(script, args)
def getLastReturnCode():
if SCRIPT_SUPPORT:
return ScriptingSupport.getLastReturnCode()
else:
return Runner.getLastReturnCode()
##
# helper functions, that can be used when sorting lists of regions
#
def byDistanceTo(x, y=None):
""" Method to compare two Region objects by distance of their top left.
or a regions top left to the given point by coordinates"""
return DistanceComparator(x, y)
def byX(m):
""" Method to compare two Region objects by x value. """
return HorizontalComparator().compare
def byY(m):
""" Method to compare two Region objects by y value. """
return VerticalComparator().compare
def verticalComparator():
""" Method to compare two Region objects by y value. """
return VerticalComparator().compare
def horizontalComparator():
""" Method to compare two Region objects by x value. """
return HorizontalComparator().compare
def distanceComparator(x, y=None):
""" Method to compare two Region objects by distance of their top left.
or a regions top left to the given point by coordinates"""
if y is None:
return DistanceComparator(x).compare # x is Region or Location
return DistanceComparator(x, y).compare # x/y as coordinates
##
################## internal use only ###########################################
#
def _addModPath(path):
if path[-1] == Settings.getFilePathSeperator():
path = path[:-1]
if not path in sys.path:
sys.path.append(path)
def _exposeAllMethods(anyObject, saved, theGlobals, exclude_list):
if not exclude_list:
exclude_list = [ 'class', 'classDictInit', 'clone', 'equals', 'finalize',
'getClass', 'hashCode', 'notify', 'notifyAll',
'toGlobalCoord', 'toString', 'getLocationFromPSRML', 'getRegionFromPSRM',
'capture', 'selectRegion', 'create', 'observeInBackground', 'waitAll',
'updateSelf', 'findNow', 'findAllNow', 'getEventManager',
'lastMatch', 'lastMatches', 'lastScreenImage', 'lastScreenImageFile']
#Debug.log(3, "Sikuli: _exposeAllMethods: %s called from: %s", anyObject, theGlobals['__name__'])
tosave = []
if not saved:
saved = []
for name in dir(anyObject):
if name in exclude_list: continue
try:
if not inspect.ismethod(getattr(anyObject,name)): continue
except:
continue
if name[0] != '_' and name[:7] != 'super__':
try:
saved.remove(name)
except:
pass
tosave.append(name)
#print "added:", name
theGlobals[name] = eval("anyObject."+name)
if name == 'checkWith': Debug.log(3, "%s %s", name, str(dict[name])[1:])
for name in saved:
if name in theGlobals:
#print "removed:", name
theGlobals.pop(name)
return tosave
############### set SCREEN as primary screen at startup ################
use()
ALL = SCREEN.all().getRegion()
Debug.log(3, "Jython: sikuli: Sikuli: ending init")