Skip to content
This repository has been archived by the owner on Mar 1, 2019. It is now read-only.

Commit

Permalink
remove watcher, add keep_screen to doc
Browse files Browse the repository at this point in the history
  • Loading branch information
codeskyblue committed Jan 18, 2017
1 parent abcf341 commit 1476ca2
Show file tree
Hide file tree
Showing 2 changed files with 27 additions and 194 deletions.
203 changes: 10 additions & 193 deletions atx/drivers/mixin.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,183 +33,6 @@
__dir__ = os.path.dirname(os.path.abspath(__file__))
log = logutils.getLogger(__name__)

_Condition = collections.namedtuple('WatchCondition', ['pattern', 'exists'])

class WatcherItem(object):
"""
How to use, for
example:
with d.watch('xx') as w:
w.on('button.png').on('enter.png').click()
w.on('yes.png').on_not('exit.png').click()
or
w = d.watch('yy')
w.on('button.png').on('enter.png').click()
w.on('button.png').click('enter.png')
w.run()
# blueprint upgrade plan
- conditions
pattern
- hooks
functions
"""
def __init__(self, watcher, rule):
self._w = watcher
self._r = rule

def on(self, pattern):
"""Trigger when pattern exists"""
self._r['conditions'].append(_Condition(pattern, True))
return self

# def on_not(self, pattern):
# """Trigger when pattern not exists"""
# self._conditions.append(_Condition(pattern, False))
# return self

def do(self, func):
"""Trigger with function call
Args:
func: function which will called when object found. For example.
def foo(event):
print event.pos # (x, y) position
w.on('kitty.png').do(foo)
Returns:
Watcher object
Raises:
SyntaxError
"""
if not callable(func):
raise SyntaxError("%s should be a function" % func)
self._r['actions'].append(func)
return self

def click(self, *args, **kwargs):
def _inner(event):
if len(args) or len(kwargs):
self._w._dev.click(*args, **kwargs)
else:
self._w._dev.click(*event.pos)
return self.do(_inner)

def click_image(self, *args, **kwargs):
""" async trigger click_image """
def _inner(event):
return self._w._dev.click_image(*args, **kwargs)

return self.do(_inner)

def quit(self):
def _inner(event):
self._w._done = True
return self.do(_inner)

class Watcher(object):
Handler = collections.namedtuple('Handler', ['selector', 'action'])
Event = collections.namedtuple('Event', ['selector', 'pos'])

def __init__(self, device, name=None, timeout=None, raise_errors=True):
self.name = name
self.timeout = timeout
self.raise_errors = raise_errors

self._dev = device
self._done = False
self._watches = []

def on(self, pattern):
w = dict(
conditions=[_Condition(pattern, True)],
actions=[],
)
self._watches.append(w)
return WatcherItem(self, w)

def on_ui(self, text):
w = dict(
conditions=[_Condition(self._dev(text=text), True)],
actions=[],
)
self._watches.append(w)
return WatcherItem(self, w)

def _do_hook(self, screen):
# patterns = set()
for rule in self._watches:
conditions = rule['conditions']
actions = rule['actions']

if not actions:
continue

ok = True
last_pos = None
for condition in conditions:
pos = self._match(condition.pattern, screen)
if pos:
log.info("watch match: %s", condition)
if bool(pos) != condition.exists:
ok = False
break
if condition.exists:
last_pos = pos
if ok:
for fn in actions:
fn(self.Event(None, last_pos))
break # FIXME(ssx): maybe need fallthrough, but for now, just simplfy it

def run(self):
# self._run = True
start_time = time.time()
while not self._done:
screen = self._dev.screenshot()
self._do_hook(screen)

if self.timeout is not None:
if time.time() - start_time > self.timeout:
if self.raise_errors:
raise errors.WatchTimeoutError("[%s] watch timeout %s" % (self.name, self.timeout,))
break
sys.stdout.write("[%s] watching %4.1fs left: %4.1fs\r" %(self.name, self.timeout, self.timeout-time.time()+start_time))
sys.stdout.flush()
sys.stdout.write('\n')

def __enter__(self):
return self

def __exit__(self, type, value, traceback):
self.run()

def _match(self, selector, screen):
''' Find position for AtxPattern or UIAutomator Object
Return:
position(x, y) or None
'''
if isinstance(selector, Pattern) or isinstance(selector, basestring):
ret = self._dev.match(selector, screen=screen)
if ret is None:
return
log.debug('watch match: %s, confidence: %s', selector, ret)
if not ret.matched:
return
return ret.pos
elif isinstance(selector, AutomatorDeviceObject):
if not selector.exists:
return None
info = selector.info['bounds']
x = (info['left'] + info['right']) / 2
y = (info['bottom'] + info['top']) / 2
return (x, y)


Traceback = collections.namedtuple('Traceback', ['stack', 'exception'])
HookEvent = nameddict('HookEvent', ['flag', 'args', 'kwargs', 'retval', 'traceback', 'depth', 'is_before'])
Expand Down Expand Up @@ -503,7 +326,16 @@ def keep_screen(self):
"""
self.__last_screen = self.screenshot()
self.__keep_screen = True
return self
inner_self = self

class _C(object):
def __enter__(self):
pass

def __exit__(self, type, value, traceback):
inner_self.free_screen()

return _C()

def free_screen(self):
"""
Expand Down Expand Up @@ -647,21 +479,6 @@ def click_image(self, pattern, timeout=20.0, action='click', safe=False, desc=No
# FIXME(ssx): maybe this function is too complex
return point #collections.namedtuple('X', ['pattern', 'point'])(pattern, point)

def watch(self, name='', timeout=None, raise_errors=True):
"""Return a new watcher
Args:
name: string watcher name
timeout: watch timeout
Returns:
watcher object
"""
warnings.warn("The 'watch' function was not recommend since v1.0.13.", DeprecationWarning, stacklevel=2)

w = Watcher(self, name, timeout, raise_errors)
w._dev = self
return w


if __name__ == '__main__':
b = Bounds(1, 2, 3, 4)
Expand Down
18 changes: 17 additions & 1 deletion docs/API.md
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,22 @@ nd = d.region(atx.Bounds(50, 50, 180, 300))
print nd.match('folder.png')
```

## 锁定当前屏幕(主要用于提高查询效率)
```
d.keep_screen()
d.click_nowait("button1.png")
d.click_nowait("button2.png")
d.free_screen()
```

这种操作,执行第二次`click_nowait`时,就不会再次截图。另外上面的代码也可以这样写

```
with d.keep_screen():
d.click_nowait("button1.png")
d.click_nowait("button2.png")
```

## 原生UI操作
下面给的例子并不完全,更多的接口需要看下面这两个链接

Expand Down Expand Up @@ -207,7 +223,7 @@ d.click_image('photo2.png')
```


## 监控事件 (即将废弃,不建议使用)
## 监控事件 (已经废弃,不建议使用)

watch是一个内部循环,对于on函数中的所有出现的图片进行监控,如果发现吻合的,就执行后续的操作,直到timeout时间到。

Expand Down

0 comments on commit 1476ca2

Please sign in to comment.