Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

WIP: Automatic script generator #701

Open
wants to merge 113 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
113 commits
Select commit Hold shift + click to select a range
25251f8
some pep8 corrections
cetygamer Mar 11, 2017
e1efd6a
add Recorder class to monitor UIA events
cetygamer Mar 11, 2017
c13d944
add more info to the output
cetygamer Mar 12, 2017
ff8f17b
added keyboard and mouse hooks
cetygamer Mar 19, 2017
42d7ba7
added contains method to RECT structure
cetygamer Mar 26, 2017
59ce993
added ControlTree class to represent apps controls
cetygamer Mar 26, 2017
f4e7ff2
trying to parse event log
cetygamer Apr 9, 2017
52b32b0
Added doc strings
cetygamer May 1, 2017
9e7191e
Merge branch 'master' of https://github.com/pywinauto/pywinauto into …
cetygamer May 1, 2017
3c08833
parse event log one last time before app.kill()
cetygamer May 1, 2017
f6909ec
added basic implementation of menu_select parsing
cetygamer May 1, 2017
4be48fe
improve speed of ControlTree
cetygamer May 21, 2017
a11287f
fixed getting control names in ControlTree
cetygamer May 26, 2017
02e5669
pep8 edits
cetygamer May 26, 2017
ae3f605
allow only uia Application object
cetygamer May 26, 2017
7d58f99
fixed recorder freezing
cetygamer May 26, 2017
20e08aa
Merge branch 'dev-script-generator' of https://github.com/cetygamer/p…
cetygamer May 26, 2017
b1ddaa7
fixed merging
cetygamer May 26, 2017
c2ac619
Merge branch 'master' of https://github.com/cetygamer/pywinauto into …
cetygamer Nov 6, 2017
8326e12
fixed detecting closing the window
cetygamer Nov 6, 2017
bc14718
fixed python 2 compatibility
cetygamer Nov 6, 2017
cbce4f1
added wait function and removed sleep after hook event (mouse lag)
cetygamer Nov 12, 2017
e98ddd4
updated recorder test using wait function
cetygamer Nov 12, 2017
19e647d
refactor recodrer using event class hierarchy
cetygamer Jan 7, 2018
fa0deea
use IUIA function to compare UIA elements
cetygamer Jan 7, 2018
e4fa158
fix KeyboardEvent creation in win32_hooks.py, create LogParser class
cetygamer Jan 7, 2018
fd3fa12
parse log on any mouse click
cetygamer Jan 7, 2018
ce112f8
added prototype for keyboard input parsing (combined)
cetygamer Jan 10, 2018
d5ac266
fix python exception in click_input
cetygamer Mar 18, 2018
0f450db
create structure for different backend recorders
cetygamer Mar 18, 2018
bce515a
created base module for recorder and all defines
cetygamer Mar 18, 2018
b6b240d
rewrite uia recorder using base class
cetygamer Mar 18, 2018
9a13328
added uia recorder defines
cetygamer Mar 18, 2018
b70d724
added base recorder defines
cetygamer Mar 18, 2018
ec58bcb
Merge branch 'master' of https://github.com/pywinauto/pywinauto into …
cetygamer Mar 18, 2018
b7def74
added property list, switch to static class variables
cetygamer Apr 8, 2018
f02c3c9
added prototype for handling property changed events
cetygamer Apr 8, 2018
8cce0e1
reformat folder structure
cetygamer May 13, 2018
c6a8785
Merge branch 'master' of https://github.com/pywinauto/pywinauto into …
cetygamer May 13, 2018
a397514
small fixes
cetygamer May 13, 2018
7e70ded
fixed launching test script from command line
cetygamer May 13, 2018
1be2185
added get_process_command_line_wmi method
cetygamer May 27, 2018
16824f1
added verbose parameter to recorder
cetygamer May 27, 2018
6d76816
added cli interface (single backend for now)
cetygamer May 27, 2018
73e939f
use list of objects of ControlNames class to map controls and their n…
cetygamer Jun 17, 2018
ce725f8
use ControlNames class in recorder
cetygamer Jun 17, 2018
08ffce5
add time traces to some functions in uia_recorder.py
cetygamer Jun 17, 2018
33b7b12
use inner functions instead of lambdas
cetygamer Jun 17, 2018
351a024
added possible_handlers to uia wrapper classes, use subtree to search…
cetygamer Jun 17, 2018
01fe523
Fix crash on older Windows 10.
vasily-v-ryabov Aug 5, 2018
1f068d0
Allow "(x, y) in rect" statement.
vasily-v-ryabov Aug 5, 2018
de600b8
Fix few issues with .click_input(), .type_keys() etc. Rename ctrl to …
vasily-v-ryabov Aug 5, 2018
74a2de1
Use pkg_resources to check if pywinauto installed.
vasily-v-ryabov Aug 7, 2018
a19d838
Small readability improvements for win32_hooks.py.
vasily-v-ryabov Aug 12, 2018
d2c37d5
Initial use of ToUnicodeEx().
vasily-v-ryabov Aug 14, 2018
791f78d
Convert scan codes to Unicode, fix encoding problems (declare encodin…
vasily-v-ryabov Sep 1, 2018
055a315
Fix __repr__() for Python 3.x.
vasily-v-ryabov Sep 9, 2018
05f67e2
Merge pull request #8 from vasily-v-ryabov/generator_fixes
cetygamer Sep 23, 2018
978b469
added progress bar window, rebuild control tree and update handlers i…
cetygamer Oct 7, 2018
f922876
Merge branch 'extend_recorder' of https://github.com/vasily-v-ryabov/…
cetygamer Oct 7, 2018
c7e0d89
added temporary unhook in _update function
cetygamer Oct 14, 2018
800dc52
Fix runtime errors with decoding
drinkertea Oct 18, 2018
d6cc6e4
Merge pull request #8 from drinkertea/extend_recorder
vasily-v-ryabov Oct 20, 2018
047d020
Merge remote-tracking branch 'remotes/sasha/dev-script-generator' int…
vasily-v-ryabov Oct 20, 2018
0820237
Merge pull request #10 from vasily-v-ryabov/extend_recorder
cetygamer Oct 27, 2018
dc5347e
draft for EventPattern class
cetygamer Nov 5, 2018
17814d5
Merge branch 'dev-script-generator' into recorder/event_patterns
cetygamer Nov 5, 2018
aa6f41e
added EventPattern/EventHandler classes, change LogParser logic
cetygamer Dec 27, 2018
5d5ac3d
- added general handlers for clicks and key presses;
cetygamer Dec 27, 2018
e0cf9bb
don't use * in imports
cetygamer Dec 28, 2018
526cf6a
fixed python 2.7 support
cetygamer Jan 5, 2019
31b0387
added RecorderConfig class, allow passing config to CLI, added key_on…
cetygamer Jan 6, 2019
4707252
added scale_click option to config
cetygamer Jan 6, 2019
ca0f1b6
attempt to draw progress window on top of the application
cetygamer Jan 13, 2019
f4b9be8
added select() handler (e.g. for RadioButton)
cetygamer Feb 17, 2019
be659c7
Merge pull request #11 from cetygamer/recorder/event_patterns
cetygamer Feb 17, 2019
9b24409
use wrapper instead of control_tree to construct update dialog
cetygamer Feb 17, 2019
5dc55c8
Merge branch 'master' of https://github.com/pywinauto/pywinauto into …
cetygamer Feb 17, 2019
c21ecd3
fixed update on menu events
cetygamer Feb 17, 2019
6f187b6
fixed event pattern detection
cetygamer Feb 17, 2019
9d382d9
added structure events defines
cetygamer Mar 10, 2019
78eafba
moved ProgressBarDialog to a new file, added ctrl_type field to Contr…
cetygamer Mar 10, 2019
e7b81cb
added test_recorder.py
cetygamer Mar 17, 2019
5d4c558
added tests for event handlers
cetygamer Mar 17, 2019
abae0c3
fix wrong pattern recognizing and backend-specific pattern map
drinkertea Mar 18, 2019
a096c2d
Merge branch 'master' of https://github.com/pywinauto/pywinauto into …
cetygamer Mar 31, 2019
706665a
fixed application.py line breaks
cetygamer Mar 31, 2019
e5ca683
rollback possible_handlers variable
cetygamer Mar 31, 2019
484fea3
Merge pull request #13 from drinkertea/recorder-logic
cetygamer Mar 31, 2019
9286e7d
added condition for rebuilding tree for TabItem selection change
cetygamer Mar 31, 2019
4395354
fixed ExpandCollapseHandler to grab correct item name
cetygamer Mar 31, 2019
824c4ed
moved test_recorder.py file, fixed codacy warnings
cetygamer Apr 13, 2019
42dee0a
Remove unnecessary __init__.py from the root folder.
vasily-v-ryabov Apr 13, 2019
710b5df
Minor improvements in win32_hooks.py.
vasily-v-ryabov Apr 13, 2019
f946e8e
Fix several unit tests.
vasily-v-ryabov Apr 13, 2019
6de94e8
Fix one more test.
vasily-v-ryabov Apr 14, 2019
8bbccdb
fixed legacy_properties method
cetygamer Apr 14, 2019
4804b82
Merge branch 'master' of https://github.com/pywinauto/pywinauto into …
cetygamer Apr 21, 2019
841fd7a
style fixes
cetygamer Apr 21, 2019
2265796
fixed invoke, toggle and select handlers, added thread lock for _upda…
cetygamer Apr 21, 2019
fb30625
Merge branch 'master' of https://github.com/pywinauto/pywinauto into …
cetygamer May 4, 2019
e92b78d
Merge branch 'master' into dev-script-generator
vasily-v-ryabov May 18, 2019
2981822
Merge branch 'master' of https://github.com/pywinauto/pywinauto into …
cetygamer May 26, 2019
80fdb53
moved UIA handlers to separate file, rewrote recorder update logic
cetygamer May 26, 2019
e34ca0e
Merge branch 'dev-script-generator' of https://github.com/cetygamer/p…
cetygamer Jun 1, 2019
aba9981
add combobox items dynamically
cetygamer Jun 2, 2019
56c592f
fixed launching recorder tests
cetygamer Jun 2, 2019
85584ab
added try-except to base event handler, call basic MouseClickHandler …
cetygamer Jun 2, 2019
6993ec9
fixed lgtm alert
cetygamer Jun 2, 2019
5e6e6e8
Merge branch 'dev-script-generator' of https://github.com/cetygamer/p…
cetygamer Jun 2, 2019
4fff7af
added tests for BaseRecorder and UiaRecorder classes
cetygamer Jun 9, 2019
54a7f80
Merge branch 'master' of https://github.com/pywinauto/pywinauto into …
cetygamer Jun 9, 2019
19867af
win7 fixes
cetygamer Jun 9, 2019
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
53 changes: 12 additions & 41 deletions pywinauto/application.py
Original file line number Diff line number Diff line change
Expand Up @@ -550,32 +550,6 @@ def wait_not(self, wait_for_not, timeout=None, retry_interval=None):
# None return value, since we are waiting for a `negative` state of the control.
# Expect that you will have nothing to do with the window closed, disabled, etc.

def _ctrl_identifiers(self):

ctrls = self.__resolve_control(self.criteria)

if ctrls[-1].is_dialog():
# dialog controls are all the control on the dialog
dialog_controls = ctrls[-1].children()

ctrls_to_print = dialog_controls[:]
# filter out hidden controls
ctrls_to_print = [
ctrl for ctrl in ctrls_to_print if ctrl.is_visible()]
else:
dialog_controls = ctrls[-1].top_level_parent().children()
ctrls_to_print = [ctrls[-1]]

# build the list of disambiguated list of control names
name_control_map = findbestmatch.build_unique_dict(dialog_controls)

# swap it around so that we are mapped off the controls
control_name_map = {}
for name, ctrl in name_control_map.items():
control_name_map.setdefault(ctrl, []).append(name)

return control_name_map

def print_control_identifiers(self, depth=None, filename=None):
"""
Prints the 'identifiers'
Expand All @@ -597,20 +571,8 @@ def print_control_identifiers(self, depth=None, filename=None):
# Create a list of this control and all its descendants
all_ctrls = [this_ctrl, ] + this_ctrl.descendants()

# Create a list of all visible text controls
txt_ctrls = [ctrl for ctrl in all_ctrls if ctrl.can_be_label and ctrl.is_visible() and ctrl.window_text()]

# Build a dictionary of disambiguated list of control names
name_ctrl_id_map = findbestmatch.UniqueDict()
for index, ctrl in enumerate(all_ctrls):
ctrl_names = findbestmatch.get_control_names(ctrl, all_ctrls, txt_ctrls)
for name in ctrl_names:
name_ctrl_id_map[name] = index

# Swap it around so that we are mapped off the control indices
ctrl_id_name_map = {}
for name, index in name_ctrl_id_map.items():
ctrl_id_name_map.setdefault(index, []).append(name)
# Build unique control names map
ctrls_names = findbestmatch.build_names_list(all_ctrls)

def print_identifiers(ctrls, current_depth=1, log_func=print):
"""Recursively print ids for ctrls and their descendants in a tree-like format"""
Expand All @@ -633,7 +595,7 @@ def print_identifiers(ctrls, current_depth=1, log_func=print):
"".format(class_name=ctrl.friendly_class_name(),
text=ctrl_text,
rect=ctrl.rectangle())
output += indent + u'{}'.format(ctrl_id_name_map[ctrl_id])
output += indent + u'{}'.format(ctrls_names[ctrl_id].to_list())

title = ctrl_text
class_name = ctrl.class_name()
Expand Down Expand Up @@ -1382,6 +1344,15 @@ def _process_get_modules_wmi():
return modules


#=========================================================================
def get_process_command_line_wmi(process_id):
"""Return full command line of process"""
from win32com.client import GetObject
_wmi = GetObject('winmgmts:')
proc = _wmi.ExecQuery("Select CommandLine from Win32_Process where ProcessId={}".format(process_id))[0]
return proc.CommandLine


#=========================================================================
def process_module(process_id):
"""Return the string module name of this process"""
Expand Down
6 changes: 2 additions & 4 deletions pywinauto/controls/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,16 +33,14 @@

from ..sysinfo import UIA_support
if UIA_support:
from . import uiawrapper # register "uia" back-end (at the end of uiawrapper module)
from . import uiawrapper # register "uia" back-end (at the end of uiawrapper module)
from . import uia_controls

from .hwndwrapper import get_dialog_props_from_handle
from .hwndwrapper import InvalidWindowHandle

# import the control classes - this will register the classes they
# contain
# import the control classes - this will register the classes they contain
from . import common_controls
from . import win32_controls


from ..base_wrapper import InvalidElement
43 changes: 10 additions & 33 deletions pywinauto/controls/uiawrapper.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,32 +48,6 @@
from .. import uia_defines as uia_defs
from ..uia_element_info import UIAElementInfo, elements_from_uia_array

# region PATTERNS
AutomationElement = IUIA().ui_automation_client.IUIAutomationElement
DockPattern = IUIA().ui_automation_client.IUIAutomationDockPattern
ExpandCollapsePattern = IUIA().ui_automation_client.IUIAutomationExpandCollapsePattern
GridItemPattern = IUIA().ui_automation_client.IUIAutomationGridItemPattern
GridPattern = IUIA().ui_automation_client.IUIAutomationGridPattern
InvokePattern = IUIA().ui_automation_client.IUIAutomationInvokePattern
ItemContainerPattern = IUIA().ui_automation_client.IUIAutomationItemContainerPattern
LegacyIAccessiblePattern = IUIA().ui_automation_client.IUIAutomationLegacyIAccessiblePattern
vasily-v-ryabov marked this conversation as resolved.
Show resolved Hide resolved
MultipleViewPattern = IUIA().ui_automation_client.IUIAutomationMultipleViewPattern
RangeValuePattern = IUIA().ui_automation_client.IUIAutomationRangeValuePattern
ScrollItemPattern = IUIA().ui_automation_client.IUIAutomationScrollItemPattern
ScrollPattern = IUIA().ui_automation_client.IUIAutomationScrollPattern
SelectionItemPattern = IUIA().ui_automation_client.IUIAutomationSelectionItemPattern
SelectionPattern = IUIA().ui_automation_client.IUIAutomationSelectionPattern
SynchronizedInputPattern = IUIA().ui_automation_client.IUIAutomationSynchronizedInputPattern
TableItemPattern = IUIA().ui_automation_client.IUIAutomationTableItemPattern
TablePattern = IUIA().ui_automation_client.IUIAutomationTablePattern
TextPattern = IUIA().ui_automation_client.IUIAutomationTextPattern
TogglePattern = IUIA().ui_automation_client.IUIAutomationTogglePattern
TransformPattern = IUIA().ui_automation_client.IUIAutomationTransformPattern
ValuePattern = IUIA().ui_automation_client.IUIAutomationValuePattern
VirtualizedItemPattern = IUIA().ui_automation_client.IUIAutomationVirtualizedItemPattern
WindowPattern = IUIA().ui_automation_client.IUIAutomationWindowPattern
# endregion

# =========================================================================
_friendly_classes = {
'Custom': None,
Expand Down Expand Up @@ -335,6 +309,13 @@ def iface_virtualized_item(self):
elem = self.element_info.element
return uia_defs.get_elem_interface(elem, "VirtualizedItem")

# ------------------------------------------------------------
@lazy_property
def iface_legacy_accessible(self):
"""Get the element's LegacyIAccessible interface pattern"""
elem = self.element_info.element
return uia_defs.get_elem_interface(elem, "LegacyIAccessible")

# ------------------------------------------------------------
@property
def writable_props(self):
Expand All @@ -349,15 +330,11 @@ def writable_props(self):
# ------------------------------------------------------------
def legacy_properties(self):
"""Get the element's LegacyIAccessible control pattern interface properties"""
elem = self.element_info.element
impl = uia_defs.get_elem_interface(elem, "LegacyIAccessible")
impl = self.iface_legacy_accessible
property_name_identifier = 'Current'

interface_properties = [prop for prop in dir(LegacyIAccessiblePattern)
if (isinstance(getattr(LegacyIAccessiblePattern, prop), property)
and property_name_identifier in prop)]

return {prop.replace(property_name_identifier, '') : getattr(impl, prop) for prop in interface_properties}
interface_properties = [prop for prop in dir(impl) if prop.startswith(property_name_identifier)]
return {prop.replace(property_name_identifier, ''): getattr(impl, prop) for prop in interface_properties}

# ------------------------------------------------------------
def friendly_class_name(self):
Expand Down