def _start_sikuli_java_process(self): libFolder = os.path.join(os.path.abspath(os.path.dirname(__file__)), 'lib') jarList = glob.glob(libFolder + os.sep + '*.jar') if len(jarList) != 1: raise Exception('Sikuli jar package should be exist in lib folder') sikuliJar = jarList[0] java = 'java' arguments = [ '-jar', sikuliJar, str(self.port), self._get_output_folder() ] process = Process() if os.getenv("DISABLE_SIKULI_LOG"): process.start_process(java, *arguments, shell=True) else: process.start_process(java, *arguments, shell=True, stdout=self._output_file(), stderr=self._err_file()) self.logger.info('Start sikuli java process on port %s' % str(self.port)) self._wait_process_started() self.logger.info('Sikuli java process is started')
def _start_sikuli_java_process(self): libFolder = os.path.join(os.path.abspath(os.path.dirname(__file__)), 'lib') jarList = glob.glob(libFolder+os.sep+'*.jar') if len(jarList) != 1: raise Exception('Sikuli jar package should be exist in lib folder') sikuliJar = jarList[0] command = 'java -jar '+sikuliJar+' %s ' % str(self.port) process = Process() process.start_process(command, shell=True) self.logger.info('Start sikuli java process on port %s' % str(self.port)) self._wait_process_started() self.logger.info('Sikuli java process is started')
def _start_sikuli_java_process(self): libFolder = os.path.join(os.path.abspath(os.path.dirname(__file__)), 'lib') jarList = glob.glob(libFolder + os.sep + '*.jar') if len(jarList) != 1: raise Exception('Sikuli jar package should be exist in lib folder') sikuliJar = jarList[0] command = 'java -jar ' + sikuliJar + ' %s ' % str( self.port) + self._get_output_folder() process = Process() process.start_process(command, shell=True, stdout=self._output_file(), stderr=self._err_file()) self.logger.info('Start sikuli java process on port %s' % str(self.port)) self._wait_process_started() self.logger.info('Sikuli java process is started')
def _run_process(self, command, *arguments, **configuration): expected_rc = int(configuration.pop('expected_rc', 0)) token = configuration.pop('token', 'process') merged_output = is_truthy(configuration.pop('merged_output', True)) input = configuration.pop('input', None) if input and not isinstance(input, bytes): input = input.encode() tty = is_truthy(configuration.pop('tty', False)) redirection = configuration.pop('redirection', None) # For compatibility with Process.run_process() timeout = configuration.pop('timeout', None) on_timeout = configuration.pop('on_timeout', 'terminate') if redirection and not tty: raise ValueError('Cannot use "redirection" without "tty"') with ExitStack() as stack: if merged_output: stdout = stack.enter_context(_Attachment(token + '-output.txt')).path stderr = 'STDOUT' else: stdout = stack.enter_context(_Attachment(token + '-stdout.txt')).path stderr = stack.enter_context(_Attachment(token + '-stderr.txt')).path if tty: joined = shlex.join((command, ) + arguments) if redirection: joined += ' ' + redirection command = 'script' arguments = list() arguments += ['--return'] arguments += ['--quiet'] arguments += ['--echo', 'never', '--log-out', '/dev/null'] arguments += ['--command', joined] process = Process() handle = process.start_process(command, *arguments, **configuration, stdout=str(stdout), stderr=str(stderr)) if input: process_object = process.get_process_object(handle) process_object.stdin.write(input) process_object.stdin.close() result = process.wait_for_process(handle, timeout, on_timeout) if result.rc != expected_rc: raise AssertionError( 'Process exited with unexpected code {}'.format(result.rc)) return result
class SikuliLibrary(object): ROBOT_LIBRARY_SCOPE = 'GLOBAL' ROBOT_LIBRARY_VERSION = VERSION def __init__(self, port=0, timeout=3.0, mode='OLD'): """ @port: sikuli java process socket port @timeout: Timeout of waiting java process started @mode: if set as 'DOC', will stop java process automatically, if set as 'PYTHON', means library is running out of robot environment if set as 'CREATE', it is only for mvn package usage, will create keywords.py file if set as 'OLD'(default), sikuli java process will be started when library is inited if set as 'NEW', user should use 'start_sikuli_process' to start java process """ self.logger = self._init_logger() self.timeout = float(timeout) self.port = None self.remote = None self.mode = mode.upper().strip() if mode == 'OLD': self.start_sikuli_process(port) if mode.upper().strip() == 'DOC': self.start_sikuli_process() self._stop_thread(4) elif mode.upper().strip() == 'PYTHON': self.connect_sikuli_process(port) elif mode.upper().strip() == 'CREATE': self._create_keywords_file() elif mode.upper().strip() != 'NEW': self._check_robot_running() def start_sikuli_process(self, port=None): """ This keyword is used to start sikuli java process. If library is inited with mode "OLD", sikuli java process is started automatically. If library is inited with mode "NEW", this keyword should be used. :param port: port of sikuli java process, if value is None or 0, a random free port will be used :return: None """ if port is None or int(port) == 0: port = self._get_free_tcp_port() self.port = port start_retries = 0 started = False while start_retries < 5: try: self._start_sikuli_java_process() except RuntimeError as err: print('error........%s' % err) if self.process: self.process.terminate_process() self.port = self._get_free_tcp_port() start_retries += 1 continue started = True break if not started: raise RuntimeError('Start sikuli java process failed!') self.remote = self._connect_remote_library() def connect_sikuli_process(self, port): self.port = port self.remote = self._connect_remote_library() def _create_keywords_file(self): keywordDict = {} self.start_sikuli_process() try: keywordList = self.get_keyword_names() for keywordName in keywordList: keywordDict[keywordName] = {} keywordDict[keywordName]['arg'] = self.get_keyword_arguments( keywordName) keywordDict[keywordName][ 'doc'] = self.get_keyword_documentation(keywordName) with codecs.open(os.path.join( os.path.abspath(os.path.dirname(__file__)), 'keywords.py'), 'w', encoding='utf-8') as f: f.write('# -*- coding: utf-8 -*-\n') # keywords = ','.join(['"%s": %s' % (k, keywordDict[k]) for k in keywordDict.keys()]) f.write('KEYWORDS = %s' % keywordDict) finally: self._stop_thread(3) def _check_robot_running(self): try: BuiltIn().get_variable_value('${SUITE SOURCE}') except Exception as err: self.logger.warn('Robot may not running, stop java process: %s' % err) self._stop_thread(1) def _init_logger(self): robotLogLevels = { 'TRACE': int(logging.DEBUG / 2), 'DEBUG': logging.DEBUG, 'INFO': logging.INFO, 'HTML': logging.INFO, 'WARN': logging.WARN } builtIn = BuiltIn() handler = logging.StreamHandler(sys.stdout) formatter = logging.Formatter('%(message)s') handler.setFormatter(formatter) logger = logging.getLogger('SikuliLibraryLogger') logger.addHandler(handler) level = logging.DEBUG try: logLevel = builtIn.get_variable_value('${LOG_LEVEL}') level = robotLogLevels[logLevel] except Exception: pass logger.setLevel(level) return logger def _get_free_tcp_port(self): sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) sock.bind(('localhost', 0)) sock.listen(1) host, port = sock.getsockname() self.logger.debug('Free TCP port is: %d' % port) sock.close() return port def _start_sikuli_java_process(self): libFolder = os.path.join(os.path.abspath(os.path.dirname(__file__)), 'lib') jarList = glob.glob(libFolder + os.sep + '*.jar') if len(jarList) != 1: raise Exception('Sikuli jar package should be exist in lib folder') sikuliJar = jarList[0] java = 'java' arguments = [ '-jar', sikuliJar, str(self.port), self._get_output_folder() ] self.process = Process() if os.getenv("DISABLE_SIKULI_LOG"): self.process.start_process(java, *arguments, shell=True) else: self.process.start_process(java, *arguments, shell=True, stdout=self._output_file(), stderr=self._err_file()) self.logger.info('Start sikuli java process on port %s' % str(self.port)) self._wait_process_started() self.logger.info('Sikuli java process is started') def _wait_process_started(self): url = "http://127.0.0.1:%s/" % str(self.port) currentTime = startedTime = time.time() started = False while (currentTime - startedTime) < self.timeout: try: urlopen(url).read() except Exception: currentTime = time.time() time.sleep(1.0) continue started = True break if not started: raise RuntimeError('Start sikuli java process failed!') def _output_file(self): outputDir = self._get_output_folder() outputFile = 'Sikuli_java_stdout_' + str(time.time()) + '.txt' return os.path.join(outputDir, outputFile) def _err_file(self): outputDir = self._get_output_folder() errFile = 'Sikuli_java_stderr_' + str(time.time()) + '.txt' return os.path.join(outputDir, errFile) def _get_output_folder(self): outputDir = os.path.abspath(os.curdir) try: outputDir = BuiltIn().get_variable_value('${OUTPUTDIR}') except Exception: pass return outputDir def _connect_remote_library(self): remoteUrl = 'http://127.0.0.1:%s/' % str(self.port) remote = Remote(remoteUrl) self._test_get_keyword_names(remote) return remote def _test_get_keyword_names(self, remote): currentTime = startedTime = time.time() started = False while (currentTime - startedTime) < self.timeout: try: remote.get_keyword_names() except Exception as err: self.logger.warn("Test get_keyword_names failed! %s" % err) currentTime = time.time() time.sleep(1.0) continue started = True break if not started: raise RuntimeError('Failed to get_keyword_names!') def get_keyword_names(self): if self.mode == 'CREATE': return self.remote.get_keyword_names() + ['start_sikuli_process'] return list(KEYWORDS.keys()) + ['start_sikuli_process'] # return self.remote.get_keyword_names() + ['start_sikuli_process'] def get_keyword_arguments(self, name): if name == 'start_sikuli_process': return ['port=None'] if self.mode == 'CREATE': return self.remote.get_keyword_arguments(name) return KEYWORDS[name]['arg'] def get_keyword_documentation(self, name): if name == 'start_sikuli_process': return self.start_sikuli_process.__doc__ elif name == '__intro__': return SikuliLibrary.__doc__ elif name == '__init__': return getattr(self, name).__doc__ if self.mode == 'CREATE': return self.remote.get_keyword_documentation(name) return KEYWORDS[name]['doc'] def run_keyword(self, name, arguments=[], kwargs={}): if name == 'start_sikuli_process': return self.start_sikuli_process(*arguments) return self.remote.run_keyword(name, arguments, kwargs) def _stop_thread(self, timeout): def stop(): time.sleep(float(timeout)) self.run_keyword('stop_remote_server') thread = threading.Thread(target=stop, args=()) thread.start()