Skip to content

Commit 176d7d7

Browse files
committed
iteration of setup() and integration engine
1 parent c2fd078 commit 176d7d7

File tree

2 files changed

+124
-54
lines changed

2 files changed

+124
-54
lines changed

setup.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
setup(
44
name='tagui',
5-
version='0.0.5',
5+
version='0.0.8',
66
py_modules=['tagui'],
77
author='Tebel.Automation',
88
author_email='[email protected]',
@@ -21,5 +21,7 @@
2121
'Operating System :: POSIX :: Linux',
2222
'Operating System :: MacOS :: MacOS X',
2323
'Operating System :: Microsoft :: Windows',
24+
'Topic :: Scientific/Engineering :: Artificial Intelligence',
25+
'Topic :: Software Development :: Libraries :: Python Modules',
2426
],
2527
)

tagui.py

Lines changed: 121 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919
# flag to track and print debug output
2020
_tagui_debug = False
2121

22-
# id to track instruction count between tagui-python and tagui
22+
# id to track instruction count from tagui python to tagui
2323
_tagui_id = 0
2424

2525
# delete tagui temp output text file to avoid reading old data
@@ -210,10 +210,19 @@ def setup():
210210
if os.path.isfile(temp_directory + '/' + tagui_zip_file):
211211
os.remove(temp_directory + '/' + tagui_zip_file)
212212

213+
# download stable delta files from tagui cutting edge version
214+
print('[TAGUI][INFO] - done. syncing TagUI files from stable cutting edge version')
215+
delta_list = ['tagui', 'tagui.cmd', 'tagui_header.js', 'tagui_parse.php']
216+
for delta_file in delta_list:
217+
tagui_delta_url = 'https://raw.githubusercontent.com/tebelorg/Tump/master/TagUI-Python/' + delta_file
218+
tagui_delta_file = temp_directory + '/' + 'tagui' + '/' + 'src' + '/' + delta_file
219+
if not download(tagui_delta_url, tagui_delta_file): return False
220+
213221
# perform Linux specific setup actions
214222
if platform.system() == 'Linux':
215223
# zipfile extractall does not preserve execute permissions
216224
# invoking chmod to set all files with execute permissions
225+
# and update delta tagui/src/tagui with execute permission
217226
if os.system('chmod -R 755 ' + temp_directory + '/' + 'tagui > /dev/null 2>&1') != 0:
218227
print('[TAGUI][ERROR] - unable to set permissions for tagui folder')
219228
return False
@@ -232,6 +241,7 @@ def setup():
232241
if platform.system() == 'Darwin':
233242
# zipfile extractall does not preserve execute permissions
234243
# invoking chmod to set all files with execute permissions
244+
# and update delta tagui/src/tagui with execute permission
235245
if os.system('chmod -R 755 ' + temp_directory + '/' + 'tagui > /dev/null 2>&1') != 0:
236246
print('[TAGUI][ERROR] - unable to set permissions for tagui folder')
237247
return False
@@ -276,7 +286,7 @@ def setup():
276286
# check that tagui packaged php is working, it has dependency on MSVCR110.dll
277287
if os.system(temp_directory + '/' + 'tagui' + '/' + 'src' + '/' + 'php/php.exe -v > nul 2>&1') != 0:
278288
print('[TAGUI][INFO] - now installing missing Visual C++ Redistributable dependency')
279-
vcredist_x86_url = 'https://github.com/tebelorg/Tump/raw/master/vcredist_x86.exe'
289+
vcredist_x86_url = 'https://raw.githubusercontent.com/tebelorg/Tump/master/vcredist_x86.exe'
280290
if download(vcredist_x86_url, temp_directory + '/vcredist_x86.exe'):
281291
os.system(temp_directory + '/vcredist_x86.exe')
282292

@@ -304,8 +314,18 @@ def init(visual_automation = False, chrome_browser = True):
304314
print('[TAGUI][ERROR] - use close() before using init() again')
305315
return False
306316

317+
# reset id to track instruction count from tagui python to tagui
318+
_tagui_id = 0
319+
320+
# get system temporary folder location to locate tagui executable
321+
temp_directory = tempfile.gettempdir()
322+
323+
# special handling for Linux as /tmp is non-executable by default
324+
if platform.system() == 'Linux':
325+
temp_directory = os.path.expanduser('~') + '/tmp'
326+
307327
# get system temporary folder location to form tagui executable path
308-
tagui_executable = tempfile.gettempdir() + '/' + 'tagui' + '/' + 'src' + '/' + 'tagui'
328+
tagui_executable = temp_directory + '/' + 'tagui' + '/' + 'src' + '/' + 'tagui'
309329

310330
# if tagui executable is not found, initiate setup() to install tagui
311331
if not os.path.isfile(tagui_executable):
@@ -320,14 +340,15 @@ def init(visual_automation = False, chrome_browser = True):
320340
shell_silencer = '> nul 2>&1'
321341
else:
322342
shell_silencer = '> /dev/null 2>&1'
343+
323344
if os.system('java -version ' + shell_silencer) != 0:
324345
print('[TAGUI][INFO] - for visual automation mode, Java JDK v8 (64-bit) or later is required')
325346
print('[TAGUI][INFO] - to use visual automation feature, download Java JDK v8 (64-bit) from below')
326347
print('[TAGUI][INFO] - https://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.html')
327348
return False
328349
else:
329350
# start a dummy first run if never run before, to let sikulix integrate jython
330-
sikulix_folder = tempfile.gettempdir() + '/' + 'tagui' + '/' + 'src' + '/' + 'sikulix'
351+
sikulix_folder = temp_directory + '/' + 'tagui' + '/' + 'src' + '/' + 'sikulix'
331352
if os.path.isfile(sikulix_folder + '/' + 'jython-standalone-2.7.1.jar'):
332353
os.system('java -jar ' + sikulix_folder + '/' + 'sikulix.jar -h ' + shell_silencer)
333354
_visual_flow()
@@ -371,11 +392,21 @@ def init(visual_automation = False, chrome_browser = True):
371392

372393
# check that tagui live mode is ready then start listening for inputs
373394
if 'LIVE MODE - type done to quit' in tagui_out:
374-
# print new line to clear live mode backspace character before listening
375-
_tagui_write('echo ""\n')
395+
# dummy + start line to clear live mode backspace char before listening
376396
_tagui_write('echo "[TAGUI][STARTED]"\n')
377397
_tagui_write('echo "[TAGUI][' + str(_tagui_id) + '] - listening for inputs"\n')
378398
_tagui_started = True
399+
400+
# loop until tagui live mode is ready and listening for inputs
401+
# also check _tagui_started to handle unexpected termination
402+
while _tagui_started and not _ready(): pass
403+
if not _tagui_started:
404+
print('[TAGUI][ERROR] - TagUI process ended unexpectedly')
405+
return False
406+
407+
# increment id and prepare for next instruction
408+
_tagui_id = _tagui_id + 1
409+
379410
return True
380411

381412
except Exception as e:
@@ -434,13 +465,6 @@ def send(tagui_instruction = None):
434465
_tagui_started = False
435466
return False
436467

437-
# loop until tagui live mode is ready and listening for inputs
438-
# also check _tagui_started to handle unexpected termination
439-
while _tagui_started and not _ready(): pass
440-
if not _tagui_started:
441-
print('[TAGUI][ERROR] - TagUI process ended unexpectedly')
442-
return False
443-
444468
# escape special characters for them to reach tagui correctly
445469
tagui_instruction = tagui_instruction.replace('\\','\\\\')
446470
tagui_instruction = tagui_instruction.replace('\n','\\n')
@@ -465,9 +489,18 @@ def send(tagui_instruction = None):
465489
# send live mode instruction to be executed
466490
_tagui_write(tagui_instruction + '\n')
467491

492+
# echo marker text to prepare for next instruction
493+
_tagui_write('echo "[TAGUI][' + str(_tagui_id) + '] - listening for inputs"\n')
494+
495+
# loop until tagui live mode is ready and listening for inputs
496+
# also check _tagui_started to handle unexpected termination
497+
while _tagui_started and not _ready(): pass
498+
if not _tagui_started:
499+
print('[TAGUI][ERROR] - TagUI process ended unexpectedly')
500+
return False
501+
468502
# increment id and prepare for next instruction
469503
_tagui_id = _tagui_id + 1
470-
_tagui_write('echo "[TAGUI][' + str(_tagui_id) + '] - listening for inputs"\n')
471504

472505
return True
473506

@@ -482,7 +515,6 @@ def close():
482515

483516
if not _tagui_started:
484517
print('[TAGUI][ERROR] - use init() before using close()')
485-
_tagui_started = False
486518
return False
487519

488520
try:
@@ -492,28 +524,23 @@ def close():
492524
_tagui_started = False
493525
return False
494526

495-
# loop until tagui live mode is ready and listening for inputs
496-
# also check _tagui_started to handle unexpected termination
497-
while _tagui_started and not _ready(): pass
498-
if not _tagui_started:
499-
print('[TAGUI][ERROR] - TagUI process ended unexpectedly')
500-
return False
501-
502527
# send 'done' instruction to terminate live mode and exit tagui
503528
_tagui_write('echo "[TAGUI][FINISHED]"\n')
504529
_tagui_write('done\n')
505530

506531
# loop until tagui process has closed before returning control
507532
while _process.poll() is None: pass
508533

509-
# remove generated tagui flow and log files if not in debug mode
534+
# remove generated tagui flow, js code and custom functions files
535+
if os.path.isfile('tagui_python'): os.remove('tagui_python')
536+
if os.path.isfile('tagui_python.js'): os.remove('tagui_python.js')
537+
if os.path.isfile('tagui_python.raw'): os.remove('tagui_python.raw')
538+
if os.path.isfile('tagui_local.js'): os.remove('tagui_local.js')
539+
540+
# remove generated tagui log and data files if not in debug mode
510541
if not debug():
511-
if os.path.isfile('tagui_python'): os.remove('tagui_python')
512-
if os.path.isfile('tagui_python.js'): os.remove('tagui_python.js')
513-
if os.path.isfile('tagui_python.raw'): os.remove('tagui_python.raw')
514542
if os.path.isfile('tagui_python.log'): os.remove('tagui_python.log')
515543
if os.path.isfile('tagui_python.txt'): os.remove('tagui_python.txt')
516-
if os.path.isfile('tagui_local.js'): os.remove('tagui_local.js')
517544

518545
_tagui_started = False
519546
return True
@@ -531,7 +558,7 @@ def exist(element_identifier = None):
531558
if element_identifier is None or element_identifier == '':
532559
return False
533560

534-
# check for existence of specified image file for visual automation
561+
# pre-emptive check for existence of specified image file for visual automation
535562
if element_identifier.lower().endswith('.png') or element_identifier.lower().endswith('.bmp'):
536563
if not os.path.isfile(element_identifier):
537564
print('[TAGUI][ERROR] - missing image file ' + element_identifier)
@@ -685,7 +712,7 @@ def type(element_identifier = None, text_to_type = None, test_coordinate = None)
685712
else:
686713
return True
687714

688-
def select(element_identifier = None, option_value = None, test_coordinate = None):
715+
def select(element_identifier = None, option_value = None, test_coordinate1 = None, test_coordinate2 = None):
689716
if not _started():
690717
print('[TAGUI][ERROR] - use init() before using select()')
691718
return False
@@ -698,9 +725,21 @@ def select(element_identifier = None, option_value = None, test_coordinate = Non
698725
print('[TAGUI][ERROR] - option value missing for select()')
699726
return False
700727

701-
if test_coordinate is not None and isinstance(option_value, int):
728+
if test_coordinate1 is not None and test_coordinate2 is not None and \
729+
isinstance(option_value, int) and isinstance(test_coordinate2, int):
702730
element_identifier = coord(element_identifier, option_value)
703-
option_value = test_coordinate
731+
option_value = coord(test_coordinate1, test_coordinate2)
732+
733+
# pre-emptive checks if image files are specified for visual automation
734+
if element_identifier.lower().endswith('.png') or element_identifier.lower().endswith('.bmp'):
735+
if not os.path.isfile(element_identifier):
736+
print('[TAGUI][ERROR] - missing image file ' + element_identifier)
737+
return False
738+
739+
if option_value.lower().endswith('.png') or option_value.lower().endswith('.bmp'):
740+
if not os.path.isfile(option_value):
741+
print('[TAGUI][ERROR] - missing image file ' + option_value)
742+
return False
704743

705744
if not exist(element_identifier):
706745
print('[TAGUI][ERROR] - cannot find ' + element_identifier)
@@ -847,8 +886,15 @@ def write(text_to_write = None, filename_to_save = None):
847886
return True
848887

849888
def ask(text_to_prompt = ''):
850-
if _python2_env(): return raw_input(text_to_prompt + ' ')
851-
else: return input(text_to_prompt + ' ')
889+
if text_to_prompt == '':
890+
space_padding = ''
891+
else:
892+
space_padding = ' '
893+
894+
if _python2_env():
895+
return raw_input(text_to_prompt + space_padding)
896+
else:
897+
return input(text_to_prompt + space_padding)
852898

853899
def keyboard(keys_and_modifiers = None):
854900
if not _started():
@@ -962,31 +1008,29 @@ def download(download_url = None, filename_to_save = None):
9621008
if os.path.isfile(filename_to_save):
9631009
os.remove(filename_to_save)
9641010

965-
if _python2_env():
966-
import urllib; urllib.urlretrieve(download_url, filename_to_save)
967-
else:
968-
import urllib.request; urllib.request.urlretrieve(download_url, filename_to_save)
1011+
# handle case where url is invalid or has no content
1012+
try:
1013+
if _python2_env():
1014+
import urllib; urllib.urlretrieve(download_url, filename_to_save)
1015+
else:
1016+
import urllib.request; urllib.request.urlretrieve(download_url, filename_to_save)
9691017

1018+
except Exception as e:
1019+
print('[TAGUI][ERROR] - failed downloading from ' + download_url)
1020+
return False
1021+
1022+
# take the existence of downloaded file as success
9701023
if os.path.isfile(filename_to_save):
9711024
return True
1025+
9721026
else:
973-
print('[TAGUI][ERROR] - downloading to ' + filename_to_save + ' failed)')
1027+
print('[TAGUI][ERROR] - failed downloading to ' + filename_to_save)
9741028
return False
9751029

9761030
def api(url_to_query = None):
977-
if not _started():
978-
print('[TAGUI][ERROR] - use init() before using api()')
979-
return ''
980-
981-
if url_to_query is None or url_to_query == '':
982-
print('[TAGUI][ERROR] - API URL missing for api()')
983-
return ''
984-
985-
else:
986-
send('api ' + _esq(url_to_query))
987-
send('dump api_result to tagui_python.txt')
988-
api_result = _tagui_output()
989-
return api_result
1031+
print('[TAGUI][INFO] - although TagUI supports calling APIs with headers and body,')
1032+
print('[TAGUI][INFO] - users better off with requests package - lots of online docs')
1033+
return True
9901034

9911035
def run(command_to_run = None):
9921036
if command_to_run is None or command_to_run == '':
@@ -1009,7 +1053,7 @@ def dom(statement_to_run = None):
10091053
return ''
10101054

10111055
else:
1012-
send('dom ' + _esq(statement_to_run))
1056+
send('dom ' + statement_to_run)
10131057
send('dump dom_result to tagui_python.txt')
10141058
dom_result = _tagui_output()
10151059
return dom_result
@@ -1023,7 +1067,7 @@ def vision(command_to_run = None):
10231067
print('[TAGUI][ERROR] - command(s) missing for vision()')
10241068
return False
10251069

1026-
elif not send('vision ' + _esq(command_to_run)):
1070+
elif not send('vision ' + command_to_run):
10271071
return False
10281072

10291073
else:
@@ -1056,6 +1100,18 @@ def present(element_identifier = None):
10561100
if element_identifier is None or element_identifier == '':
10571101
return False
10581102

1103+
# check for existence of specified image file for visual automation
1104+
if element_identifier.lower().endswith('.png') or element_identifier.lower().endswith('.bmp'):
1105+
if not os.path.isfile(element_identifier):
1106+
print('[TAGUI][ERROR] - missing image file ' + element_identifier)
1107+
return False
1108+
1109+
# assume that (x,y) coordinates for visual automation always exist
1110+
if element_identifier.startswith('(') and element_identifier.endswith(')'):
1111+
if len(element_identifier.split(',')) == 2:
1112+
if not any(c.isalpha() for c in element_identifier):
1113+
return True
1114+
10591115
send('present_result = present(\'' + _sdq(element_identifier) + '\').toString()')
10601116
send('dump present_result to tagui_python.txt')
10611117
if _tagui_output() == 'true':
@@ -1071,6 +1127,18 @@ def visible(element_identifier = None):
10711127
if element_identifier is None or element_identifier == '':
10721128
return False
10731129

1130+
# check for existence of specified image file for visual automation
1131+
if element_identifier.lower().endswith('.png') or element_identifier.lower().endswith('.bmp'):
1132+
if not os.path.isfile(element_identifier):
1133+
print('[TAGUI][ERROR] - missing image file ' + element_identifier)
1134+
return False
1135+
1136+
# assume that (x,y) coordinates for visual automation always exist
1137+
if element_identifier.startswith('(') and element_identifier.endswith(')'):
1138+
if len(element_identifier.split(',')) == 2:
1139+
if not any(c.isalpha() for c in element_identifier):
1140+
return True
1141+
10741142
send('visible_result = visible(\'' + _sdq(element_identifier) + '\').toString()')
10751143
send('dump visible_result to tagui_python.txt')
10761144
if _tagui_output() == 'true':

0 commit comments

Comments
 (0)