Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse code

initial git commit

  • Loading branch information...
commit ef8c4d87589f8229eab8fb3739cfe3d202d875fe 1 parent ceb0ca3
Md. Shaiful Islam authored

Showing 70 changed files with 9,236 additions and 0 deletions. Show diff stats Hide diff stats

  1. +479 0 easyprocess/__init__.py
  2. 0  easyprocess/examples/__init__.py
  3. +18 0 easyprocess/examples/log.py
  4. +5 0 easyprocess/examples/ver.py
  5. +64 0 easyprocess/unicodeutil.py
  6. +186 0 main.py
  7. +7 0 pyvirtualdisplay/__init__.py
  8. +95 0 pyvirtualdisplay/abstractdisplay.py
  9. +57 0 pyvirtualdisplay/display.py
  10. 0  pyvirtualdisplay/examples/__init__.py
  11. +5 0 pyvirtualdisplay/examples/lowres.py
  12. +9 0 pyvirtualdisplay/examples/screenshot1.py
  13. +15 0 pyvirtualdisplay/examples/screenshot3.py
  14. +25 0 pyvirtualdisplay/examples/screenshot4.py
  15. +14 0 pyvirtualdisplay/examples/vncserver.py
  16. +90 0 pyvirtualdisplay/smartdisplay.py
  17. +39 0 pyvirtualdisplay/xephyr.py
  18. +45 0 pyvirtualdisplay/xvfb.py
  19. +44 0 pyvirtualdisplay/xvnc.py
  20. +19 0 selenium/__init__.py
  21. +16 0 selenium/common/__init__.py
  22. +122 0 selenium/common/exceptions.py
  23. +2,111 0 selenium/selenium.py
  24. +31 0 selenium/webdriver/__init__.py
  25. +14 0 selenium/webdriver/chrome/__init__.py
  26. +132 0 selenium/webdriver/chrome/options.py
  27. +108 0 selenium/webdriver/chrome/service.py
  28. +82 0 selenium/webdriver/chrome/webdriver.py
  29. +14 0 selenium/webdriver/common/__init__.py
  30. +253 0 selenium/webdriver/common/action_chains.py
  31. +39 0 selenium/webdriver/common/alert.py
  32. +25 0 selenium/webdriver/common/by.py
  33. +93 0 selenium/webdriver/common/desired_capabilities.py
  34. 0  selenium/webdriver/common/html5/__init__.py
  35. +17 0 selenium/webdriver/common/html5/application_cache.py
  36. +84 0 selenium/webdriver/common/keys.py
  37. +136 0 selenium/webdriver/common/proxy.py
  38. +165 0 selenium/webdriver/common/touch_actions.py
  39. +46 0 selenium/webdriver/common/utils.py
  40. +14 0 selenium/webdriver/firefox/__init__.py
  41. +79 0 selenium/webdriver/firefox/extension_connection.py
  42. +178 0 selenium/webdriver/firefox/firefox_binary.py
  43. +376 0 selenium/webdriver/firefox/firefox_profile.py
  44. +84 0 selenium/webdriver/firefox/webdriver.py
  45. BIN  selenium/webdriver/firefox/webdriver.xpi
  46. +16 0 selenium/webdriver/ie/__init__.py
  47. +106 0 selenium/webdriver/ie/service.py
  48. +56 0 selenium/webdriver/ie/webdriver.py
  49. +14 0 selenium/webdriver/opera/__init__.py
  50. +80 0 selenium/webdriver/opera/service.py
  51. +68 0 selenium/webdriver/opera/webdriver.py
  52. +13 0 selenium/webdriver/phantomjs/__init__.py
  53. +96 0 selenium/webdriver/phantomjs/service.py
  54. +78 0 selenium/webdriver/phantomjs/webdriver.py
  55. +14 0 selenium/webdriver/remote/__init__.py
  56. +144 0 selenium/webdriver/remote/command.py
  57. +152 0 selenium/webdriver/remote/errorhandler.py
  58. +408 0 selenium/webdriver/remote/remote_connection.py
  59. +112 0 selenium/webdriver/remote/utils.py
  60. +824 0 selenium/webdriver/remote/webdriver.py
  61. +286 0 selenium/webdriver/remote/webelement.py
  62. +16 0 selenium/webdriver/support/__init__.py
  63. +59 0 selenium/webdriver/support/abstract_event_listener.py
  64. +303 0 selenium/webdriver/support/color.py
  65. +326 0 selenium/webdriver/support/event_firing_webdriver.py
  66. +18 0 selenium/webdriver/support/events.py
  67. +283 0 selenium/webdriver/support/expected_conditions.py
  68. +223 0 selenium/webdriver/support/select.py
  69. +19 0 selenium/webdriver/support/ui.py
  70. +87 0 selenium/webdriver/support/wait.py
479 easyprocess/__init__.py
... ... @@ -0,0 +1,479 @@
  1 +'''
  2 +Easy to use python subprocess interface.
  3 +'''
  4 +
  5 +from easyprocess.unicodeutil import split_command, unidecode, uniencode
  6 +import logging
  7 +import os.path
  8 +import platform
  9 +import signal
  10 +import subprocess
  11 +import sys
  12 +import tempfile
  13 +import threading
  14 +import time
  15 +import ConfigParser
  16 +
  17 +__version__ = '0.1.6'
  18 +
  19 +log = logging.getLogger(__name__)
  20 +# log=logging
  21 +
  22 +log.debug('version=' + __version__)
  23 +
  24 +CONFIG_FILE = '.easyprocess.cfg'
  25 +SECTION_LINK = 'link'
  26 +POLL_TIME = 0.1
  27 +USE_POLL = 0
  28 +
  29 +
  30 +class EasyProcessError(Exception):
  31 + """
  32 + """
  33 + def __init__(self, easy_process, msg=''):
  34 + self.easy_process = easy_process
  35 + self.msg = msg
  36 +
  37 + def __str__(self):
  38 + return self.msg + ' ' + repr(self.easy_process)
  39 +
  40 +template = '''cmd=%s
  41 +OSError=%s
  42 +Program install error! '''
  43 +
  44 +
  45 +class EasyProcessCheckInstalledError(Exception):
  46 + """This exception is raised when a process run by check() returns
  47 + a non-zero exit status or OSError is raised.
  48 + """
  49 + def __init__(self, easy_process):
  50 + self.easy_process = easy_process
  51 +
  52 + def __str__(self):
  53 + msg = template % (self.easy_process.cmd,
  54 + self.easy_process.oserror,
  55 + )
  56 + if self.easy_process.url:
  57 + msg += '\nhome page: ' + self.easy_process.url
  58 + if platform.dist()[0].lower() == 'ubuntu':
  59 + if self.easy_process.ubuntu_package:
  60 + msg += '\nYou can install it in terminal:\n'
  61 + msg += 'sudo apt-get install %s' % self.easy_process.ubuntu_package
  62 + return msg
  63 +
  64 +
  65 +class EasyProcess():
  66 + '''
  67 + .. module:: easyprocess
  68 +
  69 + simple interface for :mod:`subprocess`
  70 +
  71 + shell is not supported (shell=False)
  72 +
  73 + .. warning::
  74 +
  75 + unicode is supported only for string list command (Python2.x)
  76 + (check :mod:`shlex` for more information)
  77 +
  78 + :param cmd: string ('ls -l') or list of strings (['ls','-l'])
  79 + :param cwd: working directory
  80 + :param use_temp_files: use temp files instead of pipes for
  81 + stdout and stderr,
  82 + pipes can cause deadlock in some cases
  83 + (see unit tests)
  84 + '''
  85 + config = None
  86 +
  87 + def __init__(self, cmd, ubuntu_package=None, url=None, cwd=None, use_temp_files=True):
  88 + self.use_temp_files = use_temp_files
  89 + self._outputs_processed = False
  90 +
  91 + self.popen = None
  92 + self.stdout = None
  93 + self.stderr = None
  94 + self._stdout_file = None
  95 + self._stderr_file = None
  96 + self.url = url
  97 + self.ubuntu_package = ubuntu_package
  98 + self.is_started = False
  99 + self.oserror = None
  100 + self.cmd_param = cmd
  101 + self._thread = None
  102 +# self.max_bytes_to_log = max_bytes_to_log
  103 + self._stop_thread = False
  104 + self.timeout_happened = False
  105 + self.cwd = cwd
  106 + cmd = split_command(cmd)
  107 + self.cmd = cmd
  108 + self.cmd_as_string = ' '.join(self.cmd) # TODO: not perfect
  109 +
  110 + log.debug('param: "%s" command: %s ("%s")' % (
  111 + self.cmd_param, self.cmd, self.cmd_as_string))
  112 +
  113 + if not len(cmd):
  114 + raise EasyProcessError(self, 'empty command!')
  115 +
  116 + if not Proc.config:
  117 + conf_file = os.path.join(os.path.expanduser('~'), CONFIG_FILE)
  118 + log.debug('reading config: %s' % (conf_file))
  119 + Proc.config = ConfigParser.RawConfigParser()
  120 + Proc.config.read(conf_file)
  121 +
  122 + self.alias = None
  123 + try:
  124 + self.alias = Proc.config.get(SECTION_LINK, self.cmd[0])
  125 + except ConfigParser.NoSectionError:
  126 + pass
  127 + except ConfigParser.NoOptionError:
  128 + pass
  129 +
  130 + if self.alias:
  131 + log.debug('alias found: %s' % (self.alias))
  132 + self.cmd[0] = self.alias
  133 +
  134 + def __repr__(self):
  135 + msg = '<%s cmd_param=%s alias={alias} cmd=%s ({scmd}) oserror=%s returncode=%s stdout="%s" stderr="%s" timeout=%s>' % (
  136 + self.__class__.__name__,
  137 + self.cmd_param,
  138 + self.cmd,
  139 + self.oserror,
  140 + # alias=self.alias,
  141 + self.return_code,
  142 + self.stdout,
  143 + self.stderr,
  144 + # scmd=' '.join(self.cmd),
  145 + self.timeout_happened,
  146 + )
  147 + return msg
  148 +
  149 + @property
  150 + def pid(self):
  151 + '''
  152 + PID (:attr:`subprocess.Popen.pid`)
  153 +
  154 + :rtype: int
  155 + '''
  156 + if self.popen:
  157 + return self.popen.pid
  158 +
  159 + @property
  160 + def return_code(self):
  161 + '''
  162 + returncode (:attr:`subprocess.Popen.returncode`)
  163 +
  164 + :rtype: int
  165 + '''
  166 + if self.popen:
  167 + return self.popen.returncode
  168 +
  169 + def check(self, return_code=0):
  170 + '''
  171 + Run command with arguments. Wait for command to complete.
  172 + If the exit code was as expected and there is no exception then return,
  173 + otherwise raise EasyProcessError.
  174 +
  175 + :param return_code: int, expected return code
  176 + :rtype: self
  177 + '''
  178 +# try:
  179 +# ret = self.call().return_code
  180 +# ok = ret == return_code
  181 +# except Exception , e:
  182 +# log.debug('OSError exception:' + str(oserror))
  183 +# ok = False
  184 +# self.oserror = oserror
  185 +
  186 + ret = self.call().return_code
  187 + ok = ret == return_code
  188 + if not ok:
  189 + raise EasyProcessError(
  190 + self, 'check error, return code is not zero!')
  191 + return self
  192 +
  193 + def check_installed(self):
  194 + '''
  195 + Used for testing if program is installed.
  196 +
  197 + Run command with arguments. Wait for command to complete.
  198 + If OSError raised, then raise :class:`EasyProcessCheckInstalledError`
  199 + with information about program installation
  200 +
  201 + :param return_code: int, expected return code
  202 + :rtype: self
  203 + '''
  204 + try:
  205 + self.call()
  206 + except Exception:
  207 + # log.debug('exception:' + str(e))
  208 + # self.oserror = oserror
  209 + raise EasyProcessCheckInstalledError(self)
  210 + return self
  211 +
  212 + def call(self, timeout=None):
  213 + '''
  214 + Run command with arguments. Wait for command to complete.
  215 +
  216 + same as:
  217 + 1. :meth:`start`
  218 + 2. :meth:`wait`
  219 + 3. :meth:`stop`
  220 +
  221 + :rtype: self
  222 + '''
  223 + self.start().wait(timeout=timeout)
  224 + if self.is_alive():
  225 + self.stop()
  226 + return self
  227 +
  228 + def start(self):
  229 + '''
  230 + start command in background and does not wait for it
  231 +
  232 +
  233 + :rtype: self
  234 + '''
  235 + if self.is_started:
  236 + raise EasyProcessError(self, 'process was started twice!')
  237 +
  238 + if self.use_temp_files:
  239 + self._stdout_file = tempfile.TemporaryFile(prefix='stdout_')
  240 + self._stderr_file = tempfile.TemporaryFile(prefix='stderr_')
  241 + stdout = self._stdout_file
  242 + stderr = self._stderr_file
  243 +
  244 + else:
  245 + stdout = subprocess.PIPE
  246 + stderr = subprocess.PIPE
  247 +
  248 + cmd = list(map(uniencode, self.cmd))
  249 +
  250 + try:
  251 + self.popen = subprocess.Popen(cmd,
  252 + stdout=stdout,
  253 + stderr=stderr,
  254 + # shell=1,
  255 + cwd=self.cwd,
  256 + )
  257 + except OSError, oserror:
  258 + log.debug('OSError exception:%s' % (oserror))
  259 + self.oserror = oserror
  260 + raise EasyProcessError(self, 'start error')
  261 + self.is_started = True
  262 + log.debug('process was started (pid=%s)' % (str(self.pid),))
  263 +
  264 +# def target():
  265 +# self._wait4process()
  266 +
  267 +# def shutdown():
  268 +# self._stop_thread = True
  269 +# self._thread.join()
  270 +
  271 +# self._thread = threading.Thread(target=target)
  272 +# self._thread.daemon = 1
  273 +# self._thread.start()
  274 +# atexit.register(shutdown)
  275 +
  276 + return self
  277 +
  278 + def is_alive(self):
  279 + '''
  280 + poll process using :meth:`subprocess.Popen.poll`
  281 +
  282 + :rtype: bool
  283 + '''
  284 + if self.popen:
  285 + return self.popen.poll() is None
  286 + else:
  287 + return False
  288 +
  289 + def wait(self, timeout=None):
  290 + '''
  291 + Wait for command to complete.
  292 +
  293 + Timeout:
  294 + - discussion: http://stackoverflow.com/questions/1191374/subprocess-with-timeout
  295 + - implementation: threading
  296 +
  297 + :rtype: self
  298 + '''
  299 +
  300 + if timeout is not None:
  301 + if not self._thread:
  302 + self._thread = threading.Thread(target=self._wait4process)
  303 + self._thread.daemon = 1
  304 + self._thread.start()
  305 +
  306 + if self._thread:
  307 + self._thread.join(timeout=timeout)
  308 + self.timeout_happened = self.timeout_happened or self._thread.isAlive()
  309 + else:
  310 + # no timeout and no existing thread
  311 + self._wait4process()
  312 +
  313 + return self
  314 +
  315 + def _wait4process(self):
  316 + if self._outputs_processed:
  317 + return
  318 +
  319 + def remove_ending_lf(s):
  320 + if s.endswith('\n'):
  321 + return s[:-1]
  322 + else:
  323 + return s
  324 +
  325 + if self.popen:
  326 + if self.use_temp_files:
  327 + if USE_POLL:
  328 + while 1:
  329 + if self.popen.poll() is not None:
  330 + break
  331 + if self._stop_thread:
  332 + return
  333 + time.sleep(POLL_TIME)
  334 +
  335 + else:
  336 + # wait() blocks process, timeout not possible
  337 + self.popen.wait()
  338 +
  339 + self._outputs_processed = True
  340 + self._stdout_file.seek(0)
  341 + self._stderr_file.seek(0)
  342 + self.stdout = self._stdout_file.read()
  343 + self.stderr = self._stderr_file.read()
  344 +
  345 + self._stdout_file.close()
  346 + self._stderr_file.close()
  347 + else:
  348 + # This will deadlock when using stdout=PIPE and/or stderr=PIPE
  349 + # and the child process generates enough output to a pipe such
  350 + # that it blocks waiting for the OS pipe buffer to accept more data.
  351 + # Use communicate() to avoid that.
  352 + # self.popen.wait()
  353 + # self.stdout = self.popen.stdout.read()
  354 + # self.stderr = self.popen.stderr.read()
  355 +
  356 + # communicate() blocks process, timeout not possible
  357 + self._outputs_processed = True
  358 + (self.stdout, self.stderr) = self.popen.communicate()
  359 + log.debug('process has ended')
  360 + self.stdout = remove_ending_lf(unidecode(self.stdout))
  361 + self.stderr = remove_ending_lf(unidecode(self.stderr))
  362 +
  363 + log.debug('return code=' + str(self.return_code))
  364 +# def limit_str(s):
  365 +# if len(s) > self.max_bytes_to_log:
  366 +# warn = '[middle of output was removed, max_bytes_to_log=%s]'%(self.max_bytes_to_log)
  367 +# s = s[:self.max_bytes_to_log / 2] + warn + s[-self.max_bytes_to_log / 2:]
  368 +# return s
  369 + log.debug('stdout=' + (self.stdout))
  370 + log.debug('stderr=' + (self.stderr))
  371 +
  372 + def stop(self):
  373 + '''
  374 + Kill process
  375 + and wait for command to complete.
  376 +
  377 + same as:
  378 + 1. :meth:`sendstop`
  379 + 2. :meth:`wait`
  380 +
  381 + :rtype: self
  382 + '''
  383 + return self.sendstop().wait()
  384 +
  385 + def sendstop(self):
  386 + '''
  387 + Kill process (:meth:`subprocess.Popen.terminate`).
  388 + Do not wait for command to complete.
  389 +
  390 + :rtype: self
  391 + '''
  392 + if not self.is_started:
  393 + raise EasyProcessError(self, 'process was not started!')
  394 +
  395 + log.debug(
  396 + 'stopping process (pid=%s cmd="%s")' % (str(self.pid), self.cmd))
  397 + if self.popen:
  398 + if self.is_alive():
  399 + log.debug('process is active -> sending SIGTERM')
  400 +
  401 + try:
  402 + try:
  403 + self.popen.terminate()
  404 + except AttributeError:
  405 + os.kill(self.popen.pid, signal.SIGKILL)
  406 + except OSError, oserror:
  407 + log.debug('exception in terminate:%s' % (oserror))
  408 +
  409 + else:
  410 + log.debug('process was already stopped')
  411 + else:
  412 + log.debug('process was not started')
  413 +
  414 + return self
  415 +
  416 + def sleep(self, sec):
  417 + '''
  418 + sleeping (same as :func:`time.sleep`)
  419 +
  420 + :rtype: self
  421 + '''
  422 + time.sleep(sec)
  423 +
  424 + return self
  425 +
  426 + def wrap(self, func, delay=0):
  427 + '''
  428 + returns a function which:
  429 + 1. start process
  430 + 2. call func, save result
  431 + 3. stop process
  432 + 4. returns result
  433 +
  434 + similar to :keyword:`with` statement
  435 +
  436 + :rtype:
  437 + '''
  438 + def wrapped():
  439 + self.start()
  440 + if delay:
  441 + self.sleep(delay)
  442 + x = None
  443 + try:
  444 + x = func()
  445 + except OSError, oserror:
  446 + log.debug('OSError exception:%s' % (oserror))
  447 + self.oserror = oserror
  448 + raise EasyProcessError(self, 'wrap error!')
  449 + finally:
  450 + self.stop()
  451 + return x
  452 + return wrapped
  453 +
  454 + def __enter__(self):
  455 + '''used by the :keyword:`with` statement'''
  456 + self.start()
  457 + return self
  458 +
  459 + def __exit__(self, *exc_info):
  460 + '''used by the :keyword:`with` statement'''
  461 + self.stop()
  462 +
  463 +
  464 +def extract_version(txt):
  465 + '''This function tries to extract the version from the help text of any program.
  466 + '''
  467 + words = txt.replace(',', ' ').split()
  468 + version = None
  469 + for x in reversed(words):
  470 + if len(x) > 2:
  471 + if x[0].lower() == 'v':
  472 + x = x[1:]
  473 + if '.' in x and x[0].isdigit():
  474 + version = x
  475 + break
  476 + return version
  477 +
  478 +
  479 +Proc = EasyProcess
0  easyprocess/examples/__init__.py
No changes.
18 easyprocess/examples/log.py
... ... @@ -0,0 +1,18 @@
  1 +from easyprocess import EasyProcess
  2 +import logging
  3 +
  4 +# turn on logging
  5 +logging.basicConfig(level=logging.DEBUG)
  6 +
  7 +EasyProcess('python --version').call()
  8 +EasyProcess('ping localhost').start().sleep(1).stop()
  9 +EasyProcess('python --version').check()
  10 +try:
  11 + EasyProcess('bad_command').check()
  12 +except Exception, detail:
  13 + print detail
  14 +
  15 +try:
  16 + EasyProcess('sh -c bad_command').check()
  17 +except Exception, detail:
  18 + print detail
5 easyprocess/examples/ver.py
... ... @@ -0,0 +1,5 @@
  1 +from easyprocess import EasyProcess
  2 +import sys
  3 +
  4 +v = EasyProcess([sys.executable, '--version']).call().stderr
  5 +print('your python version:%s' % v)
64 easyprocess/unicodeutil.py
... ... @@ -0,0 +1,64 @@
  1 +import logging
  2 +import shlex
  3 +import sys
  4 +import unicodedata
  5 +
  6 +log = logging.getLogger(__name__)
  7 +
  8 +PY3 = sys.version_info[0] >= 3
  9 +
  10 +if PY3:
  11 + string_types = str,
  12 +else:
  13 + string_types = basestring,
  14 +
  15 +
  16 +class EasyProcessUnicodeError(Exception):
  17 + pass
  18 +
  19 +
  20 +def split_command(cmd):
  21 + '''
  22 + - cmd is string list -> nothing to do
  23 + - cmd is string -> split it using shlex
  24 +
  25 + :param cmd: string ('ls -l') or list of strings (['ls','-l'])
  26 + :rtype: string list
  27 + '''
  28 + if not isinstance(cmd, string_types):
  29 + # cmd is string list
  30 + pass
  31 + else:
  32 + if not PY3:
  33 + # cmd is string
  34 + # The shlex module currently does not support Unicode input (in
  35 + # 2.x)!
  36 + if isinstance(cmd, unicode):
  37 + try:
  38 + cmd = unicodedata.normalize(
  39 + 'NFKD', cmd).encode('ascii', 'strict')
  40 + except UnicodeEncodeError:
  41 + raise EasyProcessUnicodeError('unicode command "%s" can not be processed.' % cmd +
  42 + 'Use string list instead of string')
  43 + log.debug('unicode is normalized')
  44 + cmd = shlex.split(cmd)
  45 + return cmd
  46 +
  47 +
  48 +def uniencode(s):
  49 + if PY3:
  50 + pass
  51 +# s=s.encode()
  52 + else:
  53 + if isinstance(s, unicode):
  54 + s = s.encode('utf-8')
  55 + return s
  56 +
  57 +
  58 +def unidecode(s):
  59 + if PY3:
  60 + s = s.decode()
  61 + else:
  62 + if isinstance(s, str):
  63 + s = s.decode('utf-8')
  64 + return s
186 main.py
... ... @@ -0,0 +1,186 @@
  1 +#!/usr/bin/env python
  2 +
  3 +import os, time, datetime
  4 +#from pyvirtualdisplay import Display
  5 +from selenium import webdriver
  6 +from selenium.common.exceptions import NoSuchElementException
  7 +from selenium.webdriver.common.keys import Keys
  8 +
  9 +class seleniumApp:
  10 + def __init__( self ):
  11 + #site specific variables
  12 + self.url = 'https://www.24option.com/24option/#Trade'
  13 + self.asset = 'EUR/USD'
  14 + self.assetXtraContent = ' <span class="optionRow_asset_description_HiLo">&nbsp;</span>'
  15 + self.assetDirection = 'High'
  16 + self.username = 'pacificcoder';
  17 + self.password = 'go4succeSS'
  18 + self.pageSaveDir = 'pages/'
  19 + self.logfile = 'application_log.txt'
  20 + self.max_waiting_time = 5
  21 +
  22 + #display = Display(visible=0, size=(1024, 768))
  23 + #display.start()
  24 +
  25 + #init Selenium Webdriver
  26 + self.driver = webdriver.Firefox()
  27 +
  28 + #self.driver = webdriver.Chrome()
  29 +
  30 + def startScrap(self):
  31 + driver = self.driver
  32 + driver.get(self.url)
  33 +
  34 + try:
  35 + time.sleep(self.max_waiting_time)
  36 + elemResultTable = self.getElementByXpath("//table[@class='options_rows_list']", True)
  37 + if(elemResultTable):
  38 + self.log("main result table found")
  39 +
  40 + # click the "shot term tab"
  41 + elemShortTermTab = self.getElementByXpath('//div[@class="instrument_tab_ShortTerm"]' )
  42 + if(elemShortTermTab):
  43 + elemShortTermTab.click()
  44 + self.log("shot term tab clicked")
  45 + time.sleep(2)
  46 +
  47 + # click "60 seconds button"
  48 + elemSixtySecondButton = self.getElementByXpath('//div[@class="instrumentTypePanel"]//div[text()="60 seconds"]', True)
  49 + if(elemSixtySecondButton):
  50 + elemSixtySecondButton.click()
  51 + self.log("60 seconds button clicked")
  52 + time.sleep(2)
  53 +
  54 + #elemAsset = self.getElementByXpath('//table[@class="optionRow_layout"]//tr//td[@class="optionRow_asset"]//div[text()="'+self.asset+'"][1]' )
  55 + elemAsset = self.getElementByXpath('//table[@class="optionRow_layout"]//tr//td[@class="optionRow_asset"]//div[@title="Euro-Dollar"][1]' )
  56 +
  57 + if(elemAsset):
  58 + self.log("asset row found")
  59 + self.log(elemAsset.text)
  60 + elemAsset.click()
  61 + time.sleep(.5)
  62 +
  63 + elemTextOptionView = self.getElementByXpath('//table[@class="textOptionView"]')
  64 + if(elemTextOptionView):
  65 + self.log("textOptionView found")
  66 + elemPriceValue = self.getAssetPrice()
  67 + if(elemPriceValue):
  68 + self.log("price found: "+elemPriceValue.text)
  69 +
  70 + if(self.assetDirection == 'High'):
  71 + elemAssetDirection = self.getElementByXpath('//table[@class="textOptionView_innerContainer_HiLo"]//td[@class="textOptionView_call"]//div[1]')
  72 + if(elemAssetDirection):
  73 + elemAssetDirection.click()
  74 + self.log("High asset value clicked")
  75 + time.sleep(.2)
  76 +
  77 + elemYourSelectionInput = self.getElementByXpath('//table[@class="optionMode_amount"]//tbody//tr//td[3]//input')
  78 + if(elemYourSelectionInput):
  79 + self.log('Your selection input field found')
  80 + elemYourSelectionInput.send_keys("99" + Keys.RETURN)
  81 + time.sleep(.2)
  82 +
  83 + elemLoginPopupBox = self.getElementByXpath('//div[@class="loginPopup"]')
  84 + if(elemLoginPopupBox):
  85 + self.log('login popupbox found')
  86 + time.sleep(.2)
  87 +
  88 + elemLoginUsername = self.getElementByXpath('//div[@class="loginBoxLayout"]//input[1]')
  89 + if(elemLoginUsername):
  90 + self.log('Username input field found')
  91 + elemLoginUsername.send_keys(self.username)
  92 +
  93 + elemLoginPassword = self.getElementByXpath('//div[@class="loginBoxLayout"]//div[5]//input[1]')
  94 + if(elemLoginPassword):
  95 + self.log('Password input field found')
  96 + elemLoginPassword.send_keys(self.password)
  97 +
  98 + elemLoginButton = self.getElementByXpath('//div[@class="loginBoxLayout"]//div[@id="loginButton"]//input[1]')
  99 + if(elemLoginButton):
  100 + self.log('LoginButton found')
  101 + elemLoginButton.click()
  102 +
  103 + time.sleep(5)
  104 +
  105 +
  106 + elemBuyButton = self.getElementByXpath('//table[@class="optionMode_amount"]//tbody//tr//td[4]//div[1]')
  107 + if(elemBuyButton):
  108 + self.log('Buy button clicked')
  109 + elemBuyButton.click()
  110 +
  111 + time.sleep(10)
  112 +
  113 + else:
  114 + self.log("asset row not found")
  115 + else:
  116 + self.log("table not found")
  117 +
  118 + except NoSuchElementException:
  119 + print "Result table not found"
  120 +
  121 + driver.quit()
  122 +
  123 + def getAssetPrice(self):
  124 + elemPriceValue = self.getElementByXpath('//table[@class="textOptionView_innerContainer_HiLo"]//tbody//tr[2]//td//div[1]//div[1]')
  125 + return elemPriceValue
  126 +
  127 + #get element
  128 + def getElementByXpath(self, regex, waitForElement = False):
  129 + try:
  130 + elem = self.driver.find_element_by_xpath(regex) # Find the query box
  131 + if(elem):
  132 + return elem
  133 + else:
  134 + time.sleep(self.max_waiting_time)
  135 + if(waitForElement):
  136 + print "element not found. waiting"
  137 + self.getElementByXpath(regex, True)
  138 +
  139 +
  140 + except NoSuchElementException:
  141 + time.sleep(self.max_waiting_time)
  142 +
  143 + if(waitForElement):
  144 + print "exception. waiting"
  145 + self.getElementByXpath(regex, True)
  146 + else:
  147 + return False
  148 +
  149 + #application log
  150 + def log(self, contents):
  151 + #output to console
  152 + print contents + "\n"
  153 +
  154 + logFileName = self.logfile
  155 +
  156 + #fix contents
  157 + now = datetime.datetime.now()
  158 + currentDateTime = now.strftime("%Y-%m-%d %H:%M")
  159 + contents = currentDateTime + " " + str(contents) + "\n"
  160 +
  161 + with open(logFileName, "a") as f:
  162 + f.write(contents)
  163 +
  164 +#create application
  165 +if __name__ == "__main__":
  166 + scrapper = seleniumApp()
  167 + scrapper.startScrap()
  168 +
  169 +
  170 +
  171 +
  172 +
  173 +
  174 +
  175 +#class Login(unittest.TestCase):
  176 +# def setUp(self):
  177 +# self.driver = webdriver.Firefox()
  178 +#
  179 +# def tearDown(self):
  180 +# self.driver.quit()
  181 +#
  182 +# def test_login(self):
  183 +# driver = self.driver
  184 +# driver.get('http://testurl')
  185 +# username = driver.find_element_by_name('user_id')
  186 +# username.send_keys('admin')
7 pyvirtualdisplay/__init__.py
... ... @@ -0,0 +1,7 @@
  1 +from display import Display
  2 +import logging
  3 +
  4 +__version__ = '0.1.2'
  5 +
  6 +log = logging.getLogger(__name__)
  7 +log.debug('version=' + __version__)
95 pyvirtualdisplay/abstractdisplay.py
... ... @@ -0,0 +1,95 @@
  1 +from easyprocess import EasyProcess
  2 +import fnmatch
  3 +import logging
  4 +import os
  5 +import time
  6 +
  7 +log = logging.getLogger(__name__)
  8 +
  9 +# TODO: not perfect
  10 +# randomize to avoid possible conflicts
  11 +RANDOMIZE_DISPLAY_NR = True
  12 +if RANDOMIZE_DISPLAY_NR:
  13 + import random
  14 + random.seed()
  15 +
  16 +MIN_DISPLAY_NR = 1000
  17 +
  18 +
  19 +class AbstractDisplay(EasyProcess):
  20 + '''
  21 + Common parent for Xvfb and Xephyr
  22 + '''
  23 +
  24 + @property
  25 + def new_display_var(self):
  26 + return ':%s' % (self.display)
  27 +
  28 + @property
  29 + def _cmd(self):
  30 + raise NotImplementedError()
  31 +
  32 + def lock_files(self):
  33 + tmpdir = '/tmp'
  34 + pattern = '.X*-lock'
  35 +# ls = path('/tmp').files('.X*-lock')
  36 + # remove path.py dependency
  37 + names = fnmatch.filter(os.listdir(tmpdir), pattern)
  38 + ls = [os.path.join(tmpdir, child) for child in names]
  39 + ls = [p for p in ls if os.path.isfile(p)]
  40 + return ls
  41 +
  42 + def search_for_display(self):
  43 + # search for free display
  44 + ls = map(
  45 + lambda x: int(x.split('X')[1].split('-')[0]), self.lock_files())
  46 + if len(ls):
  47 + display = max(MIN_DISPLAY_NR, max(ls) + 1)
  48 + else:
  49 + display = MIN_DISPLAY_NR
  50 +
  51 + if RANDOMIZE_DISPLAY_NR:
  52 + display += random.randint(0, 100)
  53 + return display
  54 +
  55 + def redirect_display(self, on):
  56 + '''
  57 + on:
  58 + * True -> set $DISPLAY to virtual screen
  59 + * False -> set $DISPLAY to original screen
  60 +
  61 + :param on: bool
  62 + '''
  63 + d = self.new_display_var if on else self.old_display_var
  64 + log.debug('DISPLAY=' + d)
  65 + os.environ['DISPLAY'] = d
  66 +
  67 + def start(self):
  68 + '''
  69 + start display
  70 +
  71 + :rtype: self
  72 + '''
  73 + self.display = self.search_for_display()
  74 + EasyProcess.__init__(self, self._cmd)
  75 + EasyProcess.start(self)
  76 +
  77 + # https://github.com/ponty/PyVirtualDisplay/issues/2
  78 + self.old_display_var = os.environ[
  79 + 'DISPLAY'] if 'DISPLAY' in os.environ else ':0'
  80 +
  81 + self.redirect_display(True)
  82 + # wait until X server is active
  83 + # TODO: better method
  84 + time.sleep(0.1)
  85 + return self
  86 +
  87 + def stop(self):
  88 + '''
  89 + stop display
  90 +
  91 + :rtype: self
  92 + '''
  93 + self.redirect_display(False)
  94 + EasyProcess.stop(self)
  95 + return self
57 pyvirtualdisplay/display.py
... ... @@ -0,0 +1,57 @@
  1 +from pyvirtualdisplay.abstractdisplay import AbstractDisplay
  2 +from pyvirtualdisplay.xephyr import XephyrDisplay
  3 +from pyvirtualdisplay.xvfb import XvfbDisplay
  4 +from pyvirtualdisplay.xvnc import XvncDisplay
  5 +
  6 +
  7 +class Display(AbstractDisplay):
  8 + '''
  9 + Common class
  10 +
  11 + :param color_depth: [8, 16, 24, 32]
  12 + :param size: screen size (width,height)
  13 + :param bgcolor: background color ['black' or 'white']
  14 + :param visible: True -> Xephyr, False -> Xvfb
  15 + :param backend: 'xvfb', 'xvnc' or 'xephyr', ignores ``visible``
  16 + '''
  17 + def __init__(self, backend=None, visible=False, size=(1024, 768), color_depth=24, bgcolor='black', **kwargs):
  18 + self.color_depth = color_depth
  19 + self.size = size
  20 + self.bgcolor = bgcolor
  21 + self.screen = 0
  22 + self.process = None
  23 + self.display = None
  24 + self.visible = visible
  25 + self.backend = backend
  26 +
  27 + if not self.backend:
  28 + if self.visible:
  29 + self.backend = 'xephyr'
  30 + else:
  31 + self.backend = 'xvfb'
  32 +
  33 + self._obj = self.display_class(
  34 + size=size,
  35 + color_depth=color_depth,
  36 + bgcolor=bgcolor,
  37 + **kwargs)
  38 +
  39 + @property
  40 + def display_class(self):
  41 + assert self.backend
  42 + if self.backend == 'xvfb':
  43 + cls = XvfbDisplay
  44 + if self.backend == 'xvnc':
  45 + cls = XvncDisplay
  46 + if self.backend == 'xephyr':
  47 + cls = XephyrDisplay
  48 +
  49 + # TODO: check only once
  50 + cls.check_installed()
  51 +
  52 + return cls
  53 +
  54 + @property
  55 + def _cmd(self):
  56 + self._obj.display = self.display
  57 + return self._obj._cmd
0  pyvirtualdisplay/examples/__init__.py
No changes.
5 pyvirtualdisplay/examples/lowres.py
... ... @@ -0,0 +1,5 @@
  1 +from easyprocess import EasyProcess
  2 +from pyvirtualdisplay import Display
  3 +
  4 +Display(visible=1, size=(320, 240)).start()
  5 +EasyProcess('gnumeric').start()
9 pyvirtualdisplay/examples/screenshot1.py
... ... @@ -0,0 +1,9 @@
  1 +from easyprocess import EasyProcess
  2 +from pyvirtualdisplay.smartdisplay import SmartDisplay
  3 +
  4 +disp = SmartDisplay(visible=0, bgcolor='black').start()
  5 +xmessage = EasyProcess('xmessage hello').start()
  6 +img = disp.waitgrab()
  7 +xmessage.stop()
  8 +disp.stop()
  9 +img.show()
15 pyvirtualdisplay/examples/screenshot3.py
... ... @@ -0,0 +1,15 @@
  1 +'''
  2 +using :keyword:`with` statement
  3 +'''
  4 +import logging
  5 +logging.basicConfig(level=logging.DEBUG)
  6 +
  7 +from easyprocess import EasyProcess
  8 +from pyvirtualdisplay.smartdisplay import SmartDisplay
  9 +
  10 +with SmartDisplay(visible=0, bgcolor='black') as disp:
  11 + with EasyProcess('xmessage hello'):
  12 + img = disp.waitgrab()
  13 +
  14 +
  15 +img.show()
25 pyvirtualdisplay/examples/screenshot4.py
... ... @@ -0,0 +1,25 @@
  1 +'''
  2 +two calls
  3 +'''
  4 +import logging
  5 +logging.basicConfig(level=logging.DEBUG)
  6 +
  7 +from easyprocess import EasyProcess
  8 +from pyvirtualdisplay.smartdisplay import SmartDisplay
  9 +
  10 +backend1 = 'wx'
  11 +backend2 = 'wx'
  12 +
  13 +
  14 +with SmartDisplay(visible=0, bgcolor='black') as disp:
  15 + disp.pyscreenshot_backend = backend1
  16 + with EasyProcess('xmessage test1'):
  17 + img1 = disp.waitgrab()
  18 +
  19 +with SmartDisplay(visible=0, bgcolor='black') as disp:
  20 + disp.pyscreenshot_backend = backend2
  21 + with EasyProcess('xmessage test2'):
  22 + img2 = disp.waitgrab()
  23 +
  24 +img1.show()
  25 +img2.show()
14 pyvirtualdisplay/examples/vncserver.py
... ... @@ -0,0 +1,14 @@
  1 +'''
  2 +Example for Xvnc backend
  3 +'''
  4 +
  5 +from easyprocess import EasyProcess
  6 +from entrypoint2 import entrypoint
  7 +from pyvirtualdisplay.display import Display
  8 +
  9 +
  10 +@entrypoint
  11 +def main(rfbport=5904):
  12 + with Display(backend='xvnc', rfbport=rfbport) as disp:
  13 + with EasyProcess('xmessage hello') as proc:
  14 + proc.wait()
90 pyvirtualdisplay/smartdisplay.py
... ... @@ -0,0 +1,90 @@
  1 +from pyvirtualdisplay.display import Display
  2 +from PIL import Image
  3 +from PIL import ImageChops
  4 +import logging
  5 +import pyscreenshot
  6 +import time
  7 +
  8 +
  9 +log = logging.getLogger(__name__)
  10 +
  11 +
  12 +# class DisplayError(Exception):
  13 +# pass
  14 +
  15 +class DisplayTimeoutError(Exception):
  16 + pass
  17 +
  18 +
  19 +class SmartDisplay(Display):
  20 + pyscreenshot_backend = None
  21 + pyscreenshot_childprocess = False
  22 +
  23 + def autocrop(self, im):
  24 + '''Crop borders off an image.
  25 +
  26 + :param im: Source image.
  27 + :param bgcolor: Background color, using either a color tuple or a color name (1.1.4 only).
  28 + :return: An image without borders, or None if there's no actual content in the image.
  29 + '''
  30 + if im.mode != "RGB":
  31 + im = im.convert("RGB")
  32 + bg = Image.new("RGB", im.size, self.bgcolor)
  33 + diff = ImageChops.difference(im, bg)
  34 + bbox = diff.getbbox()
  35 + if bbox:
  36 + return im.crop(bbox)
  37 + return None # no contents
  38 +
  39 + def grab(self, autocrop=True):
  40 + try:
  41 + # first try newer pyscreenshot version
  42 + img = pyscreenshot.grab(
  43 + childprocess=self.pyscreenshot_childprocess,
  44 + backend=self.pyscreenshot_backend,
  45 + )
  46 + except TypeError:
  47 + # try older pyscreenshot version
  48 + img = pyscreenshot.grab()
  49 +
  50 + if autocrop:
  51 + img = self.autocrop(img)
  52 + return img
  53 +
  54 + def waitgrab(self, timeout=60, autocrop=True, cb_imgcheck=None):
  55 + '''start process and create screenshot.
  56 + Repeat screenshot until it is not empty and
  57 + cb_imgcheck callback function returns True
  58 + for current screenshot.
  59 +
  60 + :param autocrop: True -> crop screenshot
  61 + :param timeout: int
  62 + :param cb_imgcheck: None or callback for testing img,
  63 + True = accept img,
  64 + False = reject img
  65 + '''
  66 + t = 0
  67 + sleep_time = 0.3 # for fast windows
  68 + repeat_time = 1
  69 + while 1:
  70 + log.debug('sleeping %s secs' % str(sleep_time))
  71 + time.sleep(sleep_time)
  72 + t += sleep_time
  73 + img = self.grab(autocrop=autocrop)
  74 + if img:
  75 + if not cb_imgcheck:
  76 + break
  77 + if cb_imgcheck(img):
  78 + break
  79 + sleep_time = repeat_time
  80 + repeat_time += 1 # progressive
  81 + if t > timeout:
  82 + msg = 'Timeout! elapsed time:%s timeout:%s ' % (t, timeout)
  83 + raise DisplayTimeoutError(msg)
  84 + break
  85 +
  86 + log.debug('screenshot is empty, next try..')
  87 + assert img
  88 +# if not img:
  89 +# log.debug('screenshot is empty!')
  90 + return img
39 pyvirtualdisplay/xephyr.py
... ... @@ -0,0 +1,39 @@
  1 +from easyprocess import EasyProcess
  2 +from pyvirtualdisplay.abstractdisplay import AbstractDisplay
  3 +
  4 +PROGRAM = 'Xephyr'
  5 +URL = None
  6 +PACKAGE = 'xephyr'
  7 +
  8 +
  9 +class XephyrDisplay(AbstractDisplay):
  10 + '''
  11 + Xephyr wrapper
  12 +
  13 + Xephyr is an X server outputting to a window on a pre-existing X display
  14 + '''
  15 + def __init__(self, size=(1024, 768), color_depth=24, bgcolor='black'):
  16 + '''
  17 + :param bgcolor: 'black' or 'white'
  18 + '''
  19 + self.color_depth = color_depth
  20 + self.size = size
  21 + self.bgcolor = bgcolor
  22 + self.screen = 0
  23 + self.process = None
  24 + self.display = None
  25 +
  26 + @classmethod
  27 + def check_installed(cls):
  28 + EasyProcess([PROGRAM, '-help'], url=URL,
  29 + ubuntu_package=PACKAGE).check_installed()
  30 +
  31 + @property
  32 + def _cmd(self):
  33 + cmd = [PROGRAM,
  34 + dict(black='-br', white='-wr')[self.bgcolor],
  35 + '-screen',
  36 + 'x'.join(map(str, list(self.size) + [self.color_depth])),
  37 + self.new_display_var,
  38 + ]
  39 + return cmd
45 pyvirtualdisplay/xvfb.py
... ... @@ -0,0 +1,45 @@
  1 +from easyprocess import EasyProcess
  2 +from pyvirtualdisplay.abstractdisplay import AbstractDisplay
  3 +import logging
  4 +
  5 +log = logging.getLogger(__name__)