From 1a5855875954c86e896d807d74ff11f53478a254 Mon Sep 17 00:00:00 2001 From: Ivan Maslov Date: Thu, 30 Jun 2022 16:48:34 +0300 Subject: [PATCH] =?UTF-8?q?=D0=9F=D0=BE=D1=80=D1=82=D0=B0=D0=BB=20=D0=B4?= =?UTF-8?q?=D0=BE=D0=BA=D1=83=D0=BC=D0=B5=D0=BD=D1=82=D0=B0=D1=86=D0=B8?= =?UTF-8?q?=D0=B8=20=D0=BD=D0=B0=20=D0=A0=D1=83=D1=81=D1=81=D0=BA=D0=BE?= =?UTF-8?q?=D0=BC=20=D1=8F=D0=B7=D1=8B=D0=BA=D0=B5!?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../INSTALLER | 0 .../pyOpenRPA-1.2.13.dist-info}/METADATA | 2 +- .../pyOpenRPA-1.2.13.dist-info}/RECORD | 30 +- .../REQUESTED | 0 .../WHEEL | 0 .../top_level.txt | 0 .../Orchestrator/Managers/ControlPanel.py | 1 + .../Orchestrator/Managers/Process.py | 2 + .../Orchestrator/__Orchestrator__.py | 1221 ++++----- .../pyOpenRPA/Robot/Clipboard.py | 37 +- .../site-packages/pyOpenRPA/Robot/Keyboard.py | 345 ++- .../site-packages/pyOpenRPA/Robot/Mouse.py | 174 +- .../site-packages/pyOpenRPA/Robot/README.md | 15 +- .../pyOpenRPA/Robot/UIDesktop.py | 832 ++++-- .../Lib/site-packages/pyOpenRPA/__init__.py | 6 +- .../INSTALLER | 0 .../pyOpenRPA-1.2.13.dist-info}/METADATA | 2 +- .../pyOpenRPA-1.2.13.dist-info}/RECORD | 30 +- .../REQUESTED | 0 .../WHEEL | 0 .../top_level.txt | 0 .../Orchestrator/Managers/ControlPanel.py | 1 + .../Orchestrator/Managers/Process.py | 2 + .../Orchestrator/__Orchestrator__.py | 1221 ++++----- .../pyOpenRPA/Robot/Clipboard.py | 37 +- .../site-packages/pyOpenRPA/Robot/Keyboard.py | 345 ++- .../site-packages/pyOpenRPA/Robot/Mouse.py | 174 +- .../site-packages/pyOpenRPA/Robot/README.md | 15 +- .../pyOpenRPA/Robot/UIDesktop.py | 832 ++++-- .../Lib/site-packages/pyOpenRPA/__init__.py | 6 +- Sources/GuideSphinx/01_HowToInstall.rst | 36 +- .../GuideSphinx/03_Copyrights_Contacts.rst | 13 +- Sources/GuideSphinx/Agent/02_Defs.rst | 12 +- .../Orchestrator/01_Orchestrator.rst | 104 +- Sources/GuideSphinx/Orchestrator/02_Defs.rst | 69 +- .../Orchestrator/03_gSettingsTemplate.rst | 32 +- .../GuideSphinx/Orchestrator/04_HowToUse.rst | 35 +- Sources/GuideSphinx/Orchestrator/05_UAC.rst | 32 +- .../Orchestrator/06_Defs Managers.rst | 52 - Sources/GuideSphinx/Robot/01_Robot.rst | 40 +- Sources/GuideSphinx/Robot/02_uidesktop.rst | 432 ++-- Sources/GuideSphinx/Robot/03_uiweb.rst | 43 +- Sources/GuideSphinx/Robot/04_keyboard.rst | 20 +- Sources/GuideSphinx/Robot/05_clipboard.rst | 42 +- Sources/GuideSphinx/Robot/06_mouse.rst | 41 +- Sources/GuideSphinx/Robot/07_image.rst | 44 +- Sources/GuideSphinx/Robot/08_HowToUse.rst | 234 +- Sources/GuideSphinx/Robot/09_Dependencies.rst | 10 - Sources/GuideSphinx/Studio/01_Studio.rst | 29 +- Sources/GuideSphinx/Studio/02_HowToUse.rst | 146 +- Sources/GuideSphinx/Tools/02_Defs.rst | 2 +- Sources/GuideSphinx/index.rst | 21 +- Sources/GuideSphinx/make_RUS_Guide_PDF.cmd | 1 + Sources/pyOpenRPA/Robot/Clipboard.py | 37 +- Sources/pyOpenRPA/__init__.py | 2 +- .../doctrees/01_HowToInstall.doctree | Bin 9797 -> 12531 bytes .../doctrees/03_Copyrights_Contacts.doctree | Bin 20878 -> 31345 bytes Wiki/RUS_Guide/doctrees/Agent/02_Defs.doctree | Bin 58492 -> 53912 bytes .../Orchestrator/01_Orchestrator.doctree | Bin 15852 -> 25294 bytes .../doctrees/Orchestrator/02_Defs.doctree | Bin 742252 -> 855824 bytes .../Orchestrator/03_gSettingsTemplate.doctree | Bin 46766 -> 50877 bytes .../doctrees/Orchestrator/04_HowToUse.doctree | Bin 9239 -> 15453 bytes .../doctrees/Orchestrator/05_UAC.doctree | Bin 8861 -> 16181 bytes .../Orchestrator/06_Defs Managers.doctree | Bin 667929 -> 0 bytes .../RUS_Guide/doctrees/Robot/01_Robot.doctree | Bin 21894 -> 30086 bytes Wiki/RUS_Guide/doctrees/Robot/02_Defs.doctree | Bin 139906 -> 0 bytes .../doctrees/Robot/02_uidesktop.doctree | Bin 140456 -> 429388 bytes .../RUS_Guide/doctrees/Robot/03_uiweb.doctree | Bin 140416 -> 11743 bytes .../doctrees/Robot/04_keyboard.doctree | Bin 140446 -> 116276 bytes .../doctrees/Robot/05_clipboard.doctree | Bin 140456 -> 19848 bytes .../RUS_Guide/doctrees/Robot/06_mouse.doctree | Bin 140416 -> 123032 bytes .../RUS_Guide/doctrees/Robot/07_image.doctree | Bin 140416 -> 11743 bytes .../doctrees/Robot/08_HowToUse.doctree | Bin 34955 -> 22050 bytes .../doctrees/Robot/09_Dependencies.doctree | Bin 4893 -> 0 bytes .../doctrees/Studio/01_Studio.doctree | Bin 4115 -> 13094 bytes .../doctrees/Studio/02_HowToUse.doctree | Bin 22425 -> 33118 bytes Wiki/RUS_Guide/doctrees/Tools/02_Defs.doctree | Bin 22529 -> 18806 bytes Wiki/RUS_Guide/doctrees/environment.pickle | Bin 466686 -> 492898 bytes Wiki/RUS_Guide/doctrees/index.doctree | Bin 48383 -> 74119 bytes Wiki/RUS_Guide/html/01_HowToInstall.html | 81 +- .../html/03_Copyrights_Contacts.html | 144 +- Wiki/RUS_Guide/html/Agent/02_Defs.html | 60 +- .../html/Orchestrator/01_Orchestrator.html | 162 +- Wiki/RUS_Guide/html/Orchestrator/02_Defs.html | 1866 ++++++-------- .../Orchestrator/03_gSettingsTemplate.html | 74 +- .../html/Orchestrator/04_HowToUse.html | 81 +- Wiki/RUS_Guide/html/Orchestrator/05_UAC.html | 81 +- .../html/Orchestrator/06_Defs Managers.html | 2220 ---------------- Wiki/RUS_Guide/html/Robot/01_Robot.html | 90 +- Wiki/RUS_Guide/html/Robot/02_Defs.html | 710 ----- Wiki/RUS_Guide/html/Robot/02_uidesktop.html | 995 +++++-- Wiki/RUS_Guide/html/Robot/03_uiweb.html | 519 +--- Wiki/RUS_Guide/html/Robot/04_keyboard.html | 759 +++--- Wiki/RUS_Guide/html/Robot/05_clipboard.html | 516 +--- Wiki/RUS_Guide/html/Robot/06_mouse.html | 551 ++-- Wiki/RUS_Guide/html/Robot/07_image.html | 515 +--- Wiki/RUS_Guide/html/Robot/08_HowToUse.html | 290 +-- .../RUS_Guide/html/Robot/09_Dependencies.html | 258 -- Wiki/RUS_Guide/html/Studio/01_Studio.html | 65 +- Wiki/RUS_Guide/html/Studio/02_HowToUse.html | 202 +- Wiki/RUS_Guide/html/Tools/02_Defs.html | 63 +- Wiki/RUS_Guide/html/_images/ModalGuide.png | Bin 88412 -> 67103 bytes Wiki/RUS_Guide/html/_modules/index.html | 37 +- .../_modules/pyOpenRPA/Agent/__Agent__.html | 31 +- .../Orchestrator/Managers/ControlPanel.html | 587 ----- .../Orchestrator/Managers/Process.html | 931 ------- .../pyOpenRPA/Orchestrator/Web/Basic.html | 381 --- .../Orchestrator/__Orchestrator__.html | 1270 ++++----- .../_modules/pyOpenRPA/Robot/Clipboard.html | 283 ++ .../_modules/pyOpenRPA/Robot/Keyboard.html | 580 +++++ .../html/_modules/pyOpenRPA/Robot/Mouse.html | 409 +++ .../_modules/pyOpenRPA/Robot/UIDesktop.html | 967 ++++--- .../_modules/pyOpenRPA/Tools/Debugger.html | 31 +- .../_modules/pyOpenRPA/Tools/StopSafe.html | 31 +- .../html/_sources/01_HowToInstall.rst.txt | 38 +- .../_sources/03_Copyrights_Contacts.rst.txt | 97 +- .../html/_sources/Agent/02_Defs.rst.txt | 12 +- .../Orchestrator/01_Orchestrator.rst.txt | 111 +- .../_sources/Orchestrator/02_Defs.rst.txt | 115 +- .../Orchestrator/03_gSettingsTemplate.rst.txt | 32 +- .../_sources/Orchestrator/04_HowToUse.rst.txt | 35 +- .../html/_sources/Orchestrator/05_UAC.rst.txt | 32 +- .../Orchestrator/06_Defs Managers.rst.txt | 52 - .../html/_sources/Robot/01_Robot.rst.txt | 40 +- .../html/_sources/Robot/02_Defs.rst.txt | 36 - .../html/_sources/Robot/02_uidesktop.rst.txt | 214 +- .../html/_sources/Robot/03_uiweb.rst.txt | 43 +- .../html/_sources/Robot/04_keyboard.rst.txt | 237 +- .../html/_sources/Robot/05_clipboard.rst.txt | 42 +- .../html/_sources/Robot/06_mouse.rst.txt | 43 +- .../html/_sources/Robot/07_image.rst.txt | 44 +- .../html/_sources/Robot/08_HowToUse.rst.txt | 234 +- .../_sources/Robot/09_Dependencies.rst.txt | 10 - .../html/_sources/Studio/01_Studio.rst.txt | 29 +- .../html/_sources/Studio/02_HowToUse.rst.txt | 146 +- .../html/_sources/Tools/02_Defs.rst.txt | 13 +- Wiki/RUS_Guide/html/_sources/index.rst.txt | 183 +- Wiki/RUS_Guide/html/genindex.html | 284 +- Wiki/RUS_Guide/html/img/ModalGuide.png | Bin 88412 -> 67103 bytes Wiki/RUS_Guide/html/index.html | 380 +-- Wiki/RUS_Guide/html/objects.inv | Bin 2732 -> 2594 bytes Wiki/RUS_Guide/html/py-modindex.html | 39 +- Wiki/RUS_Guide/html/search.html | 31 +- Wiki/RUS_Guide/html/searchindex.js | 2 +- Wiki/RUS_Guide/markdown/01_HowToInstall.md | 45 +- .../markdown/03_Copyrights_Contacts.md | 107 +- Wiki/RUS_Guide/markdown/Agent/02_Defs.md | 13 +- .../markdown/Orchestrator/01_Orchestrator.md | 126 +- .../markdown/Orchestrator/02_Defs.md | 1946 +++++++------- .../Orchestrator/03_gSettingsTemplate.md | 33 +- .../markdown/Orchestrator/04_HowToUse.md | 43 +- .../RUS_Guide/markdown/Orchestrator/05_UAC.md | 43 +- .../markdown/Orchestrator/06_Defs Managers.md | 2294 ----------------- Wiki/RUS_Guide/markdown/Robot/01_Robot.md | 57 +- Wiki/RUS_Guide/markdown/Robot/02_Defs.md | 554 ---- Wiki/RUS_Guide/markdown/Robot/02_uidesktop.md | 1381 ++++++++-- Wiki/RUS_Guide/markdown/Robot/03_uiweb.md | 547 +--- Wiki/RUS_Guide/markdown/Robot/04_keyboard.md | 718 +++--- Wiki/RUS_Guide/markdown/Robot/05_clipboard.md | 543 +--- Wiki/RUS_Guide/markdown/Robot/06_mouse.md | 521 +--- Wiki/RUS_Guide/markdown/Robot/07_image.md | 547 +--- Wiki/RUS_Guide/markdown/Robot/08_HowToUse.md | 219 +- .../markdown/Robot/09_Dependencies.md | 17 - Wiki/RUS_Guide/markdown/Studio/01_Studio.md | 39 +- Wiki/RUS_Guide/markdown/Studio/02_HowToUse.md | 124 +- Wiki/RUS_Guide/markdown/Tools/02_Defs.md | 23 +- Wiki/RUS_Guide/markdown/img/ModalGuide.png | Bin 88412 -> 67103 bytes Wiki/RUS_Guide/markdown/index.md | 368 ++- Wiki/RUS_Guide/pdf/pyOpenRPA_Guide_RUS.pdf | Bin 0 -> 1418879 bytes v1.2.12 => v1.2.13 | 0 170 files changed, 14538 insertions(+), 21043 deletions(-) rename Resources/WPy32-3720/python-3.7.2/Lib/site-packages/{pyOpenRPA-1.2.12.dist-info => pyOpenRPA-1.2.13.dist-info}/INSTALLER (100%) rename Resources/{WPy64-3720/python-3.7.2.amd64/Lib/site-packages/pyOpenRPA-1.2.12.dist-info => WPy32-3720/python-3.7.2/Lib/site-packages/pyOpenRPA-1.2.13.dist-info}/METADATA (99%) rename Resources/{WPy64-3720/python-3.7.2.amd64/Lib/site-packages/pyOpenRPA-1.2.12.dist-info => WPy32-3720/python-3.7.2/Lib/site-packages/pyOpenRPA-1.2.13.dist-info}/RECORD (96%) rename Resources/WPy32-3720/python-3.7.2/Lib/site-packages/{pyOpenRPA-1.2.12.dist-info => pyOpenRPA-1.2.13.dist-info}/REQUESTED (100%) rename Resources/WPy32-3720/python-3.7.2/Lib/site-packages/{pyOpenRPA-1.2.12.dist-info => pyOpenRPA-1.2.13.dist-info}/WHEEL (100%) rename Resources/WPy32-3720/python-3.7.2/Lib/site-packages/{pyOpenRPA-1.2.12.dist-info => pyOpenRPA-1.2.13.dist-info}/top_level.txt (100%) rename Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/{pyOpenRPA-1.2.12.dist-info => pyOpenRPA-1.2.13.dist-info}/INSTALLER (100%) rename Resources/{WPy32-3720/python-3.7.2/Lib/site-packages/pyOpenRPA-1.2.12.dist-info => WPy64-3720/python-3.7.2.amd64/Lib/site-packages/pyOpenRPA-1.2.13.dist-info}/METADATA (99%) rename Resources/{WPy32-3720/python-3.7.2/Lib/site-packages/pyOpenRPA-1.2.12.dist-info => WPy64-3720/python-3.7.2.amd64/Lib/site-packages/pyOpenRPA-1.2.13.dist-info}/RECORD (96%) rename Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/{pyOpenRPA-1.2.12.dist-info => pyOpenRPA-1.2.13.dist-info}/REQUESTED (100%) rename Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/{pyOpenRPA-1.2.12.dist-info => pyOpenRPA-1.2.13.dist-info}/WHEEL (100%) rename Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/{pyOpenRPA-1.2.12.dist-info => pyOpenRPA-1.2.13.dist-info}/top_level.txt (100%) delete mode 100644 Sources/GuideSphinx/Orchestrator/06_Defs Managers.rst delete mode 100644 Sources/GuideSphinx/Robot/09_Dependencies.rst create mode 100644 Sources/GuideSphinx/make_RUS_Guide_PDF.cmd delete mode 100644 Wiki/RUS_Guide/doctrees/Orchestrator/06_Defs Managers.doctree delete mode 100644 Wiki/RUS_Guide/doctrees/Robot/02_Defs.doctree delete mode 100644 Wiki/RUS_Guide/doctrees/Robot/09_Dependencies.doctree delete mode 100644 Wiki/RUS_Guide/html/Orchestrator/06_Defs Managers.html delete mode 100644 Wiki/RUS_Guide/html/Robot/02_Defs.html delete mode 100644 Wiki/RUS_Guide/html/Robot/09_Dependencies.html delete mode 100644 Wiki/RUS_Guide/html/_modules/pyOpenRPA/Orchestrator/Managers/ControlPanel.html delete mode 100644 Wiki/RUS_Guide/html/_modules/pyOpenRPA/Orchestrator/Managers/Process.html delete mode 100644 Wiki/RUS_Guide/html/_modules/pyOpenRPA/Orchestrator/Web/Basic.html create mode 100644 Wiki/RUS_Guide/html/_modules/pyOpenRPA/Robot/Clipboard.html create mode 100644 Wiki/RUS_Guide/html/_modules/pyOpenRPA/Robot/Keyboard.html create mode 100644 Wiki/RUS_Guide/html/_modules/pyOpenRPA/Robot/Mouse.html delete mode 100644 Wiki/RUS_Guide/html/_sources/Orchestrator/06_Defs Managers.rst.txt delete mode 100644 Wiki/RUS_Guide/html/_sources/Robot/02_Defs.rst.txt delete mode 100644 Wiki/RUS_Guide/html/_sources/Robot/09_Dependencies.rst.txt delete mode 100644 Wiki/RUS_Guide/markdown/Orchestrator/06_Defs Managers.md delete mode 100644 Wiki/RUS_Guide/markdown/Robot/02_Defs.md delete mode 100644 Wiki/RUS_Guide/markdown/Robot/09_Dependencies.md create mode 100644 Wiki/RUS_Guide/pdf/pyOpenRPA_Guide_RUS.pdf rename v1.2.12 => v1.2.13 (100%) diff --git a/Resources/WPy32-3720/python-3.7.2/Lib/site-packages/pyOpenRPA-1.2.12.dist-info/INSTALLER b/Resources/WPy32-3720/python-3.7.2/Lib/site-packages/pyOpenRPA-1.2.13.dist-info/INSTALLER similarity index 100% rename from Resources/WPy32-3720/python-3.7.2/Lib/site-packages/pyOpenRPA-1.2.12.dist-info/INSTALLER rename to Resources/WPy32-3720/python-3.7.2/Lib/site-packages/pyOpenRPA-1.2.13.dist-info/INSTALLER diff --git a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/pyOpenRPA-1.2.12.dist-info/METADATA b/Resources/WPy32-3720/python-3.7.2/Lib/site-packages/pyOpenRPA-1.2.13.dist-info/METADATA similarity index 99% rename from Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/pyOpenRPA-1.2.12.dist-info/METADATA rename to Resources/WPy32-3720/python-3.7.2/Lib/site-packages/pyOpenRPA-1.2.13.dist-info/METADATA index ee047299..be5fb345 100644 --- a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/pyOpenRPA-1.2.12.dist-info/METADATA +++ b/Resources/WPy32-3720/python-3.7.2/Lib/site-packages/pyOpenRPA-1.2.13.dist-info/METADATA @@ -1,6 +1,6 @@ Metadata-Version: 2.1 Name: pyOpenRPA -Version: 1.2.12 +Version: 1.2.13 Summary: First open source RPA platform for business Home-page: https://pyopenrpa.ru/ Author: Ivan Maslov diff --git a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/pyOpenRPA-1.2.12.dist-info/RECORD b/Resources/WPy32-3720/python-3.7.2/Lib/site-packages/pyOpenRPA-1.2.13.dist-info/RECORD similarity index 96% rename from Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/pyOpenRPA-1.2.12.dist-info/RECORD rename to Resources/WPy32-3720/python-3.7.2/Lib/site-packages/pyOpenRPA-1.2.13.dist-info/RECORD index 4f6a71f0..a559ce98 100644 --- a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/pyOpenRPA-1.2.12.dist-info/RECORD +++ b/Resources/WPy32-3720/python-3.7.2/Lib/site-packages/pyOpenRPA-1.2.13.dist-info/RECORD @@ -1,9 +1,9 @@ -pyOpenRPA-1.2.12.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4 -pyOpenRPA-1.2.12.dist-info/METADATA,sha256=AmdWISfrdsF9DvjBrn42JJUXBb-TLln5OFBWKxX0VaE,4111 -pyOpenRPA-1.2.12.dist-info/RECORD,, -pyOpenRPA-1.2.12.dist-info/REQUESTED,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 -pyOpenRPA-1.2.12.dist-info/WHEEL,sha256=qB97nP5e4MrOsXW5bIU5cUn_KSVr10EV0l-GCHG9qNs,97 -pyOpenRPA-1.2.12.dist-info/top_level.txt,sha256=RPzwQXgYBRo_m5L3ZLs6Voh8aEkMeT29Xsul1w1qE0g,10 +pyOpenRPA-1.2.13.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4 +pyOpenRPA-1.2.13.dist-info/METADATA,sha256=HrNqM4-bPHXjqazFT4215H6pPafnYdCqattouxZIzVc,4111 +pyOpenRPA-1.2.13.dist-info/RECORD,, +pyOpenRPA-1.2.13.dist-info/REQUESTED,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +pyOpenRPA-1.2.13.dist-info/WHEEL,sha256=qB97nP5e4MrOsXW5bIU5cUn_KSVr10EV0l-GCHG9qNs,97 +pyOpenRPA-1.2.13.dist-info/top_level.txt,sha256=RPzwQXgYBRo_m5L3ZLs6Voh8aEkMeT29Xsul1w1qE0g,10 pyOpenRPA/.idea/inspectionProfiles/profiles_settings.xml,sha256=YXLFmX7rPNGcnKK1uX1uKYPN0fpgskYNe7t0BV7cqkY,174 pyOpenRPA/.idea/misc.xml,sha256=V-fQnOz-bYEZULgfbFgm-8mURphZrKfXMSd0wKjeEyA,188 pyOpenRPA/.idea/modules.xml,sha256=Q__U1JIA2cjxbLRXAv-SfYY00fZA0TNlpkkbY4s3ncg,277 @@ -26,9 +26,9 @@ pyOpenRPA/LICENSE.pdf,sha256=HEqffy8FIWpylw0zF7k-Wgwd8ppWQT9s9EGBgKV-6G8,321175 pyOpenRPA/Orchestrator/BackwardCompatibility.py,sha256=ABr0RugbBsIGdL5GE_EFC9QndSaKjvrjawvluhUNuMY,37795 pyOpenRPA/Orchestrator/ControlPanel.py,sha256=OzS8HjG__8OZgqhajr8L8owyugXPuSLWHLtXuKdEP78,103 pyOpenRPA/Orchestrator/Core.py,sha256=OHa3mSC3_wRAizqrWBVjlR6ln4-xVVvBpOSnWl6qVvY,529 -pyOpenRPA/Orchestrator/Managers/ControlPanel.py,sha256=BgtLjb6PR6kTlOjPLCg2YGP458LS9JOaYEfNurhS0nk,16544 +pyOpenRPA/Orchestrator/Managers/ControlPanel.py,sha256=XpmN_LB--phNq4VpsbdWHJC6ybIt7jWBsl6HKfxHP1I,16550 pyOpenRPA/Orchestrator/Managers/Git.py,sha256=dgXx2UzSwiEev4ov2hBbb-5MhXVhFKWZo2lmr19QSCQ,12582 -pyOpenRPA/Orchestrator/Managers/Process.py,sha256=7T_qofdkRJHdPQbaiEsTDOboImSf2N6d_Ku513rURkw,41369 +pyOpenRPA/Orchestrator/Managers/Process.py,sha256=DYX1pBK4gaxcfmDj-1OaLNyk83D_R_7ztZyt0SHWoik,41377 pyOpenRPA/Orchestrator/Managers/__init__.py,sha256=4my0XiwmI_QLRQVhOzNvWTggCosF3tb2yRxGkehOCq0,71 pyOpenRPA/Orchestrator/Managers/__pycache__/ControlPanel.cpython-37.pyc,, pyOpenRPA/Orchestrator/Managers/__pycache__/Git.cpython-37.pyc,, @@ -81,7 +81,7 @@ pyOpenRPA/Orchestrator/Web/Index.js,sha256=YACiZAvjr6NmFlDhQu6urkJp49BX7L8WJU9p- pyOpenRPA/Orchestrator/Web/Index.xhtml,sha256=5JUAs5rEiU0XtHM9QO6EdNMBGt-W6QOVGY7xJ_HLPFM,19257 pyOpenRPA/Orchestrator/Web/__pycache__/Basic.cpython-37.pyc,, pyOpenRPA/Orchestrator/Web/favicon.ico,sha256=6S8XwSQ_3FXPpaX6zYkf8uUewVXO9bHnrrDHEoWrEgw,112922 -pyOpenRPA/Orchestrator/__Orchestrator__.py,sha256=Zud6HTAHSsfTJVrszML5EjGTqlA7k5qhthZTsSD1pX8,151055 +pyOpenRPA/Orchestrator/__Orchestrator__.py,sha256=rlM-j8LK4BdcPfI8KNMOi1Rq-Ht8kCLs6WYsPBZgDTU,203081 pyOpenRPA/Orchestrator/__init__.py,sha256=nJhjYtBXKOUNX_yNu1rRFk5y9cDz6AFiL0M6KgX_utQ,207 pyOpenRPA/Orchestrator/__main__.py,sha256=czJrc7_57WiO3EPIYfPeF_LG3pZsQVmuAYgbl_YXcVU,273 pyOpenRPA/Orchestrator/__pycache__/BackwardCompatibility.cpython-37.pyc,, @@ -270,15 +270,15 @@ pyOpenRPA/Resources/Web/Semantic-UI-CSS-master/themes/default/assets/fonts/outli pyOpenRPA/Resources/Web/Semantic-UI-CSS-master/themes/default/assets/images/flags.png,sha256=lNXH8WYTAcSm3Ekdct1VmgYgzZF6gm8N8bAju5bqnd0,28123 pyOpenRPA/Resources/Web/jQuery/jquery-3.1.1.min.js,sha256=HPMOWdIdSuVgr3FD9ZE-_MgiK8qk_MdQjrgCtfqp6U4,86713 pyOpenRPA/Resources/Web/pyOpenRPA_logo.png,sha256=7rulXo_C57xJQEaYWmAkChxXb6xbDW2zq-werzVbDbc,4899 -pyOpenRPA/Robot/Clipboard.py,sha256=q76X8L21zJwcwdoJJNPeCEwAV30xS6ylHP1WwvtxoWI,722 -pyOpenRPA/Robot/Keyboard.py,sha256=k_5uNh7UWq5F4TKGbe4LpJwqWgUrftNieWm51HOgOBI,22 -pyOpenRPA/Robot/Mouse.py,sha256=tBW9yteyEv9znJePOfbZcU3YqxX42wyu4Wc09fVaO0c,23 +pyOpenRPA/Robot/Clipboard.py,sha256=ntvXqnJpgmTPnehrjfVibrM72-AYLrqOn-CI2xVOaDs,1577 +pyOpenRPA/Robot/Keyboard.py,sha256=6Ah71EaETse2_nPiz8EPW_fZBlhpaZg5WZ6tWZ2wC9U,17898 +pyOpenRPA/Robot/Mouse.py,sha256=Wvai_tpanqREj5jA4tFEl_-0L45cpk41cX5_Ex68mBg,16079 pyOpenRPA/Robot/OrchestratorConnector.py,sha256=JUtdiUXCruqUqBD19gJBl9jk_b-tpWWx_v3MfBoKzoQ,20445 -pyOpenRPA/Robot/README.md,sha256=e2hKh7Tx6DAsX6jY_hBDhguL1L2Wiv6iugDB5otMzIA,2293 +pyOpenRPA/Robot/README.md,sha256=bwiTAygxuMZzBlwpsndw2QgxA2smIjUyOPZnsnR341k,1623 pyOpenRPA/Robot/Screen.py,sha256=tBW9yteyEv9znJePOfbZcU3YqxX42wyu4Wc09fVaO0c,23 pyOpenRPA/Robot/SettingsTemplate.py,sha256=Rp5XPeV2I4tCS2uf4Zkqm_ERJ6pZMg4-e5_lMqGJYLk,1453 pyOpenRPA/Robot/Test.py,sha256=qXr990nXiFZX5SNv6QN9GLb_U4HZRmJnbZR2qSnwilY,2878 -pyOpenRPA/Robot/UIDesktop.py,sha256=EllVup0umNNFqcQrrO6pffdoTBzc5Y-jEKrY0oO7joU,82938 +pyOpenRPA/Robot/UIDesktop.py,sha256=y0lHHtn-Cd7I1rUQGgBYfZQpfcrGBAfMST9F5aPIxtM,124815 pyOpenRPA/Robot/UIWeb.py,sha256=NFH0brDKEmWWOJxMzO7404K5lJ4LaDn5XMnkoH13Y64,22 pyOpenRPA/Robot/Utils/JSONNormalize.py,sha256=aIuVzuZDazhxkCOzoOjfhHVz66mp2FWdfPv5E7KWF5Y,3890 pyOpenRPA/Robot/Utils/ProcessBitness.py,sha256=WlKL-DklGaoTnchtapOTM_ydxSB4yOeo9lcG3zr2VME,4524 @@ -364,6 +364,6 @@ pyOpenRPA/Tools/__pycache__/License.cpython-37.pyc,, pyOpenRPA/Tools/__pycache__/StopSafe.cpython-37.pyc,, pyOpenRPA/Tools/__pycache__/Usage.cpython-37.pyc,, pyOpenRPA/Tools/__pycache__/__init__.cpython-37.pyc,, -pyOpenRPA/__init__.py,sha256=fmC6rG7L4TIer8c0qUyp-Ypv2d7C2TBucEjIg7Wwip4,175 +pyOpenRPA/__init__.py,sha256=Q9zi3T0F5hLslWv3SoO1EvZt17wEU5fq3JJ59uqdtg8,156 pyOpenRPA/__pycache__/__init__.cpython-37.pyc,, pyOpenRPA/test.txt,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 diff --git a/Resources/WPy32-3720/python-3.7.2/Lib/site-packages/pyOpenRPA-1.2.12.dist-info/REQUESTED b/Resources/WPy32-3720/python-3.7.2/Lib/site-packages/pyOpenRPA-1.2.13.dist-info/REQUESTED similarity index 100% rename from Resources/WPy32-3720/python-3.7.2/Lib/site-packages/pyOpenRPA-1.2.12.dist-info/REQUESTED rename to Resources/WPy32-3720/python-3.7.2/Lib/site-packages/pyOpenRPA-1.2.13.dist-info/REQUESTED diff --git a/Resources/WPy32-3720/python-3.7.2/Lib/site-packages/pyOpenRPA-1.2.12.dist-info/WHEEL b/Resources/WPy32-3720/python-3.7.2/Lib/site-packages/pyOpenRPA-1.2.13.dist-info/WHEEL similarity index 100% rename from Resources/WPy32-3720/python-3.7.2/Lib/site-packages/pyOpenRPA-1.2.12.dist-info/WHEEL rename to Resources/WPy32-3720/python-3.7.2/Lib/site-packages/pyOpenRPA-1.2.13.dist-info/WHEEL diff --git a/Resources/WPy32-3720/python-3.7.2/Lib/site-packages/pyOpenRPA-1.2.12.dist-info/top_level.txt b/Resources/WPy32-3720/python-3.7.2/Lib/site-packages/pyOpenRPA-1.2.13.dist-info/top_level.txt similarity index 100% rename from Resources/WPy32-3720/python-3.7.2/Lib/site-packages/pyOpenRPA-1.2.12.dist-info/top_level.txt rename to Resources/WPy32-3720/python-3.7.2/Lib/site-packages/pyOpenRPA-1.2.13.dist-info/top_level.txt diff --git a/Resources/WPy32-3720/python-3.7.2/Lib/site-packages/pyOpenRPA/Orchestrator/Managers/ControlPanel.py b/Resources/WPy32-3720/python-3.7.2/Lib/site-packages/pyOpenRPA/Orchestrator/Managers/ControlPanel.py index cef4acd4..599eed11 100644 --- a/Resources/WPy32-3720/python-3.7.2/Lib/site-packages/pyOpenRPA/Orchestrator/Managers/ControlPanel.py +++ b/Resources/WPy32-3720/python-3.7.2/Lib/site-packages/pyOpenRPA/Orchestrator/Managers/ControlPanel.py @@ -39,6 +39,7 @@ class ControlPanel(): Jinja2DataUpdateDictSet .. code-block:: html + Hello my control panel! You can use any def from Orchestrator module here in Jinja2 HTML template: Example: OrchestratorModule.OSCMD(inCMDStr="notepad") diff --git a/Resources/WPy32-3720/python-3.7.2/Lib/site-packages/pyOpenRPA/Orchestrator/Managers/Process.py b/Resources/WPy32-3720/python-3.7.2/Lib/site-packages/pyOpenRPA/Orchestrator/Managers/Process.py index 276e4adc..ff47c075 100644 --- a/Resources/WPy32-3720/python-3.7.2/Lib/site-packages/pyOpenRPA/Orchestrator/Managers/Process.py +++ b/Resources/WPy32-3720/python-3.7.2/Lib/site-packages/pyOpenRPA/Orchestrator/Managers/Process.py @@ -22,6 +22,7 @@ class Process(): - 5_STARTED_MANUAL .. code-block:: python + # For the safe init class use ProcessInitSafe lProcess = Orchestrator.Managers.ProcessInitSafe(inAgentHostNameStr="PCNAME",inAgentUserNameStr="USER", inProcessNameWOExeStr="notepad",inStartCMDStr="notepad",inStopSafeTimeoutSecFloat=3) @@ -35,6 +36,7 @@ class Process(): How to use StopSafe on the robot side .. code-block:: python + from pyOpenRPA.Tools import StopSafe StopSafe.Init(inLogger=None) StopSafe.IsSafeStop() # True - WM_CLOSE SIGNAL has come. taskkill /im someprocess.exe diff --git a/Resources/WPy32-3720/python-3.7.2/Lib/site-packages/pyOpenRPA/Orchestrator/__Orchestrator__.py b/Resources/WPy32-3720/python-3.7.2/Lib/site-packages/pyOpenRPA/Orchestrator/__Orchestrator__.py index b47d891d..dca95b25 100644 --- a/Resources/WPy32-3720/python-3.7.2/Lib/site-packages/pyOpenRPA/Orchestrator/__Orchestrator__.py +++ b/Resources/WPy32-3720/python-3.7.2/Lib/site-packages/pyOpenRPA/Orchestrator/__Orchestrator__.py @@ -41,13 +41,13 @@ gSettingsDict = None def AgentActivityItemAdd(inHostNameStr, inUserStr, inActivityItemDict, inGSettings=None): """ - Add activity in AgentDict. Check if item is created + Добавить активность в словарь активностей выбранного Агента - :param inGSettings: Global settings dict (singleton) - :param inHostNameStr: Agent host name - :param inUserStr: User login, where agent is based - :param inActivityItemDict: ActivityItem - :return: GUID String of the ActivityItem - you can wait (sync or async) result by this guid! + :param inGSettings: Глобальный словарь настроек Оркестратора (синглтон) + :param inHostNameStr: Наименование хоста, на котором запущен Агент. Наименования подключенных агентов доступно для просмотра в панели управления + :param inUserStr: Наименование пользователя, на графической сессии которого запущен Агент. Наименования подключенных агентов доступно для просмотра в панели управления + :param inActivityItemDict: Активность (ActivityItem). См. функцию ProcessorActivityitemCreate + :return: ГУИД (GUID) строка Активности (ActivityItem). Далее можно ожидать результат этой функции по ГУИД с помощью функции AgentActivityItemReturnGet """ inGSettings = GSettingsGet(inGSettings=inGSettings) # Set the global settings @@ -72,11 +72,11 @@ def AgentActivityItemAdd(inHostNameStr, inUserStr, inActivityItemDict, inGSettin def AgentActivityItemExists(inHostNameStr, inUserStr, inGUIDStr, inGSettings = None): """ - Check by GUID if ActivityItem has exists in request list. If exist - the result response has not been recieved from the agent + Выполнить проверку, что активность (ActivityItem) была отправлена на сторону Агента. - :param inGSettings: Global settings dict (singleton) - :param inGUIDStr: GUID String of the ActivityItem - :return: True - ActivityItem is exist in AgentDict ; False - else case + :param inGSettings: Глобальный словарь настроек Оркестратора (синглтон) + :param inGUIDStr: ГУИД (GUID) активности (ActivityItem) + :return: True - Активность присутствует ; False - Активность еще не была отправлена на сторону Агента """ # Check if GUID is exists in dict - has been recieved inGSettings = GSettingsGet(inGSettings=inGSettings) # Set the global settings @@ -92,11 +92,11 @@ def AgentActivityItemExists(inHostNameStr, inUserStr, inGUIDStr, inGSettings = N def AgentActivityItemReturnExists(inGUIDStr, inGSettings = None): """ - Check by GUID if ActivityItem has been executed and result has come to the Orchestrator + Выполнить проверку, что активность (ActivityItem) была выполнена на стороне Агента и результат был получен на стороне Оркестратора. - :param inGSettings: Global settings dict (singleton) - :param inGUIDStr: GUID String of the ActivityItem - you can wait (sync or async) result by this guid! - :return: True - result has been received from the Agent to orc; False - else case + :param inGSettings: Глобальный словарь настроек Оркестратора (синглтон) + :param inGUIDStr: ГУИД (GUID) активности (ActivityItem) + :return: True - Активность присутствует; False - Активность еще не была выполнена на стороне Агента """ inGSettings = GSettingsGet(inGSettings=inGSettings) # Set the global settings @@ -106,14 +106,15 @@ def AgentActivityItemReturnExists(inGUIDStr, inGSettings = None): def AgentActivityItemReturnGet(inGUIDStr, inCheckIntervalSecFloat = 0.5, inGSettings=None): """ - Work synchroniously! Wait while result will be recieved. Get the result of the ActivityItem execution on the Agent side. Before this please check by the def AgentActivityItemReturnExists that result has come to the Orchestrator - - !ATTENTION! Use only after Orchestrator initialization! Before orchestrator init exception will be raised. + Ожидает появления результата по активности (ActivityItem). Возвращает результат выполнения активности. + + !ВНИМАНИЕ! Замораживает поток, пока не будет получен результат. + !ВНИМАНИЕ! Запускать следует после того как будет инициализировано ядро Оркестратора (см. функцию OrchestratorInitWait), иначе будет инициирована ошибка. - :param inGSettings: Global settings dict (singleton) - :param inGUIDStr: GUID String of the ActivityItem - you can wait (sync or async) result by this guid! - :param inCheckIntervalSecFloat: Interval in sec of the check Activity Item result - :return: Result of the ActivityItem executed on the Agent side anr transmitted to the Orchestrator. IMPORTANT! ONLY JSON ENABLED Types CAN BE TRANSMITTED TO ORCHESTRATOR! + :param inGSettings: Глобальный словарь настроек Оркестратора (синглтон) + :param inGUIDStr: ГУИД (GUID) активности (ActivityItem) + :param inCheckIntervalSecFloat: Интервал в секундах, с какой частотой выполнять проверку результата. По умолчанию 0.5 + :return: Результат выполнения активности. !ВНИМАНИЕ! Возвращаются только то результаты, которые могут быть интерпретированы в JSON формате. """ inGSettings = GSettingsGet(inGSettings=inGSettings) # Set the global settings #Check if Orchestrator has been initialized - else raise exception @@ -128,17 +129,17 @@ def AgentActivityItemReturnGet(inGUIDStr, inCheckIntervalSecFloat = 0.5, inGSett def AgentOSCMD(inHostNameStr, inUserStr, inCMDStr, inRunAsyncBool=True, inSendOutputToOrchestratorLogsBool=True, inCMDEncodingStr="cp1251", inGSettings=None, inCaptureBool=True): """ - Send CMD to OS thought the pyOpenRPA.Agent daemon. Result return to log + Orchestrator by the A2O connection + Отправка команды командной строки на сессию, где работает pyOpenRPA.Agent. Результат выполнения команды можно выводить в лог оркестратора. - :param inGSettings: Global settings dict (singleton) - :param inHostNameStr: Agent host name in upper case (example "RPA01", "RPA_99" and so on). Active agent session you can see on the orchestrator dashboard as Orchestrator admin - :param inUserStr: Agent user name in upper case (example "UserRPA"). Active agent session you can see on the orchestrator dashboard as Orchestrator admin - :param inCMDStr: command to execute on the Agent session - :param inRunAsyncBool: True - Agent processor don't wait execution; False - Agent processor wait cmd execution - :param inSendOutputToOrchestratorLogsBool: True - catch cmd execution output and send it to the Orchestrator logs; Flase - else case; Default True - :param inCMDEncodingStr: Set the encoding of the DOS window on the Agent server session. Windows is beautiful :) . Default is "cp1251" early was "cp866" - need test - :param inCaptureBool: !ATTENTION! If you need to start absolutely encapsulated app - set this flag as False. If you set True - the app output will come to Agent - :return: GUID String of the ActivityItem - you can wait (sync or async) result by this guid! + :param inGSettings: Глобальный словарь настроек Оркестратора (синглтон) + :param inHostNameStr: Наименование хоста, на котором запущен Агент. Наименования подключенных агентов доступно для просмотра в панели управления + :param inUserStr: Наименование пользователя, на графической сессии которого запущен Агент. Наименования подключенных агентов доступно для просмотра в панели управления + :param inCMDStr: Команда для исполнения на стороне сессии Агента + :param inRunAsyncBool: True - Агент не ожидает окончания выполнения команды. !ВНИМАНИЕ! Логирование в такой ситуации будет невозможно; False - Агент ожидает окончания выполнения операции. + :param inSendOutputToOrchestratorLogsBool: True - отправлять весь вывод от команды в логи Оркестратора; Flase - Не отправлять; Default True + :param inCMDEncodingStr: Кодировка DOS среды, в которой исполняется команда. Если некорректно установить кодировку - русские символы будут испорчены. По умолчанию установлена "cp1251" + :param inCaptureBool: True - не запускать приложение как отдельное. Результат выполнения команды будет выводиться в окне Агента (если окно Агента присутствует на экране). False - команда будет запущена в отдельном DOS окне. + :return: ГУИД (GUID) строка Активности (ActivityItem). Далее можно ожидать результат этой функции по ГУИД с помощью функции AgentActivityItemReturnGet """ inGSettings = GSettingsGet(inGSettings=inGSettings) # Set the global settings lActivityItemDict = { @@ -153,9 +154,11 @@ def AgentOSCMD(inHostNameStr, inUserStr, inCMDStr, inRunAsyncBool=True, inSendOu def AgentOSLogoff(inHostNameStr, inUserStr): """ - Logoff the agent user session + Выполнить операцию logoff на стороне пользователя. - :return: GUID String of the ActivityItem - you can wait (sync or async) result by this guid! + :param inHostNameStr: Наименование хоста, на котором запущен Агент. Наименования подключенных агентов доступно для просмотра в панели управления + :param inUserStr: Наименование пользователя, на графической сессии которого запущен Агент. Наименования подключенных агентов доступно для просмотра в панели управления + :return: ГУИД (GUID) строка Активности (ActivityItem). Далее можно ожидать результат этой функции по ГУИД с помощью функции AgentActivityItemReturnGet """ inGSettings = GSettingsGet() # Set the global settings lCMDStr = "shutdown /l" @@ -171,16 +174,17 @@ def AgentOSLogoff(inHostNameStr, inUserStr): def AgentOSFileSend(inHostNameStr, inUserStr, inOrchestratorFilePathStr, inAgentFilePathStr, inGSettings = None): """ - Send the file from the Orchestrator to Agent (synchroniously) pyOpenRPA.Agent daemon process (safe for JSON transmition). - Work safety with big files - Thread safe - you can call def even if you dont init the orchestrator - def will be executed later + Отправить файл по адресу inOrchestratorFilePathStr со стороны Оркестратора и сохранить по адресу inAgentFilePathStr на стороне Агента. + Поддерживает передачу крупных файлов (более 2-х Гб.). Функция является синхронной - не закончит свое выполнение, пока файл не будет передан полностью. - :param inGSettings: Global settings dict (singleton) - :param inHostNameStr: - :param inUserStr: - :param inFilePathStr: - :param inFileDataBytes: - :return: GUID String of the ActivityItem - you can wait (sync or async) result by this guid! + !ВНИМАНИЕ - ПОТОКОБЕЗОПАСНАЯ! Вы можете вызвать эту функцию до инициализации ядра Оркестратора. Оркестратор добавит эту функцию в процессорную очередь на исполение. Если вам нужен результат функции, то необходимо сначала убедиться в том, что ядро Оркестратора было инициализированно (см. функцию OrchestratorInitWait). + + :param inHostNameStr: Наименование хоста, на котором запущен Агент. Наименования подключенных агентов доступно для просмотра в панели управления + :param inUserStr: Наименование пользователя, на графической сессии которого запущен Агент. Наименования подключенных агентов доступно для просмотра в панели управления + :param inOrchestratorFilePathStr: Полный путь к передаваемому файлу на стороне Оркестратора. + :param inAgentFilePathStr: Полный путь к локации, в которую требуется сохранить передаваемый файл. + :param inGSettings: Глобальный словарь настроек Оркестратора (синглтон) + :return: ГУИД (GUID) строка Активности (ActivityItem). Далее можно ожидать результат этой функции по ГУИД с помощью функции AgentActivityItemReturnGet """ inGSettings = GSettingsGet(inGSettings=inGSettings) # Set the global settings @@ -237,14 +241,14 @@ def AgentOSFileSend(inHostNameStr, inUserStr, inOrchestratorFilePathStr, inAgent def AgentOSFileBinaryDataBytesCreate(inHostNameStr, inUserStr, inFilePathStr, inFileDataBytes, inGSettings=None): """ - Create binary file by the base64 string by the pyOpenRPA.Agent daemon process (safe for JSON transmition) + Создать бинарный файл, который будет расположен по адресу inFilePathStr на стороне Агента с содержимым inFileDataBytes - :param inGSettings: Global settings dict (singleton) - :param inHostNameStr: - :param inUserStr: - :param inFilePathStr: - :param inFileDataBytes: - :return: GUID String of the ActivityItem - you can wait (sync or async) result by this guid! + :param inHostNameStr: Наименование хоста, на котором запущен Агент. Наименования подключенных агентов доступно для просмотра в панели управления + :param inUserStr: Наименование пользователя, на графической сессии которого запущен Агент. Наименования подключенных агентов доступно для просмотра в панели управления + :param inFilePathStr: Полный путь к сохраняемому файлу на стороне Агента. + :param inFileDataBytes: Строка байт (b'') для отправки в создаваемый файл на стороне Агента. + :param inGSettings: Глобальный словарь настроек Оркестратора (синглтон) + :return: ГУИД (GUID) строка Активности (ActivityItem). Далее можно ожидать результат этой функции по ГУИД с помощью функции AgentActivityItemReturnGet """ inGSettings = GSettingsGet(inGSettings=inGSettings) # Set the global settings lFileDataBase64Str = base64.b64encode(inFileDataBytes).decode("utf-8") @@ -261,14 +265,14 @@ def AgentOSFileBinaryDataBytesCreate(inHostNameStr, inUserStr, inFilePathStr, in def AgentOSFileBinaryDataBase64StrCreate(inHostNameStr, inUserStr, inFilePathStr, inFileDataBase64Str, inGSettings=None): """ - Create binary file by the base64 string by the pyOpenRPA.Agent daemon process (safe for JSON transmission) - - :param inGSettings: Global settings dict (singleton) - :param inHostNameStr: - :param inUserStr: - :param inFilePathStr: - :param inFileDataBase64Str: - :return: GUID String of the ActivityItem - you can wait (sync or async) result by this guid! + Создать бинарный файл, который будет расположен по адресу inFilePathStr на стороне Агента с содержимым, декодированным с формата base64: inFileDataBase64Str + + :param inHostNameStr: Наименование хоста, на котором запущен Агент. Наименования подключенных агентов доступно для просмотра в панели управления + :param inUserStr: Наименование пользователя, на графической сессии которого запущен Агент. Наименования подключенных агентов доступно для просмотра в панели управления + :param inFilePathStr: Полный путь к сохраняемому файлу на стороне Агента. + :param inFileDataBase64Str: Строка в формате base64 для отправки в создаваемый файл на стороне Агента. + :param inGSettings: Глобальный словарь настроек Оркестратора (синглтон) + :return: ГУИД (GUID) строка Активности (ActivityItem). Далее можно ожидать результат этой функции по ГУИД с помощью функции AgentActivityItemReturnGet """ inGSettings = GSettingsGet(inGSettings=inGSettings) # Set the global settings lActivityItemDict = { @@ -284,14 +288,14 @@ def AgentOSFileBinaryDataBase64StrCreate(inHostNameStr, inUserStr, inFilePathStr def AgentOSFileBinaryDataBase64StrAppend(inHostNameStr, inUserStr, inFilePathStr, inFileDataBase64Str, inGSettings = None): """ - Append binary file by the base64 string by the pyOpenRPA.Agent daemon process (safe for JSON transmission) - - :param inGSettings: Global settings dict (singleton) - :param inHostNameStr: - :param inUserStr: - :param inFilePathStr: - :param inFileDataBase64Str: - :return: GUID String of the ActivityItem - you can wait (sync or async) result by this guid! + Добавить бинарную информацию в существующий бинарный файл, который будет расположен по адресу inFilePathStr на стороне Агента с содержимым, декодированным с формата base64: inFileDataBase64Str + + :param inHostNameStr: Наименование хоста, на котором запущен Агент. Наименования подключенных агентов доступно для просмотра в панели управления + :param inUserStr: Наименование пользователя, на графической сессии которого запущен Агент. Наименования подключенных агентов доступно для просмотра в панели управления + :param inFilePathStr: Полный путь к сохраняемому файлу на стороне Агента. + :param inFileDataBase64Str: Строка в формате base64 для отправки в создаваемый файл на стороне Агента. + :param inGSettings: Глобальный словарь настроек Оркестратора (синглтон) + :return: ГУИД (GUID) строка Активности (ActivityItem). Далее можно ожидать результат этой функции по ГУИД с помощью функции AgentActivityItemReturnGet """ inGSettings = GSettingsGet(inGSettings=inGSettings) # Set the global settings lActivityItemDict = { @@ -308,15 +312,15 @@ def AgentOSFileBinaryDataBase64StrAppend(inHostNameStr, inUserStr, inFilePathStr # Send text file to Agent (string) def AgentOSFileTextDataStrCreate(inHostNameStr, inUserStr, inFilePathStr, inFileDataStr, inEncodingStr = "utf-8",inGSettings=None): """ - Create text file by the string by the pyOpenRPA.Agent daemon process - - :param inGSettings: Global settings dict (singleton) - :param inHostNameStr: - :param inUserStr: - :param inFilePathStr: - :param inFileDataStr: - :param inEncodingStr: - :return: GUID String of the ActivityItem - you can wait (sync or async) result by this guid! + Создать текстовый файл, который будет расположен по адресу inFilePathStr на стороне Агента с содержимым inFileDataStr в кодировке inEncodingStr + + :param inHostNameStr: Наименование хоста, на котором запущен Агент. Наименования подключенных агентов доступно для просмотра в панели управления + :param inUserStr: Наименование пользователя, на графической сессии которого запущен Агент. Наименования подключенных агентов доступно для просмотра в панели управления + :param inFilePathStr: Полный путь к сохраняемому файлу на стороне Агента. + :param inFileDataStr: Строка для отправки в создаваемый файл на стороне Агента. + :param inEncodingStr: Кодировка текстового файла. По умолчанию utf-8 + :param inGSettings: Глобальный словарь настроек Оркестратора (синглтон) + :return: ГУИД (GUID) строка Активности (ActivityItem). Далее можно ожидать результат этой функции по ГУИД с помощью функции AgentActivityItemReturnGet """ inGSettings = GSettingsGet(inGSettings=inGSettings) # Set the global settings lActivityItemDict = { @@ -331,13 +335,13 @@ def AgentOSFileTextDataStrCreate(inHostNameStr, inUserStr, inFilePathStr, inFile def AgentOSFileBinaryDataBase64StrReceive(inHostNameStr, inUserStr, inFilePathStr, inGSettings = None): """ - Read binary file and encode in base64 to transmit (safe for JSON transmition) + Выполнить чтение бинарного файла и получить содержимое в формате base64 (строка) - :param inGSettings: Global settings dict (singleton) - :param inHostNameStr: - :param inUserStr: - :param inFilePathStr: File path to read - :return: GUID String of the ActivityItem - you can wait (sync or async) result by this guid! + :param inHostNameStr: Наименование хоста, на котором запущен Агент. Наименования подключенных агентов доступно для просмотра в панели управления + :param inUserStr: Наименование пользователя, на графической сессии которого запущен Агент. Наименования подключенных агентов доступно для просмотра в панели управления + :param inFilePathStr: Путь к бинарному файлу на чтение на стороне Агента + :param inGSettings: Глобальный словарь настроек Оркестратора (синглтон) + :return: ГУИД (GUID) строка Активности (ActivityItem). Далее можно ожидать результат этой функции по ГУИД с помощью функции AgentActivityItemReturnGet """ inGSettings = GSettingsGet(inGSettings=inGSettings) # Set the global settings lActivityItemDict = { @@ -353,13 +357,14 @@ def AgentOSFileBinaryDataBase64StrReceive(inHostNameStr, inUserStr, inFilePathSt def AgentOSFileBinaryDataReceive(inHostNameStr, inUserStr, inFilePathStr): """ - Read binary file from agent (synchronious) - - :param inGSettings: Global settings dict (singleton) - :param inHostNameStr: - :param inUserStr: - :param inFilePathStr: File path to read - :return: file data bytes + Чтение бинарного файла на стороне Агента по адресу inFilePathStr. + + !ВНИМАНИЕ - СИНХРОННАЯ! Функция не завершится, пока не будет получен результат чтения на стороне Агента. + + :param inHostNameStr: Наименование хоста, на котором запущен Агент. Наименования подключенных агентов доступно для просмотра в панели управления + :param inUserStr: Наименование пользователя, на графической сессии которого запущен Агент. Наименования подключенных агентов доступно для просмотра в панели управления + :param inFilePathStr: Путь к бинарному файлу, который требуется прочитать на стороне Агента + :return: Строка байт (b'') - содержимое бинарного файла """ lFileDataBytes = None inGSettings = GSettingsGet() # Set the global settings @@ -391,14 +396,16 @@ def AgentOSFileBinaryDataReceive(inHostNameStr, inUserStr, inFilePathStr): def AgentOSFileTextDataStrReceive(inHostNameStr, inUserStr, inFilePathStr, inEncodingStr="utf-8", inGSettings = None): """ - Read text file in the agent GUI session - - :param inGSettings: Global settings dict (singleton) - :param inHostNameStr: - :param inUserStr: - :param inFilePathStr: File path to read - :param inEncodingStr: Text file encoding. Default 'utf-8' - :return: GUID String of the ActivityItem - you can wait (sync or async) result by this guid! + Чтение текстового файла на стороне Агента по адресу inFilePathStr. По ГИУД с помощью функции AgentActivityItemReturnGet можно будет получить текстовую строку данных, которые были расположены в файле. + + !ВНИМАНИЕ - АСИНХРОННАЯ! Функция завершится сразу, не дожидаясь окончания выполнения операции на стороне Агента. + + :param inHostNameStr: Наименование хоста, на котором запущен Агент. Наименования подключенных агентов доступно для просмотра в панели управления + :param inUserStr: Наименование пользователя, на графической сессии которого запущен Агент. Наименования подключенных агентов доступно для просмотра в панели управления + :param inFilePathStr: Путь к бинарному файлу, который требуется прочитать на стороне Агента + :param inEncodingStr: Кодировка текстового файла. По умолчанию utf-8 + :param inGSettings: Глобальный словарь настроек Оркестратора (синглтон) + :return: ГУИД (GUID) строка Активности (ActivityItem). Далее можно ожидать результат этой функции по ГУИД с помощью функции AgentActivityItemReturnGet """ inGSettings = GSettingsGet(inGSettings=inGSettings) # Set the global settings lActivityItemDict = { @@ -413,12 +420,14 @@ def AgentOSFileTextDataStrReceive(inHostNameStr, inUserStr, inFilePathStr, inEnc def AgentProcessWOExeUpperUserListGet(inHostNameStr, inUserStr, inGSettings = None): """ - Return the process list only for the current user (where Agent is running) without .EXE in upper case. Can use in ActivityItem from Orchestrator to Agent + Получить список процессов, которые выполняется на сессии Агента. Все процессы фиксируются без постфикса .exe, а также в верхнем регистре. + + ПРИМЕР РЕЗУЛЬТАТА, КОТОРЫЙ МОЖНО ПОЛУЧИТЬ ПО ГУИД ЧЕРЕЗ ФУНКЦИЮ AgentActivityItemReturnGet: ["ORCHESTRATOR", "AGENT", "CHROME", "EXPLORER", ...] - :param inGSettings: Global settings dict (singleton) - :param inHostNameStr: - :param inUserStr: - :return: GUID String of the ActivityItem - you can wait (sync or async) result by this guid! + :param inGSettings: Глобальный словарь настроек Оркестратора (синглтон) + :param inHostNameStr: Наименование хоста, на котором запущен Агент. Наименования подключенных агентов доступно для просмотра в панели управления + :param inUserStr: Наименование пользователя, на графической сессии которого запущен Агент. Наименования подключенных агентов доступно для просмотра в панели управления + :return: ГУИД (GUID) строка Активности (ActivityItem). Далее можно ожидать результат этой функции по ГУИД с помощью функции AgentActivityItemReturnGet """ inGSettings = GSettingsGet(inGSettings=inGSettings) # Set the global settings lActivityItemDict = { @@ -432,22 +441,22 @@ def AgentProcessWOExeUpperUserListGet(inHostNameStr, inUserStr, inGSettings = No return AgentActivityItemAdd(inGSettings=inGSettings, inHostNameStr=inHostNameStr, inUserStr=inUserStr, inActivityItemDict=lActivityItemDict) # OS DEFS - def OSLogoff(): """ - Logoff the current orchestrator session + Выполнить отключение сессии, на которой выполняется Оркестратор. + :return: """ os.system("shutdown /l") def OSCredentialsVerify(inUserStr, inPasswordStr, inDomainStr=""): ## """ - Verify user credentials in windows. Return bool + Выполнить верификацию доменного (локального) пользователя по паре логин/пароль - :param inUserStr: - :param inPasswordStr: - :param inDomainStr: - :return: True - Credentials are actual; False - Credentials are not actual + :param inUserStr: Наименование пользователя + :param inPasswordStr: Пароль + :param inDomainStr: Домен. Если домена нет - не указывать или "" + :return: True - Учетные данные верны; False - Учетные данные представлены некорректно """ try: hUser = win32security.LogonUser( @@ -461,12 +470,13 @@ def OSCredentialsVerify(inUserStr, inPasswordStr, inDomainStr=""): ## def OSRemotePCRestart(inHostStr, inForceBool=True, inLogger = None): """ - Send signal via power shell to restart remote PC - ATTENTION: Orchestrator user need to have restart right on the Remote machine to restart PC. + Отправить сигнал на удаленную перезагрузку операционной системы. + + !ВНИМАНИЕ! Перезапуск будет принят, если учетная запись имеет полномочия на перезапуск на соответсвующей машине. - :param inLogger: logger to log powershell result in logs - :param inHostStr: PC hostname which you need to restart. - :param inForceBool: True - send signal to force retart PC; False - else case + :param inHostStr: Имя хоста, который требуется перезагрузить + :param inForceBool: True - принудительная перезагрузка; False - мягкая перезагрузка (дождаться окончания выполнения всех операций). По умолчанию True + :param inLogger: Логгер, в который отправлять информацию о результате выполнения команды :return: """ if inLogger is None: inLogger = OrchestratorLoggerGet() @@ -476,12 +486,12 @@ def OSRemotePCRestart(inHostStr, inForceBool=True, inLogger = None): def OSCMD(inCMDStr, inRunAsyncBool=True, inLogger = None): """ - OS send command in shell locally + Отправить команду на выполнение на сессию, где выполняется Оркестратор. - :param inCMDStr: - :param inRunAsyncBool: - :param inLogger: - :return: CMD result string + :param inCMDStr: Команда на отправку + :param inRunAsyncBool: True - выполнить команду в асинхронном режиме (не дожидаться окончания выполнения программы и не захватывать результат выполнения); False - Ждать окончания выполнения и захватывать результат + :param inLogger: Логгер, в который отправлять информацию о результате выполнения команды + :return: Строка результата выполнения команды. Если inRunAsyncBool = False """ if inLogger is None: inLogger = OrchestratorLoggerGet() lResultStr = "" @@ -521,9 +531,9 @@ def OSCMD(inCMDStr, inRunAsyncBool=True, inLogger = None): def OrchestratorRestart(inGSettings=None): """ - Orchestrator restart + Перезапуск Оркестратора с сохранением информации о запущенных RDP сессиях. - :param inGSettings: Global settings dict (singleton) + :param inGSettings: Глобальный словарь настроек Оркестратора (синглтон) """ inGSettings = GSettingsGet(inGSettings=inGSettings) # Set the global settings OrchestratorSessionSave(inGSettings=inGSettings) # Dump RDP List in file json @@ -536,27 +546,27 @@ def OrchestratorRestart(inGSettings=None): def OrchestratorLoggerGet() -> logging.Logger: """ - Get the logger from the Orchestrator + Получить логгер Оркестратора - :return: + :return: Логгер """ return GSettingsGet().get("Logger",None) def OrchestratorScheduleGet() -> schedule: """ - Get the schedule (schedule.readthedocs.io) from the Orchestrator - - Fro example you can use: + Базовый объект расписания, который можно использовать для запуска / остановки роботов. + Подробнее про объект schedule и его примеры использования см. по адресу: schedule.readthedocs.io .. code-block:: python - # One schedule threaded + + # Однопоточный schedule Orchestrator.OrchestratorScheduleGet().every(5).seconds.do(lProcess.StatusCheckStart) - #New schedule thread # See def description Orchestrator.OrchestratorThreadStart + #Многопоточный schedule. cм. описание Orchestrator.OrchestratorThreadStart Orchestrator.OrchestratorScheduleGet().every(5).seconds.do(Orchestrator.OrchestratorThreadStart,lProcess.StatusCheckStart) - :return: schedule module. Example see here https://schedule.readthedocs.io/en/stable/examples.html + :return: schedule объект """ if GSettingsGet().get("SchedulerDict",{}).get("Schedule",None) is None: GSettingsGet()["SchedulerDict"]["Schedule"]=schedule @@ -564,12 +574,12 @@ def OrchestratorScheduleGet() -> schedule: def OrchestratorThreadStart(inDef, *inArgList, **inArgDict): """ - Execute def in new thread and pass some args with list and dict types + Запустить функцию в отдельном потоке. В таком случае получить результат выполнения функции можно только через общие переменные. (Например через GSettings) - :param inDef: Python Def - :param inArgList: args as list - :param inArgDict: args as dict - :return: threading.Thread object + :param inDef: Python функция + :param inArgList: Список неименованных аргументов функции inDef + :param inArgDict: Словарь именованных аргументов функции inDef + :return: threading.Thread экземпляр """ lDefThread = threading.Thread(target=inDef,args=inArgList,kwargs=inArgDict) lDefThread.start() @@ -577,9 +587,9 @@ def OrchestratorThreadStart(inDef, *inArgList, **inArgDict): def OrchestratorIsAdmin(): """ - Check if Orchestrator process is running as administrator + Проверить, запущен ли Оркестратор с правами администратора. Права администратора нужны Оркестратору только для контроля графической сессии, на которой он запущен. Если эти права выделить индивидуально, то права администратора будут необязательны. - :return: True - run as administrator; False - not as administrator + :return: True - Запущен с правами администратора; False - Не запущен с правами администратора """ try: return ctypes.windll.shell32.IsUserAnAdmin() @@ -587,17 +597,20 @@ def OrchestratorIsAdmin(): return False def OrchestratorIsInited() -> bool: - """Check if Orchestrator initial actions were processed + """ + Проверить, было ли проинициализировано ядро Оркестратора - :return: True - orc is already inited; False - else + :return: True - Ядро Оркестратора было проинициализировано; False - Требуется время на инициализацию :rtype: bool """ return Core.IsOrchestratorInitialized(inGSettings=GSettingsGet()) def OrchestratorInitWait() -> None: - """Wait thread while orc will process initial action. - ATTENTION: DO NOT CALL THIS DEF IN THREAD WHERE ORCHESTRATOR MUST BE INITIALIZED - INFINITE LOOP + """ + Ожидать инициализацию ядра Оркестратора + + !ВНИМАНИЕ!: НИ В КОЕМ СЛУЧАЕ НЕ ЗАПУСКАТЬ ЭТУ ФУНКЦИЮ В ОСНОВНОМ ПОТОКЕ, ГДЕ ПРОИСХОДИТ ИНИЦИАЛИЗАЦИЯ ЯДРА ОРКЕСТРАТОРА - ВОЗНИКНЕТ ВЕЧНЫЙ ЦИКЛ """ lIntervalSecFloat = 0.5 while not OrchestratorIsInited(): @@ -606,9 +619,9 @@ def OrchestratorInitWait() -> None: def OrchestratorRerunAsAdmin(): """ - Check if not admin - then rerun orchestrator as administrator + Перезапустить Оркестратор с правами локального администратора. Права администратора нужны Оркестратору только для контроля графической сессии, на которой он запущен. Если эти права выделить индивидуально, то права администратора будут необязательны. - :return: True - run as administrator; False - not as administrator + :return: True - Запущен с правами администратора; False - Не запущен с правами администратора """ if not OrchestratorIsAdmin(): # Re-run the program with admin rights @@ -618,19 +631,21 @@ def OrchestratorRerunAsAdmin(): def OrchestratorPySearchInit(inGlobPatternStr, inDefStr = None, inDefArgNameGSettingsStr = None, inAsyncInitBool = False): """ - Search the py files by the glob and do the safe init (in try except). Also add inited module in sys.modules as imported (module name = file name without extension). - You can init CP in async way! + Выполнить поиск и инициализацию пользовательских .py файлов в Оркестраторе (например панелей управления роботов) + + Добавляет инициализированный модуль в пространство sys.modules как imported (имя модуля = имя файла без расширения). + .. code-block:: python - # USAGE VAR 1 (without the def auto call) - # Autoinit control panels starts with CP_ + # ВАРИАНТ ИСПОЛЬЗОВАНИЯ 1 (инициализация модуля py без вызова каких-либо функций внутри) + # автоинициализация всех .py файлов, с префиксом CP_, которые расположены в папке ControlPanel Orchestrator.OrchestratorPySearchInit(inGlobPatternStr="ControlPanel\\CP_*.py") - # USAGE VAR 2 (with the def auto call) - for the backward compatibility CP for the Orchestrator ver. < 1.2.7 - # Autoinit control panels starts with CP_ + # ВАРИАНТ ИСПОЛЬЗОВАНИЯ 2 (инициализация модуля py с вызовом функции внутри) - преимущественно для обратной совместимости старых версий панелей управления < 1.2.7 + # автоинициализация всех .py файлов, с префиксом CP_, которые расположены в папке ControlPanel Orchestrator.OrchestratorPySearchInit(inGlobPatternStr="ControlPanel\\CP_*.py", inDefStr="SettingsUpdate", inDefArgNameGSettingsStr="inGSettings") - # INFO: The code above will replace the code below + # ДЛЯ СПРАВКИ & ИСТОРИИ: Код выше позволил отказаться от блока кода ниже для каждого .py файла ## !!! For Relative import !!! CP Version Check try: sys.path.insert(0,os.path.abspath(os.path.join(r""))) @@ -639,12 +654,11 @@ def OrchestratorPySearchInit(inGlobPatternStr, inDefStr = None, inDefArgNameGSet except Exception as e: gSettings["Logger"].exception(f"Exception when init CP. See below.") - - :param inGlobPatternStr: example"..\\*\\*\\*X64*.cmd" - :param inDefStr: OPTIONAL The string name of the def. For backward compatibility if you need to auto call some def from initialized module - :param inDefArgNameGSettingsStr: OPTIONAL The name of the GSettings argument in def (if exists) - :param inAsyncInitBool: OPTIONAL True - init py modules in many threads - parallel execution. False (default) - sequence execution - :return: { "ModuleNameStr":{"PyPathStr": "", "Module": ...}, ...} + :param inGlobPatternStr: Пример "..\\*\\*\\*_CP*.py" + :param inDefStr: ОПЦИОНАЛЬНО Строковое наименование функции. Преимущественно для обратной совместимости + :param inDefArgNameGSettingsStr: ОПЦИОНАЛЬНО Наименование аргумента, в который требуется передать GSettings (если необходимо) + :param inAsyncInitBool: ОПЦИОНАЛЬНО True - Инициализация py модулей в отдельных параллельных потоках - псевдопараллельное выполнение. False - последовательная инициализация + :return: Сведения об инициализированных модулях в структуре: { "ModuleNameStr":{"PyPathStr": "", "Module": ...}, ...} """ # # # # # # # # @@ -688,16 +702,19 @@ def OrchestratorPySearchInit(inGlobPatternStr, inDefStr = None, inDefArgNameGSet def OrchestratorSessionSave(inGSettings=None): """ - Orchestrator session save in file - (from version 1.2.7) + Сохранить состояние Оркестратора (для дальнейшего восстановления в случае перезапуска): + + - RDP сессий, которые контролирует Оркестратор + - Хранилища DataStorage в глобальном словаре настроек GSettings. DataStorage поддерживает хранение объектов Python + + (до версии 1.2.7) _SessionLast_GSettings.pickle (binary) - (above the version 1.2.7) + (начиная с версии 1.2.7) _SessionLast_RDPList.json (encoding = "utf-8") _SessionLast_StorageDict.pickle (binary) - :param inGSettings: Global settings dict (singleton) - :return: True every time + :param inGSettings: Глобальный словарь настроек Оркестратора (синглтон) """ inGSettings = GSettingsGet(inGSettings=inGSettings) # Set the global settings lL = inGSettings["Logger"] @@ -730,16 +747,19 @@ def OrchestratorSessionSave(inGSettings=None): def OrchestratorSessionRestore(inGSettings=None): """ - Check _SessioLast... files in working directory. if exist - load into gsettings - (from version 1.2.7) + Восстановить состояние Оркестратора, если ранее состояние Оркестратора было сохранено с помощью функции OrchestratorSessionSave: + + - RDP сессий, которые контролирует Оркестратор + - Хранилища DataStorage в глобальном словаре настроек GSettings. DataStorage поддерживает хранение объектов Python + + (до версии 1.2.7) _SessionLast_GSettings.pickle (binary) - (above the version 1.2.7) + (начиная с версии 1.2.7) _SessionLast_RDPList.json (encoding = "utf-8") _SessionLast_StorageDict.pickle (binary) - :param inGSettings: Global settings dict (singleton) - :return: + :param inGSettings: Глобальный словарь настроек Оркестратора (синглтон) """ inGSettings = GSettingsGet(inGSettings=inGSettings) # Set the global settings lL = inGSettings.get("Logger",None) @@ -776,33 +796,47 @@ def OrchestratorSessionRestore(inGSettings=None): def UACKeyListCheck(inRequest, inRoleKeyList) -> bool: """ - Check is client is has access for the key list + Проверить права доступа для пользователя запроса по списку ключей до права. + + .. code-block:: python + + # ВАРИАНТ ИСПОЛЬЗОВАНИЯ 1 (инициализация модуля py без вызова каких-либо функций внутри) + # автоинициализация всех .py файлов, с префиксом CP_, которые расположены в папке ControlPanel + Orchestrator.UACKeyListCheck(inRequest=lRequest, inRoleKeyList=["ROBOT1","DISPLAY_DASHBOARD"]) - :param inRequest: request handler (from http.server import BaseHTTPRequestHandler) - :param inRoleKeyList: - :return: bool + :param inRequest: Экземпляр request (from http.server import BaseHTTPRequestHandler) + :param inRoleKeyList: Список ключей, права доступа к которому требуется проверить + :return: True - Пользователь обладает соответствующим правом; False - Пользователь не обладает соответствующим правом """ return inRequest.UACClientCheck(inRoleKeyList=inRoleKeyList) def UACUserDictGet(inRequest) -> dict: """ - Return user UAC hierarchy dict of the inRequest object. Empty dict - superuser access + Вернуть UAC (User Access Control) словарб доступов для пользователя, который отправил запрос. Пустой словарь - супердоступ (доступ ко всему) - :param inRequest: request handler (from http.server import BaseHTTPRequestHandler) - :return: user UAC hierarchy dict + :param inRequest: Экземпляр request (from http.server import BaseHTTPRequestHandler) + :return: Словарь доступов пользователя. Пустой словарь - супердоступ (доступ ко всему) """ return inRequest.UserRoleHierarchyGet() # get the Hierarchy def UACUpdate(inADLoginStr, inADStr="", inADIsDefaultBool=True, inURLList=None, inRoleHierarchyAllowedDict=None, inGSettings = None): """ - Update user access (UAC) - - :param inGSettings: Global settings dict (singleton) - :param inADLoginStr: - :param inADStr: - :param inADIsDefaultBool: - :param inURLList: - :param inRoleHierarchyAllowedDict: + Дообогащение словаря доступа UAC пользователя inADStr\\inADLoginStr. Если ранее словарь не устанавливался, то по умолчанию он {}. Далее идет дообогащение теми ключами, которые присутствуют в inRoleHierarchyAllowedDict + + :param inGSettings: Глобальный словарь настроек Оркестратора (синглтон) + :param inADLoginStr: Логин пользователя + :param inADStr: Домен пользователя. Если пусто - локальный компьютер или домен по-умолчанию, который настроен в ОС + :param inADIsDefaultBool: True - домен настроен по умолчанию; False - домен требуется обязательно указывать + :param inURLList: Список разрешенных URL для пользователя. Для добавления URL рекомендуем использовать функции WebURLConnectDef, WebURLConnectFile, WebURLConnectFolder + Формат: { + "Method": "GET" || "POST", + "URL": "/GetScreenshot", + "MatchType": "BeginWith" || "Equal" || "EqualCase" || "Contains" || "EqualNoParam", + "ResponseDefRequestGlobal": Функция python || "ResponseFilePath": Путь к файлу || "ResponseFolderPath": Путь к папке, в которой искать файлы, + "ResponseContentType": пример MIME "image/png", + "UACBool":False - не выполнять проверку прав доступа по запросу, + "UseCacheBool": True - кэшировать ответ}, + :param inRoleHierarchyAllowedDict: Словарь доступа пользователя UAC. Пустой словарь - полный доступ """ inGSettings = GSettingsGet(inGSettings=inGSettings) # Set the global settings lUserTurple = (inADStr.upper(),inADLoginStr.upper()) # Create turple key for inGSettings["ServerDict"]["AccessUsers"]["RuleDomainUserDict"] @@ -831,10 +865,10 @@ def UACUpdate(inADLoginStr, inADStr="", inADIsDefaultBool=True, inURLList=None, def UACSuperTokenUpdate(inSuperTokenStr, inGSettings=None): """ - Add supertoken for the all access (it is need for the robot communication without human) + Добавить супертокен (полный доступ). Супертокены используются для подключения к Оркестратору по API - :param inGSettings: Global settings dict (singleton) - :param inSuperTokenStr: + :param inGSettings: Глобальный словарь настроек Оркестратора (синглтон) + :param inSuperTokenStr: Кодовая строковая комбинация, которая будет предоставлять доступ роботу / агенту для взаимодействия с Оркестратором по API """ inGSettings = GSettingsGet(inGSettings=inGSettings) # Set the global settings lLoginStr = "SUPERTOKEN" @@ -846,31 +880,26 @@ def UACSuperTokenUpdate(inSuperTokenStr, inGSettings=None): # # # # # # # # # # # # # # # # # # # # # # # # OrchestratorWeb defs # # # # # # # # # # # # # # # # # # # # # # # - def WebURLIndexChange(inURLIndexStr:str ="/"): - """Change the index page of the orchestrator if you dont want the '/' (main) path + """ + Изменить адрес главной страницы Оркестратора. По умолчанию '/' - :param inURLIndexStr: New url for the index page of the orchestrator, defaults to "/" - :type inURLIndexStr: str, optional + :param inURLIndexStr: Новый адрес главной страницы Оркестратора. + :type inURLIndexStr: str, опционально """ GSettingsGet()["ServerDict"]["URLIndexStr"] = inURLIndexStr def WebURLConnectDef(inMethodStr, inURLStr, inMatchTypeStr, inDef, inContentTypeStr="application/octet-stream", inGSettings = None, inUACBool = None): """ - Connect URL to DEF - "inMethodStr":"GET|POST", - "inURLStr": "/index", #URL of the request - "inMatchTypeStr": "", #"BeginWith|Contains|Equal|EqualCase", - "inContentTypeStr": "", #HTTP Content-type - "inDef": None #Function with str result - - :param inGSettings: Global settings dict (singleton) - :param inMethodStr: "GET|POST", - :param inURLStr: example "/index", #URL of the request - :param inMatchTypeStr: #"BeginWith|Contains|Equal|EqualCase", - :param inDef: def arg allowed list: 2:[inRequest, inGSettings], 1: [inRequest], 0: [] - :param inContentTypeStr: default: "application/octet-stream" - :param inUACBool: default: None; True - check user access before do this URL item. None - get Server flag if ask user + Подключить функцию Python к URL. + + :param inMethodStr: Метод доступа по URL "GET" || "POST" + :param inURLStr: URL адрес. Пример "/index" + :param inMatchTypeStr: Тип соответсвия строки URL с inURLStr: "BeginWith" || "Contains" || "Equal" || "EqualCase" || "EqualNoParam" + :param inDef: Функция Python. Допускаются функции, которые принимают следующие наборы параметров: 2:[inRequest, inGSettings], 1: [inRequest], 0: [] + :param inContentTypeStr: МИМЕ тип. По умолчанию: "application/octet-stream" + :param inUACBool: True - Выполнять проверку прав доступа пользователя перед отправкой ответа; False - не выполнять проверку прав доступа пользователя + :param inGSettings: Глобальный словарь настроек Оркестратора (синглтон) """ inGSettings = GSettingsGet(inGSettings=inGSettings) # Set the global settings lURLItemDict = { @@ -889,20 +918,15 @@ def WebURLConnectDef(inMethodStr, inURLStr, inMatchTypeStr, inDef, inContentType def WebURLConnectFolder(inMethodStr, inURLStr, inMatchTypeStr, inFolderPathStr, inGSettings = None, inUACBool = None, inUseCacheBool= False): """ - Connect URL to Folder - "inMethodStr":"GET|POST", - "inURLStr": "/Folder/", #URL of the request - "inMatchTypeStr": "", #"BeginWith|Contains|Equal|EqualCase", - "inFolderPathStr": "", #Absolute or relative path - "inUACBool" - - :param inGSettings: Global settings dict (singleton) - :param inMethodStr: - :param inURLStr: - :param inMatchTypeStr: - :param inFolderPathStr: - :param inUACBool: default: None; True - check user access before do this URL item. None - get Server flag if ask user - :param inUseCacheBool: True - cache this page - dont open ever + Подключить папку к URL. + + :param inMethodStr: Метод доступа по URL "GET" || "POST" + :param inURLStr: URL адрес. Пример "/index" + :param inMatchTypeStr: Тип соответсвия строки URL с inURLStr: "BeginWith" || "Contains" || "Equal" || "EqualCase" || "EqualNoParam" + :param inFolderPathStr: Путь к папке на диске, в которой искать файл и возвращать пользователю по HTTP + :param inUACBool: True - Выполнять проверку прав доступа пользователя перед отправкой ответа; False - не выполнять проверку прав доступа пользователя + :param inUseCacheBool: True - выполнить кэширование страницы, чтобы в следющих запросах открыть быстрее; False - не кэшировать + :param inGSettings: Глобальный словарь настроек Оркестратора (синглтон) """ inGSettings = GSettingsGet(inGSettings=inGSettings) # Set the global settings # Check if last symbol is "/" - append if not exist @@ -925,20 +949,18 @@ def WebURLConnectFolder(inMethodStr, inURLStr, inMatchTypeStr, inFolderPathStr, def WebURLConnectFile(inMethodStr, inURLStr, inMatchTypeStr, inFilePathStr, inContentTypeStr=None, inGSettings = None, inUACBool = None, inUseCacheBool = False): """ - Connect URL to File - "inMethodStr":"GET|POST", - "inURLStr": "/index", #URL of the request - "inMatchTypeStr": "", #"BeginWith|Contains|Equal|EqualCase", - "inFolderPathStr": "", #Absolute or relative path - - :param inGSettings: Global settings dict (singleton) - :param inMethodStr: - :param inURLStr: - :param inMatchTypeStr: - :param inFilePathStr: - :param inContentTypeStr: If none - autodetect - :param inUACBool: default: None; True - check user access before do this URL item. None - get Server flag if ask user - :param inUseCacheBool: True - cache this page - dont open ever + + Подключить файл к URL. + + :param inMethodStr: Метод доступа по URL "GET" || "POST" + :param inURLStr: URL адрес. Пример "/index" + :param inMatchTypeStr: Тип соответсвия строки URL с inURLStr: "BeginWith" || "Contains" || "Equal" || "EqualCase" || "EqualNoParam" + :param inFilePathStr: Путь к файлу на диске, который возвращать пользователю по HTTP + :param inContentTypeStr: МИМЕ тип. Если None - выполнить автоматическое определение + :param inUACBool: True - Выполнять проверку прав доступа пользователя перед отправкой ответа; False - не выполнять проверку прав доступа пользователя + :param inUseCacheBool: True - выполнить кэширование страницы, чтобы в следющих запросах открыть быстрее; False - не кэшировать + :param inGSettings: Глобальный словарь настроек Оркестратора (синглтон) + """ inGSettings = GSettingsGet(inGSettings=inGSettings) # Set the global settings lURLItemDict = { @@ -956,13 +978,13 @@ def WebURLConnectFile(inMethodStr, inURLStr, inMatchTypeStr, inFilePathStr, inCo def WebListenCreate(inServerKeyStr="Default", inAddressStr="", inPortInt=80, inCertFilePEMPathStr=None, inKeyFilePathStr=None, inGSettings = None): """ - Create listen interface for the web server - - :param inGSettings: Global settings dict (singleton) - :param inAddressStr: IP interface to listen - :param inPortInt: Port int to listen for HTTP default is 80; for HTTPS default is 443 - :param inCertFilePEMPathStr: Path to .pem (base 64) certificate. Required for SSL connection. ATTENTION - do not use certificate with password - :param inKeyFilePathStr: Path to the private key file + Настроить веб-сервер Оркестратора. + + :param inAddressStr: IP адрес для прослушивания. Если "", то прослушивать запросы со всех сетевых карт. Если "127.0.0.1", то слушать запросы только с той ОС, на которой работает Оркестратор + :param inPortInt: Номер порта для прослушивания. Если HTTP - 80; Если HTTPS - 443. По умолчанию 80. Допускается установка других портов + :param inCertFilePEMPathStr: Путь файлу сертификата, сгенерированного в .pem (base64) формате. Обязателен при использовании защищенного HTTPS/SSL соединения. + :param inKeyFilePathStr: Путь к файлу закрытого ключа в base64 формате + :param inGSettings: Глобальный словарь настроек Оркестратора (синглтон) :return: """ inGSettings = GSettingsGet(inGSettings=inGSettings) # Set the global settings @@ -977,13 +999,13 @@ def WebListenCreate(inServerKeyStr="Default", inAddressStr="", inPortInt=80, inC def WebCPUpdate(inCPKeyStr, inHTMLRenderDef=None, inJSONGeneratorDef=None, inJSInitGeneratorDef=None, inGSettings = None): """ - Add control panel HTML, JSON generator or JS when page init + Добавить панель управления робота в Оркестратор. Для панели управления открыт доступ для использования функции-генератора HTML, генератора JSON данных, генератора JS кода. - :param inGSettings: Global settings dict (singleton) - :param inCPKeyStr: - :param inHTMLRenderDef: - :param inJSONGeneratorDef: - :param inJSInitGeneratorDef: + :param inGSettings: Глобальный словарь настроек Оркестратора (синглтон) + :param inCPKeyStr: Текстовый ключ панели управления. Ключ для каждой панели управления должен быть уникальным! + :param inHTMLRenderDef: Функция Python для генерации HTML кода. Для использования Jinja2 шаблонов HTML см. pyOpenRPA.Orchestrator.Managers.ControlPanel + :param inJSONGeneratorDef: Функция Python для генерации JSON контейнера для отправки на клиентскую часть Оркестратора + :param inJSInitGeneratorDef: Функция Python для генерации JS кода для отправки на клиентскую часть Оркестратора """ lCPManager = Managers.ControlPanel(inControlPanelNameStr=inCPKeyStr, inRefreshHTMLJinja2TemplatePathStr=None) # CASE HTMLRender @@ -996,11 +1018,11 @@ def WebCPUpdate(inCPKeyStr, inHTMLRenderDef=None, inJSONGeneratorDef=None, inJSI def WebAuditMessageCreate(inRequest=None, inOperationCodeStr="-", inMessageStr="-"): """ - Create message string with request user details (IP, Login etc...). Very actual for IT security in big company. - + Создание сообщения ИТ аудита с такими сведениями как (Домен, IP, логин и тд.). Данная функция особенно актуальна в том случае, если требуется реализовать дополнительные меры контроля ИТ системы. + .. code-block:: python - # USAGE + # ПРИМЕР from pyOpenRPA import Orchestrator lWebAuditMessageStr = Orchestrator.WebAuditMessageCreate( @@ -1008,13 +1030,13 @@ def WebAuditMessageCreate(inRequest=None, inOperationCodeStr="-", inMessageStr=" inOperationCodeStr = "OP_CODE_1", inMessageStr="Success"): - # Log the WebAudit message + # Логгирование сообщения lLogger.info(lWebAuditMessageStr) - :param inRequest: HTTP request handler. Optional if call def from request thread - :param inOperationCodeStr: operation code in string format (actual for IT audit in control panels) - :param inMessageStr: additional message after - :return: format "WebAudit :: DOMAIN\\USER@101.121.123.12 :: operation code :: message" + :param inRequest: Экземпляр HTTP request. Опционален, если сообщение фиксируется из под потока, который был инициирован запросом пользователя + :param inOperationCodeStr: Код операции, который принят в компании в соответствии с регламентными процедурами + :param inMessageStr: Дополнительное сообщение, которое необходимо отправить в сообщение об ИТ аудите + :return: Формат сообщения: "WebAudit :: DOMAIN\\USER@101.121.123.12 :: operation code :: message" """ try: if inRequest is None: inRequest = WebRequestGet() @@ -1030,10 +1052,10 @@ def WebAuditMessageCreate(inRequest=None, inOperationCodeStr="-", inMessageStr=" def WebRequestParseBodyBytes(inRequest=None): """ - Extract the body in bytes from the request + Извлечь данные в байт виде из тела (body) HTTP запроса. - :param inRequest: inRequest from the server. Optional if call def from request thread - :return: Bytes or None + :param inRequest: Экземпляр HTTP request. Опционален, если сообщение фиксируется из под потока, который был инициирован запросом пользователя + :return: Строка байт b'' или None (если тело запроса было пустым) """ if inRequest is None: inRequest = WebRequestGet() lBodyBytes=None @@ -1044,40 +1066,40 @@ def WebRequestParseBodyBytes(inRequest=None): def WebRequestParseBodyStr(inRequest=None): """ - Extract the body in str from the request + Извлечь данные в виде строки из тела (body) HTTP запроса. - :param inRequest: inRequest from the server. Optional if call def from request thread - :return: str or None + :param inRequest: Экземпляр HTTP request. Опционален, если сообщение фиксируется из под потока, который был инициирован запросом пользователя + :return: Текстовая строка '' или None (если тело запроса было пустым) """ if inRequest is None: inRequest = WebRequestGet() return WebRequestParseBodyBytes(inRequest=inRequest).decode('utf-8') def WebRequestParseBodyJSON(inRequest=None): """ - Extract the body in dict/list from the request + Извлечь из тела (body) запроса HTTP JSON данные и преобразовать в Dict / List структуры языка Python. - :param inRequest: inRequest from the server. Optional if call def from request thread - :return: dict or list + :param inRequest: Экземпляр HTTP request. Опционален, если сообщение фиксируется из под потока, который был инициирован запросом пользователя + :return: Словарь (dict), список (list) или None (если тело запроса было пустым) """ if inRequest is None: inRequest = WebRequestGet() return json.loads(WebRequestParseBodyStr(inRequest=inRequest)) def WebRequestParsePath(inRequest=None): """ - Parse the request - extract the url. Example: /pyOpenRPA/Debugging/DefHelper/... + Извлечь декодированный URL путь из HTTP запроса пользователя в формате строки. - :param inRequest: inRequest from the server. Optional if call def from request thread - :return: Str, Example: /pyOpenRPA/Debugging/DefHelper/... + :param inRequest: Экземпляр HTTP request. Опционален, если сообщение фиксируется из под потока, который был инициирован запросом пользователя + :return: str, пример: /pyOpenRPA/Debugging/DefHelper """ if inRequest is None: inRequest = WebRequestGet() return urllib.parse.unquote(inRequest.path) def WebRequestParseFile(inRequest=None): """ - Parse the request - extract the file (name, body in bytes) + Извлечь файл (наименование + содержимое в виде строки байт b'') из HTTP запроса пользователя. - :param inRequest: inRequest from the server. Optional if call def from request thread - :return: (FileNameStr, FileBodyBytes) or (None, None) + :param inRequest: Экземпляр HTTP request. Опционален, если сообщение фиксируется из под потока, который был инициирован запросом пользователя + :return: Кортеж формата (FileNameStr, FileBodyBytes) or (None, None), если файл не был обнаружен """ if inRequest is None: inRequest = WebRequestGet() lResultTurple=(None,None) @@ -1099,21 +1121,26 @@ def WebRequestParseFile(inRequest=None): return lResultTurple -def WebRequestResponseSend(inResponeStr, inRequest=None): +def WebRequestResponseSend(inResponeStr, inRequest=None, inContentTypeStr: str = None, inHeadersDict: dict = None): """ - Send response for the request + Установить ответ на HTTP запрос пользователя. - :param inRequest: inRequest from the server. Optional if call def from request thread - :return: + :param inResponeStr: Тело ответа (строка) + :param inRequest: Экземпляр HTTP request. Опционален, если сообщение фиксируется из под потока, который был инициирован запросом пользователя + :param inContentTypeStr: МИМЕ тип. Пример: "html/text" + :param inHeadersDict: Словарь (dict) ключей, которые добавить в headers HTTP ответа на запрос пользователя """ if inRequest is None: inRequest = WebRequestGet() inRequest.OpenRPAResponseDict["Body"] = bytes(inResponeStr, "utf8") + if inHeadersDict is not None: + inRequest.OpenRPAResponseDict["Headers"].update(inHeadersDict) + if inContentTypeStr is not None: + inRequest.OpenRPAResponseDict["Headers"]["Content-type"] = inContentTypeStr def WebRequestGet(): """ - Return the web request instance if current thread was created by web request from client. else return None - + Вернуть экземпляр HTTP запроса, если функция вызвана в потоке, который был порожден для отработки HTTP запроса пользователя. """ lCurrentThread = threading.current_thread() if hasattr(lCurrentThread, "request"): @@ -1121,10 +1148,10 @@ def WebRequestGet(): def WebUserInfoGet(inRequest=None): """ - Return User info about request + Информация о пользователе, который отправил HTTP запрос. - :param inRequest: inRequest from the server. Optional if call def from request thread - :return: {"DomainUpperStr": "", "UserNameUpperStr": ""} + :param inRequest: Экземпляр HTTP request. Опционален, если сообщение фиксируется из под потока, который был инициирован запросом пользователя + :return: Сведения в формате {"DomainUpperStr": "PYOPENRPA", "UserNameUpperStr": "IVAN.MASLOV"} """ if inRequest is None: inRequest = WebRequestGet() lDomainUpperStr = inRequest.OpenRPA["Domain"].upper() @@ -1133,11 +1160,11 @@ def WebUserInfoGet(inRequest=None): def WebUserIsSuperToken(inRequest = None, inGSettings = None): """ - Return bool if request is authentificated with supetoken (token which is never expires) + Проверить, авторизован ли HTTP запрос с помощью супер токена (токен, который не истекает). - :param inRequest: inRequest from the server. Optional if call def from request thread - :param inGSettings: Global settings dict (singleton) - :return: bool True - is supertoken; False - is not supertoken + :param inRequest: Экземпляр HTTP request. Опционален, если сообщение фиксируется из под потока, который был инициирован запросом пользователя + :param inGSettings: Глобальный словарь настроек Оркестратора (синглтон) + :return: True - является супертокеном; False - не является супертокеном """ if inRequest is None: inRequest = WebRequestGet() inGSettings = GSettingsGet(inGSettings=inGSettings) # Set the global settings @@ -1148,10 +1175,10 @@ def WebUserIsSuperToken(inRequest = None, inGSettings = None): def WebUserUACHierarchyGet(inRequest = None): """ - Return User UAC Hierarchy DICT Return {...} + Вернуть словарь доступа UAC в отношении пользователя, который выполнил HTTP запрос inRequest - :param inRequest: inRequest from the server. Optional if call def from request thread - :return: UAC Dict {} + :param inRequest: Экземпляр HTTP request. Опционален, если сообщение фиксируется из под потока, который был инициирован запросом пользователя + :return: UAC словарь доступа или {}, что означает полный доступ """ if inRequest is None: inRequest = WebRequestGet() return inRequest.UserRoleHierarchyGet() @@ -1171,10 +1198,10 @@ if __name__ == "pyOpenRPA.Orchestrator.__Orchestrator__" and "pyOpenRPA.Orchestr def GSettingsGet(inGSettings=None): """ - Get the GSettings from the singleton module. + Вернуть глобальный словарь настроек Оркестратора. Во время выполнения программы глобальный словарь настроек существует в единственном экземпляре (синглтон) - :param inGSettings: You can pass some GSettings to check if it equal to base gsettings. If not equal - def will merge it - :return: GSettings + :param inGSettings: Дополнительный словарь настроек, который необходимо добавить в основной глобальный словарь настроек Оркестратора (синглтон) + :return: Глобальный словарь настроек GSettings """ global GSettings # identify the global variable # Merge dictionaries if some new dictionary has come @@ -1184,12 +1211,13 @@ def GSettingsGet(inGSettings=None): def GSettingsKeyListValueSet(inValue, inKeyList=None, inGSettings = None): """ - Set value in GSettings by the key list + Установить значение из глобального словаря настроек Оркестратора GSettings по списку ключей. + + Пример: Для того, чтобы установить значение для ключа car в словаре {"complex":{"car":"green"}, "simple":"HELLO"}, необходимо передать список ключей: ["complex", "car"] - :param inGSettings: Global settings dict (singleton) - :param inValue: - :param inKeyList: - :return: bool + :param inGSettings: Глобальный словарь настроек Оркестратора (синглтон) + :param inValue: Значение для установки в глобальный словарь настроек Оркестратора GSettings + :param inKeyList: Список ключей, по адресу которого установить значение в GSettings """ inGSettings = GSettingsGet(inGSettings=inGSettings) # Set the global settings if inKeyList is None: inKeyList = [] @@ -1206,11 +1234,11 @@ def GSettingsKeyListValueSet(inValue, inKeyList=None, inGSettings = None): def GSettingsKeyListValueGet(inKeyList=None, inGSettings = None): """ - Get the value from the GSettings by the key list + Получить значение из глобального словаря настроек Оркестратора GSettings по списку ключей. - :param inGSettings: Global settings dict (singleton) - :param inKeyList: - :return: value any type + :param inGSettings: Глобальный словарь настроек Оркестратора (синглтон) + :param inKeyList: Список ключей, по адресу которого получить значение из GSettings + :return: Значение (тип данных определяется форматом хранения в GSettings) """ inGSettings = GSettingsGet(inGSettings=inGSettings) # Set the global settings if inKeyList is None: inKeyList = [] @@ -1226,11 +1254,11 @@ def GSettingsKeyListValueGet(inKeyList=None, inGSettings = None): def GSettingsKeyListValueAppend(inValue, inKeyList=None, inGSettings = None): """ - Append value in GSettings by the key list + Применить операцию .append к обьекту, расположенному по адресу списка ключей inKeyList в глобальном словаре настроек Оркестратора GSettings. Пример: Добавить значение в конец списка (list). .. code-block:: python - # USAGE + # ПРИМЕР from pyOpenRPA import Orchestrator Orchestrator.GSettingsKeyListValueAppend( @@ -1246,10 +1274,9 @@ def GSettingsKeyListValueAppend(inValue, inKeyList=None, inGSettings = None): # } #} - :param inGSettings: Global settings dict (singleton) - :param inValue: Any value to be appended in gSettings Dict by the key list - :param inKeyList: List of the nested keys (see example) - :return: True every time + :param inGSettings: Глобальный словарь настроек Оркестратора (синглтон) + :param inValue: Значение для установки в глобальный словарь настроек Оркестратора GSettings + :param inKeyList: Список ключей, по адресу которого выполнить добавление в конец списка (list) """ inGSettings = GSettingsGet(inGSettings=inGSettings) # Set the global settings if inKeyList is None: inKeyList = [] @@ -1266,11 +1293,11 @@ def GSettingsKeyListValueAppend(inValue, inKeyList=None, inGSettings = None): def GSettingsKeyListValueOperatorPlus(inValue, inKeyList=None, inGSettings = None): """ - Execute plus operation between 2 lists (1:inValue and 2:gSettings by the inKeyList) + Применить оператор сложения (+) к обьекту, расположенному по адресу списка ключей inKeyList в глобальном словаре настроек Оркестратора GSettings. Пример: соединить 2 списка (list). .. code-block:: python - # USAGE + # ПРИМЕР from pyOpenRPA import Orchestrator Orchestrator.GSettingsKeyListValueOperatorPlus( @@ -1289,10 +1316,9 @@ def GSettingsKeyListValueOperatorPlus(inValue, inKeyList=None, inGSettings = Non # } #} - :param inGSettings: Global settings dict (singleton) - :param inValue: List with values to be merged with list in gSettings - :param inKeyList: List of the nested keys (see example) - :return: True every time + :param inGSettings: Глобальный словарь настроек Оркестратора (синглтон) + :param inValue: Значение для установки в глобальный словарь настроек Оркестратора GSettings + :param inKeyList: Список ключей, по адресу которого выполнить добавление в конец списка (list) """ inGSettings = GSettingsGet(inGSettings=inGSettings) # Set the global settings if inKeyList is None: inKeyList = [] @@ -1309,19 +1335,19 @@ def GSettingsKeyListValueOperatorPlus(inValue, inKeyList=None, inGSettings = Non def StorageRobotExists(inRobotNameStr): """ - Check if robot storage exists + Проверить, существует ли ключ inRobotNameStr в хранилище пользовательской информации StorageDict (GSettings > StarageDict) - :param inRobotNameStr: Robot name (case sensitive) - :return: True - robot storage exist; False - does not exist + :param inRobotNameStr: Наименование (ключ) робота. !ВНИМАНИЕ! Наименование чувствительно к регистру + :return: True - ключ робота присутствует в хранилище; False - отсутствует """ return inRobotNameStr in GSettingsGet()["StorageDict"] def StorageRobotGet(inRobotNameStr): """ - Get the robot storage by the robot name. If Robot storage is not exist - function will create it + Получить содержимое по ключу робота inRobotNameStr в хранилище пользовательской информации StorageDict (GSettings > StarageDict) - :param inRobotNameStr: Robot name (case sensitive) - :return: Dict + :param inRobotNameStr: Наименование (ключ) робота. !ВНИМАНИЕ! Наименование чувствительно к регистру + :return: Значение или структура, которая расположена по адресу (GSettings > StarageDict > inRobotNameStr) """ if inRobotNameStr not in GSettingsGet()["StorageDict"]: GSettingsGet()["StorageDict"][inRobotNameStr]={} @@ -1329,9 +1355,9 @@ def StorageRobotGet(inRobotNameStr): def ProcessorAliasDefCreate(inDef, inAliasStr=None, inGSettings = None): """ - Create alias for def (can be used in ActivityItem in field Def) - !WHEN DEF ALIAS IS REQUIRED! - Def alias is required when you try to call Python def from the Orchestrator WEB side (because you can't transmit Python def object out of the Python environment) - Deprecated. See ActivityItemDefAliasCreate + Создать синоним (текстовый ключ) для инициации выполнения функции в том случае, если запрос на выполнения пришел из вне (передача функций невозможна). + + Старая версия. Новую версию см. ActivityItemDefAliasCreate .. code-block:: python @@ -1346,18 +1372,19 @@ def ProcessorAliasDefCreate(inDef, inAliasStr=None, inGSettings = None): inAliasStr="TestDefAlias") # Now you can call TestDef by the alias from var lAliasStr with help of ActivityItem (key Def = lAliasStr) - :param inGSettings: Global settings dict (singleton) - :param inDef: Def - :param inAliasStr: String alias for associated def - :return: str Alias string (Alias can be regenerated if previous alias was occupied) + + :param inDef: функция Python + :param inAliasStr: Строковый ключ (синоним), который можно будет использовать в Активности (ActivityItem) + :param inGSettings: Глобальный словарь настроек Оркестратора (синглтон) + :return: Строковый ключ, который был назначен. Ключ может быть изменен, если входящий текстовый ключ был уже занят. """ return ActivityItemDefAliasCreate(inDef=inDef, inAliasStr=inAliasStr, inGSettings = inGSettings) def ProcessorAliasDefUpdate(inDef, inAliasStr, inGSettings = None): """ - Update alias for def (can be used in ActivityItem in field Def). - !WHEN DEF ALIAS IS REQUIRED! - Def alias is required when you try to call Python def from the Orchestrator WEB side (because you can't transmit Python def object out of the Python environment) - Deprecated. See ActivityItemDefAliasUpdate + Обновить синоним (текстовый ключ) для инициации выполнения функции в том случае, если запрос на выполнения пришел из вне (передача функций невозможна). + + Старая версия. Новую версию см. ActivityItemDefAliasUpdate .. code-block:: python @@ -1372,20 +1399,20 @@ def ProcessorAliasDefUpdate(inDef, inAliasStr, inGSettings = None): inAliasStr="TestDefAlias") # Now you can call TestDef by the alias "TestDefAlias" with help of ActivityItem (key Def = "TestDefAlias") - :param inGSettings: Global settings dict (singleton) - :param inDef: Def - :param inAliasStr: String alias for associated def - :return: str Alias string + :param inGSettings: Глобальный словарь настроек Оркестратора (синглтон) + :param inDef: функция Python + :param inAliasStr: Строковый ключ (синоним), который можно будет использовать в Активности (ActivityItem) + :return: Строковый ключ, который был назначен. Ключ будет тем же, если входящий текстовый ключ был уже занят. """ return ActivityItemDefAliasUpdate(inDef=inDef, inAliasStr=inAliasStr, inGSettings = inGSettings) # ActivityItem defs def ActivityItemHelperDefList(inDefQueryStr=None): """ - Create list of the available Def names in activity item. You can use query def filter via arg inDefQueryStr + Получить список синонимов (текстовых ключей), доступных для использования в Активностях (ActivityItem). - :param inDefStr: - :return: ["ActivityItemDefAliasUpdate", "ActivityItemDefAliasCreate", etc...] + :param inDefStr: Часть текстового ключ (начало / середина / конец) + :return: Список доступных ключей в формате: ["ActivityItemDefAliasUpdate", "ActivityItemDefAliasCreate", etc...] """ lResultList = [] if inDefQueryStr is not None: # do search alg @@ -1399,10 +1426,17 @@ def ActivityItemHelperDefList(inDefQueryStr=None): def ActivityItemHelperDefAutofill(inDef): """ - Detect def by the name and prepare the activity item dict with values. + Анализ аргументов функции по синониму (текстовому ключу). - :param inDef: - :return: + :param inDef: Часть текстового ключ (начало / середина / конец) + :return: Преднастроенная структура активности (ActivityItem) + { + "Def": None, + "ArgList": [], + "ArgDict": {}, + "ArgGSettingsStr": None, + "ArgLoggerStr": None + } """ lResultDict = { "Def": None, @@ -1431,14 +1465,14 @@ def ActivityItemHelperDefAutofill(inDef): def ActivityItemCreate(inDef, inArgList=None, inArgDict=None, inArgGSettingsStr=None, inArgLoggerStr=None, inGUIDStr = None, inThreadBool = False): """ - Create activity item. Activity item can be used as list item in ProcessorActivityItemAppend or in Processor.ActivityListExecute. + Создать Активность (ActivityItem). Активность можно использовать в ProcessorActivityItemAppend или в Processor.ActivityListExecute или в функциях работы с Агентами. .. code-block:: python - # USAGE + # ПРИМЕР from pyOpenRPA import Orchestrator - # EXAMPLE 1 + # ВАРИАНТ 1 def TestDef(inArg1Str, inGSettings, inLogger): pass lActivityItem = Orchestrator.ActivityItemCreate( @@ -1456,7 +1490,7 @@ def ActivityItemCreate(inDef, inArgList=None, inArgDict=None, inArgGSettingsStr= # "ArgLogger": "inLogger" # } - # EXAMPLE 2 + # ВАРИАНТ 2 def TestDef(inArg1Str): pass Orchestrator.ActivityItemDefAliasUpdate( @@ -1478,14 +1512,23 @@ def ActivityItemCreate(inDef, inArgList=None, inArgDict=None, inArgGSettingsStr= # "ArgLogger": None # } - :param inDef: def link or def alias (look gSettings["Processor"]["AliasDefDict"]) - :param inArgList: Args list for the Def - :param inArgDict: Args dict for the def - :param inArgGSettingsStr: Name of def argument of the GSettings dict - :param inArgLoggerStr: Name of def argument of the logging object - :param inGUIDStr: GUID which you can specify. If None the GUID will be generated - :param inThreadBool: True - execute ActivityItem in new thread; False - in processor thread - :return: {} + :param inDef: Функция Python или синоним (текстовый ключ) + :param inArgList: Список (list) неименованных аргументов к функции + :param inArgDict: Словарь (dict) именованных аргументов к функции + :param inArgGSettingsStr: Текстовое наименование аргумента GSettings (если требуется передавать) + :param inArgLoggerStr: Текстовое наименование аргумента logger (если требуется передавать) + :param inGUIDStr: ГУИД идентификатор активности (ActivityItem). Если ГУИД не указан, то он будет сгенерирован автоматически + :param inThreadBool: True - выполнить ActivityItem в новом потоке; False - выполнить последовательно в общем потоке процессорной очереди + :return: + lActivityItemDict= { + "Def":inDef, # def link or def alias (look gSettings["Processor"]["AliasDefDict"]) + "ArgList":inArgList, # Args list + "ArgDict":inArgDict, # Args dictionary + "ArgGSettings": inArgGSettingsStr, # Name of GSettings attribute: str (ArgDict) or index (for ArgList) + "ArgLogger": inArgLoggerStr, # Name of GSettings attribute: str (ArgDict) or index (for ArgList) + "GUIDStr": inGUIDStr, + "ThreadBool": inThreadBool + } """ # Work about GUID in Activity items if inGUIDStr is None: @@ -1506,12 +1549,11 @@ def ActivityItemCreate(inDef, inArgList=None, inArgDict=None, inArgGSettingsStr= def ActivityItemDefAliasCreate(inDef, inAliasStr=None, inGSettings = None): """ - Create alias for def (can be used in ActivityItem in field Def) - !WHEN DEF ALIAS IS REQUIRED! - Def alias is required when you try to call Python def from the Orchestrator WEB side (because you can't transmit Python def object out of the Python environment) - + Создать синоним (текстовый ключ) для инициации выполнения функции в том случае, если запрос на выполнения пришел из вне (передача функций невозможна). + .. code-block:: python - # USAGE + # ПРИМЕР from pyOpenRPA import Orchestrator def TestDef(): @@ -1522,10 +1564,10 @@ def ActivityItemDefAliasCreate(inDef, inAliasStr=None, inGSettings = None): inAliasStr="TestDefAlias") # Now you can call TestDef by the alias from var lAliasStr with help of ActivityItem (key Def = lAliasStr) - :param inGSettings: Global settings dict (singleton) - :param inDef: Def - :param inAliasStr: String alias for associated def - :return: str Alias string (Alias can be regenerated if previous alias was occupied) + :param inDef: функция Python + :param inAliasStr: Строковый ключ (синоним), который можно будет использовать в Активности (ActivityItem) + :param inGSettings: Глобальный словарь настроек Оркестратора (синглтон) + :return: Строковый ключ, который был назначен. Ключ может быть изменен, если входящий текстовый ключ был уже занят. """ #TODO Pay attention - New alias can be used too - need to create more complex algorythm to create new alias! inGSettings = GSettingsGet(inGSettings=inGSettings) # Set the global settings @@ -1540,9 +1582,7 @@ def ActivityItemDefAliasCreate(inDef, inAliasStr=None, inGSettings = None): def ActivityItemDefAliasModulesLoad(): """ - Load all def from sys.modules... in ActivityItem def alias dict - - :return: None + Загрузить все функции из импортированных модулей sys.modules в ActivityItem синонимы - полезно для отладки со стороны панели управления. """ lL = OrchestratorLoggerGet() lL.info(f"ActivityItem aliases: start to load sys.modules") @@ -1560,9 +1600,8 @@ def ActivityItemDefAliasModulesLoad(): def ActivityItemDefAliasUpdate(inDef, inAliasStr, inGSettings = None): """ - Update alias for def (can be used in ActivityItem in field Def). - !WHEN DEF ALIAS IS REQUIRED! - Def alias is required when you try to call Python def from the Orchestrator WEB side (because you can't transmit Python def object out of the Python environment) - + Обновить синоним (текстовый ключ) для инициации выполнения функции в том случае, если запрос на выполнения пришел из вне (передача функций невозможна). + .. code-block:: python # USAGE @@ -1576,10 +1615,10 @@ def ActivityItemDefAliasUpdate(inDef, inAliasStr, inGSettings = None): inAliasStr="TestDefAlias") # Now you can call TestDef by the alias "TestDefAlias" with help of ActivityItem (key Def = "TestDefAlias") - :param inGSettings: Global settings dict (singleton) - :param inDef: Def - :param inAliasStr: String alias for associated def - :return: str Alias string + :param inDef: функция Python + :param inAliasStr: Строковый ключ (синоним), который можно будет использовать в Активности (ActivityItem) + :param inGSettings: Глобальный словарь настроек Оркестратора (синглтон) + :return: Строковый ключ, который был назначен. Ключ будет тем же, если входящий текстовый ключ был уже занят. """ inGSettings = GSettingsGet(inGSettings=inGSettings) # Set the global settings if callable(inDef): inGSettings["ProcessorDict"]["AliasDefDict"][inAliasStr] = inDef @@ -1590,14 +1629,16 @@ def ActivityItemDefAliasUpdate(inDef, inAliasStr, inGSettings = None): def ProcessorActivityItemCreate(inDef, inArgList=None, inArgDict=None, inArgGSettingsStr=None, inArgLoggerStr=None, inGUIDStr = None, inThreadBool = False): """ - Create activity item. Activity item can be used as list item in ProcessorActivityItemAppend or in Processor.ActivityListExecute. - Deprecated. See ActivityItemCreate + Создать Активность (ActivityItem). Активность можно использовать в ProcessorActivityItemAppend или в Processor.ActivityListExecute или в функциях работы с Агентами. + + Старая версия. Новую версию см. в ActivityItemCreate + .. code-block:: python - # USAGE + # ПРИМЕР from pyOpenRPA import Orchestrator - # EXAMPLE 1 + # ВАРИАНТ 1 def TestDef(inArg1Str, inGSettings, inLogger): pass lActivityItem = Orchestrator.ProcessorActivityItemCreate( @@ -1615,7 +1656,7 @@ def ProcessorActivityItemCreate(inDef, inArgList=None, inArgDict=None, inArgGSet # "ArgLogger": "inLogger" # } - # EXAMPLE 2 + # ВАРИАНТ 2 def TestDef(inArg1Str): pass Orchestrator.ProcessorAliasDefUpdate( @@ -1637,22 +1678,31 @@ def ProcessorActivityItemCreate(inDef, inArgList=None, inArgDict=None, inArgGSet # "ArgLogger": None # } - :param inDef: def link or def alias (look gSettings["Processor"]["AliasDefDict"]) - :param inArgList: Args list for the Def - :param inArgDict: Args dict for the def - :param inArgGSettingsStr: Name of def argument of the GSettings dict - :param inArgLoggerStr: Name of def argument of the logging object - :param inGUIDStr: GUID which you can specify. If None the GUID will be generated - :param inThreadBool: True - execute ActivityItem in new thread; False - in processor thread - :return: {} + :param inDef: Функция Python или синоним (текстовый ключ) + :param inArgList: Список (list) неименованных аргументов к функции + :param inArgDict: Словарь (dict) именованных аргументов к функции + :param inArgGSettingsStr: Текстовое наименование аргумента GSettings (если требуется передавать) + :param inArgLoggerStr: Текстовое наименование аргумента logger (если требуется передавать) + :param inGUIDStr: ГУИД идентификатор активности (ActivityItem). Если ГУИД не указан, то он будет сгенерирован автоматически + :param inThreadBool: True - выполнить ActivityItem в новом потоке; False - выполнить последовательно в общем потоке процессорной очереди + :return: + lActivityItemDict= { + "Def":inDef, # def link or def alias (look gSettings["Processor"]["AliasDefDict"]) + "ArgList":inArgList, # Args list + "ArgDict":inArgDict, # Args dictionary + "ArgGSettings": inArgGSettingsStr, # Name of GSettings attribute: str (ArgDict) or index (for ArgList) + "ArgLogger": inArgLoggerStr, # Name of GSettings attribute: str (ArgDict) or index (for ArgList) + "GUIDStr": inGUIDStr, + "ThreadBool": inThreadBool + } """ return ActivityItemCreate(inDef=inDef, inArgList=inArgList, inArgDict=inArgDict, inArgGSettingsStr=inArgGSettingsStr, inArgLoggerStr=inArgLoggerStr, inGUIDStr=inGUIDStr, inThreadBool=inThreadBool) def ProcessorActivityItemAppend(inGSettings = None, inDef=None, inArgList=None, inArgDict=None, inArgGSettingsStr=None, inArgLoggerStr=None, inActivityItemDict=None): """ - Create and add activity item in processor queue. - + Добавить активность (ActivityItem) в процессорную очередь. + .. code-block:: python # USAGE @@ -1688,14 +1738,16 @@ def ProcessorActivityItemAppend(inGSettings = None, inDef=None, inArgList=None, inActivityItemDict = lActivityItem) # Activity have been already append in the processor queue - :param inGSettings: Global settings dict (singleton) - :param inDef: def link or def alias (look gSettings["Processor"]["AliasDefDict"]) - :param inArgList: Args list for the Def - :param inArgDict: Args dict for the Def - :param inArgGSettingsStr: Name of def argument of the GSettings dict - :param inArgLoggerStr: Name of def argument of the logging object - :param inActivityItemDict: Fill if you already have ActivityItemDict (don't fill inDef, inArgList, inArgDict, inArgGSettingsStr, inArgLoggerStr) - :return ActivityItem GUIDStr + :param inGSettings: Глобальный словарь настроек Оркестратора (синглтон) + :param inDef: Функция Python или синоним (текстовый ключ) + :param inArgList: Список (list) неименованных аргументов к функции + :param inArgDict: Словарь (dict) именованных аргументов к функции + :param inArgGSettingsStr: Текстовое наименование аргумента GSettings (если требуется передавать) + :param inArgLoggerStr: Текстовое наименование аргумента logger (если требуется передавать) + :param inGUIDStr: ГУИД идентификатор активности (ActivityItem). Если ГУИД не указан, то он будет сгенерирован автоматически + :param inThreadBool: True - выполнить ActivityItem в новом потоке; False - выполнить последовательно в общем потоке процессорной очереди + :param inActivityItemDict: Альтернативный вариант заполнения, если уже имеется Активность (ActivityItem). В таком случае не требуется заполнять аргументы inDef, inArgList, inArgDict, inArgGSettingsStr, inArgLoggerStr + :return ГУИД активности (ActivityItem) """ inGSettings = GSettingsGet(inGSettings=inGSettings) # Set the global settings if inActivityItemDict is None: @@ -1727,18 +1779,20 @@ def ProcessorActivityItemAppend(inGSettings = None, inDef=None, inArgList=None, ## Process defs def ProcessIsStarted(inProcessNameWOExeStr): # Check if process is started """ - Check if there is any running process that contains the given name processName. + Проверить, запущен ли процесс, который в наименовании содержит inProcessNameWOExeStr. + !ВНИМАНИЕ! ПРОВЕРЯЕТ ВСЕ ПРОЦЕССЫ ОПЕРАЦИОННОЙ СИСТЕМЫ. И ДРУГИХ ПОЛЬЗОВАТЕЛЬСКИХ СЕССИЙ, ЕСЛИ ОНИ ЗАПУЩЕНЫ НА ЭТОЙ МАШИНЕ. + .. code-block:: python - # USAGE + # ПРИМЕР from pyOpenRPA import Orchestrator lProcessIsStartedBool = Orchestrator.ProcessIsStarted(inProcessNameWOExeStr = "notepad") # lProcessIsStartedBool is True - notepad.exe is running on the Orchestrator machine - :param inProcessNameWOExeStr: Process name WithOut (WO) '.exe' postfix. Example: "notepad" (not "notepad.exe") - :return: True - process is running on the orchestrator machine; False - process is not running on the orchestrator machine + :param inProcessNameWOExeStr: Наименование процесса без расширения .exe (WO = WithOut = Без) Пример: Для проверки процесса блокнота нужно указывать "notepad", не "notepad.exe" + :return: True - Процесс запущен на ОС ; False - Процесс не запущен на ОС, где работает Оркестратор """ #Iterate over the all the running process for proc in psutil.process_iter(): @@ -1752,11 +1806,13 @@ def ProcessIsStarted(inProcessNameWOExeStr): # Check if process is started def ProcessStart(inPathStr, inArgList, inStopProcessNameWOExeStr=None): """ - Start process locally. Extra feature: Use inStopProcessNameWOExeStr to stop the execution if current process is running. + Запуск процесса на сессии Оркестратора, если на ОС не запущен процесс inStopProcessNameWOExeStr. + + !ВНИМАНИЕ! ПРИ ПРОВЕРКЕ РАНЕЕ ЗАПУЩЕННЫХ ПРОЦЕССОВ ПРОВЕРЯЕТ ВСЕ ПРОЦЕССЫ ОПЕРАЦИОННОЙ СИСТЕМЫ. И ДРУГИХ ПОЛЬЗОВАТЕЛЬСКИХ СЕССИЙ, ЕСЛИ ОНИ ЗАПУЩЕНЫ НА ЭТОЙ МАШИНЕ. .. code-block:: python - # USAGE + # ПРИМЕР from pyOpenRPA import Orchestrator Orchestrator.ProcessStart( @@ -1765,10 +1821,9 @@ def ProcessStart(inPathStr, inArgList, inStopProcessNameWOExeStr=None): inStopProcessNameWOExeStr = "notepad") # notepad.exe will be started if no notepad.exe is active on the machine - :param inPathStr: Command to send in CMD - :param inArgList: List of the arguments for the CMD command. Example: ["test.txt"] - :param inStopProcessNameWOExeStr: Trigger: stop execution if process is running. Process name WithOut (WO) '.exe' postfix. Example: "notepad" (not "notepad.exe") - :return: None - nothing is returned. If process will not start -exception will be raised + :param inPathStr: Путь к файлу запускаемого процесса + :param inArgList: Список аргументов, передаваемых в запускаемый процесс. Пример: ["test.txt"] + :param inStopProcessNameWOExeStr: Доп. контроль: Не запускать процесс, если обнаружен запущенный процесс под наименованием inStopProcessNameWOExeStr без расширения .exe (WO = WithOut = Без) """ lStartProcessBool = True if inStopProcessNameWOExeStr is not None: #Check if process running @@ -1789,11 +1844,11 @@ def ProcessStart(inPathStr, inArgList, inStopProcessNameWOExeStr=None): def ProcessStop(inProcessNameWOExeStr, inCloseForceBool, inUserNameStr = "%username%"): """ - Stop process on the orchestrator machine. You can set user session on the machine and set flag about to force close process. + Остановить процесс на ОС, где работает Оркестратор, под учетной записью inUserNameStr. .. code-block:: python - # USAGE + # ПРИМЕР from pyOpenRPA import Orchestrator Orchestrator.ProcessStop( @@ -1802,10 +1857,9 @@ def ProcessStop(inProcessNameWOExeStr, inCloseForceBool, inUserNameStr = "%usern inUserNameStr = "USER_99") # Will close process "notepad.exe" on the user session "USER_99" (!ATTENTION! if process not exists no exceptions will be raised) - :param inProcessNameWOExeStr: Process name WithOut (WO) '.exe' postfix. Example: "notepad" (not "notepad.exe") - :param inCloseForceBool: True - do force close. False - send signal to safe close (!ATTENTION! - Safe close works only in orchestrator session. Win OS doens't allow to send safe close signal between GUI sessions) - :param inUserNameStr: User name which is has current process to close. Default value is close process on the Orchestrator session - :return: None + :param inProcessNameWOExeStr: Наименование процесса без расширения .exe (WO = WithOut = Без). Пример: Для проверки процесса блокнота нужно указывать "notepad", не "notepad.exe" + :param inCloseForceBool: True - принудительно завершить процесс. False - отправить сигнал на безопасное отключение (!ВНИМАНИЕ! - ОС не позволяет отправлять сигнал на безопасное отключение на другую сесиию - только на той, где работает Оркестратор) + :param inUserNameStr: Наименование пользователя, под именем которого искать процесс для остановки. По умолчанию "%username%" - искать процесс на текущей сессии """ # Support input arg if with .exe lProcessNameWExeStr = inProcessNameWOExeStr @@ -1826,30 +1880,32 @@ def ProcessStop(inProcessNameWOExeStr, inCloseForceBool, inUserNameStr = "%usern def ProcessListGet(inProcessNameWOExeList=None): """ - Return process list on the orchestrator machine sorted by Memory Usage. You can determine the list of the processes you are interested - def will return the list about it. + Вернуть список процессов, запущенных на ОС, где работает Оркестратор. В списке отсортировать процессы по количеству используемой оперативной памяти. Также можно указать перечень процессов, которые интересуют - функция будет показывать активные из них. + + !ВНИМАНИЕ! ДЛЯ ПОЛУЧЕНИЯ СПИСКА ВСЕХ ПРОЦЕССОВ ОС НЕОБХОДИМО ЗАПУСКАТЬ ОРКЕСТРАТОР С ПРАВАМИ АДМИНИСТРАТОРА. .. code-block:: python - # USAGE + # ПРИМЕР from pyOpenRPA import Orchestrator lProcessList = Orchestrator.ProcessListGet() # Return the list of the process on the machine. # !ATTENTION! RUn orchestrator as administrator to get all process list on the machine. - :param inProcessNameWOExeList: - :return: { - "ProcessWOExeList": ["notepad","..."], - "ProcessWOExeUpperList": ["NOTEPAD","..."], - "ProcessDetailList": [ - { - 'pid': 412, - 'username': "DESKTOP\\USER", - 'name': 'notepad.exe', - 'vms': 13.77767775, - 'NameWOExeUpperStr': 'NOTEPAD', - 'NameWOExeStr': "'notepad'"}, - {...}] + :param inProcessNameWOExeList: Список процессов, среди которых искать активные. Если параметр не указывать - вернет перечень всех доступных процессов + :return: Сведения о запущенных процессах в следующем формате { + "ProcessWOExeList": ["notepad","..."], + "ProcessWOExeUpperList": ["NOTEPAD","..."], + "ProcessDetailList": [ + { + 'pid': 412, # Идентификатор процесса + 'username': "DESKTOP\\USER", + 'name': 'notepad.exe', + 'vms': 13.77767775, # В Мб + 'NameWOExeUpperStr': 'NOTEPAD', + 'NameWOExeStr': "'notepad'"}, + {...}] """ if inProcessNameWOExeList is None: inProcessNameWOExeList = [] @@ -1884,19 +1940,18 @@ def ProcessListGet(inProcessNameWOExeList=None): def ProcessDefIntervalCall(inDef, inIntervalSecFloat, inIntervalAsyncBool=False, inDefArgList=None, inDefArgDict=None, inDefArgGSettingsNameStr=None, inDefArgLoggerNameStr=None, inExecuteInNewThreadBool=True, inLogger=None, inGSettings = None): """ - Use this procedure if you need to run periodically some def. Set def, args, interval and enjoy :) - - :param inGSettings: global settings - :param inDef: def link, which will be called with interval inIntervalSecFloat - :param inIntervalSecFloat: Interval in seconds between call - :param inIntervalAsyncBool: False - wait interval before next call after the previous iteration result; True - wait interval after previous iteration call - :param inDefArgList: List of the args in def. Default None (empty list) - :param inDefArgDict: Dict of the args in def. Default None (empty dict) - :param inDefArgGSettingsNameStr: Name of the GSettings arg name for def (optional) - :param inDefArgLoggerNameStr: Name of the Logger arg name for def (optional). If Use - please check fill of the inLogger arg. - :param inExecuteInNewThreadBool: True - create new thread for the periodic execution; False - execute in current thread. Default: True - :param inLogger: logging def if some case is appear - :return: + Периодический вызов функции Python. + + :param inDef: Функция Python, которую потребуется периодически вызывать + :param inIntervalSecFloat: Интервал между вызовами функции в сек. + :param inIntervalAsyncBool: False - ожидать интервал inIntervalSecFloat только после окончания выполнения предыдущей итерации; True - Ожидать интервал сразу после запуска итерации + :param inDefArgList: Список (list) неименованных аргументов для передачи в функцию. По умолчанию None + :param inDefArgDict: Словарь (dict) именованных аргументов для передачи в функцию. По умолчанию None + :param inDefArgGSettingsNameStr: Наименование аргумента глобального словаря настроек Оркестратора GSettings (опционально) + :param inDefArgLoggerNameStr: Наименование аргумента логгера Оркестратора (опционально) + :param inExecuteInNewThreadBool: True - периодический вызов выполнять в отдельном потоке (не останавливать выполнение текущего потока); False - Выполнение периодического вызова в текущем потоке, в котором была вызвана функция ProcessDefIntervalCall. По умолчанию: True + :param inLogger: Логгер для фиксации сообщений выполнения функции (опционально) + :param inGSettings: Глобальный словарь настроек Оркестратора (синглтон) """ inGSettings = GSettingsGet(inGSettings=inGSettings) # Set the global settings if inLogger is None: inLogger = OrchestratorLoggerGet() @@ -1965,15 +2020,15 @@ def ProcessDefIntervalCall(inDef, inIntervalSecFloat, inIntervalAsyncBool=False, # Python def - start module function def PythonStart(inModulePathStr, inDefNameStr, inArgList=None, inArgDict=None, inLogger = None): """ - Import module and run def in the Orchestrator process. + Импорт модуля и выполнение функции в процессе Оркестратора. .. note:: - Import module will be each time when PythonStart def will be called. + Импорт модуля inModulePathStr будет происходить каждый раз в вызовом функции PythonStart. .. code-block:: python - # USAGE + # ПРИМЕР from pyOpenRPA import Orchestrator Orchestrator.PythonStart( @@ -1981,12 +2036,11 @@ def PythonStart(inModulePathStr, inDefNameStr, inArgList=None, inArgDict=None, i inDefNameStr="TestDef") # Import module in Orchestrator process and call def "TestDef" from module "ModuleToCall.py" - :param inModulePathStr: Absolute or relative (working directory of the orchestrator process) path to the importing module .py - :param inDefNameStr: Def name in module - :param inArgList: List of the arguments for callable def - :param inArgDict: Dict of the named arguments for callable def - :param inLogger: Logger instance to log some information when PythonStart def is running - :return: None + :param inModulePathStr: Абсолютный или относительный путь (относительно рабочей директории процесса Оркестратора), по которому расположен импортируемый .py файл + :param inDefNameStr: Наименование функции в модуле .py + :param inArgList: Список (list) неименованных аргументов для передачи в функцию. По умолчанию None + :param inArgDict: Словарь (dict) именованных аргументов для передачи в функцию. По умолчанию None + :param inLogger: Логгер для фиксации сообщений выполнения функции (опционально) """ if inLogger is None: inLogger = OrchestratorLoggerGet() if inArgList is None: inArgList=[] @@ -2001,17 +2055,16 @@ def PythonStart(inModulePathStr, inDefNameStr, inArgList=None, inArgDict=None, i # # # # # # # # # # # # # # # # # # # # # # # # Scheduler # # # # # # # # # # # # # # # # # # # # # # # - def SchedulerActivityTimeAddWeekly(inTimeHHMMStr="23:55:", inWeekdayList=None, inActivityList=None, inGSettings = None): """ - Add activity item list in scheduler. You can set weekday list and set time when launch. Activity list will be executed at planned time/day. + Добавить активность по расписанию. Допускается указание времени и дней недели, в которые производить запуск. .. code-block:: python - # USAGE + # ПРИМЕР from pyOpenRPA import Orchestrator - # EXAMPLE 1 + # ВАРИАНТ 1 def TestDef(inArg1Str): pass lActivityItem = Orchestrator.ProcessorActivityItemCreate( @@ -2027,11 +2080,10 @@ def SchedulerActivityTimeAddWeekly(inTimeHHMMStr="23:55:", inWeekdayList=None, i inActivityList = [lActivityItem]) # Activity will be executed at 04:34 Wednesday (2), thursday (3), friday (4) - :param inGSettings: Global settings dict (singleton) - :param inTimeHHMMStr: Activation time from "00:00" to "23:59". Example: "05:29" - :param inWeekdayList: Week day list to initiate activity list. Use int from 0 (monday) to 6 (sunday) as list items. Example: [0,1,2,3,4]. Default value is everyday ([0,1,2,3,4,5,6]) - :param inActivityList: Activity list structure - :return: None + :param inGSettings: Глобальный словарь настроек Оркестратора (синглтон) + :param inTimeHHMMStr: Время запуска активности. Допускаются значения от "00:00" до "23:59". Example: "05:29" + :param inWeekdayList: Список (list) дней недели, в которые выполнять запуск список активностей (ActivityItem list). 0 (понедельник) - 6 (воскресенье). Пример: [0,1,2,3,4]. По умолчанию устанавливается каждый день [0,1,2,3,4,5,6] + :param inActivityList: Список активностей (ActivityItem list) на исполнение """ inGSettings = GSettingsGet(inGSettings=inGSettings) # Set the global settings if inWeekdayList is None: inWeekdayList=[0,1,2,3,4,5,6] @@ -2052,11 +2104,11 @@ def SchedulerActivityTimeAddWeekly(inTimeHHMMStr="23:55:", inWeekdayList=None, i def RDPTemplateCreate(inLoginStr, inPasswordStr, inHostStr="127.0.0.1", inPortInt = 3389, inWidthPXInt = 1680, inHeightPXInt = 1050, inUseBothMonitorBool = False, inDepthBitInt = 32, inSharedDriveList=None, inRedirectClipboardBool=True): """ - Create RDP connect dict item/ Use it connect/reconnect (Orchestrator.RDPSessionConnect) + Создать шаблон подключения RDP (dict). Данный шаблон далее можно использовать в Orchestrator.RDPSessionConnect .. code-block:: python - # USAGE + # ПРИМЕР from pyOpenRPA import Orchestrator lRDPItemDict = Orchestrator.RDPTemplateCreate( @@ -2068,49 +2120,38 @@ def RDPTemplateCreate(inLoginStr, inPasswordStr, inHostStr="127.0.0.1", inPortIn inHeightPXInt = 1050, inUseBothMonitorBool = False, inDepthBitInt = 32, - inSharedDriveList=None) - # lRDPTemplateDict= { # Init the configuration item - # "Host": "127.0.0.1", "Port": "3389", "Login": "USER_99", "Password": "USER_PASS_HERE", - # "Screen": { "Width": 1680, "Height": 1050, "FlagUseAllMonitors": False, "DepthBit": "32" }, - # "SharedDriveList": ["c"], - # "RedirectClipboardBool": True, # True - share clipboard to RDP; False - else - # ###### Will updated in program ############ - # "SessionHex": "77777sdfsdf77777dsfdfsf77777777", # Hex is created when robot runs, example "" - # "SessionIsWindowExistBool": False, "SessionIsWindowResponsibleBool": False, "SessionIsIgnoredBool": False - # } - - :param inLoginStr: User/Robot Login, example "USER_99" - :param inPasswordStr: Password, example "USER_PASS_HERE" - :param inHostStr: Host address, example "77.77.22.22" - :param inPortInt: RDP Port, example "3389" (default) - :param inWidthPXInt: Width of the remote desktop in pixels, example 1680 - :param inHeightPXInt: Height of the remote desktop in pixels, example 1050 - :param inUseBothMonitorBool: True - connect to the RDP with both monitors. False - else case - :param inDepthBitInt: Remote desktop bitness. Available: 32 or 24 or 16 or 15, example 32 - :param inSharedDriveList: Host local disc to connect to the RDP session. Example: ["c", "d"] - :param inRedirectClipboardBool: # True - share clipboard to RDP; False - else + inSharedDriveList=None, + inRedirectClipboardBool=False) + + :param inLoginStr: Логин учетной записи, на которую будет происходить вход по RDP + :param inPasswordStr: Пароль учетной записи, на которую будет происходить вход по RDP. !ВНИМАНИЕ! Пароль нигде не сохраняется - конфиденциальность обеспечена + :param inHostStr: Имя хоста, к которому планируется подключение по RDP. Пример "77.77.22.22" + :param inPortInt: RDP порт, по которому будет происходить подключение. По умолчанию 3389 (стандартный порт RDP) + :param inWidthPXInt: Разрешение ширины RDP графической сессии в пикселях. По умолчанию 1680 + :param inHeightPXInt: Разрешение высоты RDP графической сессии в пикселях. По умолчанию 1050 + :param inUseBothMonitorBool: True - Использовать все подключенные мониторы на RDP сессии; False - Использовать только один монитор на подключенной RDP сессии + :param inDepthBitInt: Глубина цвета на удаленной RDP графической сессии. Допустимые варианты: 32 || 24 || 16 || 15. По умолчанию 32 + :param inSharedDriveList: Перечень общих дисков, доступ к которым предоставить на сторону удаленной RDP сессии. Пример: ["c", "d"] + :param inRedirectClipboardBool: True - Синхронизировать буфер обмена между сессией Оркестратора и удаленной RDP сессией; False - Не синхронизировать буфер обмена. По умолчанию True (в целях обратной совместимости). !ВНИМАНИЕ! Для учетных записей роботов мы рекомендуем не синхронизировать буфер обмена, так как это может привести к ошибкам роботов, которые работают с клавиатурой и буфером обмена :return: { - "Host": inHostStr, # Host address, example "77.77.22.22" - "Port": str(inPortInt), # RDP Port, example "3389" - "Login": inLoginStr, # Login, example "test" - "Password": inPasswordStr, # Password, example "test" + "Host": inHostStr, # Адрес хоста, пример "77.77.22.22" + "Port": str(inPortInt), # RDP порт, пример "3389" + "Login": inLoginStr, # Логин УЗ, пример "test" + "Password": inPasswordStr, # Пароль УЗ, пример "test" "Screen": { - "Width": inWidthPXInt, # Width of the remote desktop in pixels, example 1680 - "Height": inHeightPXInt, # Height of the remote desktop in pixels, example 1050 - # "640x480" or "1680x1050" or "FullScreen". If Resolution not exists set full screen, example - "FlagUseAllMonitors": inUseBothMonitorBool, # True or False, example False - "DepthBit": str(inDepthBitInt) # "32" or "24" or "16" or "15", example "32" + "Width": inWidthPXInt, # Разрешение ширины RDP графической сессии в пикселях. По умолчанию 1680 + "Height": inHeightPXInt, Разрешение высоты RDP графической сессии в пикселях. По умолчанию 1050 + "FlagUseAllMonitors": inUseBothMonitorBool, + "DepthBit": str(inDepthBitInt) }, - "SharedDriveList": inSharedDriveList, # List of the Root sesion hard drives, example ["c"] - "RedirectClipboardBool": True, # True - share clipboard to RDP; False - else - ###### Will updated in program ############ - "SessionHex": "77777sdfsdf77777dsfdfsf77777777", # Hex is created when robot runs, example "" + "SharedDriveList": inSharedDriveList, + "RedirectClipboardBool": True, + ###### PROGRAM VARIABLE ############ + "SessionHex": "77777sdfsdf77777dsfdfsf77777777", "SessionIsWindowExistBool": False, - # Flag if the RDP window is exist, old name "FlagSessionIsActive". Check every n seconds , example False "SessionIsWindowResponsibleBool": False, - # Flag if RDP window is responsible (recieve commands). Check every nn seconds. If window is Responsible - window is Exist too , example False - "SessionIsIgnoredBool": False # Flag to ignore RDP window False - dont ignore, True - ignore, example False + "SessionIsIgnoredBool": False } """ @@ -2144,27 +2185,22 @@ def RDPTemplateCreate(inLoginStr, inPasswordStr, inHostStr="127.0.0.1", inPortIn # TODO Search dublicates in GSettings RDPlist ! # Return list if dublicates def RDPSessionDublicatesResolve(inGSettings): - """ - DEVELOPING Search duplicates in GSettings RDPlist - !def is developing! - - :param inGSettings: Global settings dict (singleton) - :return: - """ pass #for lItemKeyStr in inGSettings["RobotRDPActive"]["RDPList"]: # lItemDict = inGSettings["RobotRDPActive"]["RDPList"][lItemKeyStr] def RDPSessionConnect(inRDPSessionKeyStr, inRDPTemplateDict=None, inHostStr=None, inPortStr=None, inLoginStr=None, inPasswordStr=None, inGSettings = None, inRedirectClipboardBool=True): """ - Create new RDPSession in RobotRDPActive. Attention - activity will be ignored if RDP key is already exists - 2 way of the use - Var 1 (Main stream): inGSettings, inRDPSessionKeyStr, inRDPTemplateDict - Var 2 (Backward compatibility): inGSettings, inRDPSessionKeyStr, inHostStr, inPortStr, inLoginStr, inPasswordStr + Выполнить подключение к RDP и следить за стабильностью соединения со стороны Оркестратора. + !ВНИМАНИЕ! - Подключение будет проигнорировано, если соединение по таком RDP ключу уже было инициализировано ранее. + + 2 способа использования функции: + ВАРИАНТ 1 (ОСНОВНОЙ): inGSettings, inRDPSessionKeyStr, inRDPTemplateDict. Для получения inRDPTemplateDict см. функцию Orchestrator.RDPTemplateCreate + ВАРИАНТ 2 (ОБРАТНАЯ СОВМЕСТИМОСТЬ ДО ВЕРСИИ 1.1.20): inGSettings, inRDPSessionKeyStr, inHostStr, inPortStr, inLoginStr, inPasswordStr .. code-block:: python - # USAGE + # ПРИМЕР (ВАРИАНТ 1) from pyOpenRPA import Orchestrator lRDPItemDict = Orchestrator.RDPTemplateCreate( @@ -2176,15 +2212,15 @@ def RDPSessionConnect(inRDPSessionKeyStr, inRDPTemplateDict=None, inHostStr=None inRDPSessionKeyStr = "RDPKey", inRDPTemplateDict = lRDPItemDict) # Orchestrator will create RDP session by the lRDPItemDict configuration - - :param inGSettings: Global settings dict (singleton) - :param inRDPSessionKeyStr: RDP Session string key - need for the further identification - :param inRDPTemplateDict: RDP configuration dict with settings (see def Orchestrator.RDPTemplateCreate) - :param inHostStr: Backward compatibility from Orchestrator v 1.1.20. Use inRDPTemplateDict - :param inPortStr: Backward compatibility from Orchestrator v 1.1.20. Use inRDPTemplateDict - :param inLoginStr: Backward compatibility from Orchestrator v 1.1.20. Use inRDPTemplateDict - :param inPasswordStr: Backward compatibility from Orchestrator v 1.1.20. Use inRDPTemplateDict - :return: True every time :) + + :param inRDPSessionKeyStr: Ключ RDP сессии - необходим для дальнейшей идентификации + :param inRDPTemplateDict: Конфигурационный словарь (dict) RDP подключения (см. функцию Orchestrator.RDPTemplateCreate) + :param inLoginStr: Логин учетной записи, на которую будет происходить вход по RDP. Обратная совместимость до версии v 1.1.20. Мы рекомендуем использовать inRDPTemplateDict (см. функцию Orchestrator.RDPTemplateCreate) + :param inPasswordStr: Пароль учетной записи, на которую будет происходить вход по RDP. !ВНИМАНИЕ! Пароль нигде не сохраняется - конфиденциальность обеспечена. Обратная совместимость до версии v 1.1.20. Мы рекомендуем использовать inRDPTemplateDict (см. функцию Orchestrator.RDPTemplateCreate) + :param inHostStr: Имя хоста, к которому планируется подключение по RDP. Пример "77.77.22.22". Обратная совместимость до версии v 1.1.20. Мы рекомендуем использовать inRDPTemplateDict (см. функцию Orchestrator.RDPTemplateCreate) + :param inPortInt: RDP порт, по которому будет происходить подключение. По умолчанию 3389 (стандартный порт RDP). Обратная совместимость до версии v 1.1.20. Мы рекомендуем использовать inRDPTemplateDict (см. функцию Orchestrator.RDPTemplateCreate) + :param inGSettings: Глобальный словарь настроек Оркестратора (синглтон) + :param inRedirectClipboardBool: True - Синхронизировать буфер обмена между сессией Оркестратора и удаленной RDP сессией; False - Не синхронизировать буфер обмена. По умолчанию True (в целях обратной совместимости). !ВНИМАНИЕ! Для учетных записей роботов мы рекомендуем не синхронизировать буфер обмена, так как это может привести к ошибкам роботов, которые работают с клавиатурой и буфером обмена """ inGSettings = GSettingsGet(inGSettings=inGSettings) # Set the global settings # Check thread @@ -2217,11 +2253,11 @@ def RDPSessionConnect(inRDPSessionKeyStr, inRDPTemplateDict=None, inHostStr=None def RDPSessionDisconnect(inRDPSessionKeyStr, inBreakTriggerProcessWOExeList = None, inGSettings = None): """ - Disconnect the RDP session and stop monitoring it. + Выполнить отключение RDP сессии и прекратить мониторить его активность. .. code-block:: python - # USAGE + # ПРИМЕР from pyOpenRPA import Orchestrator Orchestrator.RDPSessionDisconnect( @@ -2229,14 +2265,9 @@ def RDPSessionDisconnect(inRDPSessionKeyStr, inBreakTriggerProcessWOExeList = No inRDPSessionKeyStr = "RDPKey") # Orchestrator will disconnect RDP session and will stop to monitoring current RDP - :param inGSettings: Global settings dict (singleton) - :param inRDPSessionKeyStr: RDP Session string key - need for the further identification - :param inBreakTriggerProcessWOExeList: List of the processes, which will stop the execution. Example ["notepad"] - - .. note:: - - Orchestrator look processes on the current machine - :return: True every time + :param inRDPSessionKeyStr: Ключ RDP сессии - необходим для дальнейшей идентификации + :param inBreakTriggerProcessWOExeList: Список процессов, наличие которых в диспетчере задач приведет к прерыванию задачи по остановке RDP соединения. Пример ["notepad"] + :param inGSettings: Глобальный словарь настроек Оркестратора (синглтон) """ inGSettings = GSettingsGet(inGSettings=inGSettings) # Set the global settings if inBreakTriggerProcessWOExeList is None: inBreakTriggerProcessWOExeList = [] @@ -2265,11 +2296,11 @@ def RDPSessionDisconnect(inRDPSessionKeyStr, inBreakTriggerProcessWOExeList = No def RDPSessionReconnect(inRDPSessionKeyStr, inRDPTemplateDict=None, inGSettings = None): """ - Reconnect the RDP session + Выполнить переподключение RDP сессии и продолжить мониторить его активность. .. code-block:: python - # USAGE + # ПРИМЕР from pyOpenRPA import Orchestrator lRDPItemDict = Orchestrator.RDPTemplateCreate( @@ -2282,10 +2313,9 @@ def RDPSessionReconnect(inRDPSessionKeyStr, inRDPTemplateDict=None, inGSettings inRDPTemplateDict = inRDPTemplateDict) # Orchestrator will reconnect RDP session and will continue to monitoring current RDP - :param inGSettings: Global settings dict (singleton) - :param inRDPSessionKeyStr: RDP Session string key - need for the further identification - :param inRDPTemplateDict: RDP configuration dict with settings (see def Orchestrator.RDPTemplateCreate) - :return: + :param inRDPSessionKeyStr: Ключ RDP сессии - необходим для дальнейшей идентификации + :param inRDPTemplateDict: Конфигурационный словарь (dict) RDP подключения (см. функцию Orchestrator.RDPTemplateCreate) + :param inGSettings: Глобальный словарь настроек Оркестратора (синглтон) """ inGSettings = GSettingsGet(inGSettings=inGSettings) # Set the global settings # Check thread @@ -2312,11 +2342,11 @@ def RDPSessionReconnect(inRDPSessionKeyStr, inRDPTemplateDict=None, inGSettings def RDPSessionMonitorStop(inRDPSessionKeyStr, inGSettings = None): """ - Stop monitoring the RDP session by the Orchestrator process. Current def don't kill RDP session - only stop to track it (it can give ) - + Прекратить мониторить активность RDP соединения со стороны Оркестратора. Данная функция не уничтожает активное RDP соединение. + .. code-block:: python - # USAGE + # ПРИМЕР from pyOpenRPA import Orchestrator Orchestrator.RDPSessionMonitorStop( @@ -2324,9 +2354,8 @@ def RDPSessionMonitorStop(inRDPSessionKeyStr, inGSettings = None): inRDPSessionKeyStr = "RDPKey") # Orchestrator will stop the RDP monitoring - :param inGSettings: Global settings dict (singleton) - :param inRDPSessionKeyStr: RDP Session string key - need for the further identification - :return: True every time :> + :param inRDPSessionKeyStr: Ключ RDP сессии - необходим для дальнейшей идентификации + :param inGSettings: Глобальный словарь настроек Оркестратора (синглтон) """ inGSettings = GSettingsGet(inGSettings=inGSettings) # Set the global settings lResult = True @@ -2335,11 +2364,11 @@ def RDPSessionMonitorStop(inRDPSessionKeyStr, inGSettings = None): def RDPSessionLogoff(inRDPSessionKeyStr, inBreakTriggerProcessWOExeList = None, inGSettings = None): """ - Logoff the RDP session from the Orchestrator process (close all apps in session when logoff) + Выполнить отключение (logoff) на RDP сессии и прекратить мониторить активность со стороны Оркестратора. .. code-block:: python - # USAGE + # ПРИМЕР from pyOpenRPA import Orchestrator Orchestrator.RDPSessionLogoff( @@ -2348,10 +2377,11 @@ def RDPSessionLogoff(inRDPSessionKeyStr, inBreakTriggerProcessWOExeList = None, inBreakTriggerProcessWOExeList = ['Notepad']) # Orchestrator will logoff the RDP session - :param inGSettings: Global settings dict (singleton) - :param inRDPSessionKeyStr: RDP Session string key - need for the further identification - :param inBreakTriggerProcessWOExeList: List of the processes, which will stop the execution. Example ["notepad"] - :return: True - logoff is successful + + :param inRDPSessionKeyStr: Ключ RDP сессии - необходим для дальнейшей идентификации + :param inBreakTriggerProcessWOExeList: Список процессов, наличие которых в диспетчере задач приведет к прерыванию задачи по остановке RDP соединения. Пример ["notepad"] + :param inGSettings: Глобальный словарь настроек Оркестратора (синглтон) + :return: True - Отключение прошло успешно; False - были зафиксированы ошибки при отключении. """ inGSettings = GSettingsGet(inGSettings=inGSettings) # Set the global settings if inBreakTriggerProcessWOExeList is None: inBreakTriggerProcessWOExeList = [] @@ -2382,13 +2412,6 @@ def RDPSessionLogoff(inRDPSessionKeyStr, inBreakTriggerProcessWOExeList = None, return lResult def RDPSessionResponsibilityCheck(inRDPSessionKeyStr, inGSettings = None): - """ - DEVELOPING, MAYBE NOT USEFUL Check RDP Session responsibility TODO NEED DEV + TEST - - :param inGSettings: Global settings dict (singleton) - :param inRDPSessionKeyStr: RDP Session string key - need for the further identification - :return: True every time - """ inGSettings = GSettingsGet(inGSettings=inGSettings) # Set the global settings # Check thread if not Core.IsProcessorThread(inGSettings=inGSettings): @@ -2427,11 +2450,13 @@ def RDPSessionResponsibilityCheck(inRDPSessionKeyStr, inGSettings = None): def RDPSessionProcessStartIfNotRunning(inRDPSessionKeyStr, inProcessNameWEXEStr, inFilePathStr, inFlagGetAbsPathBool=True, inGSettings = None): """ - Start process in RDP if it is not running (check by the arg inProcessNameWEXEStr) + Выполнить запуск процесса на RDP сессии через графические UI инструменты (без Агента). + + !ВНИМАНИЕ! Данная функция может работать нестабильно из-за использования графических элементов UI при работе с RDP. Мы рекомендуем использовать конструкцию взаимодействия Оркестратора с Агентом. .. code-block:: python - # USAGE + # ПРИМЕР from pyOpenRPA import Orchestrator Orchestrator.RDPSessionProcessStartIfNotRunning( @@ -2442,12 +2467,11 @@ def RDPSessionProcessStartIfNotRunning(inRDPSessionKeyStr, inProcessNameWEXEStr, inFlagGetAbsPathBool = True) # Orchestrator will start the process in RDP session - :param inGSettings: Global settings dict (singleton) - :param inRDPSessionKeyStr: RDP Session string key - need for the further identification - :param inProcessNameWEXEStr: Process name with extension (.exe). This arg allow to check the process is running. Example: "Notepad.exe" - :param inFilePathStr: Path to run process if it is not running. - :param inFlagGetAbsPathBool: True - get abs path from the relative path in inFilePathStr. False - else case - :return: True every time :) + :param inRDPSessionKeyStr: Ключ RDP сессии - необходим для дальнейшей идентификации + :param inProcessNameWEXEStr: Наименование процесса с расширением .exe (WEXE - WITH EXE - С EXE). Параметр позволяет не допустить повторного запуска процесса, если он уже был запущен. Example: "Notepad.exe" + :param inFilePathStr: Путь к файлу запуска процесса на стороне RDP сессии + :param inFlagGetAbsPathBool: True - Преобразовать относительный путь inFilePathStr в абсолютный с учетом рабочей директории Оркестратора; False - Не выполнять преобразований + :param inGSettings: Глобальный словарь настроек Оркестратора (синглтон) """ inGSettings = GSettingsGet(inGSettings=inGSettings) # Set the global settings # Check thread @@ -2474,11 +2498,13 @@ def RDPSessionProcessStartIfNotRunning(inRDPSessionKeyStr, inProcessNameWEXEStr, def RDPSessionCMDRun(inRDPSessionKeyStr, inCMDStr, inModeStr="CROSSCHECK", inGSettings = None): """ - Send CMD command to the RDP session "RUN" window + Отправить CMD команду на удаленную сесиию через RDP окно (без Агента). + + !ВНИМАНИЕ! Данная функция может работать нестабильно из-за использования графических элементов UI при работе с RDP. Мы рекомендуем использовать конструкцию взаимодействия Оркестратора с Агентом. .. code-block:: python - # USAGE + # ПРИМЕР from pyOpenRPA import Orchestrator lResultDict = Orchestrator.RDPSessionCMDRun( @@ -2486,18 +2512,18 @@ def RDPSessionCMDRun(inRDPSessionKeyStr, inCMDStr, inModeStr="CROSSCHECK", inGSe inRDPSessionKeyStr = "RDPKey", inModeStr = 'LISTEN') # Orchestrator will send CMD to RDP and return the result (see return section) - - :param inGSettings: Global settings dict (singleton) - :param inRDPSessionKeyStr: RDP Session string key - need for the further identification - :param inCMDStr: Any CMD string - :param inModeStr: Variants: - "LISTEN" - Get result of the cmd command in result; - "CROSSCHECK" - Check if the command was successfully sent - "RUN" - Run without crosscheck and get clipboard - :return: # OLD > True - CMD was executed successfully + + :param inRDPSessionKeyStr: Ключ RDP сессии - необходим для дальнейшей идентификации + :param inCMDStr: Команда CMD, которую отправить на удаленную сессию + :param inModeStr: По умолчанию "CROSSCHECK". Варианты: + "LISTEN" - Получить результат выполнения операции. Внимание! необходим общий буфер обмена с сессией Оркестратора! + "CROSSCHECK" - Выполнить проверку, что операция была выполнена (без получения результата отработки CMD команды). Внимание! необходим общий буфер обмена с сессией Оркестратора! + "RUN" - Не получать результат и не выполнять проверку + :param inGSettings: Глобальный словарь настроек Оркестратора (синглтон) + :return: Результат выполнения операции в соответсвии с параметрами инициализации функции. Выходная структура: { - "OutStr": <> # Result string - "IsResponsibleBool": True|False # Flag is RDP is responsible - works only when inModeStr = CROSSCHECK + "OutStr": <> # Результат выполнения CMD (если inModeStr = "LISTEN") + "IsResponsibleBool": True|False # True - RDP приняло команду; False - обратная связь не была получена (если inModeStr = "CROSSCHECK") } """ inGSettings = GSettingsGet(inGSettings=inGSettings) # Set the global settings @@ -2528,11 +2554,13 @@ def RDPSessionCMDRun(inRDPSessionKeyStr, inCMDStr, inModeStr="CROSSCHECK", inGSe def RDPSessionProcessStop(inRDPSessionKeyStr, inProcessNameWEXEStr, inFlagForceCloseBool, inGSettings = None): """ - Send CMD command to the RDP session "RUN" window. + Отправка CMD команды в RDP окне на остановку процесса (без Агента). + + !ВНИМАНИЕ! Данная функция может работать нестабильно из-за использования графических элементов UI при работе с RDP. Мы рекомендуем использовать конструкцию взаимодействия Оркестратора с Агентом. .. code-block:: python - # USAGE + # ПРИМЕР from pyOpenRPA import Orchestrator lResultDict = Orchestrator.RDPSessionProcessStop( @@ -2542,11 +2570,11 @@ def RDPSessionProcessStop(inRDPSessionKeyStr, inProcessNameWEXEStr, inFlagForceC inFlagForceCloseBool = True) # Orchestrator will send CMD to RDP and return the result (see return section) - :param inGSettings: Global settings dict (singleton) - :param inRDPSessionKeyStr: RDP Session string key - need for the further identification - :param inProcessNameWEXEStr: Process name to kill. Example: 'notepad.exe' - :param inFlagForceCloseBool: True - force close the process. False - safe close the process - :return: True every time + + :param inRDPSessionKeyStr: Ключ RDP сессии - необходим для дальнейшей идентификации + :param inProcessNameWEXEStr: Наименование процесса, который требуется выключить с расширением .exe (WEXE - WITH EXE - С EXE). Пример: "Notepad.exe" + :param inFlagForceCloseBool: True - Принудительное отключение. False - Отправка сигнала на безопасное отключение (если процесс поддерживает) + :param inGSettings: Глобальный словарь настроек Оркестратора (синглтон) """ inGSettings = GSettingsGet(inGSettings=inGSettings) # Set the global settings # Check thread @@ -2574,11 +2602,15 @@ def RDPSessionProcessStop(inRDPSessionKeyStr, inProcessNameWEXEStr, inFlagForceC def RDPSessionFileStoredSend(inRDPSessionKeyStr, inHostFilePathStr, inRDPFilePathStr, inGSettings = None): """ - Send file from Orchestrator session to the RDP session using shared drive in RDP (see RDP Configuration Dict, Shared drive) + Отправка файла со стороны Оркестратора на сторону RDP сессии через UI инструменты RDP окна (без Агента). + + !ВНИМАНИЕ! Данная функция может работать нестабильно из-за использования графических элементов UI при работе с RDP. Мы рекомендуем использовать конструкцию взаимодействия Оркестратора с Агентом. + + !ВНИМАНИЕ! Для работы функции требуется открыть доступ по RDP к тем дискам, с которых будет производится копирование файла. .. code-block:: python - # USAGE + # ПРИМЕР from pyOpenRPA import Orchestrator lResultDict = Orchestrator.RDPSessionFileStoredSend( @@ -2588,11 +2620,10 @@ def RDPSessionFileStoredSend(inRDPSessionKeyStr, inHostFilePathStr, inRDPFilePat inRDPFilePathStr = "C:\\RPA\\TESTDIR\\Test.py") # Orchestrator will send CMD to RDP and return the result (see return section) - :param inGSettings: Global settings dict (singleton) - :param inRDPSessionKeyStr: RDP Session string key - need for the further identification - :param inHostFilePathStr: Relative or absolute path to the file location on the Orchestrator side. Example: "TESTDIR\\Test.py" - :param inRDPFilePathStr: !Absolute! path to the destination file location on the RDP side. Example: "C:\\RPA\\TESTDIR\\Test.py" - :return: True every time + :param inRDPSessionKeyStr: Ключ RDP сессии - необходим для дальнейшей идентификации + :param inHostFilePathStr: Откуда взять файл. Относительный или абсолютный путь к файлу на стороне Оркестратора. Пример: "TESTDIR\\Test.py" + :param inRDPFilePathStr: Куда скопировать файл. !Абсолютный! путь на стороне RDP сессии. Пример: "C:\\RPA\\TESTDIR\\Test.py" + :param inGSettings: Глобальный словарь настроек Оркестратора (синглтон) """ inGSettings = GSettingsGet(inGSettings=inGSettings) # Set the global settings # Check thread @@ -2619,11 +2650,15 @@ def RDPSessionFileStoredSend(inRDPSessionKeyStr, inHostFilePathStr, inRDPFilePat def RDPSessionFileStoredRecieve(inRDPSessionKeyStr, inRDPFilePathStr, inHostFilePathStr, inGSettings = None): """ - Recieve file from RDP session to the Orchestrator session using shared drive in RDP (see RDP Configuration Dict, Shared drive) + Получение файла со стороны RDP сессии на сторону Оркестратора через UI инструменты RDP окна (без Агента). + + !ВНИМАНИЕ! Данная функция может работать нестабильно из-за использования графических элементов UI при работе с RDP. Мы рекомендуем использовать конструкцию взаимодействия Оркестратора с Агентом. + + !ВНИМАНИЕ! Для работы функции требуется открыть доступ по RDP к тем дискам, с которых будет производится копирование файла. .. code-block:: python - # USAGE + # ПРИМЕР from pyOpenRPA import Orchestrator lResultDict = Orchestrator.RDPSessionFileStoredRecieve( @@ -2633,11 +2668,10 @@ def RDPSessionFileStoredRecieve(inRDPSessionKeyStr, inRDPFilePathStr, inHostFile inRDPFilePathStr = "C:\\RPA\\TESTDIR\\Test.py") # Orchestrator will send CMD to RDP and return the result (see return section) - :param inGSettings: Global settings dict (singleton) - :param inRDPSessionKeyStr: RDP Session string key - need for the further identification - :param inRDPFilePathStr: !Absolute! path to the destination file location on the RDP side. Example: "C:\\RPA\\TESTDIR\\Test.py" - :param inHostFilePathStr: Relative or absolute path to the file location on the Orchestrator side. Example: "TESTDIR\\Test.py" - :return: True every time + :param inRDPSessionKeyStr: Ключ RDP сессии - необходим для дальнейшей идентификации + :param inRDPFilePathStr: Откуда скопировать файл. !Абсолютный! путь на стороне RDP сессии. Пример: "C:\\RPA\\TESTDIR\\Test.py" + :param inHostFilePathStr: Куда скопировать файл. Относительный или абсолютный путь к файлу на стороне Оркестратора. Пример: "TESTDIR\\Test.py" + :param inGSettings: Глобальный словарь настроек Оркестратора (синглтон) """ inGSettings = GSettingsGet(inGSettings=inGSettings) # Set the global settings # Check thread @@ -2665,13 +2699,8 @@ def RDPSessionFileStoredRecieve(inRDPSessionKeyStr, inRDPFilePathStr, inHostFile # # # # # Start orchestrator # # # # # # # # # # # # # # # # # # # # # # # +#HIDDEN Interval gSettings auto cleaner def to clear some garbage. def GSettingsAutocleaner(inGSettings=None): - """ - HIDDEN Interval gSettings auto cleaner def to clear some garbage. - - :param inGSettings: Global settings dict (singleton) - :return: None - """ inGSettings = GSettingsGet(inGSettings=inGSettings) # Set the global settings while True: time.sleep(inGSettings["Autocleaner"]["IntervalSecFloat"]) # Wait for the next iteration @@ -2700,23 +2729,15 @@ def GSettingsAutocleaner(inGSettings=None): from .. import __version__ # Get version from the package def Start(inDumpRestoreBool = True, inRunAsAdministratorBool = True): - """ - Start the orchestrator threads execution - - :param inDumpRestoreBool: True - restore data from the dumo - :param inRunAsAdministratorBool: True - rerun as admin if not - :return: - """ Orchestrator(inDumpRestoreBool = True, inRunAsAdministratorBool = True) def Orchestrator(inGSettings=None, inDumpRestoreBool = True, inRunAsAdministratorBool = True): """ - Main def to start orchestrator + Инициализация ядра Оркестратора (всех потоков) - :param inGSettings: - :param inDumpRestoreBool: - :param inRunAsAdministratorBool: - :return: + :param inGSettings: Глобальный словарь настроек Оркестратора (синглтон) + :param inDumpRestoreBool: True - Восстановить информацию о RDP сессиях и StorageDict; False - не восстанавливать + :param inRunAsAdministratorBool: True - Проверить права администратратора и обеспечить их; False - Не обеспечивать права администратора """ lL = inGSettings["Logger"] # https://stackoverflow.com/questions/130763/request-uac-elevation-from-within-a-python-script @@ -2801,8 +2822,6 @@ def Orchestrator(inGSettings=None, inDumpRestoreBool = True, inRunAsAdministrato lRobotRDPActiveThread.start() # Start the thread execution. if lL: lL.info("Robot RDP active has been started") #Logging - - # Init autocleaner in another thread lAutocleanerThread = threading.Thread(target= GSettingsAutocleaner, kwargs={"inGSettings":gSettingsDict}) lAutocleanerThread.daemon = True # Run the thread in daemon mode. diff --git a/Resources/WPy32-3720/python-3.7.2/Lib/site-packages/pyOpenRPA/Robot/Clipboard.py b/Resources/WPy32-3720/python-3.7.2/Lib/site-packages/pyOpenRPA/Robot/Clipboard.py index 12b43186..279e699b 100644 --- a/Resources/WPy32-3720/python-3.7.2/Lib/site-packages/pyOpenRPA/Robot/Clipboard.py +++ b/Resources/WPy32-3720/python-3.7.2/Lib/site-packages/pyOpenRPA/Robot/Clipboard.py @@ -4,17 +4,42 @@ import win32clipboard #################################### # GUI Module - interaction with Windows clipboard -################ -###ClipboardGet -################ +def Get(): + """ + Получить текстовое содержимое буфера обмена. + + .. code-block:: python + + # Clipboard: Взаимодействие с буфером + from pyOpenRPA.Robot import Clipboard + lClipStr = Clipboard.Get() + + :return: Текстовое содержимое буфера обмена + :rtype: str + """ + return ClipboardGet() + +def Set(inTextStr:str): + """ + Установить текстовое содержимое в буфер обмена. + + .. code-block:: python + + # Clipboard: Взаимодействие с буфером + from pyOpenRPA.Robot import Clipboard + lClipStr = Clipboard.Set(inTextStr="HELLO WORLD") + + :param inTextStr: Текстовое содержимое для установки в буфера обмена + :type inTextStr: str + """ + ClipboardSet(inText=inTextStr) + def ClipboardGet(): win32clipboard.OpenClipboard() lResult = win32clipboard.GetClipboardData(win32clipboard.CF_UNICODETEXT) win32clipboard.CloseClipboard() return lResult -################ -###ClipboardSet -################ + def ClipboardSet(inText): win32clipboard.OpenClipboard() win32clipboard.EmptyClipboard() diff --git a/Resources/WPy32-3720/python-3.7.2/Lib/site-packages/pyOpenRPA/Robot/Keyboard.py b/Resources/WPy32-3720/python-3.7.2/Lib/site-packages/pyOpenRPA/Robot/Keyboard.py index b6a278fc..d6cbacc5 100644 --- a/Resources/WPy32-3720/python-3.7.2/Lib/site-packages/pyOpenRPA/Robot/Keyboard.py +++ b/Resources/WPy32-3720/python-3.7.2/Lib/site-packages/pyOpenRPA/Robot/Keyboard.py @@ -1 +1,344 @@ -from keyboard import * \ No newline at end of file +from keyboard import * +import time + +# Настройки модуля Keyboard +WAIT_AFTER_SEC_FLOAT = 0.4 # Время, которое ожидать после выполнения любой операции модуля Keyboard. Настройка является единой для всех участов кода, использующих модуль Keyboard. Если для некоторой функции требуется изменить данное время ожидания, то в отношении этой функции можно применить соответсвующий аргумент. + +# ШЕСТНАДЦАТИРИЧНЫЙ СКАН-КОД В РУССКОЙ РАСКЛАДКЕ (НЕЗАВИСИМО ОТ ВЫБРАННОГО ЯЗЫКА НА КЛАВИАТУРЕ) +# ОТОБРАЖЕНИЕ СКАН КОДОВ НА КЛАВИАТУРЕ https://snipp.ru/handbk/scan-codes + +KEY_RUS_Ф = 0x1E #A +KEY_RUS_И = 0x30 #B +KEY_RUS_С = 0x2E #C +KEY_RUS_В = 0x20 #D +KEY_RUS_У = 0x12 #E +KEY_RUS_А = 0x21 #F +KEY_RUS_П = 0x22 #G +KEY_RUS_Р = 0x23 #H +KEY_RUS_Ш = 0x17 #I +KEY_RUS_О = 0x24 #J +KEY_RUS_Л = 0x25 #K +KEY_RUS_Д = 0x26 #L +KEY_RUS_Ь = 0x32 #M +KEY_RUS_Т = 0x31 #N +KEY_RUS_Щ = 0x18 #O +KEY_RUS_З = 0x19 #P +KEY_RUS_Й = 0x10 #Q +KEY_RUS_К = 0x13 #R +KEY_RUS_Ы = 0x1F #S +KEY_RUS_Е = 0x14 #T +KEY_RUS_Г = 0x16 #U +KEY_RUS_М = 0x2F #V +KEY_RUS_Ц = 0x11 #W +KEY_RUS_Ч = 0x2D #X +KEY_RUS_Н = 0x15 #Y +KEY_RUS_Я = 0x2C #Z +KEY_RUS_Ё = 0x29 #~ +KEY_RUS_Ж = 0x27 #: +KEY_RUS_Б = 0x33 #< +KEY_RUS_Ю = 0x34 #> +KEY_RUS_Х = 0x1A #[ +KEY_RUS_Ъ = 0x1B #] +KEY_RUS_Э = 0x28 #' + +KEY_ENG_A = 0x1E #A +KEY_ENG_B = 0x30 #B +KEY_ENG_C = 0x2E #C +KEY_ENG_D = 0x20 #D +KEY_ENG_E = 0x12 #E +KEY_ENG_F = 0x21 #F +KEY_ENG_G = 0x22 #G +KEY_ENG_H = 0x23 #H +KEY_ENG_I = 0x17 #I +KEY_ENG_J = 0x24 #J +KEY_ENG_K = 0x25 #K +KEY_ENG_L = 0x26 #L +KEY_ENG_M = 0x32 #M +KEY_ENG_N = 0x31 #N +KEY_ENG_O = 0x18 #O +KEY_ENG_P = 0x19 #P +KEY_ENG_Q = 0x10 #Q +KEY_ENG_R = 0x13 #R +KEY_ENG_S = 0x1F #S +KEY_ENG_T = 0x14 #T +KEY_ENG_U = 0x16 #U +KEY_ENG_V = 0x2F #V +KEY_ENG_W = 0x11 #W +KEY_ENG_X = 0x2D #X +KEY_ENG_Y = 0x15 #Y +KEY_ENG_Z = 0x2C #Z + + +KEY_HOT_NUMPAD_0 = 0x52 +KEY_HOT_NUMPAD_1 = 0x4F +KEY_HOT_NUMPAD_2 = 0x50 +KEY_HOT_NUMPAD_3 = 0x51 +KEY_HOT_NUMPAD_4 = 0x4B +KEY_HOT_NUMPAD_5 = 0x4C +KEY_HOT_NUMPAD_6 = 0x4D +KEY_HOT_NUMPAD_7 = 0x47 +KEY_HOT_NUMPAD_8 = 0x48 +KEY_HOT_NUMPAD_9 = 0x49 +KEY_HOT_NUMPAD_ASTERISK = 0x37 #* +KEY_HOT_NUMPAD_PLUS = 0x4E +KEY_HOT_NUMPAD_MINUS = 0x4A +KEY_HOT_NUMPAD_DELETE = 0x53 +KEY_HOT_NUMPAD_SOLIDUS = 0x35 #/ +KEY_HOT_NUMPAD_ENTER = 0x11c + +KEY_HOT_F1 = 0x3B +KEY_HOT_F2 = 0x3C +KEY_HOT_F3 = 0x3D +KEY_HOT_F4 = 0x3E +KEY_HOT_F5 = 0x3F +KEY_HOT_F6 = 0x40 +KEY_HOT_F7 = 0x41 +KEY_HOT_F8 = 0x42 +KEY_HOT_F9 = 0x43 +KEY_HOT_F10 = 0x44 +KEY_HOT_F11 = 0x57 +KEY_HOT_F12 = 0x58 +KEY_HOT_F13 = 0x7C +KEY_HOT_F14 = 0x7D +KEY_HOT_F15 = 0x7E +KEY_HOT_F16 = 0x7F +KEY_HOT_F17 = 0x80 +KEY_HOT_F18 = 0x81 +KEY_HOT_F19 = 0x82 +KEY_HOT_F20 = 0x83 +KEY_HOT_F21 = 0x84 +KEY_HOT_F22 = 0x85 +KEY_HOT_F23 = 0x86 +KEY_HOT_F24 = 0x87 + +KEY_HOT_TILDE = 0x29 #~ +KEY_HOT_COLON = 0x27 #: +KEY_HOT_PLUS = 0x0D #+ +KEY_HOT_MINUS = 0x0C #- +KEY_HOT_LESS_THAN = 0x33 #< , +KEY_HOT_GREATER_THAN = 0x34 #> . +KEY_HOT_SOLIDUS = 0x35 #/ ? +KEY_HOT_SQUARE_BRACKET_LEFT = 0x1A #[ +KEY_HOT_SQUARE_BRACKET_RIGHT = 0x1B #] +KEY_HOT_APOSTROPHE = 0x28 #' " +KEY_HOT_VERTICAL_LINE = 0x2B #| \ + +KEY_HOT_ESC = 0x1 +KEY_HOT_BACKSPACE = 0x0E +KEY_HOT_TAB = 0x0F +KEY_HOT_ENTER = 0x1C +KEY_HOT_CONTEXT_MENU = 0x15D +KEY_HOT_SHIFT_LEFT = 0x2A +KEY_HOT_SHIFT_RIGHT = 0x36 +KEY_HOT_CTRL_LEFT = 0x1D +KEY_HOT_CTRL_RIGHT = 0x11D +KEY_HOT_ALT_LEFT = 0x38 +KEY_HOT_ALT_RIGHT = 0x138 +KEY_HOT_WIN_LEFT = 57435 #OLD AND DONT WORK 0x5B +KEY_HOT_WIN_RIGHT = 57436 #OLD AND DONT WORK 0x5C +KEY_HOT_CAPS_LOCK = 0x3A +KEY_HOT_NUM_LOCK = 0x45 +KEY_HOT_SCROLL_LOCK = 0x46 +KEY_HOT_END = 0x4F +KEY_HOT_HOME = 0x47 +KEY_HOT_SPACE = 0x39 +KEY_HOT_PAGE_UP = 0x49 +KEY_HOT_PAGE_DOWN = 0x51 +KEY_HOT_CLEAR = 0x4C +KEY_HOT_LEFT = 0x4B +KEY_HOT_UP = 0x48 +KEY_HOT_RIGHT = 0x4D +KEY_HOT_DOWN = 0x50 +KEY_HOT_PRINT_SCREEN = 0x137 +KEY_HOT_INSERT = 0x52 +KEY_HOT_DELETE = 0x53 + +KEY_HOT_0 = 0xB +KEY_HOT_1 = 0x2 +KEY_HOT_2 = 0x3 +KEY_HOT_3 = 0x4 +KEY_HOT_4 = 0x5 +KEY_HOT_5 = 0x6 +KEY_HOT_6 = 0x7 +KEY_HOT_7 = 0x8 +KEY_HOT_8 = 0x9 +KEY_HOT_9 = 0xA + +def Write(inTextStr:str, inDelayFloat:float=0, inRestoreStateAfterBool:bool=True, inExactBool:bool=None, inWaitAfterSecFloat:float=WAIT_AFTER_SEC_FLOAT): + """ + Печатает текст, который был передан в переменной inTextStr (поддерживает передачу в одной строке символов разного языка). Не зависит от текущей раскладки клавиатуры! Посылает искусственные клавишные события в ОС, моделируя печать данного текста. Знаки, не доступные на клавиатуре, напечатаны как явный unicode знаки, использующие определенную для ОС функциональность, такие как alt+codepoint. + Чтобы гарантировать текстовую целостность, все в настоящее время нажатые ключи выпущены прежде текст напечатан, и модификаторы восстановлены впоследствии. + + ВНИМАНИЕ! ПЕЧАТАЕТ ЛЮБУЮ СТРОКУ, ДАЖЕ В СОЧЕТАНИИ НЕСКОЛЬКИХ ЯЗЫКОВ ОДНОВРЕМЕННО. ДЛЯ РАБОТЫ С ГОРЯЧИМИ КЛАВИШАМИ ИСПОЛЬЗУЙ ФУНКЦИЮ Send, Up, Down, HotkeyCombination + + .. code-block:: python + + # Keyboard: Взаимодействие с клавиатурой + from pyOpenRPA.Robot import Keyboard + Keyboard.Write("Привет мой милый мир! Hello my dear world!") + + :param inTextStr: Текст, отправляемый на печать. Не зависит от текущей раскладки клавиатуры! + :type inTextStr: str + :param inDelayFloat: Число секунд, которое ожидать между нажатиями. По умолчанию 0 + :type inDelayFloat: float, опциональный + :param inRestoreStateAfterBool: Может использоваться, чтобы восстановить регистр нажатых ключей после того, как текст напечатан, т.е. нажимает ключи, которые были выпущены в начало. + :type inRestoreStateAfterBool: bool, опциональный + :param inExactBool: Печатает все знаки как явный unicode. Необязательный параметр + :type inExactBool: bool, опциональный + :param inWaitAfterSecFloat: Количество секунд, которые ожидать после выполнения операции. По умолчанию установлено в настройках модуля Keyboard (базовое значение 0.4) + :type inWaitAfterSecFloat: float, опциональный + """ + write(text=inTextStr, delay=inDelayFloat, restore_state_after=inRestoreStateAfterBool, exact=inExactBool) + time.sleep(inWaitAfterSecFloat) + +def HotkeyCombination(*inKeyList, inDelaySecFloat = 0.3,inWaitAfterSecFloat:float=WAIT_AFTER_SEC_FLOAT): + """Получает перечень клавиш для одновременного нажатия. Между нажатиями программа ожидания время inDelaySecFloat + ВНИМАНИЕ! НЕ ЗАВИСИТ ОТ ТЕКУЩЕЙ РАСКЛАДКИ КЛАВИАТУРЫ + + .. code-block:: python + + # Keyboard: Взаимодействие с клавиатурой + from pyOpenRPA.Robot import Keyboard + Keyboard.HotkeyCombination(Keyboard.KEY_HOT_CTRL_LEFT,Keyboard.KEY_ENG_A) # Ctrl + a + Keyboard.HotkeyCombination(Keyboard.KEY_HOT_CTRL_LEFT,Keyboard.KEY_ENG_C) # Ctrl + c + Keyboard.HotkeyCombination(Keyboard.KEY_HOT_CTRL_LEFT,Keyboard.KEY_ENG_A) + Keyboard.HotkeyCombination(Keyboard.KEY_HOT_ALT_LEFT,Keyboard.KEY_HOT_TAB, Keyboard.KEY_HOT_TAB) + + :param inKeyList: Список клавиш для одновременного нажатия. Перечень клавиш см. в разделе "Коды клавиш". Пример: KEY_HOT_CTRL_LEFT,KEY_ENG_A + :param inDelaySecFloat: Интервал между нажатиями. Необходим в связи с тем, что операционной системе требуется время на реакцию на нажатие клавиш, по умолчанию: 0.3 + :type inDelaySecFloat: float, опциональный + :param inWaitAfterSecFloat: Количество секунд, которые ожидать после выполнения операции. По умолчанию установлено в настройках модуля Keyboard (базовое значение 0.4) + :type inWaitAfterSecFloat: float, опциональный + """ + for l_key_item in inKeyList: + if l_key_item == inKeyList[-1]: + send(l_key_item) + else: + press(l_key_item) + time.sleep(inDelaySecFloat) + lRevKeyList = list(reversed(inKeyList)) + for l_key_item in lRevKeyList: + if l_key_item == lRevKeyList[0]: + pass + else: + release(l_key_item) + time.sleep(inDelaySecFloat) + time.sleep(inWaitAfterSecFloat) + +def HotkeyCtrlA_CtrlC(inWaitAfterSecFloat:float=0.4) -> None: + """Выполнить выделение текста, после чего скопировать его в буфер обмена + ВНИМАНИЕ! НЕ ЗАВИСИТ ОТ ТЕКУЩЕЙ РАСКЛАДКИ КЛАВИАТУРЫ + + .. code-block:: python + + # Keyboard: Взаимодействие с клавиатурой + from pyOpenRPA.Robot import Keyboard + Keyboard.HotkeyCtrlA_CtrlC() # Отправить команды: выделить все, скопировать в буфер обмена + + :param inWaitAfterSecFloat: Количество секунд, которые ожидать после выполнения операции. По умолчанию установлено в настройках модуля Keyboard (базовое значение 0.4) + :type inWaitAfterSecFloat: float, опциональный + """ + HotkeyCombination(KEY_HOT_CTRL_LEFT,KEY_ENG_A) # Ctrl + a + HotkeyCombination(KEY_HOT_CTRL_LEFT,KEY_ENG_C) # Ctrl + c + time.sleep(inWaitAfterSecFloat) + +def Send(inKeyInt:int, inDoPressBool:bool=True, inDoReleaseBool:bool=True,inWaitAfterSecFloat:float=WAIT_AFTER_SEC_FLOAT) -> None: + """ + Имитация нажатия/отпускания любой физической клавиши. Посылает событие в операционную систему, которые выполняет нажатие и отпускание данной клавиши + + ВНИМАНИЕ! ПРИ ПОПЫТКЕ ПЕЧАТИ ТЕКСТА БУДЕТ УЧИТЫВАТЬ ТЕКУЩУЮ РАСКЛАДКУ КЛАВИАТУРЫ. ДЛЯ ПЕЧАТИ ТЕКСТА ИСПОЛЬЗУЙ Write! + + .. code-block:: python + + # Keyboard: Взаимодействие с клавиатурой + from pyOpenRPA.Robot import Keyboard + Keyboard.Send(Keyboard.KEY_ENG_A) # Нажать клавишу A. Если будет активна русская раскладка, то будет выведена буква ф. + + :param inKeyInt: Перечень клавиш см. в разделе "Коды клавиш". Пример: KEY_HOT_CTRL_LEFT,KEY_ENG_A + :type inKeyInt: int + :param inDoPressBool: Выполнить событие нажатия клавиши, По умолчанию True + :type inDoPressBool: bool, опциональный + :param inDoReleaseBool: Выполнить событие отпускания клавиши, По умолчанию True + :type inDoReleaseBool: bool, опциональный + :param inWaitAfterSecFloat: Количество секунд, которые ожидать после выполнения операции. По умолчанию установлено в настройках модуля Keyboard (базовое значение 0.4) + :type inWaitAfterSecFloat: float, опциональный + """ + send(hotkey=inKeyInt, do_press=inDoPressBool, do_release=inDoReleaseBool) + time.sleep(inWaitAfterSecFloat) + +def Up(inKeyInt:int, inWaitAfterSecFloat:float=WAIT_AFTER_SEC_FLOAT) -> None: + """ + Отпустить (поднять) клавишу. Если клавиша уже была поднята, то ничего не произойдет. + + ВНИМАНИЕ! ПРИ ПОПЫТКЕ ПЕЧАТИ ТЕКСТА БУДЕТ УЧИТЫВАТЬ ТЕКУЩУЮ РАСКЛАДКУ КЛАВИАТУРЫ. ДЛЯ ПЕЧАТИ ТЕКСТА ИСПОЛЬЗУЙ Write! + + .. code-block:: python + + # Keyboard: Взаимодействие с клавиатурой + from pyOpenRPA.Robot import Keyboard + Keyboard.Up(Keyboard.KEY_ENG_A) # Отпустить клавишу A. + + :param inKeyInt: Перечень клавиш см. в разделе "Коды клавиш". Пример: KEY_HOT_CTRL_LEFT, KEY_ENG_A + :type inKeyInt: int + :param inWaitAfterSecFloat: Количество секунд, которые ожидать после выполнения операции. По умолчанию установлено в настройках модуля Keyboard (базовое значение 0.4) + :type inWaitAfterSecFloat: float, опциональный + """ + send(hotkey=inKeyInt, do_press=False, do_release=True) + time.sleep(inWaitAfterSecFloat) + +def Down(inKeyInt:int, inWaitAfterSecFloat:float=WAIT_AFTER_SEC_FLOAT) -> None: + """ + Нажать (опустить) клавишу. Если клавиша уже была опущена, то ничего не произойдет. + + ВНИМАНИЕ! ПРИ ПОПЫТКЕ ПЕЧАТИ ТЕКСТА БУДЕТ УЧИТЫВАТЬ ТЕКУЩУЮ РАСКЛАДКУ КЛАВИАТУРЫ. ДЛЯ ПЕЧАТИ ТЕКСТА ИСПОЛЬЗУЙ Write! + + .. code-block:: python + + # Keyboard: Взаимодействие с клавиатурой + from pyOpenRPA.Robot import Keyboard + Keyboard.Down(Keyboard.KEY_ENG_A) # Отпустить клавишу A. + + :param inKeyInt: Перечень клавиш см. в разделе "Коды клавиш". Пример: KEY_HOT_CTRL_LEFT, KEY_ENG_A + :type inKeyInt: int + :param inWaitAfterSecFloat: Количество секунд, которые ожидать после выполнения операции. По умолчанию установлено в настройках модуля Keyboard (базовое значение 0.4) + :type inWaitAfterSecFloat: float, опциональный + """ + send(hotkey=inKeyInt, do_press=True, do_release=False) + time.sleep(inWaitAfterSecFloat) + +def IsDown(inKeyInt:int) -> bool: + """ + Проверить, опущена ли клавиша. Вернет True если опущена; False если поднята. + + ВНИМАНИЕ! ПРИ ПОПЫТКЕ ПЕЧАТИ ТЕКСТА БУДЕТ УЧИТЫВАТЬ ТЕКУЩУЮ РАСКЛАДКУ КЛАВИАТУРЫ. ДЛЯ ПЕЧАТИ ТЕКСТА ИСПОЛЬЗУЙ Write! + + .. code-block:: python + + # Keyboard: Взаимодействие с клавиатурой + from pyOpenRPA.Robot import Keyboard + lKeyAIsPressedBool = Keyboard.IsDown(Keyboard.KEY_ENG_A) # Проверить, опущена ли клавиша A. + + :param inKeyInt: Перечень клавиш см. в разделе "Коды клавиш". Пример: KEY_HOT_CTRL_LEFT, KEY_ENG_A + :type inKeyInt: int + """ + return is_pressed(inKeyInt) + +def Wait(inKeyInt:int,inWaitAfterSecFloat:float=WAIT_AFTER_SEC_FLOAT): + """Блокирует осуществление программы, пока данная обозначенная клавиша не будет нажата. + ВНИМАНИЕ! НЕ ЗАВИСИТ ОТ ТЕКУЩЕЙ РАСКЛАДКИ КЛАВИАТУРЫ. ОЖИДАЕТ НАЖАТИЕ СООТВЕТСВУЮЩЕЙ ФИЗИЧЕСКОЙ КЛАВИШИ + + .. code-block:: python + + # Keyboard: Взаимодействие с клавиатурой + from pyOpenRPA.Robot import Keyboard + Keyboard.Wait(Keyboard.KEY_ENG_A) # Ждать нажатие клавиши A. + + :param inKeyInt: Перечень клавиш см. в разделе "Коды клавиш". Пример: KEY_HOT_CTRL_LEFT,KEY_ENG_A + :type inKeyInt: int + :param inWaitAfterSecFloat: Количество секунд, которые ожидать после выполнения операции. По умолчанию установлено в настройках модуля Keyboard (базовое значение 0.4) + :type inWaitAfterSecFloat: float, опциональный + """ + wait(hotkey=inKeyInt) + time.sleep(inWaitAfterSecFloat) + +key_to_scan_codes("win") # 2022 06 10 Люблю смотреть скан код клавиши Виндовс :) \ No newline at end of file diff --git a/Resources/WPy32-3720/python-3.7.2/Lib/site-packages/pyOpenRPA/Robot/Mouse.py b/Resources/WPy32-3720/python-3.7.2/Lib/site-packages/pyOpenRPA/Robot/Mouse.py index 49af0760..e693a900 100644 --- a/Resources/WPy32-3720/python-3.7.2/Lib/site-packages/pyOpenRPA/Robot/Mouse.py +++ b/Resources/WPy32-3720/python-3.7.2/Lib/site-packages/pyOpenRPA/Robot/Mouse.py @@ -1 +1,173 @@ -from pyautogui import * \ No newline at end of file +from pyautogui import * +import time + +WAIT_AFTER_SEC_FLOAT = 0.4 # Настройка модуля Mouse: Время, которое ожидать после выполнения любой операции модуля Mouse. Настройка является единой для всех участов кода, использующих модуль Mouse. Если для некоторой функции требуется изменить данное время ожидания, то в отношении этой функции можно применить соответсвующий аргумент. + +def Click(inXInt:int=None, inYInt:int=None, inClickCountInt:int=1, inIntervalSecFloat:float=0.0, inButtonStr:str='left', inMoveDurationSecFloat:float=0.0, inWaitAfterSecFloat:float=WAIT_AFTER_SEC_FLOAT): + """Нажатие (вниз) кнопки мыши и затем немедленно выпуск (вверх) её. Допускается следующая параметризация. Если не указаны inXInt и inYInt - клик производится по месту нахождения указателя мыши. + + !ВНИМАНИЕ! Отсчет координат inXInt, inYInt начинается с левого верхнего края рабочей области (экрана). + + .. code-block:: python + + # Mouse: Взаимодействие с мышью + from pyOpenRPA.Robot import Mouse + Mouse.Click(100,150) #Выполнить нажатие левой клавиши мыши на экране по координатам: X(гор) 100px, Y(вер) 150px. + + :param inXInt: Целевая позиция указателя мыши по оси X (горизонтальная ось). + :type inXInt: int, опциональный + :param inYInt: Целевая позиция указателя мыши по оси Y (вертикальная ось). + :type inYInt: int, опциональный + :param inClickCountInt: Количество нажатий (вниз и вверх) кнопкой мыши, По умолчанию 1 + :type inClickCountInt: int, опциональный + :param inIntervalSecFloat: Интервал ожидания в секундах между нажатиями, По умолчанию 0.0 + :type inIntervalSecFloat: float, опциональный + :param inButtonStr: Номер кнопки, которую требуется нажать. Возможные варианты: 'left', 'middle', 'right' или 1, 2, 3. В остальных случаях инициирует исключение ValueError. По умолчанию 'left' + :type inButtonStr: str, опциональный + :param inMoveDurationSecFloat: Время перемещения указателя мыши, По умолчанию 0.0 (моментальное перемещение) + :type inMoveDurationSecFloat: float, опциональный + :param inWaitAfterSecFloat: Количество секунд, которые ожидать после выполнения операции. По умолчанию установлено в настройках модуля Mouse (базовое значение 0.4) + :type inWaitAfterSecFloat: float, опциональный + """ + click(x=inXInt, y=inYInt, clicks=inClickCountInt, interval=inIntervalSecFloat, button=inButtonStr, duration=inMoveDurationSecFloat) + time.sleep(inWaitAfterSecFloat) + +def ClickDouble(inXInt:int=None, inYInt:int=None, inWaitAfterSecFloat:float=WAIT_AFTER_SEC_FLOAT): + """Двойное нажатие левой клавиши мыши. Данное действие аналогично вызову функции (см. ниже). + + !ВНИМАНИЕ! Отсчет координат inXInt, inYInt начинается с левого верхнего края рабочей области (экрана). + + .. code-block:: python + + # Mouse: Взаимодействие с мышью + from pyOpenRPA.Robot import Mouse + Mouse.ClickDouble(100,150) #Выполнить двойное нажатие левой клавиши мыши на экране по координатам: X(гор) 100px, Y(вер) 150px. + + :param inXInt: Целевая позиция указателя мыши по оси X (горизонтальная ось). + :type inXInt: int, опциональный + :param inYInt: Целевая позиция указателя мыши по оси Y (вертикальная ось). + :type inYInt: int, опциональный + :param inButtonStr: Номер кнопки, которую требуется нажать. Возможные варианты: 'left', 'middle', 'right' или 1, 2, 3. В остальных случаях инициирует исключение ValueError. По умолчанию 'left' + :type inButtonStr: str, опциональный + :param inWaitAfterSecFloat: Количество секунд, которые ожидать после выполнения операции. По умолчанию установлено в настройках модуля Mouse (базовое значение 0.4) + :type inWaitAfterSecFloat: float, опциональный + """ + doubleClick(x=inXInt, y=inYInt) + time.sleep(inWaitAfterSecFloat) + +def Down(inXInt:int=None, inYInt:int=None, inButtonStr:str='left', inWaitAfterSecFloat:float=WAIT_AFTER_SEC_FLOAT): + """Переместить указатель по координатам inXInt, inYInt, после чего нажать (вниз) клавишу мыши и не отпускать до выполнения соответсвующей команды (см. Up). Если координаты inXInt, inYInt не переданы - нажатие происходит на тех координатах X/Y, на которых указатель мыши находится. + + !ВНИМАНИЕ! Отсчет координат inXInt, inYInt начинается с левого верхнего края рабочей области (экрана). + + .. code-block:: python + + # Mouse: Взаимодействие с мышью + from pyOpenRPA.Robot import Mouse + Mouse.Down() #Опустить левую клавишу мыши + + :param inXInt: Целевая позиция указателя мыши по оси X (горизонтальная ось). + :type inXInt: int, опциональный + :param inYInt: Целевая позиция указателя мыши по оси Y (вертикальная ось). + :type inYInt: int, опциональный + :param inButtonStr: Номер кнопки, которую требуется нажать. Возможные варианты: 'left', 'middle', 'right' или 1, 2, 3. В остальных случаях инициирует исключение ValueError. По умолчанию 'left' + :type inButtonStr: str, опциональный + :param inWaitAfterSecFloat: Количество секунд, которые ожидать после выполнения операции. По умолчанию установлено в настройках модуля Mouse (базовое значение 0.4) + :type inWaitAfterSecFloat: float, опциональный + """ + mouseDown(x=inXInt, y=inYInt, button = inButtonStr) + time.sleep(inWaitAfterSecFloat) + +def Up(inXInt:int=None, inYInt:int=None, inButtonStr:str='left', inWaitAfterSecFloat:float=WAIT_AFTER_SEC_FLOAT): + """Отпустить (вверх) клавишу мыши. Если координаты inXInt, inYInt не переданы - нажатие происходит на тех координатах X/Y, на которых указатель мыши находится. + + !ВНИМАНИЕ! Отсчет координат inXInt, inYInt начинается с левого верхнего края рабочей области. + + .. code-block:: python + + # Mouse: Взаимодействие с мышью + from pyOpenRPA.Robot import Mouse + Mouse.Up(inButtonStr:str='right') #Поднять правую клавишу мыши + + :param inXInt: Целевая позиция указателя мыши по оси X (горизонтальная ось). + :type inXInt: int, опциональный + :param inYInt: Целевая позиция указателя мыши по оси Y (вертикальная ось). + :type inYInt: int, опциональный + :param inButtonStr: Номер кнопки, которую требуется поднять. Возможные варианты: 'left', 'middle', 'right' или 1, 2, 3. В остальных случаях инициирует исключение ValueError. По умолчанию 'left' + :type inButtonStr: str, опциональный + :param inWaitAfterSecFloat: Количество секунд, которые ожидать после выполнения операции. По умолчанию установлено в настройках модуля Mouse (базовое значение 0.4) + :type inWaitAfterSecFloat: float, опциональный + """ + mouseUp(x=inXInt, y=inYInt, button = inButtonStr) + time.sleep(inWaitAfterSecFloat) + +def MoveTo(inXInt=None, inYInt=None, inMoveDurationSecFloat:float=0.0, inWaitAfterSecFloat:float=WAIT_AFTER_SEC_FLOAT): + """Переместить указатель мыши на позицию inXInt, inYInt за время inMoveDurationSecFloat. + + !ВНИМАНИЕ! Отсчет координат inXInt, inYInt начинается с левого верхнего края рабочей области (экрана). + + .. code-block:: python + + # Mouse: Взаимодействие с мышью + from pyOpenRPA.Robot import Mouse + Mouse.MoveTo(inXInt=100, inYInt=200) #Переместить указатель мыши по координатам: X(гор) 100, Y(вер) 200 + + :param inXInt: Целевая позиция указателя мыши по оси X (горизонтальная ось). + :type inXInt: int, опциональный + :param inYInt: Целевая позиция указателя мыши по оси Y (вертикальная ось). + :type inYInt: int, опциональный + :param inMoveDurationSecFloat: Время перемещения указателя мыши, По умолчанию 0.0 (моментальное перемещение) + :type inMoveDurationSecFloat: float, опциональный + :param inWaitAfterSecFloat: Количество секунд, которые ожидать после выполнения операции. По умолчанию установлено в настройках модуля Mouse (базовое значение 0.4) + :type inWaitAfterSecFloat: float, опциональный + """ + moveTo(x=inXInt, y=inYInt, duration=inMoveDurationSecFloat) + time.sleep(inWaitAfterSecFloat) + +def ScrollVertical(inScrollClickCountInt, inXInt=None, inYInt=None, inWaitAfterSecFloat:float=WAIT_AFTER_SEC_FLOAT): + """Переместить указатель мыши на позицию inXInt, inYInt и выполнить вертикальную прокрутку (скроллинг) колесом мыши на количество щелчков inScrollClickCountInt. + + !ВНИМАНИЕ! Отсчет координат inXInt, inYInt начинается с левого верхнего края рабочей области (экрана). + + .. code-block:: python + + # Mouse: Взаимодействие с мышью + from pyOpenRPA.Robot import Mouse + Mouse.ScrollVertical(100, inXInt=100, inYInt=200) #Крутить колесо мыши вниз на 100 кликов по координатам: X(гор) 100, Y(вер) 200 + Mouse.ScrollVertical(-100) #Крутить колесо мыши вверх на 100 кликов по текущим координатам указателя мыши. + + :param inScrollClickCountInt: Количество щелчок колеса мыши, которое требуется !вертикально! прокрутить. Аргумент может принимать как положительное (прокрутка вниз), так и отрицательное (прокрутка вверх) значения + :type inScrollClickCountInt: int, обязательный + :param inXInt: Целевая позиция указателя мыши по оси X (горизонтальная ось). + :type inXInt: int, опциональный + :param inYInt: Целевая позиция указателя мыши по оси Y (вертикальная ось). + :type inYInt: int, опциональный + :param inWaitAfterSecFloat: Количество секунд, которые ожидать после выполнения операции. По умолчанию установлено в настройках модуля Mouse (базовое значение 0.4) + :type inWaitAfterSecFloat: float, опциональный + """ + vscroll(inScrollClickCountInt, x=inXInt, y=inYInt) + time.sleep(inWaitAfterSecFloat) + +def ScrollHorizontal(inScrollClickCountInt, inXInt=None, inYInt=None, inWaitAfterSecFloat:float=WAIT_AFTER_SEC_FLOAT): + """!ТОЛЬКО ДЛЯ LINUX! Переместить указатель мыши на позицию inXInt, inYInt и выполнить горизонтальную прокрутку (скроллинг) виртуальным колесом мыши на количество щелчков inScrollClickCountInt. + + !ВНИМАНИЕ! Отсчет координат inXInt, inYInt начинается с левого верхнего края рабочей области (экрана). + + .. code-block:: python + + # Mouse: Взаимодействие с мышью + from pyOpenRPA.Robot import Mouse + Mouse.ScrollHorizontal(100, inXInt=100, inYInt=200) #Крутить колесо мыши вниз на 100 кликов по координатам: X(гор) 100, Y(вер) 200 + Mouse.ScrollHorizontal(-100) #Крутить колесо мыши вверх на 100 кликов по текущим координатам указателя мыши. + + :param inScrollClickCountInt: Количество щелчок колеса мыши, которое требуется !горизонтально! прокрутить. Аргумент может принимать как положительное (прокрутка вправо), так и отрицательное (прокрутка влево) значения + :type inScrollClickCountInt: int, обязательный + :param inXInt: Целевая позиция указателя мыши по оси X (горизонтальная ось). + :type inXInt: int, опциональный + :param inYInt: Целевая позиция указателя мыши по оси Y (вертикальная ось). + :type inYInt: int, опциональный + :param inWaitAfterSecFloat: Количество секунд, которые ожидать после выполнения операции. По умолчанию установлено в настройках модуля Mouse (базовое значение 0.4) + :type inWaitAfterSecFloat: float, опциональный + """ + hscroll(inScrollClickCountInt, x=inXInt, y=inYInt) + time.sleep(inWaitAfterSecFloat) diff --git a/Resources/WPy32-3720/python-3.7.2/Lib/site-packages/pyOpenRPA/Robot/README.md b/Resources/WPy32-3720/python-3.7.2/Lib/site-packages/pyOpenRPA/Robot/README.md index f5f30305..4ae5e05c 100644 --- a/Resources/WPy32-3720/python-3.7.2/Lib/site-packages/pyOpenRPA/Robot/README.md +++ b/Resources/WPy32-3720/python-3.7.2/Lib/site-packages/pyOpenRPA/Robot/README.md @@ -43,16 +43,5 @@ Resources\WPy64-3720\python-3.7.2.amd64\python.exe ] -# Open RPA Wiki -- [Home](https://gitlab.com/UnicodeLabs/OpenRPA/wikis/home) -- [04. Desktop app access (win32 & ui automation)](https://gitlab.com/UnicodeLabs/OpenRPA/wikis/04.-Desktop-app-access-(win32-&-ui-automation)) - -#Dependencies -* Python 3 x32 [psutil, pywinauto, wmi, PIL, keyboard, pyautogui, win32api (pywin32), selenium, openCV, tesseract, requests, lxml, PyMuPDF] -* Python 3 x64 [psutil, pywinauto, wmi, PIL, keyboard, pyautogui, win32api (pywin32), selenium, openCV, tesseract, requests, lxml, PyMuPDF] -* pywinauto (Windows GUI automation) -* Semantic UI CSS framework -* JsRender by https://www.jsviews.com (switch to Handlebars) -* Handlebars - -Created by Unicode Labs (Ivan Maslov) \ No newline at end of file + +Created by pyOpenRPA LLC (Ivan Maslov) \ No newline at end of file diff --git a/Resources/WPy32-3720/python-3.7.2/Lib/site-packages/pyOpenRPA/Robot/UIDesktop.py b/Resources/WPy32-3720/python-3.7.2/Lib/site-packages/pyOpenRPA/Robot/UIDesktop.py index e084d515..fa101c2b 100644 --- a/Resources/WPy32-3720/python-3.7.2/Lib/site-packages/pyOpenRPA/Robot/UIDesktop.py +++ b/Resources/WPy32-3720/python-3.7.2/Lib/site-packages/pyOpenRPA/Robot/UIDesktop.py @@ -29,7 +29,7 @@ import copy #TODO В перспективе нужно реализовать алгоритм определения разрядности не в Robot.py, а в UIDesktop.py, тк начинают появляться функции, на входе в которые еще неизвестна разрядность элемента + селектор может охватить сразу два элемента из 2-х разных разрядностей - обрабатываться это должно непосредственно при выполнении #################################### -#Info: GUI module of the Robot app (OpenRPA - Robot) +#Info: GUI module of the Robot app (pyOpenRPA - Robot) #################################### # GUI Module - interaction with Desktop application @@ -99,19 +99,27 @@ mDefaultPywinautoBackend="win32" # "rich_text" - наименование rich_text # } #] -################ -#return: List of UI Object -#inElement - Входной элемент - показатель, что не требуется выполнять коннект к процессу -#inFlagRaiseException - Флаг True - выкинуть ошибку в случае обнаружении пустого списка -#old name - PywinautoExtElementsGet + +#old:PywinautoExtElementsGet def UIOSelector_Get_UIOList (inSpecificationList,inElement=None,inFlagRaiseException=True): ''' - Get the UIO list by the selector + Получить список UIO объектов по UIO селектору + + .. code-block:: python + + # UIDesktop: Взаимодействие с UI объектами приложений + from pyOpenRPA.Robot import UIDesktop + # 1С: UIO Селектор выбора базы + lDemoBaseUIOSelector = [{"title":"Запуск 1С:Предприятия","class_name":"V8TopLevelFrameTaxiStarter","backend":"uia"},{"title":"DEMO", "depth_start": 5, "depth_end": 5}] + lDemoBaseUIOList = UIDesktop.UIOSelector_Get_UIOList(lDemoBaseUIOSelector) #Получить список UIO объектов, которые удовлетворяют требованиям UIO селектора. В нашем примере либо [], либо [UIO объект] - :param inSpecificationList: UIO Selector - :param inElement: Входной элемент - показатель, что не требуется выполнять коннект к процессу - :param inFlagRaiseException: Флаг True - выкинуть ошибку в случае обнаружении пустого списка - :return: + :param inSpecificationList: UIO Селектор, который определяет критерии поиска UI элементов + :type inSpecificationList: list, обязательный + :param inElement: Родительский элемент, от которого выполнить поиск UIO объектов по заданному UIO селектору. Если аргумент не задан, платформа выполнит поиск UIO объектов среди всех доступных приложений windows, которые запущены на текущей сессии + :type inElement: UIO объект, опциональный + :param inFlagRaiseException: True - формировать ошибку exception, если платформа не обнаружина ни одного UIO объекта по заданному UIO селектору. False - обратный случай. По умолчанию True + :type inFlagRaiseException: bool, опциональный + :return: Список UIO объектов, которые удовлетворяют условиям UIO селектора ''' #Создать копию входного листа, чтобы не менять массив в других верхнеуровневых функциях inSpecificationList=copy.deepcopy(inSpecificationList) @@ -235,20 +243,26 @@ def UIOSelector_Get_UIOList (inSpecificationList,inElement=None,inFlagRaiseExcep raise pywinauto.findwindows.ElementNotFoundError("Robot can't find element by the UIOSelector") return lResultList -################################################################################################# -#Get first (in more than one) UIO (UI Object) -#inSpecificationList - UIOSelector -#inElement - Входной элемент - показатель, что не требуется выполнять коннект к процессу -#inFlagRaiseException - Флаг True - выкинуть ошибку в случае обнаружении пустого списка -#old name - PywinautoExtElementGet +#old:PywinautoExtElementGet def UIOSelector_Get_UIO (inSpecificationList,inElement=None,inFlagRaiseException=True): ''' - Get the pywinauto object by the UIO selector. + Получить список UIO объект по UIO селектору. Если критериям UIO селектора удовлетворяет несколько UIO объектов - вернуть первый из списка + + .. code-block:: python + + # UIDesktop: Взаимодействие с UI объектами приложений + from pyOpenRPA.Robot import UIDesktop + # 1С: UIO Селектор выбора базы + lDemoBaseUIOSelector = [{"title":"Запуск 1С:Предприятия","class_name":"V8TopLevelFrameTaxiStarter","backend":"uia"},{"title":"DEMO", "depth_start": 5, "depth_end": 5}] + lDemoBaseUIOList = UIDesktop.UIOSelector_Get_UIO(lDemoBaseUIOSelector) #Получить 1-й UIO объект, которые удовлетворяет требованиям UIO селектора. В нашем примере либо None, либо UIO объект - :param inSpecificationList: - :param inElement: - :param inFlagRaiseException: - :return: + :param inSpecificationList: UIO Селектор, который определяет критерии поиска UI элементов + :type inSpecificationList: list, обязательный + :param inElement: Родительский элемент, от которого выполнить поиск UIO объектов по заданному UIO селектору. Если аргумент не задан, платформа выполнит поиск UIO объектов среди всех доступных приложений windows, которые запущены на текущей сессии + :type inElement: UIO объект, опциональный + :param inFlagRaiseException: True - формировать ошибку exception, если платформа не обнаружина ни одного UIO объекта по заданному UIO селектору. False - обратный случай. По умолчанию True + :type inFlagRaiseException: bool, опциональный + :return: UIO объект, которые удовлетворяют условиям UIO селектора, или None ''' lResult=None #Получить родительский объект если на вход ничего не поступило @@ -259,17 +273,25 @@ def UIOSelector_Get_UIO (inSpecificationList,inElement=None,inFlagRaiseException if lResult is None and inFlagRaiseException: raise pywinauto.findwindows.ElementNotFoundError("Robot can't find element by the UIOSelector") return lResult -################################################################################################# -#Check if UIO exist (Identified by the UIOSelector) -#!!!!!Safe call is included (you can set activity and UIDesktop will choose the bitness and return the result)!!!!! -#UIOSelector -#old name - - + +#old:- def UIOSelector_Exist_Bool (inUIOSelector): ''' - Check if object is exist by the UIO selector. + Проверить существование хотя бы 1-го UIO объекта по заданному UIO селектору + + !ВНИМАНИЕ! ДАННАЯ ФУНКЦИОНАЛЬНОСТЬ В АВТОМАТИЧЕСКОМ РЕЖИМЕ ПОДДЕРЖИВАЕТ ВСЕ РАЗРЯДНОСТИ ПРИЛОЖЕНИЙ (32|64), КОТОРЫЕ ЗАПУЩЕНЫ В СЕСИИ. PYTHON x64 ИМЕЕТ ВОЗМОЖНОСТЬ ВЗЗАИМОДЕЙСТВИЯ С x32 UIO ОБЪЕКТАМИ, НО МЫ РЕКОМЕНДУЕМ ДОПОЛНИТЕЛЬНО ИСПОЛЬЗОВАТЬ ИНТЕРПРЕТАТОР PYTHON x32 (ПОДРОБНЕЕ СМ. ФУНКЦИЮ Configure()) + + .. code-block:: python + + # UIDesktop: Взаимодействие с UI объектами приложений + from pyOpenRPA.Robot import UIDesktop + # 1С: UIO Селектор выбора базы + lDemoBaseUIOSelector = [{"title":"Запуск 1С:Предприятия","class_name":"V8TopLevelFrameTaxiStarter","backend":"uia"},{"title":"DEMO", "depth_start": 5, "depth_end": 5}] + lDemoBaseUIOExistBool = UIDesktop.UIOSelector_Exist_Bool(lDemoBaseUIOSelector) # Получить булевый результат проверки существования UIO объекта - :param inUIOSelector: - :return: True - Object is exist. False - else case + :param inUIOSelector: UIO Селектор, который определяет критерии поиска UIO объектов + :type inUIOSelector: list, обязательный + :return: True - существует хотя бы 1 UIO объект. False - не существует ни одного UIO объекта по заданному UIO селектору ''' lResult=False #Check the bitness @@ -294,27 +316,34 @@ def UIOSelector_Exist_Bool (inUIOSelector): else: lResult = lPIPEResponseDict["Result"] return lResult -################################################################################################# -#Wait for UIO is appear (at least one of them or all at the same time) -#inSpecificationListList - List of the UIOSelector -#inWaitSecs - Время ожидания объекта в секундах -#inFlagWaitAllInMoment - доп. условие - ожидать появление всех UIOSelector одновременно -#return: [0,1,2] - index of UIOSpecification, which is appear -#old name - - -#####Внимание##### -##Функция ожидания появления элементов (тк элементы могут быть недоступны, неизвестно в каком фреймворке каждый из них может появиться) -def UIOSelectorsSecs_WaitAppear_List (inSpecificationListList,inWaitSecs,inFlagWaitAllInMoment=False): + +#old: - +def UIOSelectorsSecs_WaitAppear_List (inSpecificationListList,inWaitSecs=86400.0,inFlagWaitAllInMoment=False): ''' - Wait for many UI object will appear in GUI for inWaitSecs seconds. + Ожидать появление хотя бы 1-го / всех UIO объектов по заданным UIO селекторам + + !ВНИМАНИЕ! ДАННАЯ ФУНКЦИОНАЛЬНОСТЬ В АВТОМАТИЧЕСКОМ РЕЖИМЕ ПОДДЕРЖИВАЕТ ВСЕ РАЗРЯДНОСТИ ПРИЛОЖЕНИЙ (32|64), КОТОРЫЕ ЗАПУЩЕНЫ В СЕСИИ. PYTHON x64 ИМЕЕТ ВОЗМОЖНОСТЬ ВЗЗАИМОДЕЙСТВИЯ С x32 UIO ОБЪЕКТАМИ, НО МЫ РЕКОМЕНДУЕМ ДОПОЛНИТЕЛЬНО ИСПОЛЬЗОВАТЬ ИНТЕРПРЕТАТОР PYTHON x32 (ПОДРОБНЕЕ СМ. ФУНКЦИЮ Configure()) + + .. code-block:: python - :param inSpecificationListList: UIOSelector list. - Example: [ + # UIDesktop: Взаимодействие с UI объектами приложений + from pyOpenRPA.Robot import UIDesktop + # 1С: UIO Селектор выбора базы + lDemoBaseUIOSelector = [{"title":"Запуск 1С:Предприятия","class_name":"V8TopLevelFrameTaxiStarter","backend":"uia"},{"title":"DEMO", "depth_start": 5, "depth_end": 5}] + lNotepadOKSelector = [{"title":"notepad"},{"title":"OK"}] + lNotepadCancelSelector = [{"title":"notepad"},{"title":"Cancel"}] + lDemoBaseUIOExistList = UIDesktop.UIOSelectorsSecs_WaitAppear_List([lDemoBaseUIOSelector, lNotepadOKSelector, lNotepadCancelSelector]) # Ожидать появление UIO объекта + + :param inSpecificationListList: Список UIO селекторов, которые определяют критерии поиска UIO объектов + Пример: [ [{"title":"notepad"},{"title":"OK"}], [{"title":"notepad"},{"title":"Cancel"}] ] - :param inWaitSecs: Float value (seconds) for wait UI element appear in GUI - :param inFlagWaitAllInMoment: True - Wait all UI objects from the UIOSelector list to be appeared - :return: List of index, which UI object UIO will be appeared. Example: [1] # Appear only UI object with UIO selector: [{"title":"notepad"},{"title":"Cancel"}] + :type inSpecificationListList: list, обязательный + :param inWaitSecs: Количество секунд, которые отвести на ожидание UIO объектов. По умолчанию 24 часа (86400 секунд) + :type inWaitSecs: float, необязательный + :param inFlagWaitAllInMoment: True - Ожидать до того момента, пока не появятся все запрашиваемые UIO объекты на рабочей области + :return: Список индексов, которые указывают на номер входящих UIO селекторов, которые были обнаружены на рабочей области. Пример: [0,2] ''' lResultFlag=False lSecsSleep = 1 #Настроечный параметр @@ -345,29 +374,36 @@ def UIOSelectorsSecs_WaitAppear_List (inSpecificationListList,inWaitSecs,inFlagW lSecsDone=lSecsDone+lSecsSleep time.sleep(lSecsSleep) return lResultList -################################################################################################# -#Wait for UIO is Disappear (at least one of them or all at the same time) -#inSpecificationListList - List of the UIOSelector -#inWaitSecs - Время ожидания пропажи объекта в секундах -#inFlagWaitAllInMoment - доп. условие - ожидать пропажу всех UIOSelector одновременно -#return: [0,1,2] - index of UIOSpecification, which is Disappear -#old name - - -#####Внимание##### -##Функция ожидания пропажи элементов (тк элементы могут быть недоступны, неизвестно в каком фреймворке каждый из них может появиться) -def UIOSelectorsSecs_WaitDisappear_List (inSpecificationListList,inWaitSecs,inFlagWaitAllInMoment=False): + +#old: - +def UIOSelectorsSecs_WaitDisappear_List (inSpecificationListList,inWaitSecs=86400.0,inFlagWaitAllInMoment=False): ''' - Wait for many UI object will disappear in GUI for inWaitSecs seconds. + Ожидать исчезновение хотя бы 1-го / всех UIO объектов по заданным UIO селекторам + + !ВНИМАНИЕ! ДАННАЯ ФУНКЦИОНАЛЬНОСТЬ В АВТОМАТИЧЕСКОМ РЕЖИМЕ ПОДДЕРЖИВАЕТ ВСЕ РАЗРЯДНОСТИ ПРИЛОЖЕНИЙ (32|64), КОТОРЫЕ ЗАПУЩЕНЫ В СЕСИИ. PYTHON x64 ИМЕЕТ ВОЗМОЖНОСТЬ ВЗЗАИМОДЕЙСТВИЯ С x32 UIO ОБЪЕКТАМИ, НО МЫ РЕКОМЕНДУЕМ ДОПОЛНИТЕЛЬНО ИСПОЛЬЗОВАТЬ ИНТЕРПРЕТАТОР PYTHON x32 (ПОДРОБНЕЕ СМ. ФУНКЦИЮ Configure()) + + .. code-block:: python + + # UIDesktop: Взаимодействие с UI объектами приложений + from pyOpenRPA.Robot import UIDesktop + # 1С: UIO Селектор выбора базы + lDemoBaseUIOSelector = [{"title":"Запуск 1С:Предприятия","class_name":"V8TopLevelFrameTaxiStarter","backend":"uia"},{"title":"DEMO", "depth_start": 5, "depth_end": 5}] + lNotepadOKSelector = [{"title":"notepad"},{"title":"OK"}] + lNotepadCancelSelector = [{"title":"notepad"},{"title":"Cancel"}] + lDemoBaseUIOExistList = UIDesktop.UIOSelectorsSecs_WaitDisappear_List([lDemoBaseUIOSelector, lNotepadOKSelector, lNotepadCancelSelector]) # Ожидать исчезновение UIO объектов - :param inSpecificationListList: UIOSelector list. - Example: [ + :param inSpecificationListList: Список UIO селекторов, которые определяют критерии поиска UIO объектов + Пример: [ [{"title":"notepad"},{"title":"OK"}], [{"title":"notepad"},{"title":"Cancel"}] ] - :param inWaitSecs: Float value (seconds) for wait UI element disappear in GUI - :param inFlagWaitAllInMoment: True - Wait all UI objects from the UIOSelector list to be disappeared. - :return: List of index, which UI object UIO will be disappeared. Example: [1] # Disappear only UI object with UIO selector: [{"title":"notepad"},{"title":"Cancel"}] - :return: + :type inSpecificationListList: list, обязательный + :param inWaitSecs: Количество секунд, которые отвести на ожидание исчезновения UIO объектов. По умолчанию 24 часа (86400 секунд) + :type inWaitSecs: float, необязательный + :param inFlagWaitAllInMoment: True - Ожидать до того момента, пока не исчезнут все запрашиваемые UIO объекты на рабочей области + :return: Список индексов, которые указывают на номер входящих UIO селекторов, которые были обнаружены на рабочей области. Пример: [0,2] ''' + lResultFlag=False lSecsSleep = 1 #Настроечный параметр lSecsDone = 0 @@ -397,56 +433,77 @@ def UIOSelectorsSecs_WaitDisappear_List (inSpecificationListList,inWaitSecs,inFl lSecsDone=lSecsDone+lSecsSleep time.sleep(lSecsSleep) return lResultList -################################################################################################# -#Wait for UIO is appear (at least one of them or all at the same time) -#inSpecificationList - UIOSelector -#inWaitSecs - Время ожидания объекта в секундах -#return: Bool - True - UIO is appear -#old name - - + +#old: - def UIOSelectorSecs_WaitAppear_Bool (inSpecificationList,inWaitSecs): ''' - Wait for UI object will appear in GUI for inWaitSecs seconds. + Ожидать появление 1-го UIO объекта по заданному UIO селектору + + !ВНИМАНИЕ! ДАННАЯ ФУНКЦИОНАЛЬНОСТЬ В АВТОМАТИЧЕСКОМ РЕЖИМЕ ПОДДЕРЖИВАЕТ ВСЕ РАЗРЯДНОСТИ ПРИЛОЖЕНИЙ (32|64), КОТОРЫЕ ЗАПУЩЕНЫ В СЕСИИ. PYTHON x64 ИМЕЕТ ВОЗМОЖНОСТЬ ВЗЗАИМОДЕЙСТВИЯ С x32 UIO ОБЪЕКТАМИ, НО МЫ РЕКОМЕНДУЕМ ДОПОЛНИТЕЛЬНО ИСПОЛЬЗОВАТЬ ИНТЕРПРЕТАТОР PYTHON x32 (ПОДРОБНЕЕ СМ. ФУНКЦИЮ Configure()) + + .. code-block:: python + + # UIDesktop: Взаимодействие с UI объектами приложений + from pyOpenRPA.Robot import UIDesktop + # 1С: UIO Селектор выбора базы + lDemoBaseUIOSelector = [{"title":"Запуск 1С:Предприятия","class_name":"V8TopLevelFrameTaxiStarter","backend":"uia"},{"title":"DEMO", "depth_start": 5, "depth_end": 5}] + lDemoBaseUIOExistBool = UIDesktop.UIOSelectorSecs_WaitAppear_Bool(lDemoBaseUIOSelector) # Ожидать появление UIO объекта - :param inSpecificationList: UIOSelector. Example: [{"title":"notepad"},{"title":"OK"}] - :param inWaitSecs: Float value (seconds) for wait UI element appear in GUI - :return: True - UI object will appear. False - else case + :param inSpecificationList: UIO селектор, который определяет критерии поиска UIO объекта + :type inSpecificationList: list, обязательный + :param inWaitSecs: Количество секунд, которые отвести на ожидание UIO объекта. По умолчанию 24 часа (86400 секунд) + :type inWaitSecs: float, необязательный + :return: True - UIO объект был обнаружен. False - обратная ситуациая ''' lWaitAppearList=UIOSelectorsSecs_WaitAppear_List([inSpecificationList],inWaitSecs) lResult=False if len(lWaitAppearList)>0: lResult=True return lResult -################################################################################################# -#Wait for UIO is disappear (at least one of them or all at the same time) -#inSpecificationList - UIOSelector -#inWaitSecs - Время ожидания пропажи объекта в секундах -#return: Bool - True - UIO is Disappear + #old name - - def UIOSelectorSecs_WaitDisappear_Bool (inSpecificationList,inWaitSecs): ''' - Wait for UI object will disappear in GUI for inWaitSecs seconds. + Ожидать исчезновение 1-го UIO объекта по заданному UIO селектору + + !ВНИМАНИЕ! ДАННАЯ ФУНКЦИОНАЛЬНОСТЬ В АВТОМАТИЧЕСКОМ РЕЖИМЕ ПОДДЕРЖИВАЕТ ВСЕ РАЗРЯДНОСТИ ПРИЛОЖЕНИЙ (32|64), КОТОРЫЕ ЗАПУЩЕНЫ В СЕСИИ. PYTHON x64 ИМЕЕТ ВОЗМОЖНОСТЬ ВЗЗАИМОДЕЙСТВИЯ С x32 UIO ОБЪЕКТАМИ, НО МЫ РЕКОМЕНДУЕМ ДОПОЛНИТЕЛЬНО ИСПОЛЬЗОВАТЬ ИНТЕРПРЕТАТОР PYTHON x32 (ПОДРОБНЕЕ СМ. ФУНКЦИЮ Configure()) + + .. code-block:: python + + # UIDesktop: Взаимодействие с UI объектами приложений + from pyOpenRPA.Robot import UIDesktop + # 1С: UIO Селектор выбора базы + lDemoBaseUIOSelector = [{"title":"Запуск 1С:Предприятия","class_name":"V8TopLevelFrameTaxiStarter","backend":"uia"},{"title":"DEMO", "depth_start": 5, "depth_end": 5}] + lDemoBaseUIOExistBool = UIDesktop.UIOSelectorSecs_WaitDisappear_Bool(lDemoBaseUIOSelector) # Ожидать исчезновение UIO объекта - :param inSpecificationList: UIOSelector. - Example: [{"title":"notepad"},{"title":"OK"}] - :param inWaitSecs: Float value (seconds) for wait UI element disappear in GUI - :return: True - UI object will disappear. False - else case + :param inSpecificationList: UIO селектор, который определяет критерии поиска UIO объекта + :type inSpecificationList: list, обязательный + :param inWaitSecs: Количество секунд, которые отвести на исчезновение UIO объекта. По умолчанию 24 часа (86400 секунд) + :type inWaitSecs: float, необязательный + :return: True - UIO объект был обнаружен. False - обратная ситуациая ''' lWaitDisappearList=UIOSelectorsSecs_WaitDisappear_List([inSpecificationList],inWaitSecs) lResult=False if len(lWaitDisappearList)>0: lResult=True return lResult -################################################################################################# -#Get process bitness (32 or 64) -#inSpecificationList - UIOSelector -#old name - None -#return None (if Process not found), int 32, or int 64 + +#old: - def UIOSelector_Get_BitnessInt (inSpecificationList): ''' - Detect process bitness by the UI Object UIO Selector. + Определить разрядность приложения по UIO селектору. Вернуть результат в формате целого числа (64 или 32) + + .. code-block:: python - :param inSpecificationList: UIOSelector. Example: [{"title":"notepad"},{"title":"OK"}] - :return: int 32 or int 64 + # UIDesktop: Взаимодействие с UI объектами приложений + from pyOpenRPA.Robot import UIDesktop + # 1С: UIO Селектор выбора базы + lDemoBaseUIOSelector = [{"title":"Запуск 1С:Предприятия","class_name":"V8TopLevelFrameTaxiStarter","backend":"uia"},{"title":"DEMO", "depth_start": 5, "depth_end": 5}] + lDemoBaseBitInt = UIDesktop.UIOSelector_Get_BitnessInt(lDemoBaseUIOSelector) # Определить разрядность приложения, в котором обнаружен UIO объект по селектору + + :param inSpecificationList: UIO селектор, который определяет критерии поиска UIO объекта + :type inSpecificationList: list, обязательный + :return: None - UIO объект не обнаружен; 64 (int) - разрядность приложения равна 64 битам; 32 (int) - разрядность приложения равна 32 битам ''' lResult=None #Получить объект Application (Для проверки разрядности) @@ -457,18 +514,24 @@ def UIOSelector_Get_BitnessInt (inSpecificationList): else: lResult=32 return lResult -################################################################################################# -#Get process bitness ("32" or "64") -#inSpecificationList - UIOSelector -#old name - None -#return None (if Process not found), int 32, or int 64 + +#old: - def UIOSelector_Get_BitnessStr (inSpecificationList): - ''' - Detect process bitness by the UI Object UIO Selector. + """ + Определить разрядность приложения по UIO селектору. Вернуть результат в формате строки ("64" или "32") - :param inSpecificationList: UIOSelector. Example: [{"title":"notepad"},{"title":"OK"}] - :return: str "32" or str "64" - ''' + .. code-block:: python + + # UIDesktop: Взаимодействие с UI объектами приложений + from pyOpenRPA.Robot import UIDesktop + # 1С: UIO Селектор выбора базы + lDemoBaseUIOSelector = [{"title":"Запуск 1С:Предприятия","class_name":"V8TopLevelFrameTaxiStarter","backend":"uia"},{"title":"DEMO", "depth_start": 5, "depth_end": 5}] + lDemoBaseBitStr = UIDesktop.UIOSelector_Get_BitnessStr(lDemoBaseUIOSelector) # Определить разрядность приложения, в котором обнаружен UIO объект по селектору + + :param inSpecificationList: UIO селектор, который определяет критерии поиска UIO объекта + :type inSpecificationList: list, обязательный + :return: None - UIO объект не обнаружен; "64" (str) - разрядность приложения равна 64 битам; "32" (str) - разрядность приложения равна 32 битам + """ lResult=None #Получить объект Application (Для проверки разрядности) lRootElement=PWASpecification_Get_PWAApplication(inSpecificationList) @@ -478,28 +541,40 @@ def UIOSelector_Get_BitnessStr (inSpecificationList): else: lResult="32" return lResult -################################################################################################# -#Get OS bitness (32 or 64) -#old name - None -#return int 32, or int 64 + +#old: - def Get_OSBitnessInt (): ''' - Detect OS bitness. + Определить разрядность робота, в котором запускается данная функция - :return: int 32 or int 64 + .. code-block:: python + + from pyOpenRPA.Robot import UIDesktop + lRobotBitInt = UIDesktop.Get_OSBitnessInt() # Определить разрядность робота, в котором была вызвана это функция + + :return: 64 (int) - разрядность приложения равна 64 битам; 32 (int) - разрядность приложения равна 32 битам ''' lResult=32 if pywinauto.sysinfo.is_x64_OS(): lResult=64 return lResult -################################################################################################# +#old: - def UIOSelector_SafeOtherGet_Process(inUIOSelector): - ''' - Safe get other process or None if destination app is the other/same bitness + """ + Получить процесс робота другой разрядности (если приложение UIO объекта выполняется в другой разрядности). Функция возвращает None, если разрядность робота совпадает с разрядностью приложения UIO объекта, либо если при инициализации робота не устанавливался интерпретатор другой разрядности. - :param inUIOSelector: UIO Selector of the UI object - :return: None or process (of the other bitness) - ''' + .. code-block:: python + + # UIDesktop: Взаимодействие с UI объектами приложений + from pyOpenRPA.Robot import UIDesktop + # 1С: UIO Селектор выбора базы + lDemoBaseUIOSelector = [{"title":"Запуск 1С:Предприятия","class_name":"V8TopLevelFrameTaxiStarter","backend":"uia"},{"title":"DEMO", "depth_start": 5, "depth_end": 5}] + lOtherBitnessProcess = UIDesktop.UIOSelector_SafeOtherGet_Process(lDemoBaseUIOSelector) # Вернуть процесс робота, схожей разрядности + + :param inUIOSelector: UIO селектор, который определяет критерии поиска UIO объекта + :type inUIOSelector: list, обязательный + :return: Процесс робота схожей разрядности + """ #Default value lResult = None #Go check bitness if selector exists @@ -509,15 +584,44 @@ def UIOSelector_SafeOtherGet_Process(inUIOSelector): if lUIOSelectorAppBitness and Utils.ProcessBitness.mSettingsDict["BitnessProcessCurrent"] != lUIOSelectorAppBitness: lResult = Utils.ProcessBitness.OtherProcessGet() return lResult -################################################################################################## +#old: GetControl def PWASpecification_Get_UIO(inControlSpecificationArray): - ''' - #Backend def selection - attribute "backend" ("win32" || "uia") in 1-st list element - #old name - GetControl + """ + Получить UIO объект по PWA (pywinauto) селектору. (https://pywinauto.readthedocs.io/en/latest/code/pywinauto.findwindows.html). Мы рекомендуем использовать метод UIOSelector_UIO_Get, так как UIO селектор обладает большей функциональностью. - :param inControlSpecificationArray: List of dict, dict in pywinauto.find_windows notation - :return: list of UIO object - ''' + .. code-block:: python + + # UIDesktop: Взаимодействие с UI объектами приложений + from pyOpenRPA.Robot import UIDesktop + # 1С: UIO Селектор выбора базы + lDemoBaseUIOSelector = [{"title":"Запуск 1С:Предприятия","class_name":"V8TopLevelFrameTaxiStarter","backend":"uia"}] + lUIOObject = UIDesktop.PWASpecification_Get_UIO(lDemoBaseUIOSelector) # Получить UIO объект по PWA селектору + + :param inControlSpecificationArray: PWA селектор, который определяет критерии поиска UIO объекта + Допустимые ключи PWA селектора: + + - class_name содержимое атрибута class UIO объекта + - class_name_re содержимое атрибута class UIO объекта, которое удовлетворяет установленному рег. выражению + - process идентификатор процесса, в котором находится UIO объект + - title содержимое атрибута title UIO объекта + - title_re содержимое атрибута title UIO объекта, которое удовлетворяет установленному рег. выражению + - top_level_only признак поиска только на верхнем уровне приложения. По умолчанию True + - visible_only признак поиска только среди видимых UIO объектов. По умолчанию True + - enabled_only признак поиска только среди разблокированных UIO объектов. По умолчанию False + - best_match содержимое атрибута title UIO объекта максимально приближено к заданному + - handle идентификатор handle искомого UIO объекта + - ctrl_index индекс UIO объекта среди всех дочерних объектов в списке родительского + - found_index индекс UIO объекта среди всех обнаруженных + - predicate_func пользовательская функция проверки соответсвия UIO элемента + - active_only признак поиска только среди активных UIO объектов. По умолчанию False + - control_id идентификатор control_id искомого UIO объекта + - control_type тип элемента (применимо, если backend == "uia") + - auto_id идентификатор auto_id искомого UIO объекта (применимо, если backend == "uia") + - framework_id идентификатор framework_id искомого UIO объекта (применимо, если backend == "uia") + - backend вид технологии подключения к поиску UIO объекта ("uia" или "win32") + :type inControlSpecificationArray: list, обязательный + :return: UIO объект + """ #Определение backend lBackend=mDefaultPywinautoBackend if "backend" in inControlSpecificationArray[0]: @@ -563,14 +667,44 @@ def PWASpecification_Get_UIO(inControlSpecificationArray): #Добавить объект в результирующий массив lResultList.append(lTempObject) return lResultList -################################################################################################## + def PWASpecification_Get_PWAApplication(inControlSpecificationArray): - ''' - #Backend selection - attribute "backend" ("win32" || "uia") in 1-st list element + """ + Получить значение атрибута backend по PWA (pywinauto) селектору. Мы рекомендуем использовать метод UIOSelector_UIO_Get, так как UIO селектор обладает большей функциональностью. - :param inControlSpecificationArray: List of dict, dict in pywinauto.find_windows notation - :return: process application object - ''' + .. code-block:: python + + # UIDesktop: Взаимодействие с UI объектами приложений + from pyOpenRPA.Robot import UIDesktop + # 1С: UIO Селектор выбора базы + lDemoBaseUIOSelector = [{"title":"Запуск 1С:Предприятия","class_name":"V8TopLevelFrameTaxiStarter","backend":"uia"}] + lBackendStr = UIDesktop.PWASpecification_Get_PWAApplication(lDemoBaseUIOSelector) # Получить backend по PWA селектору + + :param inControlSpecificationArray: PWA селектор, который определяет критерии поиска UIO объекта + Допустимые ключи PWA селектора: + + - class_name содержимое атрибута class UIO объекта + - class_name_re содержимое атрибута class UIO объекта, которое удовлетворяет установленному рег. выражению + - process идентификатор процесса, в котором находится UIO объект + - title содержимое атрибута title UIO объекта + - title_re содержимое атрибута title UIO объекта, которое удовлетворяет установленному рег. выражению + - top_level_only признак поиска только на верхнем уровне приложения. По умолчанию True + - visible_only признак поиска только среди видимых UIO объектов. По умолчанию True + - enabled_only признак поиска только среди разблокированных UIO объектов. По умолчанию False + - best_match содержимое атрибута title UIO объекта максимально приближено к заданному + - handle идентификатор handle искомого UIO объекта + - ctrl_index индекс UIO объекта среди всех дочерних объектов в списке родительского + - found_index индекс UIO объекта среди всех обнаруженных + - predicate_func пользовательская функция проверки соответсвия UIO элемента + - active_only признак поиска только среди активных UIO объектов. По умолчанию False + - control_id идентификатор control_id искомого UIO объекта + - control_type тип элемента (применимо, если backend == "uia") + - auto_id идентификатор auto_id искомого UIO объекта (применимо, если backend == "uia") + - framework_id идентификатор framework_id искомого UIO объекта (применимо, если backend == "uia") + - backend вид технологии подключения к поиску UIO объекта ("uia" или "win32") + :type inControlSpecificationArray: list, обязательный + :return: "win32" или "uia" + """ inControlSpecificationArray=copy.deepcopy(inControlSpecificationArray) #Определение backend lBackend=mDefaultPywinautoBackend @@ -600,16 +734,23 @@ def PWASpecification_Get_PWAApplication(inControlSpecificationArray): #Скорректировано из-за недопонимания структуры lTempObject=lRPAApplication return lTempObject - -########################################################################################################### +#old: AutomationSearchMouseElement def UIOSelector_SearchChildByMouse_UIO(inElementSpecification): - ''' - UIOSelector (see description on the top of the document) - #old name - AutomationSearchMouseElement + """ + Инициировать визуальный поиск UIO объекта с помощью указателя мыши. При наведении указателя мыши UIO объект выделяется зеленой рамкой. Остановить режим поиска можно с помощью зажима клавиши ctrl left на протяжении нескольких секунд. После этого в веб окне студии будет отображено дерево расположения искомого UIO объекта. - :param inElementSpecification: UIOSelector of the UI Object - :return: pywinauto element wrapper instance or None - ''' + .. code-block:: python + + # UIDesktop: Взаимодействие с UI объектами приложений + from pyOpenRPA.Robot import UIDesktop + # 1С: UIO Селектор выбора базы + lDemoBaseUIOSelector = [{"title":"Запуск 1С:Предприятия","class_name":"V8TopLevelFrameTaxiStarter","backend":"uia"}] + lUIO = UIDesktop.UIOSelector_SearchChildByMouse_UIO(lDemoBaseUIOSelector) # Инициировать поиск дочернего UIO объекта, который расположен внутри lDemoBaseUIOSelector. + + :param inElementSpecification: UIO селектор, который определяет критерии поиска родительского UIO объекта, в котором будет производиться поиск дочернего UIO объекта + :type inElementSpecification: list, обязательный + :return: UIO объект или None (если UIO не был обнаружен) + """ lGUISearchElementSelected=None #Настройка - частота обновления подсвечивания lTimeSleepSeconds=0.4 @@ -647,15 +788,26 @@ def UIOSelector_SearchChildByMouse_UIO(inElementSpecification): #Вернуть результат поиска return lElementFoundedList -#################################################################################################### -#old name - AutomationSearchMouseElementHierarchy +#old: - AutomationSearchMouseElementHierarchy def UIOSelector_SearchChildByMouse_UIOTree(inUIOSelector): - ''' - !!!!Safe call is included (you can set activity and UIDesktop will choose the bitness and return the result)!!!!! + """ + Получить список уровней UIO объекта с указнием всех имеющихся атрибутов по входящему UIO селектору. + + !ВНИМАНИЕ! ДАННАЯ ФУНКЦИОНАЛЬНОСТЬ В АВТОМАТИЧЕСКОМ РЕЖИМЕ ПОДДЕРЖИВАЕТ ВСЕ РАЗРЯДНОСТИ ПРИЛОЖЕНИЙ (32|64), КОТОРЫЕ ЗАПУЩЕНЫ В СЕСИИ. PYTHON x64 ИМЕЕТ ВОЗМОЖНОСТЬ ВЗЗАИМОДЕЙСТВИЯ С x32 UIO ОБЪЕКТАМИ, НО МЫ РЕКОМЕНДУЕМ ДОПОЛНИТЕЛЬНО ИСПОЛЬЗОВАТЬ ИНТЕРПРЕТАТОР PYTHON x32 (ПОДРОБНЕЕ СМ. ФУНКЦИЮ Configure()) + + .. code-block:: python + + # UIDesktop: Взаимодействие с UI объектами приложений + from pyOpenRPA.Robot import UIDesktop + # 1С: UIO Селектор выбора базы + lDemoBaseUIOSelector = [{"title":"Запуск 1С:Предприятия","class_name":"V8TopLevelFrameTaxiStarter","backend":"uia"}] + lBackendStr = UIDesktop.UIOSelector_SearchChildByMouse_UIOTree(lDemoBaseUIOSelector) # Получить список атрибутов всех родительских элементов lDemoBaseUIOSelector. + + :param inUIOSelector: UIO селектор, который определяет UIO объект, для которого будет произведено извлечение всех атрибутов на всех уровнях. + :type inUIOSelector: list, обязательный + :return: list, список атрибутов на каждом уровне UIO объекта + """ - :param inUIOSelector: UIOSelector of the UI Object - :return: ? - ''' lItemInfo = [] #Check the bitness lSafeOtherProcess = UIOSelector_SafeOtherGet_Process(inUIOSelector) @@ -715,10 +867,24 @@ def UIOSelector_SearchChildByMouse_UIOTree(inUIOSelector): lItemInfo = lPIPEResponseDict["Result"] #Вернуть результат return lItemInfo -#################################################################################################### -#inElement- UIO (UI Object) #old name - PywinautoExtElementCtrlIndexGet def UIO_GetCtrlIndex_Int(inElement): + """ + Получить индекс UIO объекта inElement в списке родительского UIO объекта. + + .. code-block:: python + + # UIDesktop: Взаимодействие с UI объектами приложений + from pyOpenRPA.Robot import UIDesktop + # 1С: UIO Селектор выбора базы + lDemoBaseUIOSelector = [{"title":"Запуск 1С:Предприятия","class_name":"V8TopLevelFrameTaxiStarter","backend":"uia"}] + lUIO = UIDesktop.UIOSelector_Get_UIO(lDemoBaseUIOSelector) # Получить UIO объект по UIO селектору. + lUIOIndexInt = UIDesktop.UIO_GetCtrlIndex_Int(lUIO) # Получить индекс UIO объекта в списке у родительского UIO объекта. + + :param inElement: UIO объект, для которого требуется определить индекс в списке родительского UIO объекта. + :type inElement: list, обязательный + :return: int, индекс UIO объекта в списке родительского UIO объекта + """ lResult = None #Выполнить алгоритм, если есть Element if inElement is not None: @@ -747,12 +913,27 @@ def UIO_GetCtrlIndex_Int(inElement): #Вернуть результат return lResult -#################################################################################################### -# Get the UIO Info list for the selected criteria -#!!!!!Safe call is included (you can set activity and UIDesktop will choose the bitness and return the result)!!!!! -#inSpecificationList - UIOSelector -#old name - PywinautoExtElementsGetInfo +#old: - PywinautoExtElementsGetInfo def UIOSelector_Get_UIOInfoList (inUIOSelector, inElement=None): + """ + Техническая функция: Получить список параметров последних уровней UIO селектора по UIO объектам, которые удовлетворяют входящим inUIOSelector, поиск по которым будет производится от уровня inElement. + + !ВНИМАНИЕ! ДАННАЯ ФУНКЦИОНАЛЬНОСТЬ В АВТОМАТИЧЕСКОМ РЕЖИМЕ ПОДДЕРЖИВАЕТ ВСЕ РАЗРЯДНОСТИ ПРИЛОЖЕНИЙ (32|64), КОТОРЫЕ ЗАПУЩЕНЫ В СЕСИИ. PYTHON x64 ИМЕЕТ ВОЗМОЖНОСТЬ ВЗЗАИМОДЕЙСТВИЯ С x32 UIO ОБЪЕКТАМИ, НО МЫ РЕКОМЕНДУЕМ ДОПОЛНИТЕЛЬНО ИСПОЛЬЗОВАТЬ ИНТЕРПРЕТАТОР PYTHON x32 (ПОДРОБНЕЕ СМ. ФУНКЦИЮ Configure()) + + .. code-block:: python + + # UIDesktop: Взаимодействие с UI объектами приложений + from pyOpenRPA.Robot import UIDesktop + # 1С: UIO Селектор выбора базы + lDemoBaseUIOSelector = [{"title":"Запуск 1С:Предприятия","class_name":"V8TopLevelFrameTaxiStarter","backend":"uia"}] + lUIOInfoList = UIDesktop.UIOSelector_Get_UIOInfoList(lDemoBaseUIOSelector) # Получить словарь параметров по UIO селектору. + + :param inUIOSelector: UIO селектор, который определяет UIO объект, для которого будет произведено извлечение всех атрибутов на всех уровнях. + :type inUIOSelector: list, обязательный + :param inElement: UIO объект, от которого выполнить поиск дочерних UIO объектов по UIO селектору inUIOSelector. По умолчанию None - поиск среди всех приложений. + :type inElement: UIO объект, необязательный + :return: dict, пример: {"title":None,"rich_text":None,"process_id":None,"process":None,"handle":None,"class_name":None,"control_type":None,"control_id":None,"rectangle":{"left":None,"top":None,"right":None,"bottom":None}, 'runtime_id':None} + """ #Check the bitness lSafeOtherProcess = UIOSelector_SafeOtherGet_Process(inUIOSelector) if lSafeOtherProcess is None: @@ -778,17 +959,25 @@ def UIOSelector_Get_UIOInfoList (inUIOSelector, inElement=None): lResultList = lPIPEResponseDict["Result"] return lResultList -#################################################################################################### -#Try to restore (maximize) window, if it's was minimized -#(особенность uia backend - он не может прицепиться к окну, если оно свернуто) -#inSpecificationList - UIOSelector -#old name - PywinautoExtTryToRestore +#old: - PywinautoExtTryToRestore def UIOSelector_TryRestore_Dict(inSpecificationList): """ - Try to restore (maximize) window, if it's minimized. (!IMPORTANT! When use UIA framework minimized windows doesn't appear by the UIOSelector. You need to try restore windows and after that try to get UIO) + Восстановить окно приложения на экране по UIO селектору inSpecificationList, если оно было свернуто. Функция обернута в try .. except - ошибок не возникнет. + + !ВНИМАНИЕ! ДАННАЯ ФУНКЦИОНАЛЬНОСТЬ УЖЕ ИСПОЛЬЗУЕТСЯ В РЯДЕ ДРУГИХ ФУНКЦИЙ ТАК КАК АДРЕССАЦИЯ ПО UIA FRAMEWORK НЕДОСТУПНА, ЕСЛИ ПРИЛОЖЕНИЕ СВЕРНУТО. + + !ВНИМАНИЕ! ДАННАЯ ФУНКЦИОНАЛЬНОСТЬ В АВТОМАТИЧЕСКОМ РЕЖИМЕ ПОДДЕРЖИВАЕТ ВСЕ РАЗРЯДНОСТИ ПРИЛОЖЕНИЙ (32|64), КОТОРЫЕ ЗАПУЩЕНЫ В СЕСИИ. PYTHON x64 ИМЕЕТ ВОЗМОЖНОСТЬ ВЗЗАИМОДЕЙСТВИЯ С x32 UIO ОБЪЕКТАМИ, НО МЫ РЕКОМЕНДУЕМ ДОПОЛНИТЕЛЬНО ИСПОЛЬЗОВАТЬ ИНТЕРПРЕТАТОР PYTHON x32 (ПОДРОБНЕЕ СМ. ФУНКЦИЮ Configure()) + + .. code-block:: python + + # UIDesktop: Взаимодействие с UI объектами приложений + from pyOpenRPA.Robot import UIDesktop + # 1С: UIO Селектор выбора базы + lDemoBaseUIOSelector = [{"title":"Запуск 1С:Предприятия","class_name":"V8TopLevelFrameTaxiStarter","backend":"uia"}] + UIDesktop.UIOSelector_TryRestore_Dict(lDemoBaseUIOSelector) # Попытка восстановления свернутого окна по UIO селектору. - :param inSpecificationList: UIOSelector - List of items, which contains condition attributes - :return: + :param inSpecificationList: UIO селектор, который определяет UIO объект, для которого будет произведено извлечение всех атрибутов на всех уровнях. + :type inSpecificationList: list, обязательный """ lResult={} try: @@ -802,17 +991,24 @@ def UIOSelector_TryRestore_Dict(inSpecificationList): except Exception: True==False return lResult -#################################################################################################### -#Get the list of the UI object activities -#!!!!!Safe call is included (you can set activity and UIDesktop will choose the bitness and return the result)!!!!! -#inControlSpecificationArray - UIOSelector -#old name - ElementActionGetList + +#old: - ElementActionGetList def UIOSelector_Get_UIOActivityList (inUIOSelector): """ - Get the list of the UI object activities + Получить список доступных действий/функций по UIO селектору inUIOSelector. Описание возможных активностей см. ниже. + + !ВНИМАНИЕ! ДАННАЯ ФУНКЦИОНАЛЬНОСТЬ В АВТОМАТИЧЕСКОМ РЕЖИМЕ ПОДДЕРЖИВАЕТ ВСЕ РАЗРЯДНОСТИ ПРИЛОЖЕНИЙ (32|64), КОТОРЫЕ ЗАПУЩЕНЫ В СЕСИИ. PYTHON x64 ИМЕЕТ ВОЗМОЖНОСТЬ ВЗЗАИМОДЕЙСТВИЯ С x32 UIO ОБЪЕКТАМИ, НО МЫ РЕКОМЕНДУЕМ ДОПОЛНИТЕЛЬНО ИСПОЛЬЗОВАТЬ ИНТЕРПРЕТАТОР PYTHON x32 (ПОДРОБНЕЕ СМ. ФУНКЦИЮ Configure()) + + .. code-block:: python - :param inUIOSelector: UIOSelector - List of items, which contains condition attributes - :return: + # UIDesktop: Взаимодействие с UI объектами приложений + from pyOpenRPA.Robot import UIDesktop + # 1С: UIO Селектор выбора базы + lDemoBaseUIOSelector = [{"title":"Запуск 1С:Предприятия","class_name":"V8TopLevelFrameTaxiStarter","backend":"uia"}] + lActivityList = UIDesktop.UIOSelector_Get_UIOActivityList(lDemoBaseUIOSelector) # Получить список активностей по UIO селектору. + + :param inUIOSelector: UIO селектор, который определяет UIO объект, для которого будет представлен перечень доступных активностей. + :type inUIOSelector: list, обязательный """ #Check the bitness lSafeOtherProcess = UIOSelector_SafeOtherGet_Process(inUIOSelector) @@ -845,21 +1041,30 @@ def UIOSelector_Get_UIOActivityList (inUIOSelector): lResult = lPIPEResponseDict["Result"] return lResult -#################################################################################################### -#Run the activity in UIO (UI Object) -#!!!!!Safe call is included (you can set activity and UIDesktop will choose the bitness and return the result)!!!!! -#inUIOSelector -#inActionName - UIOActivity (name) from Pywinauto -#old name - ElementRunAction +#old: - ElementRunAction def UIOSelectorUIOActivity_Run_Dict(inUIOSelector, inActionName, inArgumentList=None, inkwArgumentObject=None): """ - Run the activity in UIO (UI Object) + Выполнить активность inActionName над UIO объектом, полученным с помощью UIO селектора inUIOSelector. Описание возможных активностей см. ниже. + + !ВНИМАНИЕ! ДАННАЯ ФУНКЦИОНАЛЬНОСТЬ В АВТОМАТИЧЕСКОМ РЕЖИМЕ ПОДДЕРЖИВАЕТ ВСЕ РАЗРЯДНОСТИ ПРИЛОЖЕНИЙ (32|64), КОТОРЫЕ ЗАПУЩЕНЫ В СЕСИИ. PYTHON x64 ИМЕЕТ ВОЗМОЖНОСТЬ ВЗЗАИМОДЕЙСТВИЯ С x32 UIO ОБЪЕКТАМИ, НО МЫ РЕКОМЕНДУЕМ ДОПОЛНИТЕЛЬНО ИСПОЛЬЗОВАТЬ ИНТЕРПРЕТАТОР PYTHON x32 (ПОДРОБНЕЕ СМ. ФУНКЦИЮ Configure()) - :param inUIOSelector: UIOSelector - List of items, which contains condition attributes - :param inActionName: UIOActivity (name) activity name string from Pywinauto - :param inArgumentList: - :param inkwArgumentObject: - :return: + .. code-block:: python + + # UIDesktop: Взаимодействие с UI объектами приложений + from pyOpenRPA.Robot import UIDesktop + # 1С: UIO Селектор выбора базы + lDemoBaseUIOSelector = [{"title":"Запуск 1С:Предприятия","class_name":"V8TopLevelFrameTaxiStarter","backend":"uia"}] + lActivityResult = UIDesktop.UIOSelectorUIOActivity_Run_Dict(lDemoBaseUIOSelector, "click") # выполнить действие над UIO объектом с помощью UIO селектора. + + :param inUIOSelector: UIO селектор, который определяет UIO объект, для которого будет представлен перечень доступных активностей. + :type inUIOSelector: list, обязательный + :param inActionName: наименование активности, которую требуется выполнить над UIO объектом + :type inActionName: str, обязательный + :param inArgumentList: список передаваемых неименованных аргументов в функцию inActionName + :type inArgumentList: list, необязательный + :param inkwArgumentObject: словарь передаваемых именованных аргументов в функцию inActionName + :type inkwArgumentObject: dict, необязательный + :return: возвращает результат запускаемой функции с наименованием inActionName над UIO объектом """ if inArgumentList is None: inArgumentList=[] # 2021 02 22 Minor fix by Ivan Maslov if inkwArgumentObject is None: inkwArgumentObject={} # 2021 02 22 Minor fix by Ivan Maslov @@ -905,16 +1110,57 @@ def UIOSelectorUIOActivity_Run_Dict(inUIOSelector, inActionName, inArgumentList= lResult = lPIPEResponseDict["Result"] return lResult -#################################################################################################### -#Get the UIO dict of the attributes -#!!!!!Safe call is included (you can set activity and UIDesktop will choose the bitness and return the result)!!!!! #old name - ElementGetInfo def UIOSelector_Get_UIOInfo(inUIOSelector): """ - Get the UIO dict of the attributes + Получить свойства UIO объекта (element_info), по заданному UIO селектору. Ниже представлен перечень возвращаемых свойств. + + Для backend = win32: + + - automation_id (int) + - class_name (str) + - control_id (int) + - control_type (str) + - full_control_type (str) + - enabled (bool) + - handle (int) + - name (str) + - parent (object/UIO) + - process_id (int) + - rectangle (object/rect) + - rich_text (str) + - visible (bool) + + Для backend = uia: - :param inUIOSelector: UIOSelector - List of items, which contains condition attributes - :return: + - automation_id (int) + - class_name (str) + - control_id (int) + - control_type (str) + - enabled (bool) + - framework_id (int) + - handle (int) + - name (str) + - parent (object/UIO) + - process_id (int) + - rectangle (object/rect) + - rich_text (str) + - runtime_id (int) + - visible (bool) + + !ВНИМАНИЕ! ДАННАЯ ФУНКЦИОНАЛЬНОСТЬ В АВТОМАТИЧЕСКОМ РЕЖИМЕ ПОДДЕРЖИВАЕТ ВСЕ РАЗРЯДНОСТИ ПРИЛОЖЕНИЙ (32|64), КОТОРЫЕ ЗАПУЩЕНЫ В СЕСИИ. PYTHON x64 ИМЕЕТ ВОЗМОЖНОСТЬ ВЗЗАИМОДЕЙСТВИЯ С x32 UIO ОБЪЕКТАМИ, НО МЫ РЕКОМЕНДУЕМ ДОПОЛНИТЕЛЬНО ИСПОЛЬЗОВАТЬ ИНТЕРПРЕТАТОР PYTHON x32 (ПОДРОБНЕЕ СМ. ФУНКЦИЮ Configure()) + + .. code-block:: python + + # UIDesktop: Взаимодействие с UI объектами приложений + from pyOpenRPA.Robot import UIDesktop + # 1С: UIO Селектор выбора базы + lDemoBaseUIOSelector = [{"title":"Запуск 1С:Предприятия","class_name":"V8TopLevelFrameTaxiStarter","backend":"uia"}] + lUIOElementInfoDict = UIDesktop.UIOSelector_Get_UIOInfo(lDemoBaseUIOSelector) #Получить свойства над UIO объектом с помощью UIO селектора. + + :param inUIOSelector: UIO селектор, который определяет UIO объект, для которого будет представлен перечень доступных активностей. + :type inUIOSelector: list, обязательный + :return: словарь свойств element_info: Пример {"control_id": ..., "process_id": ...} """ #Check the bitness lSafeOtherProcess = UIOSelector_SafeOtherGet_Process(inUIOSelector) @@ -945,12 +1191,28 @@ def UIOSelector_Get_UIOInfo(inUIOSelector): else: lResultList = lPIPEResponseDict["Result"] return lResultList -#################################################################################################### -#Search child UIO by the: Parent UIO, X, Y -#inHierarchyList: [{"index":<>,"element":<>}] - technical argument for internal purpose -#result -List of dict [{"index":<>,"element":<>}] -- list of element hierarchy specifications -#old name - GUISearchElementByRootXY +#old: - GUISearchElementByRootXY def UIOXY_SearchChild_ListDict(inRootElement,inX,inY,inHierarchyList=None): + """ + Техническая функция: Получить иерархию вложенности UIO объекта по заданным корневому UIO объекту, координатам X и Y. + + .. code-block:: python + + # UIDesktop: Взаимодействие с UI объектами приложений + from pyOpenRPA.Robot import UIDesktop + # 1С: UIO Селектор выбора базы + lDemoBaseUIOSelector = [{"title":"Запуск 1С:Предприятия","class_name":"V8TopLevelFrameTaxiStarter","backend":"uia"}] + lUIO = UIDesktop.UIOSelector_Get_UIO(lDemoBaseUIOSelector) # Получить UIO объект с помощью UIO селектора + lUIOHierarchyList = UIDesktop.UIOXY_SearchChild_ListDict(lUIO, 100, 200) # Получить UIO объект с помощью UIO селектора родительского элемента и координат X / Y + + :param inRootElement: родительский UIO объект, полученный ранее с помощью UIO селектора. + :type inRootElement: object UIO, обязательный + :param inX: родительский UIO объект, полученный ранее с помощью UIO селектора. + :type inX: int, обязательный + :param inY: родительский UIO объект, полученный ранее с помощью UIO селектора. + :type inY: int, обязательный + :return: Список словарей - уровней UIO объектов + """ if inHierarchyList is None: inHierarchyList = [] #Инициализация результирующего значения lResultElement = None @@ -1035,21 +1297,27 @@ def UIOXY_SearchChild_ListDict(inRootElement,inX,inY,inHierarchyList=None): False == False return lResultHierarchyList -################################################################################################### -#Get list of child UIO's by Parent UIOSelector -#!!!!!Safe call is included (you can set activity and UIDesktop will choose the bitness and return the result)!!!!! -#inControlSpecificationArray- UIOSelector -#old name - ElementGetChildElementList +#old: - ElementGetChildElementList def UIOSelector_GetChildList_UIOList(inUIOSelector=None, inBackend=mDefaultPywinautoBackend): """ - Get list of child UIO's by the parent UIOSelector + Получить список дочерних UIO объектов по входящему UIO селектору inUIOSelector. + + !ВНИМАНИЕ! ДАННАЯ ФУНКЦИОНАЛЬНОСТЬ В АВТОМАТИЧЕСКОМ РЕЖИМЕ ПОДДЕРЖИВАЕТ ВСЕ РАЗРЯДНОСТИ ПРИЛОЖЕНИЙ (32|64), КОТОРЫЕ ЗАПУЩЕНЫ В СЕСИИ. PYTHON x64 ИМЕЕТ ВОЗМОЖНОСТЬ ВЗЗАИМОДЕЙСТВИЯ С x32 UIO ОБЪЕКТАМИ, НО МЫ РЕКОМЕНДУЕМ ДОПОЛНИТЕЛЬНО ИСПОЛЬЗОВАТЬ ИНТЕРПРЕТАТОР PYTHON x32 (ПОДРОБНЕЕ СМ. ФУНКЦИЮ Configure()) - :param inUIOSelector: UIOSelector - List of items, which contains condition attributes - :param inBackend: "win32" or "uia" - :return: - """ + .. code-block:: python + # UIDesktop: Взаимодействие с UI объектами приложений + from pyOpenRPA.Robot import UIDesktop + # 1С: UIO Селектор выбора базы + lDemoBaseUIOSelector = [{"title":"Запуск 1С:Предприятия","class_name":"V8TopLevelFrameTaxiStarter","backend":"uia"}] + lUIOList = UIDesktop.UIOSelector_GetChildList_UIOList(lDemoBaseUIOSelector) # Получить список дочерних UIO объектов с помощью UIO селектора + :param inUIOSelector: родительский UIO объект, полученный ранее с помощью UIO селектора. + :type inUIOSelector: list, обязательный + :param inBackend: вид backend "win32" или "uia". По умолчанию mDefaultPywinautoBackend ("win32") + :type inBackend: str, необязательный + :return: список дочерних UIO объектов + """ if inUIOSelector is None: inUIOSelector = [] #mRobotLogger.info(f"File!!!!") #mRobotLogger.info(f"inSelector:{str(inUIOSelector)}, inBackend:{str(inBackend)}") @@ -1099,12 +1367,24 @@ def UIOSelector_GetChildList_UIOList(inUIOSelector=None, inBackend=mDefaultPywin lResultList = lPIPEResponseDict["Result"] return lResultList -#################################################################################################### -#Подготовить массив для обращшения к поиску элемементов -#inControlSpecificationArray - UIOSelector (can be dirty) -#old name 1 - ElementSpecificationArraySearchPrepare -#old name 2 - ElementSpecificationListNormalize +#old1: - ElementSpecificationArraySearchPrepare +#old2: - ElementSpecificationListNormalize def UIOSelector_SearchUIONormalize_UIOSelector (inControlSpecificationArray): + """ + Нормализовать UIO селектор для дальнейшего использования в функциях поиск UIO объекта. Если недопустимых атрибутов не присутствует, то оставить как есть. + + .. code-block:: python + + # UIDesktop: Взаимодействие с UI объектами приложений + from pyOpenRPA.Robot import UIDesktop + # 1С: UIO Селектор выбора базы + lDemoBaseUIOSelectorDitry = [{"title":"Запуск 1С:Предприятия","class_name":"V8TopLevelFrameTaxiStarter","backend":"uia"}] + lDemoBaseUIOSelectorClean = UIDesktop.UIOSelector_SearchUIONormalize_UIOSelector(lDemoBaseUIOSelectorDitry) # Очистить UIO селектор от недопустимых ключей для дальнейшего использования + + :param inControlSpecificationArray: UIO селектор, который определяет UIO объект, для которого будет представлен перечень доступных активностей. + :type inControlSpecificationArray: list, обязательный + :return: нормализованный UIO селектор + """ lResult=[] #Циклический обход for lSpecificationItem in inControlSpecificationArray: @@ -1172,12 +1452,25 @@ def UIOSelector_SearchUIONormalize_UIOSelector (inControlSpecificationArray): lResult.append(lSpecificationItemNew) #Вернуть результат return lResult -#################################################################################################### -#Подготовить массив для обращшения к поиску процесса (отличается от поиска элемента, тк данная функция нужна для нормализации спецификации для подключения к процессу с окнами) -#inControlSpecificationArray - UIOSelector (can be dirty) + #old name 1 - ElementSpecificationArraySearchPrepare #old name 2 - ElementSpecificationListNormalize def UIOSelector_SearchProcessNormalize_UIOSelector (inControlSpecificationArray): + """ + Нормализовать UIO селектор для дальнейшего использования в функциях поиска процесса, в котором находится искомый UIO объект. Если недопустимых атрибутов не присутствует, то оставить как есть. + + .. code-block:: python + + # UIDesktop: Взаимодействие с UI объектами приложений + from pyOpenRPA.Robot import UIDesktop + # 1С: UIO Селектор выбора базы + lDemoBaseUIOSelectorDitry = [{"title":"Запуск 1С:Предприятия","class_name":"V8TopLevelFrameTaxiStarter","backend":"uia"}] + lDemoBaseUIOSelectorClean = UIDesktop.UIOSelector_SearchProcessNormalize_UIOSelector(lDemoBaseUIOSelectorDitry) # Очистить UIO селектор от недопустимых ключей для дальнейшего использования + + :param inControlSpecificationArray: UIO селектор, который определяет UIO объект, для которого будет представлен перечень доступных активностей. + :type inControlSpecificationArray: list, обязательный + :return: нормализованный UIO селектор + """ lResult=[] #Циклический обход for lSpecificationItem in inControlSpecificationArray: @@ -1250,11 +1543,25 @@ def UIOSelector_SearchProcessNormalize_UIOSelector (inControlSpecificationArray) lResult.append(lSpecificationItemNew) #Вернуть результат return lResult -#################################################################################################### -#Transfer UI object element info (pywinauto) to UIOInfo (dict of attributes) -#inElementInfo - UIOEI -#old name - ElementInfoExportObject + +#old: - ElementInfoExportObject def UIOEI_Convert_UIOInfo(inElementInfo): + """ + Техническая функция: Дообогащение словаря с параметрами UIO объекта по заданному UIO.element_info + + .. code-block:: python + + # UIDesktop: Взаимодействие с UI объектами приложений + from pyOpenRPA.Robot import UIDesktop + # 1С: UIO Селектор выбора базы + lDemoBaseUIOSelector = [{"title":"Запуск 1С:Предприятия","class_name":"V8TopLevelFrameTaxiStarter","backend":"uia"}] + lUIO = UIDesktop.UIOSelector_Get_UIO(lDemoBaseUIOSelector) # Получить UIO объект по UIO селектору. + lUIOProcessInfoDict = UIDesktop.UIOEI_Convert_UIOInfo(lUIO.element_info) + + :param inElementInfo: экземпляр класса UIO.element_info, для которого требуется дообогатить словарь с параметрами (в дальнейшем можно использовать как элемент UIO селектора). + :type inElementInfo: object, обязательный + :return: dict, пример: {"title":None,"rich_text":None,"process_id":None,"process":None,"handle":None,"class_name":None,"control_type":None,"control_id":None,"rectangle":{"left":None,"top":None,"right":None,"bottom":None}, 'runtime_id':None} + """ #Подготовить выходную структуру данных lResult = {"title":None,"rich_text":None,"process_id":None,"process":None,"handle":None,"class_name":None,"control_type":None,"control_id":None,"rectangle":{"left":None,"top":None,"right":None,"bottom":None}, 'runtime_id':None} #Проверка name @@ -1322,10 +1629,21 @@ def UIOEI_Convert_UIOInfo(inElementInfo): #Вернуть результат return lResult -################################################################################################### -#Get list of top level -#old name - GetRootElementList +#old: - GetRootElementList def BackendStr_GetTopLevelList_UIOInfo(inBackend=mDefaultPywinautoBackend): + """ + Получить список UIOInfo словарей - процессы, которые запущены в рабочей сессии и готовы для взаимодействия с роботом через backend inBackend + + .. code-block:: python + + # UIDesktop: Взаимодействие с UI объектами приложений + from pyOpenRPA.Robot import UIDesktop + lAppList = UIDesktop.BackendStr_GetTopLevelList_UIOInfo() # Очистить UIO селектор от недопустимых ключей для дальнейшего использования + + :param inBackend: вид backend, который планируется использовать для взаимодействия с UIO объектами + :type inBackend: list, обязательный + :return: список UIOInfo словарей + """ #Получить список объектов lResultList=pywinauto.findwindows.find_elements(top_level_only=True,backend=inBackend) lResultList2=[] @@ -1334,16 +1652,23 @@ def BackendStr_GetTopLevelList_UIOInfo(inBackend=mDefaultPywinautoBackend): lResultList2.append(UIOEI_Convert_UIOInfo(lI)) return lResultList2 -################################################################################################### -#Highlight the UI object -#!!!!!Safe call is included (you can set activity and UIDesktop will choose the bitness and return the result)!!!!! -#old name - ElementDrawOutlineNew +#old: - ElementDrawOutlineNew def UIOSelector_Highlight(inUIOSelector): """ - Highlight (draw outline) the element (in app) by the UIO selector. + Подсветить на несколько секунд на экране зеленой рамкой UIO объект, который соответствует входящему UIO селектору inUIOSelector - :param inUIOSelector: UIOSelector - List of items, which contains condition attributes - :return: + !ВНИМАНИЕ! ДАННАЯ ФУНКЦИОНАЛЬНОСТЬ В АВТОМАТИЧЕСКОМ РЕЖИМЕ ПОДДЕРЖИВАЕТ ВСЕ РАЗРЯДНОСТИ ПРИЛОЖЕНИЙ (32|64), КОТОРЫЕ ЗАПУЩЕНЫ В СЕСИИ. PYTHON x64 ИМЕЕТ ВОЗМОЖНОСТЬ ВЗЗАИМОДЕЙСТВИЯ С x32 UIO ОБЪЕКТАМИ, НО МЫ РЕКОМЕНДУЕМ ДОПОЛНИТЕЛЬНО ИСПОЛЬЗОВАТЬ ИНТЕРПРЕТАТОР PYTHON x32 (ПОДРОБНЕЕ СМ. ФУНКЦИЮ Configure()) + + .. code-block:: python + + # UIDesktop: Взаимодействие с UI объектами приложений + from pyOpenRPA.Robot import UIDesktop + # 1С: UIO Селектор выбора базы + lDemoBaseUIOSelector = [{"title":"Запуск 1С:Предприятия","class_name":"V8TopLevelFrameTaxiStarter","backend":"uia"}] + UIDesktop.UIOSelector_Highlight(lDemoBaseUIOSelector) # Подсветить UIO объект по UIO селектору + + :param inUIOSelector: UIO селектор, который определяет UIO объект, для которого будет представлен перечень доступных активностей. + :type inUIOSelector: list, обязательный """ #Check the bitness lSafeOtherProcess = UIOSelector_SafeOtherGet_Process(inUIOSelector) @@ -1364,17 +1689,23 @@ def UIOSelector_Highlight(inUIOSelector): else: return lPIPEResponseDict["Result"] return True - -################################################################################################### -#inSpecificationArray - UIOSelector -#!!!!!Safe call is included (you can set activity and UIDesktop will choose the bitness and return the result)!!!!! -#old name - ElementDrawOutlineNewFocus +#old: - ElementDrawOutlineNewFocus def UIOSelector_FocusHighlight(inUIOSelector): """ - Set focus and highlight (draw outline) the element (in app) by the UIO selector. + Установить фокус и подсветить на несколько секунд на экране зеленой рамкой UIO объект, который соответствует входящему UIO селектору inUIOSelector + + !ВНИМАНИЕ! ДАННАЯ ФУНКЦИОНАЛЬНОСТЬ В АВТОМАТИЧЕСКОМ РЕЖИМЕ ПОДДЕРЖИВАЕТ ВСЕ РАЗРЯДНОСТИ ПРИЛОЖЕНИЙ (32|64), КОТОРЫЕ ЗАПУЩЕНЫ В СЕСИИ. PYTHON x64 ИМЕЕТ ВОЗМОЖНОСТЬ ВЗЗАИМОДЕЙСТВИЯ С x32 UIO ОБЪЕКТАМИ, НО МЫ РЕКОМЕНДУЕМ ДОПОЛНИТЕЛЬНО ИСПОЛЬЗОВАТЬ ИНТЕРПРЕТАТОР PYTHON x32 (ПОДРОБНЕЕ СМ. ФУНКЦИЮ Configure()) - :param inUIOSelector: UIOSelector - List of items, which contains condition attributes - :return: + .. code-block:: python + + # UIDesktop: Взаимодействие с UI объектами приложений + from pyOpenRPA.Robot import UIDesktop + # 1С: UIO Селектор выбора базы + lDemoBaseUIOSelector = [{"title":"Запуск 1С:Предприятия","class_name":"V8TopLevelFrameTaxiStarter","backend":"uia"}] + UIDesktop.UIOSelector_FocusHighlight(lDemoBaseUIOSelector) # Установить фокус и подсветить UIO объект по UIO селектору + + :param inUIOSelector: UIO селектор, который определяет UIO объект, для которого будет представлен перечень доступных активностей. + :type inUIOSelector: list, обязательный """ #Check the bitness @@ -1397,9 +1728,29 @@ def UIOSelector_FocusHighlight(inUIOSelector): return lPIPEResponseDict["Result"] return True -################################################################################################### -#old name - draw_outline_new +#old: - draw_outline_new def UIO_Highlight(lWrapperObject,colour='green',thickness=2,fill=win32defines.BS_NULL,rect=None,inFlagSetFocus=False): + """ + Выполнить подсветку UIO объекта на экране + + .. code-block:: python + + # UIDesktop: Взаимодействие с UI объектами приложений + from pyOpenRPA.Robot import UIDesktop + # 1С: UIO Селектор выбора базы + lDemoBaseUIOSelector = [{"title":"Запуск 1С:Предприятия","class_name":"V8TopLevelFrameTaxiStarter","backend":"uia"}] + lUIO = UIDesktop.UIOSelector_Get_UIO(lDemoBaseUIOSelector) # Получить UIO объект по UIO селектору + UIDesktop.UIO_Highlight(lUIO) # Подсветить UIO объект по UIO селектору зеленым цветом с толщиной подсветки 2 px. + + :param lWrapperObject: UIO объект, который будет подсвечен + :type lWrapperObject: object UIO, обязательный + :param colour: цвет подсветки UIO объекта. Варианты: 'red', 'green', 'blue'. По умолчанию 'green' + :type colour: str, необязательный + :param thickness: толщина подсветки UIO объекта. По умолчанию 2 + :type thickness: int, необязательный + :param inFlagSetFocus: признак установки фокуса на UIO объект перед подсветкой. По умолчанию False + :type inFlagSetFocus: bool, необязательный + """ if lWrapperObject is not None: """ Draw an outline around the window. @@ -1449,10 +1800,27 @@ def UIO_Highlight(lWrapperObject,colour='green',thickness=2,fill=win32defines.BS # delete the Display context that we created win32functions.DeleteDC(dc) -################################################################################################### -#Аналог подсвечивания + установка фокуса -#old name - draw_outline_new_focus +#old: - draw_outline_new_focus def UIO_FocusHighlight(lWrapperObject,colour='green',thickness=2,fill=win32defines.BS_NULL,rect=None): + """ + Установить фокус и выполнить подсветку UIO объекта на экране + + .. code-block:: python + + # UIDesktop: Взаимодействие с UI объектами приложений + from pyOpenRPA.Robot import UIDesktop + # 1С: UIO Селектор выбора базы + lDemoBaseUIOSelector = [{"title":"Запуск 1С:Предприятия","class_name":"V8TopLevelFrameTaxiStarter","backend":"uia"}] + lUIO = UIDesktop.UIOSelector_Get_UIO(lDemoBaseUIOSelector) # Получить UIO объект по UIO селектору + UIDesktop.UIO_FocusHighlight(lUIO) # Установить фокус и подсветить UIO объект по UIO селектору зеленым цветом с толщиной подсветки 2 px. + + :param lWrapperObject: UIO объект, который будет подсвечен + :type lWrapperObject: object UIO, обязательный + :param colour: цвет подсветки UIO объекта. Варианты: 'red', 'green', 'blue'. По умолчанию 'green' + :type colour: str, необязательный + :param thickness: толщина подсветки UIO объекта. По умолчанию 2 + :type thickness: int, необязательный + """ UIO_Highlight(lWrapperObject,'green',2,win32defines.BS_NULL,None,True) #Определить разрядность процесса diff --git a/Resources/WPy32-3720/python-3.7.2/Lib/site-packages/pyOpenRPA/__init__.py b/Resources/WPy32-3720/python-3.7.2/Lib/site-packages/pyOpenRPA/__init__.py index 8c4b3aa6..fc97568b 100644 --- a/Resources/WPy32-3720/python-3.7.2/Lib/site-packages/pyOpenRPA/__init__.py +++ b/Resources/WPy32-3720/python-3.7.2/Lib/site-packages/pyOpenRPA/__init__.py @@ -1,9 +1,9 @@ r""" -The OpenRPA package (from UnicodeLabs) +The pyOpenRPA package """ -__version__ = 'v1.2.12' +__version__ = 'v1.2.13' __all__ = [] -__author__ = 'Ivan Maslov ' +__author__ = 'Ivan Maslov ' #from .Core import Robot \ No newline at end of file diff --git a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/pyOpenRPA-1.2.12.dist-info/INSTALLER b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/pyOpenRPA-1.2.13.dist-info/INSTALLER similarity index 100% rename from Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/pyOpenRPA-1.2.12.dist-info/INSTALLER rename to Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/pyOpenRPA-1.2.13.dist-info/INSTALLER diff --git a/Resources/WPy32-3720/python-3.7.2/Lib/site-packages/pyOpenRPA-1.2.12.dist-info/METADATA b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/pyOpenRPA-1.2.13.dist-info/METADATA similarity index 99% rename from Resources/WPy32-3720/python-3.7.2/Lib/site-packages/pyOpenRPA-1.2.12.dist-info/METADATA rename to Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/pyOpenRPA-1.2.13.dist-info/METADATA index ee047299..be5fb345 100644 --- a/Resources/WPy32-3720/python-3.7.2/Lib/site-packages/pyOpenRPA-1.2.12.dist-info/METADATA +++ b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/pyOpenRPA-1.2.13.dist-info/METADATA @@ -1,6 +1,6 @@ Metadata-Version: 2.1 Name: pyOpenRPA -Version: 1.2.12 +Version: 1.2.13 Summary: First open source RPA platform for business Home-page: https://pyopenrpa.ru/ Author: Ivan Maslov diff --git a/Resources/WPy32-3720/python-3.7.2/Lib/site-packages/pyOpenRPA-1.2.12.dist-info/RECORD b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/pyOpenRPA-1.2.13.dist-info/RECORD similarity index 96% rename from Resources/WPy32-3720/python-3.7.2/Lib/site-packages/pyOpenRPA-1.2.12.dist-info/RECORD rename to Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/pyOpenRPA-1.2.13.dist-info/RECORD index 4f6a71f0..a559ce98 100644 --- a/Resources/WPy32-3720/python-3.7.2/Lib/site-packages/pyOpenRPA-1.2.12.dist-info/RECORD +++ b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/pyOpenRPA-1.2.13.dist-info/RECORD @@ -1,9 +1,9 @@ -pyOpenRPA-1.2.12.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4 -pyOpenRPA-1.2.12.dist-info/METADATA,sha256=AmdWISfrdsF9DvjBrn42JJUXBb-TLln5OFBWKxX0VaE,4111 -pyOpenRPA-1.2.12.dist-info/RECORD,, -pyOpenRPA-1.2.12.dist-info/REQUESTED,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 -pyOpenRPA-1.2.12.dist-info/WHEEL,sha256=qB97nP5e4MrOsXW5bIU5cUn_KSVr10EV0l-GCHG9qNs,97 -pyOpenRPA-1.2.12.dist-info/top_level.txt,sha256=RPzwQXgYBRo_m5L3ZLs6Voh8aEkMeT29Xsul1w1qE0g,10 +pyOpenRPA-1.2.13.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4 +pyOpenRPA-1.2.13.dist-info/METADATA,sha256=HrNqM4-bPHXjqazFT4215H6pPafnYdCqattouxZIzVc,4111 +pyOpenRPA-1.2.13.dist-info/RECORD,, +pyOpenRPA-1.2.13.dist-info/REQUESTED,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +pyOpenRPA-1.2.13.dist-info/WHEEL,sha256=qB97nP5e4MrOsXW5bIU5cUn_KSVr10EV0l-GCHG9qNs,97 +pyOpenRPA-1.2.13.dist-info/top_level.txt,sha256=RPzwQXgYBRo_m5L3ZLs6Voh8aEkMeT29Xsul1w1qE0g,10 pyOpenRPA/.idea/inspectionProfiles/profiles_settings.xml,sha256=YXLFmX7rPNGcnKK1uX1uKYPN0fpgskYNe7t0BV7cqkY,174 pyOpenRPA/.idea/misc.xml,sha256=V-fQnOz-bYEZULgfbFgm-8mURphZrKfXMSd0wKjeEyA,188 pyOpenRPA/.idea/modules.xml,sha256=Q__U1JIA2cjxbLRXAv-SfYY00fZA0TNlpkkbY4s3ncg,277 @@ -26,9 +26,9 @@ pyOpenRPA/LICENSE.pdf,sha256=HEqffy8FIWpylw0zF7k-Wgwd8ppWQT9s9EGBgKV-6G8,321175 pyOpenRPA/Orchestrator/BackwardCompatibility.py,sha256=ABr0RugbBsIGdL5GE_EFC9QndSaKjvrjawvluhUNuMY,37795 pyOpenRPA/Orchestrator/ControlPanel.py,sha256=OzS8HjG__8OZgqhajr8L8owyugXPuSLWHLtXuKdEP78,103 pyOpenRPA/Orchestrator/Core.py,sha256=OHa3mSC3_wRAizqrWBVjlR6ln4-xVVvBpOSnWl6qVvY,529 -pyOpenRPA/Orchestrator/Managers/ControlPanel.py,sha256=BgtLjb6PR6kTlOjPLCg2YGP458LS9JOaYEfNurhS0nk,16544 +pyOpenRPA/Orchestrator/Managers/ControlPanel.py,sha256=XpmN_LB--phNq4VpsbdWHJC6ybIt7jWBsl6HKfxHP1I,16550 pyOpenRPA/Orchestrator/Managers/Git.py,sha256=dgXx2UzSwiEev4ov2hBbb-5MhXVhFKWZo2lmr19QSCQ,12582 -pyOpenRPA/Orchestrator/Managers/Process.py,sha256=7T_qofdkRJHdPQbaiEsTDOboImSf2N6d_Ku513rURkw,41369 +pyOpenRPA/Orchestrator/Managers/Process.py,sha256=DYX1pBK4gaxcfmDj-1OaLNyk83D_R_7ztZyt0SHWoik,41377 pyOpenRPA/Orchestrator/Managers/__init__.py,sha256=4my0XiwmI_QLRQVhOzNvWTggCosF3tb2yRxGkehOCq0,71 pyOpenRPA/Orchestrator/Managers/__pycache__/ControlPanel.cpython-37.pyc,, pyOpenRPA/Orchestrator/Managers/__pycache__/Git.cpython-37.pyc,, @@ -81,7 +81,7 @@ pyOpenRPA/Orchestrator/Web/Index.js,sha256=YACiZAvjr6NmFlDhQu6urkJp49BX7L8WJU9p- pyOpenRPA/Orchestrator/Web/Index.xhtml,sha256=5JUAs5rEiU0XtHM9QO6EdNMBGt-W6QOVGY7xJ_HLPFM,19257 pyOpenRPA/Orchestrator/Web/__pycache__/Basic.cpython-37.pyc,, pyOpenRPA/Orchestrator/Web/favicon.ico,sha256=6S8XwSQ_3FXPpaX6zYkf8uUewVXO9bHnrrDHEoWrEgw,112922 -pyOpenRPA/Orchestrator/__Orchestrator__.py,sha256=Zud6HTAHSsfTJVrszML5EjGTqlA7k5qhthZTsSD1pX8,151055 +pyOpenRPA/Orchestrator/__Orchestrator__.py,sha256=rlM-j8LK4BdcPfI8KNMOi1Rq-Ht8kCLs6WYsPBZgDTU,203081 pyOpenRPA/Orchestrator/__init__.py,sha256=nJhjYtBXKOUNX_yNu1rRFk5y9cDz6AFiL0M6KgX_utQ,207 pyOpenRPA/Orchestrator/__main__.py,sha256=czJrc7_57WiO3EPIYfPeF_LG3pZsQVmuAYgbl_YXcVU,273 pyOpenRPA/Orchestrator/__pycache__/BackwardCompatibility.cpython-37.pyc,, @@ -270,15 +270,15 @@ pyOpenRPA/Resources/Web/Semantic-UI-CSS-master/themes/default/assets/fonts/outli pyOpenRPA/Resources/Web/Semantic-UI-CSS-master/themes/default/assets/images/flags.png,sha256=lNXH8WYTAcSm3Ekdct1VmgYgzZF6gm8N8bAju5bqnd0,28123 pyOpenRPA/Resources/Web/jQuery/jquery-3.1.1.min.js,sha256=HPMOWdIdSuVgr3FD9ZE-_MgiK8qk_MdQjrgCtfqp6U4,86713 pyOpenRPA/Resources/Web/pyOpenRPA_logo.png,sha256=7rulXo_C57xJQEaYWmAkChxXb6xbDW2zq-werzVbDbc,4899 -pyOpenRPA/Robot/Clipboard.py,sha256=q76X8L21zJwcwdoJJNPeCEwAV30xS6ylHP1WwvtxoWI,722 -pyOpenRPA/Robot/Keyboard.py,sha256=k_5uNh7UWq5F4TKGbe4LpJwqWgUrftNieWm51HOgOBI,22 -pyOpenRPA/Robot/Mouse.py,sha256=tBW9yteyEv9znJePOfbZcU3YqxX42wyu4Wc09fVaO0c,23 +pyOpenRPA/Robot/Clipboard.py,sha256=ntvXqnJpgmTPnehrjfVibrM72-AYLrqOn-CI2xVOaDs,1577 +pyOpenRPA/Robot/Keyboard.py,sha256=6Ah71EaETse2_nPiz8EPW_fZBlhpaZg5WZ6tWZ2wC9U,17898 +pyOpenRPA/Robot/Mouse.py,sha256=Wvai_tpanqREj5jA4tFEl_-0L45cpk41cX5_Ex68mBg,16079 pyOpenRPA/Robot/OrchestratorConnector.py,sha256=JUtdiUXCruqUqBD19gJBl9jk_b-tpWWx_v3MfBoKzoQ,20445 -pyOpenRPA/Robot/README.md,sha256=e2hKh7Tx6DAsX6jY_hBDhguL1L2Wiv6iugDB5otMzIA,2293 +pyOpenRPA/Robot/README.md,sha256=bwiTAygxuMZzBlwpsndw2QgxA2smIjUyOPZnsnR341k,1623 pyOpenRPA/Robot/Screen.py,sha256=tBW9yteyEv9znJePOfbZcU3YqxX42wyu4Wc09fVaO0c,23 pyOpenRPA/Robot/SettingsTemplate.py,sha256=Rp5XPeV2I4tCS2uf4Zkqm_ERJ6pZMg4-e5_lMqGJYLk,1453 pyOpenRPA/Robot/Test.py,sha256=qXr990nXiFZX5SNv6QN9GLb_U4HZRmJnbZR2qSnwilY,2878 -pyOpenRPA/Robot/UIDesktop.py,sha256=EllVup0umNNFqcQrrO6pffdoTBzc5Y-jEKrY0oO7joU,82938 +pyOpenRPA/Robot/UIDesktop.py,sha256=y0lHHtn-Cd7I1rUQGgBYfZQpfcrGBAfMST9F5aPIxtM,124815 pyOpenRPA/Robot/UIWeb.py,sha256=NFH0brDKEmWWOJxMzO7404K5lJ4LaDn5XMnkoH13Y64,22 pyOpenRPA/Robot/Utils/JSONNormalize.py,sha256=aIuVzuZDazhxkCOzoOjfhHVz66mp2FWdfPv5E7KWF5Y,3890 pyOpenRPA/Robot/Utils/ProcessBitness.py,sha256=WlKL-DklGaoTnchtapOTM_ydxSB4yOeo9lcG3zr2VME,4524 @@ -364,6 +364,6 @@ pyOpenRPA/Tools/__pycache__/License.cpython-37.pyc,, pyOpenRPA/Tools/__pycache__/StopSafe.cpython-37.pyc,, pyOpenRPA/Tools/__pycache__/Usage.cpython-37.pyc,, pyOpenRPA/Tools/__pycache__/__init__.cpython-37.pyc,, -pyOpenRPA/__init__.py,sha256=fmC6rG7L4TIer8c0qUyp-Ypv2d7C2TBucEjIg7Wwip4,175 +pyOpenRPA/__init__.py,sha256=Q9zi3T0F5hLslWv3SoO1EvZt17wEU5fq3JJ59uqdtg8,156 pyOpenRPA/__pycache__/__init__.cpython-37.pyc,, pyOpenRPA/test.txt,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 diff --git a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/pyOpenRPA-1.2.12.dist-info/REQUESTED b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/pyOpenRPA-1.2.13.dist-info/REQUESTED similarity index 100% rename from Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/pyOpenRPA-1.2.12.dist-info/REQUESTED rename to Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/pyOpenRPA-1.2.13.dist-info/REQUESTED diff --git a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/pyOpenRPA-1.2.12.dist-info/WHEEL b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/pyOpenRPA-1.2.13.dist-info/WHEEL similarity index 100% rename from Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/pyOpenRPA-1.2.12.dist-info/WHEEL rename to Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/pyOpenRPA-1.2.13.dist-info/WHEEL diff --git a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/pyOpenRPA-1.2.12.dist-info/top_level.txt b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/pyOpenRPA-1.2.13.dist-info/top_level.txt similarity index 100% rename from Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/pyOpenRPA-1.2.12.dist-info/top_level.txt rename to Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/pyOpenRPA-1.2.13.dist-info/top_level.txt diff --git a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/pyOpenRPA/Orchestrator/Managers/ControlPanel.py b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/pyOpenRPA/Orchestrator/Managers/ControlPanel.py index cef4acd4..599eed11 100644 --- a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/pyOpenRPA/Orchestrator/Managers/ControlPanel.py +++ b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/pyOpenRPA/Orchestrator/Managers/ControlPanel.py @@ -39,6 +39,7 @@ class ControlPanel(): Jinja2DataUpdateDictSet .. code-block:: html + Hello my control panel! You can use any def from Orchestrator module here in Jinja2 HTML template: Example: OrchestratorModule.OSCMD(inCMDStr="notepad") diff --git a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/pyOpenRPA/Orchestrator/Managers/Process.py b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/pyOpenRPA/Orchestrator/Managers/Process.py index 276e4adc..ff47c075 100644 --- a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/pyOpenRPA/Orchestrator/Managers/Process.py +++ b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/pyOpenRPA/Orchestrator/Managers/Process.py @@ -22,6 +22,7 @@ class Process(): - 5_STARTED_MANUAL .. code-block:: python + # For the safe init class use ProcessInitSafe lProcess = Orchestrator.Managers.ProcessInitSafe(inAgentHostNameStr="PCNAME",inAgentUserNameStr="USER", inProcessNameWOExeStr="notepad",inStartCMDStr="notepad",inStopSafeTimeoutSecFloat=3) @@ -35,6 +36,7 @@ class Process(): How to use StopSafe on the robot side .. code-block:: python + from pyOpenRPA.Tools import StopSafe StopSafe.Init(inLogger=None) StopSafe.IsSafeStop() # True - WM_CLOSE SIGNAL has come. taskkill /im someprocess.exe diff --git a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/pyOpenRPA/Orchestrator/__Orchestrator__.py b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/pyOpenRPA/Orchestrator/__Orchestrator__.py index b47d891d..dca95b25 100644 --- a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/pyOpenRPA/Orchestrator/__Orchestrator__.py +++ b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/pyOpenRPA/Orchestrator/__Orchestrator__.py @@ -41,13 +41,13 @@ gSettingsDict = None def AgentActivityItemAdd(inHostNameStr, inUserStr, inActivityItemDict, inGSettings=None): """ - Add activity in AgentDict. Check if item is created + Добавить активность в словарь активностей выбранного Агента - :param inGSettings: Global settings dict (singleton) - :param inHostNameStr: Agent host name - :param inUserStr: User login, where agent is based - :param inActivityItemDict: ActivityItem - :return: GUID String of the ActivityItem - you can wait (sync or async) result by this guid! + :param inGSettings: Глобальный словарь настроек Оркестратора (синглтон) + :param inHostNameStr: Наименование хоста, на котором запущен Агент. Наименования подключенных агентов доступно для просмотра в панели управления + :param inUserStr: Наименование пользователя, на графической сессии которого запущен Агент. Наименования подключенных агентов доступно для просмотра в панели управления + :param inActivityItemDict: Активность (ActivityItem). См. функцию ProcessorActivityitemCreate + :return: ГУИД (GUID) строка Активности (ActivityItem). Далее можно ожидать результат этой функции по ГУИД с помощью функции AgentActivityItemReturnGet """ inGSettings = GSettingsGet(inGSettings=inGSettings) # Set the global settings @@ -72,11 +72,11 @@ def AgentActivityItemAdd(inHostNameStr, inUserStr, inActivityItemDict, inGSettin def AgentActivityItemExists(inHostNameStr, inUserStr, inGUIDStr, inGSettings = None): """ - Check by GUID if ActivityItem has exists in request list. If exist - the result response has not been recieved from the agent + Выполнить проверку, что активность (ActivityItem) была отправлена на сторону Агента. - :param inGSettings: Global settings dict (singleton) - :param inGUIDStr: GUID String of the ActivityItem - :return: True - ActivityItem is exist in AgentDict ; False - else case + :param inGSettings: Глобальный словарь настроек Оркестратора (синглтон) + :param inGUIDStr: ГУИД (GUID) активности (ActivityItem) + :return: True - Активность присутствует ; False - Активность еще не была отправлена на сторону Агента """ # Check if GUID is exists in dict - has been recieved inGSettings = GSettingsGet(inGSettings=inGSettings) # Set the global settings @@ -92,11 +92,11 @@ def AgentActivityItemExists(inHostNameStr, inUserStr, inGUIDStr, inGSettings = N def AgentActivityItemReturnExists(inGUIDStr, inGSettings = None): """ - Check by GUID if ActivityItem has been executed and result has come to the Orchestrator + Выполнить проверку, что активность (ActivityItem) была выполнена на стороне Агента и результат был получен на стороне Оркестратора. - :param inGSettings: Global settings dict (singleton) - :param inGUIDStr: GUID String of the ActivityItem - you can wait (sync or async) result by this guid! - :return: True - result has been received from the Agent to orc; False - else case + :param inGSettings: Глобальный словарь настроек Оркестратора (синглтон) + :param inGUIDStr: ГУИД (GUID) активности (ActivityItem) + :return: True - Активность присутствует; False - Активность еще не была выполнена на стороне Агента """ inGSettings = GSettingsGet(inGSettings=inGSettings) # Set the global settings @@ -106,14 +106,15 @@ def AgentActivityItemReturnExists(inGUIDStr, inGSettings = None): def AgentActivityItemReturnGet(inGUIDStr, inCheckIntervalSecFloat = 0.5, inGSettings=None): """ - Work synchroniously! Wait while result will be recieved. Get the result of the ActivityItem execution on the Agent side. Before this please check by the def AgentActivityItemReturnExists that result has come to the Orchestrator - - !ATTENTION! Use only after Orchestrator initialization! Before orchestrator init exception will be raised. + Ожидает появления результата по активности (ActivityItem). Возвращает результат выполнения активности. + + !ВНИМАНИЕ! Замораживает поток, пока не будет получен результат. + !ВНИМАНИЕ! Запускать следует после того как будет инициализировано ядро Оркестратора (см. функцию OrchestratorInitWait), иначе будет инициирована ошибка. - :param inGSettings: Global settings dict (singleton) - :param inGUIDStr: GUID String of the ActivityItem - you can wait (sync or async) result by this guid! - :param inCheckIntervalSecFloat: Interval in sec of the check Activity Item result - :return: Result of the ActivityItem executed on the Agent side anr transmitted to the Orchestrator. IMPORTANT! ONLY JSON ENABLED Types CAN BE TRANSMITTED TO ORCHESTRATOR! + :param inGSettings: Глобальный словарь настроек Оркестратора (синглтон) + :param inGUIDStr: ГУИД (GUID) активности (ActivityItem) + :param inCheckIntervalSecFloat: Интервал в секундах, с какой частотой выполнять проверку результата. По умолчанию 0.5 + :return: Результат выполнения активности. !ВНИМАНИЕ! Возвращаются только то результаты, которые могут быть интерпретированы в JSON формате. """ inGSettings = GSettingsGet(inGSettings=inGSettings) # Set the global settings #Check if Orchestrator has been initialized - else raise exception @@ -128,17 +129,17 @@ def AgentActivityItemReturnGet(inGUIDStr, inCheckIntervalSecFloat = 0.5, inGSett def AgentOSCMD(inHostNameStr, inUserStr, inCMDStr, inRunAsyncBool=True, inSendOutputToOrchestratorLogsBool=True, inCMDEncodingStr="cp1251", inGSettings=None, inCaptureBool=True): """ - Send CMD to OS thought the pyOpenRPA.Agent daemon. Result return to log + Orchestrator by the A2O connection + Отправка команды командной строки на сессию, где работает pyOpenRPA.Agent. Результат выполнения команды можно выводить в лог оркестратора. - :param inGSettings: Global settings dict (singleton) - :param inHostNameStr: Agent host name in upper case (example "RPA01", "RPA_99" and so on). Active agent session you can see on the orchestrator dashboard as Orchestrator admin - :param inUserStr: Agent user name in upper case (example "UserRPA"). Active agent session you can see on the orchestrator dashboard as Orchestrator admin - :param inCMDStr: command to execute on the Agent session - :param inRunAsyncBool: True - Agent processor don't wait execution; False - Agent processor wait cmd execution - :param inSendOutputToOrchestratorLogsBool: True - catch cmd execution output and send it to the Orchestrator logs; Flase - else case; Default True - :param inCMDEncodingStr: Set the encoding of the DOS window on the Agent server session. Windows is beautiful :) . Default is "cp1251" early was "cp866" - need test - :param inCaptureBool: !ATTENTION! If you need to start absolutely encapsulated app - set this flag as False. If you set True - the app output will come to Agent - :return: GUID String of the ActivityItem - you can wait (sync or async) result by this guid! + :param inGSettings: Глобальный словарь настроек Оркестратора (синглтон) + :param inHostNameStr: Наименование хоста, на котором запущен Агент. Наименования подключенных агентов доступно для просмотра в панели управления + :param inUserStr: Наименование пользователя, на графической сессии которого запущен Агент. Наименования подключенных агентов доступно для просмотра в панели управления + :param inCMDStr: Команда для исполнения на стороне сессии Агента + :param inRunAsyncBool: True - Агент не ожидает окончания выполнения команды. !ВНИМАНИЕ! Логирование в такой ситуации будет невозможно; False - Агент ожидает окончания выполнения операции. + :param inSendOutputToOrchestratorLogsBool: True - отправлять весь вывод от команды в логи Оркестратора; Flase - Не отправлять; Default True + :param inCMDEncodingStr: Кодировка DOS среды, в которой исполняется команда. Если некорректно установить кодировку - русские символы будут испорчены. По умолчанию установлена "cp1251" + :param inCaptureBool: True - не запускать приложение как отдельное. Результат выполнения команды будет выводиться в окне Агента (если окно Агента присутствует на экране). False - команда будет запущена в отдельном DOS окне. + :return: ГУИД (GUID) строка Активности (ActivityItem). Далее можно ожидать результат этой функции по ГУИД с помощью функции AgentActivityItemReturnGet """ inGSettings = GSettingsGet(inGSettings=inGSettings) # Set the global settings lActivityItemDict = { @@ -153,9 +154,11 @@ def AgentOSCMD(inHostNameStr, inUserStr, inCMDStr, inRunAsyncBool=True, inSendOu def AgentOSLogoff(inHostNameStr, inUserStr): """ - Logoff the agent user session + Выполнить операцию logoff на стороне пользователя. - :return: GUID String of the ActivityItem - you can wait (sync or async) result by this guid! + :param inHostNameStr: Наименование хоста, на котором запущен Агент. Наименования подключенных агентов доступно для просмотра в панели управления + :param inUserStr: Наименование пользователя, на графической сессии которого запущен Агент. Наименования подключенных агентов доступно для просмотра в панели управления + :return: ГУИД (GUID) строка Активности (ActivityItem). Далее можно ожидать результат этой функции по ГУИД с помощью функции AgentActivityItemReturnGet """ inGSettings = GSettingsGet() # Set the global settings lCMDStr = "shutdown /l" @@ -171,16 +174,17 @@ def AgentOSLogoff(inHostNameStr, inUserStr): def AgentOSFileSend(inHostNameStr, inUserStr, inOrchestratorFilePathStr, inAgentFilePathStr, inGSettings = None): """ - Send the file from the Orchestrator to Agent (synchroniously) pyOpenRPA.Agent daemon process (safe for JSON transmition). - Work safety with big files - Thread safe - you can call def even if you dont init the orchestrator - def will be executed later + Отправить файл по адресу inOrchestratorFilePathStr со стороны Оркестратора и сохранить по адресу inAgentFilePathStr на стороне Агента. + Поддерживает передачу крупных файлов (более 2-х Гб.). Функция является синхронной - не закончит свое выполнение, пока файл не будет передан полностью. - :param inGSettings: Global settings dict (singleton) - :param inHostNameStr: - :param inUserStr: - :param inFilePathStr: - :param inFileDataBytes: - :return: GUID String of the ActivityItem - you can wait (sync or async) result by this guid! + !ВНИМАНИЕ - ПОТОКОБЕЗОПАСНАЯ! Вы можете вызвать эту функцию до инициализации ядра Оркестратора. Оркестратор добавит эту функцию в процессорную очередь на исполение. Если вам нужен результат функции, то необходимо сначала убедиться в том, что ядро Оркестратора было инициализированно (см. функцию OrchestratorInitWait). + + :param inHostNameStr: Наименование хоста, на котором запущен Агент. Наименования подключенных агентов доступно для просмотра в панели управления + :param inUserStr: Наименование пользователя, на графической сессии которого запущен Агент. Наименования подключенных агентов доступно для просмотра в панели управления + :param inOrchestratorFilePathStr: Полный путь к передаваемому файлу на стороне Оркестратора. + :param inAgentFilePathStr: Полный путь к локации, в которую требуется сохранить передаваемый файл. + :param inGSettings: Глобальный словарь настроек Оркестратора (синглтон) + :return: ГУИД (GUID) строка Активности (ActivityItem). Далее можно ожидать результат этой функции по ГУИД с помощью функции AgentActivityItemReturnGet """ inGSettings = GSettingsGet(inGSettings=inGSettings) # Set the global settings @@ -237,14 +241,14 @@ def AgentOSFileSend(inHostNameStr, inUserStr, inOrchestratorFilePathStr, inAgent def AgentOSFileBinaryDataBytesCreate(inHostNameStr, inUserStr, inFilePathStr, inFileDataBytes, inGSettings=None): """ - Create binary file by the base64 string by the pyOpenRPA.Agent daemon process (safe for JSON transmition) + Создать бинарный файл, который будет расположен по адресу inFilePathStr на стороне Агента с содержимым inFileDataBytes - :param inGSettings: Global settings dict (singleton) - :param inHostNameStr: - :param inUserStr: - :param inFilePathStr: - :param inFileDataBytes: - :return: GUID String of the ActivityItem - you can wait (sync or async) result by this guid! + :param inHostNameStr: Наименование хоста, на котором запущен Агент. Наименования подключенных агентов доступно для просмотра в панели управления + :param inUserStr: Наименование пользователя, на графической сессии которого запущен Агент. Наименования подключенных агентов доступно для просмотра в панели управления + :param inFilePathStr: Полный путь к сохраняемому файлу на стороне Агента. + :param inFileDataBytes: Строка байт (b'') для отправки в создаваемый файл на стороне Агента. + :param inGSettings: Глобальный словарь настроек Оркестратора (синглтон) + :return: ГУИД (GUID) строка Активности (ActivityItem). Далее можно ожидать результат этой функции по ГУИД с помощью функции AgentActivityItemReturnGet """ inGSettings = GSettingsGet(inGSettings=inGSettings) # Set the global settings lFileDataBase64Str = base64.b64encode(inFileDataBytes).decode("utf-8") @@ -261,14 +265,14 @@ def AgentOSFileBinaryDataBytesCreate(inHostNameStr, inUserStr, inFilePathStr, in def AgentOSFileBinaryDataBase64StrCreate(inHostNameStr, inUserStr, inFilePathStr, inFileDataBase64Str, inGSettings=None): """ - Create binary file by the base64 string by the pyOpenRPA.Agent daemon process (safe for JSON transmission) - - :param inGSettings: Global settings dict (singleton) - :param inHostNameStr: - :param inUserStr: - :param inFilePathStr: - :param inFileDataBase64Str: - :return: GUID String of the ActivityItem - you can wait (sync or async) result by this guid! + Создать бинарный файл, который будет расположен по адресу inFilePathStr на стороне Агента с содержимым, декодированным с формата base64: inFileDataBase64Str + + :param inHostNameStr: Наименование хоста, на котором запущен Агент. Наименования подключенных агентов доступно для просмотра в панели управления + :param inUserStr: Наименование пользователя, на графической сессии которого запущен Агент. Наименования подключенных агентов доступно для просмотра в панели управления + :param inFilePathStr: Полный путь к сохраняемому файлу на стороне Агента. + :param inFileDataBase64Str: Строка в формате base64 для отправки в создаваемый файл на стороне Агента. + :param inGSettings: Глобальный словарь настроек Оркестратора (синглтон) + :return: ГУИД (GUID) строка Активности (ActivityItem). Далее можно ожидать результат этой функции по ГУИД с помощью функции AgentActivityItemReturnGet """ inGSettings = GSettingsGet(inGSettings=inGSettings) # Set the global settings lActivityItemDict = { @@ -284,14 +288,14 @@ def AgentOSFileBinaryDataBase64StrCreate(inHostNameStr, inUserStr, inFilePathStr def AgentOSFileBinaryDataBase64StrAppend(inHostNameStr, inUserStr, inFilePathStr, inFileDataBase64Str, inGSettings = None): """ - Append binary file by the base64 string by the pyOpenRPA.Agent daemon process (safe for JSON transmission) - - :param inGSettings: Global settings dict (singleton) - :param inHostNameStr: - :param inUserStr: - :param inFilePathStr: - :param inFileDataBase64Str: - :return: GUID String of the ActivityItem - you can wait (sync or async) result by this guid! + Добавить бинарную информацию в существующий бинарный файл, который будет расположен по адресу inFilePathStr на стороне Агента с содержимым, декодированным с формата base64: inFileDataBase64Str + + :param inHostNameStr: Наименование хоста, на котором запущен Агент. Наименования подключенных агентов доступно для просмотра в панели управления + :param inUserStr: Наименование пользователя, на графической сессии которого запущен Агент. Наименования подключенных агентов доступно для просмотра в панели управления + :param inFilePathStr: Полный путь к сохраняемому файлу на стороне Агента. + :param inFileDataBase64Str: Строка в формате base64 для отправки в создаваемый файл на стороне Агента. + :param inGSettings: Глобальный словарь настроек Оркестратора (синглтон) + :return: ГУИД (GUID) строка Активности (ActivityItem). Далее можно ожидать результат этой функции по ГУИД с помощью функции AgentActivityItemReturnGet """ inGSettings = GSettingsGet(inGSettings=inGSettings) # Set the global settings lActivityItemDict = { @@ -308,15 +312,15 @@ def AgentOSFileBinaryDataBase64StrAppend(inHostNameStr, inUserStr, inFilePathStr # Send text file to Agent (string) def AgentOSFileTextDataStrCreate(inHostNameStr, inUserStr, inFilePathStr, inFileDataStr, inEncodingStr = "utf-8",inGSettings=None): """ - Create text file by the string by the pyOpenRPA.Agent daemon process - - :param inGSettings: Global settings dict (singleton) - :param inHostNameStr: - :param inUserStr: - :param inFilePathStr: - :param inFileDataStr: - :param inEncodingStr: - :return: GUID String of the ActivityItem - you can wait (sync or async) result by this guid! + Создать текстовый файл, который будет расположен по адресу inFilePathStr на стороне Агента с содержимым inFileDataStr в кодировке inEncodingStr + + :param inHostNameStr: Наименование хоста, на котором запущен Агент. Наименования подключенных агентов доступно для просмотра в панели управления + :param inUserStr: Наименование пользователя, на графической сессии которого запущен Агент. Наименования подключенных агентов доступно для просмотра в панели управления + :param inFilePathStr: Полный путь к сохраняемому файлу на стороне Агента. + :param inFileDataStr: Строка для отправки в создаваемый файл на стороне Агента. + :param inEncodingStr: Кодировка текстового файла. По умолчанию utf-8 + :param inGSettings: Глобальный словарь настроек Оркестратора (синглтон) + :return: ГУИД (GUID) строка Активности (ActivityItem). Далее можно ожидать результат этой функции по ГУИД с помощью функции AgentActivityItemReturnGet """ inGSettings = GSettingsGet(inGSettings=inGSettings) # Set the global settings lActivityItemDict = { @@ -331,13 +335,13 @@ def AgentOSFileTextDataStrCreate(inHostNameStr, inUserStr, inFilePathStr, inFile def AgentOSFileBinaryDataBase64StrReceive(inHostNameStr, inUserStr, inFilePathStr, inGSettings = None): """ - Read binary file and encode in base64 to transmit (safe for JSON transmition) + Выполнить чтение бинарного файла и получить содержимое в формате base64 (строка) - :param inGSettings: Global settings dict (singleton) - :param inHostNameStr: - :param inUserStr: - :param inFilePathStr: File path to read - :return: GUID String of the ActivityItem - you can wait (sync or async) result by this guid! + :param inHostNameStr: Наименование хоста, на котором запущен Агент. Наименования подключенных агентов доступно для просмотра в панели управления + :param inUserStr: Наименование пользователя, на графической сессии которого запущен Агент. Наименования подключенных агентов доступно для просмотра в панели управления + :param inFilePathStr: Путь к бинарному файлу на чтение на стороне Агента + :param inGSettings: Глобальный словарь настроек Оркестратора (синглтон) + :return: ГУИД (GUID) строка Активности (ActivityItem). Далее можно ожидать результат этой функции по ГУИД с помощью функции AgentActivityItemReturnGet """ inGSettings = GSettingsGet(inGSettings=inGSettings) # Set the global settings lActivityItemDict = { @@ -353,13 +357,14 @@ def AgentOSFileBinaryDataBase64StrReceive(inHostNameStr, inUserStr, inFilePathSt def AgentOSFileBinaryDataReceive(inHostNameStr, inUserStr, inFilePathStr): """ - Read binary file from agent (synchronious) - - :param inGSettings: Global settings dict (singleton) - :param inHostNameStr: - :param inUserStr: - :param inFilePathStr: File path to read - :return: file data bytes + Чтение бинарного файла на стороне Агента по адресу inFilePathStr. + + !ВНИМАНИЕ - СИНХРОННАЯ! Функция не завершится, пока не будет получен результат чтения на стороне Агента. + + :param inHostNameStr: Наименование хоста, на котором запущен Агент. Наименования подключенных агентов доступно для просмотра в панели управления + :param inUserStr: Наименование пользователя, на графической сессии которого запущен Агент. Наименования подключенных агентов доступно для просмотра в панели управления + :param inFilePathStr: Путь к бинарному файлу, который требуется прочитать на стороне Агента + :return: Строка байт (b'') - содержимое бинарного файла """ lFileDataBytes = None inGSettings = GSettingsGet() # Set the global settings @@ -391,14 +396,16 @@ def AgentOSFileBinaryDataReceive(inHostNameStr, inUserStr, inFilePathStr): def AgentOSFileTextDataStrReceive(inHostNameStr, inUserStr, inFilePathStr, inEncodingStr="utf-8", inGSettings = None): """ - Read text file in the agent GUI session - - :param inGSettings: Global settings dict (singleton) - :param inHostNameStr: - :param inUserStr: - :param inFilePathStr: File path to read - :param inEncodingStr: Text file encoding. Default 'utf-8' - :return: GUID String of the ActivityItem - you can wait (sync or async) result by this guid! + Чтение текстового файла на стороне Агента по адресу inFilePathStr. По ГИУД с помощью функции AgentActivityItemReturnGet можно будет получить текстовую строку данных, которые были расположены в файле. + + !ВНИМАНИЕ - АСИНХРОННАЯ! Функция завершится сразу, не дожидаясь окончания выполнения операции на стороне Агента. + + :param inHostNameStr: Наименование хоста, на котором запущен Агент. Наименования подключенных агентов доступно для просмотра в панели управления + :param inUserStr: Наименование пользователя, на графической сессии которого запущен Агент. Наименования подключенных агентов доступно для просмотра в панели управления + :param inFilePathStr: Путь к бинарному файлу, который требуется прочитать на стороне Агента + :param inEncodingStr: Кодировка текстового файла. По умолчанию utf-8 + :param inGSettings: Глобальный словарь настроек Оркестратора (синглтон) + :return: ГУИД (GUID) строка Активности (ActivityItem). Далее можно ожидать результат этой функции по ГУИД с помощью функции AgentActivityItemReturnGet """ inGSettings = GSettingsGet(inGSettings=inGSettings) # Set the global settings lActivityItemDict = { @@ -413,12 +420,14 @@ def AgentOSFileTextDataStrReceive(inHostNameStr, inUserStr, inFilePathStr, inEnc def AgentProcessWOExeUpperUserListGet(inHostNameStr, inUserStr, inGSettings = None): """ - Return the process list only for the current user (where Agent is running) without .EXE in upper case. Can use in ActivityItem from Orchestrator to Agent + Получить список процессов, которые выполняется на сессии Агента. Все процессы фиксируются без постфикса .exe, а также в верхнем регистре. + + ПРИМЕР РЕЗУЛЬТАТА, КОТОРЫЙ МОЖНО ПОЛУЧИТЬ ПО ГУИД ЧЕРЕЗ ФУНКЦИЮ AgentActivityItemReturnGet: ["ORCHESTRATOR", "AGENT", "CHROME", "EXPLORER", ...] - :param inGSettings: Global settings dict (singleton) - :param inHostNameStr: - :param inUserStr: - :return: GUID String of the ActivityItem - you can wait (sync or async) result by this guid! + :param inGSettings: Глобальный словарь настроек Оркестратора (синглтон) + :param inHostNameStr: Наименование хоста, на котором запущен Агент. Наименования подключенных агентов доступно для просмотра в панели управления + :param inUserStr: Наименование пользователя, на графической сессии которого запущен Агент. Наименования подключенных агентов доступно для просмотра в панели управления + :return: ГУИД (GUID) строка Активности (ActivityItem). Далее можно ожидать результат этой функции по ГУИД с помощью функции AgentActivityItemReturnGet """ inGSettings = GSettingsGet(inGSettings=inGSettings) # Set the global settings lActivityItemDict = { @@ -432,22 +441,22 @@ def AgentProcessWOExeUpperUserListGet(inHostNameStr, inUserStr, inGSettings = No return AgentActivityItemAdd(inGSettings=inGSettings, inHostNameStr=inHostNameStr, inUserStr=inUserStr, inActivityItemDict=lActivityItemDict) # OS DEFS - def OSLogoff(): """ - Logoff the current orchestrator session + Выполнить отключение сессии, на которой выполняется Оркестратор. + :return: """ os.system("shutdown /l") def OSCredentialsVerify(inUserStr, inPasswordStr, inDomainStr=""): ## """ - Verify user credentials in windows. Return bool + Выполнить верификацию доменного (локального) пользователя по паре логин/пароль - :param inUserStr: - :param inPasswordStr: - :param inDomainStr: - :return: True - Credentials are actual; False - Credentials are not actual + :param inUserStr: Наименование пользователя + :param inPasswordStr: Пароль + :param inDomainStr: Домен. Если домена нет - не указывать или "" + :return: True - Учетные данные верны; False - Учетные данные представлены некорректно """ try: hUser = win32security.LogonUser( @@ -461,12 +470,13 @@ def OSCredentialsVerify(inUserStr, inPasswordStr, inDomainStr=""): ## def OSRemotePCRestart(inHostStr, inForceBool=True, inLogger = None): """ - Send signal via power shell to restart remote PC - ATTENTION: Orchestrator user need to have restart right on the Remote machine to restart PC. + Отправить сигнал на удаленную перезагрузку операционной системы. + + !ВНИМАНИЕ! Перезапуск будет принят, если учетная запись имеет полномочия на перезапуск на соответсвующей машине. - :param inLogger: logger to log powershell result in logs - :param inHostStr: PC hostname which you need to restart. - :param inForceBool: True - send signal to force retart PC; False - else case + :param inHostStr: Имя хоста, который требуется перезагрузить + :param inForceBool: True - принудительная перезагрузка; False - мягкая перезагрузка (дождаться окончания выполнения всех операций). По умолчанию True + :param inLogger: Логгер, в который отправлять информацию о результате выполнения команды :return: """ if inLogger is None: inLogger = OrchestratorLoggerGet() @@ -476,12 +486,12 @@ def OSRemotePCRestart(inHostStr, inForceBool=True, inLogger = None): def OSCMD(inCMDStr, inRunAsyncBool=True, inLogger = None): """ - OS send command in shell locally + Отправить команду на выполнение на сессию, где выполняется Оркестратор. - :param inCMDStr: - :param inRunAsyncBool: - :param inLogger: - :return: CMD result string + :param inCMDStr: Команда на отправку + :param inRunAsyncBool: True - выполнить команду в асинхронном режиме (не дожидаться окончания выполнения программы и не захватывать результат выполнения); False - Ждать окончания выполнения и захватывать результат + :param inLogger: Логгер, в который отправлять информацию о результате выполнения команды + :return: Строка результата выполнения команды. Если inRunAsyncBool = False """ if inLogger is None: inLogger = OrchestratorLoggerGet() lResultStr = "" @@ -521,9 +531,9 @@ def OSCMD(inCMDStr, inRunAsyncBool=True, inLogger = None): def OrchestratorRestart(inGSettings=None): """ - Orchestrator restart + Перезапуск Оркестратора с сохранением информации о запущенных RDP сессиях. - :param inGSettings: Global settings dict (singleton) + :param inGSettings: Глобальный словарь настроек Оркестратора (синглтон) """ inGSettings = GSettingsGet(inGSettings=inGSettings) # Set the global settings OrchestratorSessionSave(inGSettings=inGSettings) # Dump RDP List in file json @@ -536,27 +546,27 @@ def OrchestratorRestart(inGSettings=None): def OrchestratorLoggerGet() -> logging.Logger: """ - Get the logger from the Orchestrator + Получить логгер Оркестратора - :return: + :return: Логгер """ return GSettingsGet().get("Logger",None) def OrchestratorScheduleGet() -> schedule: """ - Get the schedule (schedule.readthedocs.io) from the Orchestrator - - Fro example you can use: + Базовый объект расписания, который можно использовать для запуска / остановки роботов. + Подробнее про объект schedule и его примеры использования см. по адресу: schedule.readthedocs.io .. code-block:: python - # One schedule threaded + + # Однопоточный schedule Orchestrator.OrchestratorScheduleGet().every(5).seconds.do(lProcess.StatusCheckStart) - #New schedule thread # See def description Orchestrator.OrchestratorThreadStart + #Многопоточный schedule. cм. описание Orchestrator.OrchestratorThreadStart Orchestrator.OrchestratorScheduleGet().every(5).seconds.do(Orchestrator.OrchestratorThreadStart,lProcess.StatusCheckStart) - :return: schedule module. Example see here https://schedule.readthedocs.io/en/stable/examples.html + :return: schedule объект """ if GSettingsGet().get("SchedulerDict",{}).get("Schedule",None) is None: GSettingsGet()["SchedulerDict"]["Schedule"]=schedule @@ -564,12 +574,12 @@ def OrchestratorScheduleGet() -> schedule: def OrchestratorThreadStart(inDef, *inArgList, **inArgDict): """ - Execute def in new thread and pass some args with list and dict types + Запустить функцию в отдельном потоке. В таком случае получить результат выполнения функции можно только через общие переменные. (Например через GSettings) - :param inDef: Python Def - :param inArgList: args as list - :param inArgDict: args as dict - :return: threading.Thread object + :param inDef: Python функция + :param inArgList: Список неименованных аргументов функции inDef + :param inArgDict: Словарь именованных аргументов функции inDef + :return: threading.Thread экземпляр """ lDefThread = threading.Thread(target=inDef,args=inArgList,kwargs=inArgDict) lDefThread.start() @@ -577,9 +587,9 @@ def OrchestratorThreadStart(inDef, *inArgList, **inArgDict): def OrchestratorIsAdmin(): """ - Check if Orchestrator process is running as administrator + Проверить, запущен ли Оркестратор с правами администратора. Права администратора нужны Оркестратору только для контроля графической сессии, на которой он запущен. Если эти права выделить индивидуально, то права администратора будут необязательны. - :return: True - run as administrator; False - not as administrator + :return: True - Запущен с правами администратора; False - Не запущен с правами администратора """ try: return ctypes.windll.shell32.IsUserAnAdmin() @@ -587,17 +597,20 @@ def OrchestratorIsAdmin(): return False def OrchestratorIsInited() -> bool: - """Check if Orchestrator initial actions were processed + """ + Проверить, было ли проинициализировано ядро Оркестратора - :return: True - orc is already inited; False - else + :return: True - Ядро Оркестратора было проинициализировано; False - Требуется время на инициализацию :rtype: bool """ return Core.IsOrchestratorInitialized(inGSettings=GSettingsGet()) def OrchestratorInitWait() -> None: - """Wait thread while orc will process initial action. - ATTENTION: DO NOT CALL THIS DEF IN THREAD WHERE ORCHESTRATOR MUST BE INITIALIZED - INFINITE LOOP + """ + Ожидать инициализацию ядра Оркестратора + + !ВНИМАНИЕ!: НИ В КОЕМ СЛУЧАЕ НЕ ЗАПУСКАТЬ ЭТУ ФУНКЦИЮ В ОСНОВНОМ ПОТОКЕ, ГДЕ ПРОИСХОДИТ ИНИЦИАЛИЗАЦИЯ ЯДРА ОРКЕСТРАТОРА - ВОЗНИКНЕТ ВЕЧНЫЙ ЦИКЛ """ lIntervalSecFloat = 0.5 while not OrchestratorIsInited(): @@ -606,9 +619,9 @@ def OrchestratorInitWait() -> None: def OrchestratorRerunAsAdmin(): """ - Check if not admin - then rerun orchestrator as administrator + Перезапустить Оркестратор с правами локального администратора. Права администратора нужны Оркестратору только для контроля графической сессии, на которой он запущен. Если эти права выделить индивидуально, то права администратора будут необязательны. - :return: True - run as administrator; False - not as administrator + :return: True - Запущен с правами администратора; False - Не запущен с правами администратора """ if not OrchestratorIsAdmin(): # Re-run the program with admin rights @@ -618,19 +631,21 @@ def OrchestratorRerunAsAdmin(): def OrchestratorPySearchInit(inGlobPatternStr, inDefStr = None, inDefArgNameGSettingsStr = None, inAsyncInitBool = False): """ - Search the py files by the glob and do the safe init (in try except). Also add inited module in sys.modules as imported (module name = file name without extension). - You can init CP in async way! + Выполнить поиск и инициализацию пользовательских .py файлов в Оркестраторе (например панелей управления роботов) + + Добавляет инициализированный модуль в пространство sys.modules как imported (имя модуля = имя файла без расширения). + .. code-block:: python - # USAGE VAR 1 (without the def auto call) - # Autoinit control panels starts with CP_ + # ВАРИАНТ ИСПОЛЬЗОВАНИЯ 1 (инициализация модуля py без вызова каких-либо функций внутри) + # автоинициализация всех .py файлов, с префиксом CP_, которые расположены в папке ControlPanel Orchestrator.OrchestratorPySearchInit(inGlobPatternStr="ControlPanel\\CP_*.py") - # USAGE VAR 2 (with the def auto call) - for the backward compatibility CP for the Orchestrator ver. < 1.2.7 - # Autoinit control panels starts with CP_ + # ВАРИАНТ ИСПОЛЬЗОВАНИЯ 2 (инициализация модуля py с вызовом функции внутри) - преимущественно для обратной совместимости старых версий панелей управления < 1.2.7 + # автоинициализация всех .py файлов, с префиксом CP_, которые расположены в папке ControlPanel Orchestrator.OrchestratorPySearchInit(inGlobPatternStr="ControlPanel\\CP_*.py", inDefStr="SettingsUpdate", inDefArgNameGSettingsStr="inGSettings") - # INFO: The code above will replace the code below + # ДЛЯ СПРАВКИ & ИСТОРИИ: Код выше позволил отказаться от блока кода ниже для каждого .py файла ## !!! For Relative import !!! CP Version Check try: sys.path.insert(0,os.path.abspath(os.path.join(r""))) @@ -639,12 +654,11 @@ def OrchestratorPySearchInit(inGlobPatternStr, inDefStr = None, inDefArgNameGSet except Exception as e: gSettings["Logger"].exception(f"Exception when init CP. See below.") - - :param inGlobPatternStr: example"..\\*\\*\\*X64*.cmd" - :param inDefStr: OPTIONAL The string name of the def. For backward compatibility if you need to auto call some def from initialized module - :param inDefArgNameGSettingsStr: OPTIONAL The name of the GSettings argument in def (if exists) - :param inAsyncInitBool: OPTIONAL True - init py modules in many threads - parallel execution. False (default) - sequence execution - :return: { "ModuleNameStr":{"PyPathStr": "", "Module": ...}, ...} + :param inGlobPatternStr: Пример "..\\*\\*\\*_CP*.py" + :param inDefStr: ОПЦИОНАЛЬНО Строковое наименование функции. Преимущественно для обратной совместимости + :param inDefArgNameGSettingsStr: ОПЦИОНАЛЬНО Наименование аргумента, в который требуется передать GSettings (если необходимо) + :param inAsyncInitBool: ОПЦИОНАЛЬНО True - Инициализация py модулей в отдельных параллельных потоках - псевдопараллельное выполнение. False - последовательная инициализация + :return: Сведения об инициализированных модулях в структуре: { "ModuleNameStr":{"PyPathStr": "", "Module": ...}, ...} """ # # # # # # # # @@ -688,16 +702,19 @@ def OrchestratorPySearchInit(inGlobPatternStr, inDefStr = None, inDefArgNameGSet def OrchestratorSessionSave(inGSettings=None): """ - Orchestrator session save in file - (from version 1.2.7) + Сохранить состояние Оркестратора (для дальнейшего восстановления в случае перезапуска): + + - RDP сессий, которые контролирует Оркестратор + - Хранилища DataStorage в глобальном словаре настроек GSettings. DataStorage поддерживает хранение объектов Python + + (до версии 1.2.7) _SessionLast_GSettings.pickle (binary) - (above the version 1.2.7) + (начиная с версии 1.2.7) _SessionLast_RDPList.json (encoding = "utf-8") _SessionLast_StorageDict.pickle (binary) - :param inGSettings: Global settings dict (singleton) - :return: True every time + :param inGSettings: Глобальный словарь настроек Оркестратора (синглтон) """ inGSettings = GSettingsGet(inGSettings=inGSettings) # Set the global settings lL = inGSettings["Logger"] @@ -730,16 +747,19 @@ def OrchestratorSessionSave(inGSettings=None): def OrchestratorSessionRestore(inGSettings=None): """ - Check _SessioLast... files in working directory. if exist - load into gsettings - (from version 1.2.7) + Восстановить состояние Оркестратора, если ранее состояние Оркестратора было сохранено с помощью функции OrchestratorSessionSave: + + - RDP сессий, которые контролирует Оркестратор + - Хранилища DataStorage в глобальном словаре настроек GSettings. DataStorage поддерживает хранение объектов Python + + (до версии 1.2.7) _SessionLast_GSettings.pickle (binary) - (above the version 1.2.7) + (начиная с версии 1.2.7) _SessionLast_RDPList.json (encoding = "utf-8") _SessionLast_StorageDict.pickle (binary) - :param inGSettings: Global settings dict (singleton) - :return: + :param inGSettings: Глобальный словарь настроек Оркестратора (синглтон) """ inGSettings = GSettingsGet(inGSettings=inGSettings) # Set the global settings lL = inGSettings.get("Logger",None) @@ -776,33 +796,47 @@ def OrchestratorSessionRestore(inGSettings=None): def UACKeyListCheck(inRequest, inRoleKeyList) -> bool: """ - Check is client is has access for the key list + Проверить права доступа для пользователя запроса по списку ключей до права. + + .. code-block:: python + + # ВАРИАНТ ИСПОЛЬЗОВАНИЯ 1 (инициализация модуля py без вызова каких-либо функций внутри) + # автоинициализация всех .py файлов, с префиксом CP_, которые расположены в папке ControlPanel + Orchestrator.UACKeyListCheck(inRequest=lRequest, inRoleKeyList=["ROBOT1","DISPLAY_DASHBOARD"]) - :param inRequest: request handler (from http.server import BaseHTTPRequestHandler) - :param inRoleKeyList: - :return: bool + :param inRequest: Экземпляр request (from http.server import BaseHTTPRequestHandler) + :param inRoleKeyList: Список ключей, права доступа к которому требуется проверить + :return: True - Пользователь обладает соответствующим правом; False - Пользователь не обладает соответствующим правом """ return inRequest.UACClientCheck(inRoleKeyList=inRoleKeyList) def UACUserDictGet(inRequest) -> dict: """ - Return user UAC hierarchy dict of the inRequest object. Empty dict - superuser access + Вернуть UAC (User Access Control) словарб доступов для пользователя, который отправил запрос. Пустой словарь - супердоступ (доступ ко всему) - :param inRequest: request handler (from http.server import BaseHTTPRequestHandler) - :return: user UAC hierarchy dict + :param inRequest: Экземпляр request (from http.server import BaseHTTPRequestHandler) + :return: Словарь доступов пользователя. Пустой словарь - супердоступ (доступ ко всему) """ return inRequest.UserRoleHierarchyGet() # get the Hierarchy def UACUpdate(inADLoginStr, inADStr="", inADIsDefaultBool=True, inURLList=None, inRoleHierarchyAllowedDict=None, inGSettings = None): """ - Update user access (UAC) - - :param inGSettings: Global settings dict (singleton) - :param inADLoginStr: - :param inADStr: - :param inADIsDefaultBool: - :param inURLList: - :param inRoleHierarchyAllowedDict: + Дообогащение словаря доступа UAC пользователя inADStr\\inADLoginStr. Если ранее словарь не устанавливался, то по умолчанию он {}. Далее идет дообогащение теми ключами, которые присутствуют в inRoleHierarchyAllowedDict + + :param inGSettings: Глобальный словарь настроек Оркестратора (синглтон) + :param inADLoginStr: Логин пользователя + :param inADStr: Домен пользователя. Если пусто - локальный компьютер или домен по-умолчанию, который настроен в ОС + :param inADIsDefaultBool: True - домен настроен по умолчанию; False - домен требуется обязательно указывать + :param inURLList: Список разрешенных URL для пользователя. Для добавления URL рекомендуем использовать функции WebURLConnectDef, WebURLConnectFile, WebURLConnectFolder + Формат: { + "Method": "GET" || "POST", + "URL": "/GetScreenshot", + "MatchType": "BeginWith" || "Equal" || "EqualCase" || "Contains" || "EqualNoParam", + "ResponseDefRequestGlobal": Функция python || "ResponseFilePath": Путь к файлу || "ResponseFolderPath": Путь к папке, в которой искать файлы, + "ResponseContentType": пример MIME "image/png", + "UACBool":False - не выполнять проверку прав доступа по запросу, + "UseCacheBool": True - кэшировать ответ}, + :param inRoleHierarchyAllowedDict: Словарь доступа пользователя UAC. Пустой словарь - полный доступ """ inGSettings = GSettingsGet(inGSettings=inGSettings) # Set the global settings lUserTurple = (inADStr.upper(),inADLoginStr.upper()) # Create turple key for inGSettings["ServerDict"]["AccessUsers"]["RuleDomainUserDict"] @@ -831,10 +865,10 @@ def UACUpdate(inADLoginStr, inADStr="", inADIsDefaultBool=True, inURLList=None, def UACSuperTokenUpdate(inSuperTokenStr, inGSettings=None): """ - Add supertoken for the all access (it is need for the robot communication without human) + Добавить супертокен (полный доступ). Супертокены используются для подключения к Оркестратору по API - :param inGSettings: Global settings dict (singleton) - :param inSuperTokenStr: + :param inGSettings: Глобальный словарь настроек Оркестратора (синглтон) + :param inSuperTokenStr: Кодовая строковая комбинация, которая будет предоставлять доступ роботу / агенту для взаимодействия с Оркестратором по API """ inGSettings = GSettingsGet(inGSettings=inGSettings) # Set the global settings lLoginStr = "SUPERTOKEN" @@ -846,31 +880,26 @@ def UACSuperTokenUpdate(inSuperTokenStr, inGSettings=None): # # # # # # # # # # # # # # # # # # # # # # # # OrchestratorWeb defs # # # # # # # # # # # # # # # # # # # # # # # - def WebURLIndexChange(inURLIndexStr:str ="/"): - """Change the index page of the orchestrator if you dont want the '/' (main) path + """ + Изменить адрес главной страницы Оркестратора. По умолчанию '/' - :param inURLIndexStr: New url for the index page of the orchestrator, defaults to "/" - :type inURLIndexStr: str, optional + :param inURLIndexStr: Новый адрес главной страницы Оркестратора. + :type inURLIndexStr: str, опционально """ GSettingsGet()["ServerDict"]["URLIndexStr"] = inURLIndexStr def WebURLConnectDef(inMethodStr, inURLStr, inMatchTypeStr, inDef, inContentTypeStr="application/octet-stream", inGSettings = None, inUACBool = None): """ - Connect URL to DEF - "inMethodStr":"GET|POST", - "inURLStr": "/index", #URL of the request - "inMatchTypeStr": "", #"BeginWith|Contains|Equal|EqualCase", - "inContentTypeStr": "", #HTTP Content-type - "inDef": None #Function with str result - - :param inGSettings: Global settings dict (singleton) - :param inMethodStr: "GET|POST", - :param inURLStr: example "/index", #URL of the request - :param inMatchTypeStr: #"BeginWith|Contains|Equal|EqualCase", - :param inDef: def arg allowed list: 2:[inRequest, inGSettings], 1: [inRequest], 0: [] - :param inContentTypeStr: default: "application/octet-stream" - :param inUACBool: default: None; True - check user access before do this URL item. None - get Server flag if ask user + Подключить функцию Python к URL. + + :param inMethodStr: Метод доступа по URL "GET" || "POST" + :param inURLStr: URL адрес. Пример "/index" + :param inMatchTypeStr: Тип соответсвия строки URL с inURLStr: "BeginWith" || "Contains" || "Equal" || "EqualCase" || "EqualNoParam" + :param inDef: Функция Python. Допускаются функции, которые принимают следующие наборы параметров: 2:[inRequest, inGSettings], 1: [inRequest], 0: [] + :param inContentTypeStr: МИМЕ тип. По умолчанию: "application/octet-stream" + :param inUACBool: True - Выполнять проверку прав доступа пользователя перед отправкой ответа; False - не выполнять проверку прав доступа пользователя + :param inGSettings: Глобальный словарь настроек Оркестратора (синглтон) """ inGSettings = GSettingsGet(inGSettings=inGSettings) # Set the global settings lURLItemDict = { @@ -889,20 +918,15 @@ def WebURLConnectDef(inMethodStr, inURLStr, inMatchTypeStr, inDef, inContentType def WebURLConnectFolder(inMethodStr, inURLStr, inMatchTypeStr, inFolderPathStr, inGSettings = None, inUACBool = None, inUseCacheBool= False): """ - Connect URL to Folder - "inMethodStr":"GET|POST", - "inURLStr": "/Folder/", #URL of the request - "inMatchTypeStr": "", #"BeginWith|Contains|Equal|EqualCase", - "inFolderPathStr": "", #Absolute or relative path - "inUACBool" - - :param inGSettings: Global settings dict (singleton) - :param inMethodStr: - :param inURLStr: - :param inMatchTypeStr: - :param inFolderPathStr: - :param inUACBool: default: None; True - check user access before do this URL item. None - get Server flag if ask user - :param inUseCacheBool: True - cache this page - dont open ever + Подключить папку к URL. + + :param inMethodStr: Метод доступа по URL "GET" || "POST" + :param inURLStr: URL адрес. Пример "/index" + :param inMatchTypeStr: Тип соответсвия строки URL с inURLStr: "BeginWith" || "Contains" || "Equal" || "EqualCase" || "EqualNoParam" + :param inFolderPathStr: Путь к папке на диске, в которой искать файл и возвращать пользователю по HTTP + :param inUACBool: True - Выполнять проверку прав доступа пользователя перед отправкой ответа; False - не выполнять проверку прав доступа пользователя + :param inUseCacheBool: True - выполнить кэширование страницы, чтобы в следющих запросах открыть быстрее; False - не кэшировать + :param inGSettings: Глобальный словарь настроек Оркестратора (синглтон) """ inGSettings = GSettingsGet(inGSettings=inGSettings) # Set the global settings # Check if last symbol is "/" - append if not exist @@ -925,20 +949,18 @@ def WebURLConnectFolder(inMethodStr, inURLStr, inMatchTypeStr, inFolderPathStr, def WebURLConnectFile(inMethodStr, inURLStr, inMatchTypeStr, inFilePathStr, inContentTypeStr=None, inGSettings = None, inUACBool = None, inUseCacheBool = False): """ - Connect URL to File - "inMethodStr":"GET|POST", - "inURLStr": "/index", #URL of the request - "inMatchTypeStr": "", #"BeginWith|Contains|Equal|EqualCase", - "inFolderPathStr": "", #Absolute or relative path - - :param inGSettings: Global settings dict (singleton) - :param inMethodStr: - :param inURLStr: - :param inMatchTypeStr: - :param inFilePathStr: - :param inContentTypeStr: If none - autodetect - :param inUACBool: default: None; True - check user access before do this URL item. None - get Server flag if ask user - :param inUseCacheBool: True - cache this page - dont open ever + + Подключить файл к URL. + + :param inMethodStr: Метод доступа по URL "GET" || "POST" + :param inURLStr: URL адрес. Пример "/index" + :param inMatchTypeStr: Тип соответсвия строки URL с inURLStr: "BeginWith" || "Contains" || "Equal" || "EqualCase" || "EqualNoParam" + :param inFilePathStr: Путь к файлу на диске, который возвращать пользователю по HTTP + :param inContentTypeStr: МИМЕ тип. Если None - выполнить автоматическое определение + :param inUACBool: True - Выполнять проверку прав доступа пользователя перед отправкой ответа; False - не выполнять проверку прав доступа пользователя + :param inUseCacheBool: True - выполнить кэширование страницы, чтобы в следющих запросах открыть быстрее; False - не кэшировать + :param inGSettings: Глобальный словарь настроек Оркестратора (синглтон) + """ inGSettings = GSettingsGet(inGSettings=inGSettings) # Set the global settings lURLItemDict = { @@ -956,13 +978,13 @@ def WebURLConnectFile(inMethodStr, inURLStr, inMatchTypeStr, inFilePathStr, inCo def WebListenCreate(inServerKeyStr="Default", inAddressStr="", inPortInt=80, inCertFilePEMPathStr=None, inKeyFilePathStr=None, inGSettings = None): """ - Create listen interface for the web server - - :param inGSettings: Global settings dict (singleton) - :param inAddressStr: IP interface to listen - :param inPortInt: Port int to listen for HTTP default is 80; for HTTPS default is 443 - :param inCertFilePEMPathStr: Path to .pem (base 64) certificate. Required for SSL connection. ATTENTION - do not use certificate with password - :param inKeyFilePathStr: Path to the private key file + Настроить веб-сервер Оркестратора. + + :param inAddressStr: IP адрес для прослушивания. Если "", то прослушивать запросы со всех сетевых карт. Если "127.0.0.1", то слушать запросы только с той ОС, на которой работает Оркестратор + :param inPortInt: Номер порта для прослушивания. Если HTTP - 80; Если HTTPS - 443. По умолчанию 80. Допускается установка других портов + :param inCertFilePEMPathStr: Путь файлу сертификата, сгенерированного в .pem (base64) формате. Обязателен при использовании защищенного HTTPS/SSL соединения. + :param inKeyFilePathStr: Путь к файлу закрытого ключа в base64 формате + :param inGSettings: Глобальный словарь настроек Оркестратора (синглтон) :return: """ inGSettings = GSettingsGet(inGSettings=inGSettings) # Set the global settings @@ -977,13 +999,13 @@ def WebListenCreate(inServerKeyStr="Default", inAddressStr="", inPortInt=80, inC def WebCPUpdate(inCPKeyStr, inHTMLRenderDef=None, inJSONGeneratorDef=None, inJSInitGeneratorDef=None, inGSettings = None): """ - Add control panel HTML, JSON generator or JS when page init + Добавить панель управления робота в Оркестратор. Для панели управления открыт доступ для использования функции-генератора HTML, генератора JSON данных, генератора JS кода. - :param inGSettings: Global settings dict (singleton) - :param inCPKeyStr: - :param inHTMLRenderDef: - :param inJSONGeneratorDef: - :param inJSInitGeneratorDef: + :param inGSettings: Глобальный словарь настроек Оркестратора (синглтон) + :param inCPKeyStr: Текстовый ключ панели управления. Ключ для каждой панели управления должен быть уникальным! + :param inHTMLRenderDef: Функция Python для генерации HTML кода. Для использования Jinja2 шаблонов HTML см. pyOpenRPA.Orchestrator.Managers.ControlPanel + :param inJSONGeneratorDef: Функция Python для генерации JSON контейнера для отправки на клиентскую часть Оркестратора + :param inJSInitGeneratorDef: Функция Python для генерации JS кода для отправки на клиентскую часть Оркестратора """ lCPManager = Managers.ControlPanel(inControlPanelNameStr=inCPKeyStr, inRefreshHTMLJinja2TemplatePathStr=None) # CASE HTMLRender @@ -996,11 +1018,11 @@ def WebCPUpdate(inCPKeyStr, inHTMLRenderDef=None, inJSONGeneratorDef=None, inJSI def WebAuditMessageCreate(inRequest=None, inOperationCodeStr="-", inMessageStr="-"): """ - Create message string with request user details (IP, Login etc...). Very actual for IT security in big company. - + Создание сообщения ИТ аудита с такими сведениями как (Домен, IP, логин и тд.). Данная функция особенно актуальна в том случае, если требуется реализовать дополнительные меры контроля ИТ системы. + .. code-block:: python - # USAGE + # ПРИМЕР from pyOpenRPA import Orchestrator lWebAuditMessageStr = Orchestrator.WebAuditMessageCreate( @@ -1008,13 +1030,13 @@ def WebAuditMessageCreate(inRequest=None, inOperationCodeStr="-", inMessageStr=" inOperationCodeStr = "OP_CODE_1", inMessageStr="Success"): - # Log the WebAudit message + # Логгирование сообщения lLogger.info(lWebAuditMessageStr) - :param inRequest: HTTP request handler. Optional if call def from request thread - :param inOperationCodeStr: operation code in string format (actual for IT audit in control panels) - :param inMessageStr: additional message after - :return: format "WebAudit :: DOMAIN\\USER@101.121.123.12 :: operation code :: message" + :param inRequest: Экземпляр HTTP request. Опционален, если сообщение фиксируется из под потока, который был инициирован запросом пользователя + :param inOperationCodeStr: Код операции, который принят в компании в соответствии с регламентными процедурами + :param inMessageStr: Дополнительное сообщение, которое необходимо отправить в сообщение об ИТ аудите + :return: Формат сообщения: "WebAudit :: DOMAIN\\USER@101.121.123.12 :: operation code :: message" """ try: if inRequest is None: inRequest = WebRequestGet() @@ -1030,10 +1052,10 @@ def WebAuditMessageCreate(inRequest=None, inOperationCodeStr="-", inMessageStr=" def WebRequestParseBodyBytes(inRequest=None): """ - Extract the body in bytes from the request + Извлечь данные в байт виде из тела (body) HTTP запроса. - :param inRequest: inRequest from the server. Optional if call def from request thread - :return: Bytes or None + :param inRequest: Экземпляр HTTP request. Опционален, если сообщение фиксируется из под потока, который был инициирован запросом пользователя + :return: Строка байт b'' или None (если тело запроса было пустым) """ if inRequest is None: inRequest = WebRequestGet() lBodyBytes=None @@ -1044,40 +1066,40 @@ def WebRequestParseBodyBytes(inRequest=None): def WebRequestParseBodyStr(inRequest=None): """ - Extract the body in str from the request + Извлечь данные в виде строки из тела (body) HTTP запроса. - :param inRequest: inRequest from the server. Optional if call def from request thread - :return: str or None + :param inRequest: Экземпляр HTTP request. Опционален, если сообщение фиксируется из под потока, который был инициирован запросом пользователя + :return: Текстовая строка '' или None (если тело запроса было пустым) """ if inRequest is None: inRequest = WebRequestGet() return WebRequestParseBodyBytes(inRequest=inRequest).decode('utf-8') def WebRequestParseBodyJSON(inRequest=None): """ - Extract the body in dict/list from the request + Извлечь из тела (body) запроса HTTP JSON данные и преобразовать в Dict / List структуры языка Python. - :param inRequest: inRequest from the server. Optional if call def from request thread - :return: dict or list + :param inRequest: Экземпляр HTTP request. Опционален, если сообщение фиксируется из под потока, который был инициирован запросом пользователя + :return: Словарь (dict), список (list) или None (если тело запроса было пустым) """ if inRequest is None: inRequest = WebRequestGet() return json.loads(WebRequestParseBodyStr(inRequest=inRequest)) def WebRequestParsePath(inRequest=None): """ - Parse the request - extract the url. Example: /pyOpenRPA/Debugging/DefHelper/... + Извлечь декодированный URL путь из HTTP запроса пользователя в формате строки. - :param inRequest: inRequest from the server. Optional if call def from request thread - :return: Str, Example: /pyOpenRPA/Debugging/DefHelper/... + :param inRequest: Экземпляр HTTP request. Опционален, если сообщение фиксируется из под потока, который был инициирован запросом пользователя + :return: str, пример: /pyOpenRPA/Debugging/DefHelper """ if inRequest is None: inRequest = WebRequestGet() return urllib.parse.unquote(inRequest.path) def WebRequestParseFile(inRequest=None): """ - Parse the request - extract the file (name, body in bytes) + Извлечь файл (наименование + содержимое в виде строки байт b'') из HTTP запроса пользователя. - :param inRequest: inRequest from the server. Optional if call def from request thread - :return: (FileNameStr, FileBodyBytes) or (None, None) + :param inRequest: Экземпляр HTTP request. Опционален, если сообщение фиксируется из под потока, который был инициирован запросом пользователя + :return: Кортеж формата (FileNameStr, FileBodyBytes) or (None, None), если файл не был обнаружен """ if inRequest is None: inRequest = WebRequestGet() lResultTurple=(None,None) @@ -1099,21 +1121,26 @@ def WebRequestParseFile(inRequest=None): return lResultTurple -def WebRequestResponseSend(inResponeStr, inRequest=None): +def WebRequestResponseSend(inResponeStr, inRequest=None, inContentTypeStr: str = None, inHeadersDict: dict = None): """ - Send response for the request + Установить ответ на HTTP запрос пользователя. - :param inRequest: inRequest from the server. Optional if call def from request thread - :return: + :param inResponeStr: Тело ответа (строка) + :param inRequest: Экземпляр HTTP request. Опционален, если сообщение фиксируется из под потока, который был инициирован запросом пользователя + :param inContentTypeStr: МИМЕ тип. Пример: "html/text" + :param inHeadersDict: Словарь (dict) ключей, которые добавить в headers HTTP ответа на запрос пользователя """ if inRequest is None: inRequest = WebRequestGet() inRequest.OpenRPAResponseDict["Body"] = bytes(inResponeStr, "utf8") + if inHeadersDict is not None: + inRequest.OpenRPAResponseDict["Headers"].update(inHeadersDict) + if inContentTypeStr is not None: + inRequest.OpenRPAResponseDict["Headers"]["Content-type"] = inContentTypeStr def WebRequestGet(): """ - Return the web request instance if current thread was created by web request from client. else return None - + Вернуть экземпляр HTTP запроса, если функция вызвана в потоке, который был порожден для отработки HTTP запроса пользователя. """ lCurrentThread = threading.current_thread() if hasattr(lCurrentThread, "request"): @@ -1121,10 +1148,10 @@ def WebRequestGet(): def WebUserInfoGet(inRequest=None): """ - Return User info about request + Информация о пользователе, который отправил HTTP запрос. - :param inRequest: inRequest from the server. Optional if call def from request thread - :return: {"DomainUpperStr": "", "UserNameUpperStr": ""} + :param inRequest: Экземпляр HTTP request. Опционален, если сообщение фиксируется из под потока, который был инициирован запросом пользователя + :return: Сведения в формате {"DomainUpperStr": "PYOPENRPA", "UserNameUpperStr": "IVAN.MASLOV"} """ if inRequest is None: inRequest = WebRequestGet() lDomainUpperStr = inRequest.OpenRPA["Domain"].upper() @@ -1133,11 +1160,11 @@ def WebUserInfoGet(inRequest=None): def WebUserIsSuperToken(inRequest = None, inGSettings = None): """ - Return bool if request is authentificated with supetoken (token which is never expires) + Проверить, авторизован ли HTTP запрос с помощью супер токена (токен, который не истекает). - :param inRequest: inRequest from the server. Optional if call def from request thread - :param inGSettings: Global settings dict (singleton) - :return: bool True - is supertoken; False - is not supertoken + :param inRequest: Экземпляр HTTP request. Опционален, если сообщение фиксируется из под потока, который был инициирован запросом пользователя + :param inGSettings: Глобальный словарь настроек Оркестратора (синглтон) + :return: True - является супертокеном; False - не является супертокеном """ if inRequest is None: inRequest = WebRequestGet() inGSettings = GSettingsGet(inGSettings=inGSettings) # Set the global settings @@ -1148,10 +1175,10 @@ def WebUserIsSuperToken(inRequest = None, inGSettings = None): def WebUserUACHierarchyGet(inRequest = None): """ - Return User UAC Hierarchy DICT Return {...} + Вернуть словарь доступа UAC в отношении пользователя, который выполнил HTTP запрос inRequest - :param inRequest: inRequest from the server. Optional if call def from request thread - :return: UAC Dict {} + :param inRequest: Экземпляр HTTP request. Опционален, если сообщение фиксируется из под потока, который был инициирован запросом пользователя + :return: UAC словарь доступа или {}, что означает полный доступ """ if inRequest is None: inRequest = WebRequestGet() return inRequest.UserRoleHierarchyGet() @@ -1171,10 +1198,10 @@ if __name__ == "pyOpenRPA.Orchestrator.__Orchestrator__" and "pyOpenRPA.Orchestr def GSettingsGet(inGSettings=None): """ - Get the GSettings from the singleton module. + Вернуть глобальный словарь настроек Оркестратора. Во время выполнения программы глобальный словарь настроек существует в единственном экземпляре (синглтон) - :param inGSettings: You can pass some GSettings to check if it equal to base gsettings. If not equal - def will merge it - :return: GSettings + :param inGSettings: Дополнительный словарь настроек, который необходимо добавить в основной глобальный словарь настроек Оркестратора (синглтон) + :return: Глобальный словарь настроек GSettings """ global GSettings # identify the global variable # Merge dictionaries if some new dictionary has come @@ -1184,12 +1211,13 @@ def GSettingsGet(inGSettings=None): def GSettingsKeyListValueSet(inValue, inKeyList=None, inGSettings = None): """ - Set value in GSettings by the key list + Установить значение из глобального словаря настроек Оркестратора GSettings по списку ключей. + + Пример: Для того, чтобы установить значение для ключа car в словаре {"complex":{"car":"green"}, "simple":"HELLO"}, необходимо передать список ключей: ["complex", "car"] - :param inGSettings: Global settings dict (singleton) - :param inValue: - :param inKeyList: - :return: bool + :param inGSettings: Глобальный словарь настроек Оркестратора (синглтон) + :param inValue: Значение для установки в глобальный словарь настроек Оркестратора GSettings + :param inKeyList: Список ключей, по адресу которого установить значение в GSettings """ inGSettings = GSettingsGet(inGSettings=inGSettings) # Set the global settings if inKeyList is None: inKeyList = [] @@ -1206,11 +1234,11 @@ def GSettingsKeyListValueSet(inValue, inKeyList=None, inGSettings = None): def GSettingsKeyListValueGet(inKeyList=None, inGSettings = None): """ - Get the value from the GSettings by the key list + Получить значение из глобального словаря настроек Оркестратора GSettings по списку ключей. - :param inGSettings: Global settings dict (singleton) - :param inKeyList: - :return: value any type + :param inGSettings: Глобальный словарь настроек Оркестратора (синглтон) + :param inKeyList: Список ключей, по адресу которого получить значение из GSettings + :return: Значение (тип данных определяется форматом хранения в GSettings) """ inGSettings = GSettingsGet(inGSettings=inGSettings) # Set the global settings if inKeyList is None: inKeyList = [] @@ -1226,11 +1254,11 @@ def GSettingsKeyListValueGet(inKeyList=None, inGSettings = None): def GSettingsKeyListValueAppend(inValue, inKeyList=None, inGSettings = None): """ - Append value in GSettings by the key list + Применить операцию .append к обьекту, расположенному по адресу списка ключей inKeyList в глобальном словаре настроек Оркестратора GSettings. Пример: Добавить значение в конец списка (list). .. code-block:: python - # USAGE + # ПРИМЕР from pyOpenRPA import Orchestrator Orchestrator.GSettingsKeyListValueAppend( @@ -1246,10 +1274,9 @@ def GSettingsKeyListValueAppend(inValue, inKeyList=None, inGSettings = None): # } #} - :param inGSettings: Global settings dict (singleton) - :param inValue: Any value to be appended in gSettings Dict by the key list - :param inKeyList: List of the nested keys (see example) - :return: True every time + :param inGSettings: Глобальный словарь настроек Оркестратора (синглтон) + :param inValue: Значение для установки в глобальный словарь настроек Оркестратора GSettings + :param inKeyList: Список ключей, по адресу которого выполнить добавление в конец списка (list) """ inGSettings = GSettingsGet(inGSettings=inGSettings) # Set the global settings if inKeyList is None: inKeyList = [] @@ -1266,11 +1293,11 @@ def GSettingsKeyListValueAppend(inValue, inKeyList=None, inGSettings = None): def GSettingsKeyListValueOperatorPlus(inValue, inKeyList=None, inGSettings = None): """ - Execute plus operation between 2 lists (1:inValue and 2:gSettings by the inKeyList) + Применить оператор сложения (+) к обьекту, расположенному по адресу списка ключей inKeyList в глобальном словаре настроек Оркестратора GSettings. Пример: соединить 2 списка (list). .. code-block:: python - # USAGE + # ПРИМЕР from pyOpenRPA import Orchestrator Orchestrator.GSettingsKeyListValueOperatorPlus( @@ -1289,10 +1316,9 @@ def GSettingsKeyListValueOperatorPlus(inValue, inKeyList=None, inGSettings = Non # } #} - :param inGSettings: Global settings dict (singleton) - :param inValue: List with values to be merged with list in gSettings - :param inKeyList: List of the nested keys (see example) - :return: True every time + :param inGSettings: Глобальный словарь настроек Оркестратора (синглтон) + :param inValue: Значение для установки в глобальный словарь настроек Оркестратора GSettings + :param inKeyList: Список ключей, по адресу которого выполнить добавление в конец списка (list) """ inGSettings = GSettingsGet(inGSettings=inGSettings) # Set the global settings if inKeyList is None: inKeyList = [] @@ -1309,19 +1335,19 @@ def GSettingsKeyListValueOperatorPlus(inValue, inKeyList=None, inGSettings = Non def StorageRobotExists(inRobotNameStr): """ - Check if robot storage exists + Проверить, существует ли ключ inRobotNameStr в хранилище пользовательской информации StorageDict (GSettings > StarageDict) - :param inRobotNameStr: Robot name (case sensitive) - :return: True - robot storage exist; False - does not exist + :param inRobotNameStr: Наименование (ключ) робота. !ВНИМАНИЕ! Наименование чувствительно к регистру + :return: True - ключ робота присутствует в хранилище; False - отсутствует """ return inRobotNameStr in GSettingsGet()["StorageDict"] def StorageRobotGet(inRobotNameStr): """ - Get the robot storage by the robot name. If Robot storage is not exist - function will create it + Получить содержимое по ключу робота inRobotNameStr в хранилище пользовательской информации StorageDict (GSettings > StarageDict) - :param inRobotNameStr: Robot name (case sensitive) - :return: Dict + :param inRobotNameStr: Наименование (ключ) робота. !ВНИМАНИЕ! Наименование чувствительно к регистру + :return: Значение или структура, которая расположена по адресу (GSettings > StarageDict > inRobotNameStr) """ if inRobotNameStr not in GSettingsGet()["StorageDict"]: GSettingsGet()["StorageDict"][inRobotNameStr]={} @@ -1329,9 +1355,9 @@ def StorageRobotGet(inRobotNameStr): def ProcessorAliasDefCreate(inDef, inAliasStr=None, inGSettings = None): """ - Create alias for def (can be used in ActivityItem in field Def) - !WHEN DEF ALIAS IS REQUIRED! - Def alias is required when you try to call Python def from the Orchestrator WEB side (because you can't transmit Python def object out of the Python environment) - Deprecated. See ActivityItemDefAliasCreate + Создать синоним (текстовый ключ) для инициации выполнения функции в том случае, если запрос на выполнения пришел из вне (передача функций невозможна). + + Старая версия. Новую версию см. ActivityItemDefAliasCreate .. code-block:: python @@ -1346,18 +1372,19 @@ def ProcessorAliasDefCreate(inDef, inAliasStr=None, inGSettings = None): inAliasStr="TestDefAlias") # Now you can call TestDef by the alias from var lAliasStr with help of ActivityItem (key Def = lAliasStr) - :param inGSettings: Global settings dict (singleton) - :param inDef: Def - :param inAliasStr: String alias for associated def - :return: str Alias string (Alias can be regenerated if previous alias was occupied) + + :param inDef: функция Python + :param inAliasStr: Строковый ключ (синоним), который можно будет использовать в Активности (ActivityItem) + :param inGSettings: Глобальный словарь настроек Оркестратора (синглтон) + :return: Строковый ключ, который был назначен. Ключ может быть изменен, если входящий текстовый ключ был уже занят. """ return ActivityItemDefAliasCreate(inDef=inDef, inAliasStr=inAliasStr, inGSettings = inGSettings) def ProcessorAliasDefUpdate(inDef, inAliasStr, inGSettings = None): """ - Update alias for def (can be used in ActivityItem in field Def). - !WHEN DEF ALIAS IS REQUIRED! - Def alias is required when you try to call Python def from the Orchestrator WEB side (because you can't transmit Python def object out of the Python environment) - Deprecated. See ActivityItemDefAliasUpdate + Обновить синоним (текстовый ключ) для инициации выполнения функции в том случае, если запрос на выполнения пришел из вне (передача функций невозможна). + + Старая версия. Новую версию см. ActivityItemDefAliasUpdate .. code-block:: python @@ -1372,20 +1399,20 @@ def ProcessorAliasDefUpdate(inDef, inAliasStr, inGSettings = None): inAliasStr="TestDefAlias") # Now you can call TestDef by the alias "TestDefAlias" with help of ActivityItem (key Def = "TestDefAlias") - :param inGSettings: Global settings dict (singleton) - :param inDef: Def - :param inAliasStr: String alias for associated def - :return: str Alias string + :param inGSettings: Глобальный словарь настроек Оркестратора (синглтон) + :param inDef: функция Python + :param inAliasStr: Строковый ключ (синоним), который можно будет использовать в Активности (ActivityItem) + :return: Строковый ключ, который был назначен. Ключ будет тем же, если входящий текстовый ключ был уже занят. """ return ActivityItemDefAliasUpdate(inDef=inDef, inAliasStr=inAliasStr, inGSettings = inGSettings) # ActivityItem defs def ActivityItemHelperDefList(inDefQueryStr=None): """ - Create list of the available Def names in activity item. You can use query def filter via arg inDefQueryStr + Получить список синонимов (текстовых ключей), доступных для использования в Активностях (ActivityItem). - :param inDefStr: - :return: ["ActivityItemDefAliasUpdate", "ActivityItemDefAliasCreate", etc...] + :param inDefStr: Часть текстового ключ (начало / середина / конец) + :return: Список доступных ключей в формате: ["ActivityItemDefAliasUpdate", "ActivityItemDefAliasCreate", etc...] """ lResultList = [] if inDefQueryStr is not None: # do search alg @@ -1399,10 +1426,17 @@ def ActivityItemHelperDefList(inDefQueryStr=None): def ActivityItemHelperDefAutofill(inDef): """ - Detect def by the name and prepare the activity item dict with values. + Анализ аргументов функции по синониму (текстовому ключу). - :param inDef: - :return: + :param inDef: Часть текстового ключ (начало / середина / конец) + :return: Преднастроенная структура активности (ActivityItem) + { + "Def": None, + "ArgList": [], + "ArgDict": {}, + "ArgGSettingsStr": None, + "ArgLoggerStr": None + } """ lResultDict = { "Def": None, @@ -1431,14 +1465,14 @@ def ActivityItemHelperDefAutofill(inDef): def ActivityItemCreate(inDef, inArgList=None, inArgDict=None, inArgGSettingsStr=None, inArgLoggerStr=None, inGUIDStr = None, inThreadBool = False): """ - Create activity item. Activity item can be used as list item in ProcessorActivityItemAppend or in Processor.ActivityListExecute. + Создать Активность (ActivityItem). Активность можно использовать в ProcessorActivityItemAppend или в Processor.ActivityListExecute или в функциях работы с Агентами. .. code-block:: python - # USAGE + # ПРИМЕР from pyOpenRPA import Orchestrator - # EXAMPLE 1 + # ВАРИАНТ 1 def TestDef(inArg1Str, inGSettings, inLogger): pass lActivityItem = Orchestrator.ActivityItemCreate( @@ -1456,7 +1490,7 @@ def ActivityItemCreate(inDef, inArgList=None, inArgDict=None, inArgGSettingsStr= # "ArgLogger": "inLogger" # } - # EXAMPLE 2 + # ВАРИАНТ 2 def TestDef(inArg1Str): pass Orchestrator.ActivityItemDefAliasUpdate( @@ -1478,14 +1512,23 @@ def ActivityItemCreate(inDef, inArgList=None, inArgDict=None, inArgGSettingsStr= # "ArgLogger": None # } - :param inDef: def link or def alias (look gSettings["Processor"]["AliasDefDict"]) - :param inArgList: Args list for the Def - :param inArgDict: Args dict for the def - :param inArgGSettingsStr: Name of def argument of the GSettings dict - :param inArgLoggerStr: Name of def argument of the logging object - :param inGUIDStr: GUID which you can specify. If None the GUID will be generated - :param inThreadBool: True - execute ActivityItem in new thread; False - in processor thread - :return: {} + :param inDef: Функция Python или синоним (текстовый ключ) + :param inArgList: Список (list) неименованных аргументов к функции + :param inArgDict: Словарь (dict) именованных аргументов к функции + :param inArgGSettingsStr: Текстовое наименование аргумента GSettings (если требуется передавать) + :param inArgLoggerStr: Текстовое наименование аргумента logger (если требуется передавать) + :param inGUIDStr: ГУИД идентификатор активности (ActivityItem). Если ГУИД не указан, то он будет сгенерирован автоматически + :param inThreadBool: True - выполнить ActivityItem в новом потоке; False - выполнить последовательно в общем потоке процессорной очереди + :return: + lActivityItemDict= { + "Def":inDef, # def link or def alias (look gSettings["Processor"]["AliasDefDict"]) + "ArgList":inArgList, # Args list + "ArgDict":inArgDict, # Args dictionary + "ArgGSettings": inArgGSettingsStr, # Name of GSettings attribute: str (ArgDict) or index (for ArgList) + "ArgLogger": inArgLoggerStr, # Name of GSettings attribute: str (ArgDict) or index (for ArgList) + "GUIDStr": inGUIDStr, + "ThreadBool": inThreadBool + } """ # Work about GUID in Activity items if inGUIDStr is None: @@ -1506,12 +1549,11 @@ def ActivityItemCreate(inDef, inArgList=None, inArgDict=None, inArgGSettingsStr= def ActivityItemDefAliasCreate(inDef, inAliasStr=None, inGSettings = None): """ - Create alias for def (can be used in ActivityItem in field Def) - !WHEN DEF ALIAS IS REQUIRED! - Def alias is required when you try to call Python def from the Orchestrator WEB side (because you can't transmit Python def object out of the Python environment) - + Создать синоним (текстовый ключ) для инициации выполнения функции в том случае, если запрос на выполнения пришел из вне (передача функций невозможна). + .. code-block:: python - # USAGE + # ПРИМЕР from pyOpenRPA import Orchestrator def TestDef(): @@ -1522,10 +1564,10 @@ def ActivityItemDefAliasCreate(inDef, inAliasStr=None, inGSettings = None): inAliasStr="TestDefAlias") # Now you can call TestDef by the alias from var lAliasStr with help of ActivityItem (key Def = lAliasStr) - :param inGSettings: Global settings dict (singleton) - :param inDef: Def - :param inAliasStr: String alias for associated def - :return: str Alias string (Alias can be regenerated if previous alias was occupied) + :param inDef: функция Python + :param inAliasStr: Строковый ключ (синоним), который можно будет использовать в Активности (ActivityItem) + :param inGSettings: Глобальный словарь настроек Оркестратора (синглтон) + :return: Строковый ключ, который был назначен. Ключ может быть изменен, если входящий текстовый ключ был уже занят. """ #TODO Pay attention - New alias can be used too - need to create more complex algorythm to create new alias! inGSettings = GSettingsGet(inGSettings=inGSettings) # Set the global settings @@ -1540,9 +1582,7 @@ def ActivityItemDefAliasCreate(inDef, inAliasStr=None, inGSettings = None): def ActivityItemDefAliasModulesLoad(): """ - Load all def from sys.modules... in ActivityItem def alias dict - - :return: None + Загрузить все функции из импортированных модулей sys.modules в ActivityItem синонимы - полезно для отладки со стороны панели управления. """ lL = OrchestratorLoggerGet() lL.info(f"ActivityItem aliases: start to load sys.modules") @@ -1560,9 +1600,8 @@ def ActivityItemDefAliasModulesLoad(): def ActivityItemDefAliasUpdate(inDef, inAliasStr, inGSettings = None): """ - Update alias for def (can be used in ActivityItem in field Def). - !WHEN DEF ALIAS IS REQUIRED! - Def alias is required when you try to call Python def from the Orchestrator WEB side (because you can't transmit Python def object out of the Python environment) - + Обновить синоним (текстовый ключ) для инициации выполнения функции в том случае, если запрос на выполнения пришел из вне (передача функций невозможна). + .. code-block:: python # USAGE @@ -1576,10 +1615,10 @@ def ActivityItemDefAliasUpdate(inDef, inAliasStr, inGSettings = None): inAliasStr="TestDefAlias") # Now you can call TestDef by the alias "TestDefAlias" with help of ActivityItem (key Def = "TestDefAlias") - :param inGSettings: Global settings dict (singleton) - :param inDef: Def - :param inAliasStr: String alias for associated def - :return: str Alias string + :param inDef: функция Python + :param inAliasStr: Строковый ключ (синоним), который можно будет использовать в Активности (ActivityItem) + :param inGSettings: Глобальный словарь настроек Оркестратора (синглтон) + :return: Строковый ключ, который был назначен. Ключ будет тем же, если входящий текстовый ключ был уже занят. """ inGSettings = GSettingsGet(inGSettings=inGSettings) # Set the global settings if callable(inDef): inGSettings["ProcessorDict"]["AliasDefDict"][inAliasStr] = inDef @@ -1590,14 +1629,16 @@ def ActivityItemDefAliasUpdate(inDef, inAliasStr, inGSettings = None): def ProcessorActivityItemCreate(inDef, inArgList=None, inArgDict=None, inArgGSettingsStr=None, inArgLoggerStr=None, inGUIDStr = None, inThreadBool = False): """ - Create activity item. Activity item can be used as list item in ProcessorActivityItemAppend or in Processor.ActivityListExecute. - Deprecated. See ActivityItemCreate + Создать Активность (ActivityItem). Активность можно использовать в ProcessorActivityItemAppend или в Processor.ActivityListExecute или в функциях работы с Агентами. + + Старая версия. Новую версию см. в ActivityItemCreate + .. code-block:: python - # USAGE + # ПРИМЕР from pyOpenRPA import Orchestrator - # EXAMPLE 1 + # ВАРИАНТ 1 def TestDef(inArg1Str, inGSettings, inLogger): pass lActivityItem = Orchestrator.ProcessorActivityItemCreate( @@ -1615,7 +1656,7 @@ def ProcessorActivityItemCreate(inDef, inArgList=None, inArgDict=None, inArgGSet # "ArgLogger": "inLogger" # } - # EXAMPLE 2 + # ВАРИАНТ 2 def TestDef(inArg1Str): pass Orchestrator.ProcessorAliasDefUpdate( @@ -1637,22 +1678,31 @@ def ProcessorActivityItemCreate(inDef, inArgList=None, inArgDict=None, inArgGSet # "ArgLogger": None # } - :param inDef: def link or def alias (look gSettings["Processor"]["AliasDefDict"]) - :param inArgList: Args list for the Def - :param inArgDict: Args dict for the def - :param inArgGSettingsStr: Name of def argument of the GSettings dict - :param inArgLoggerStr: Name of def argument of the logging object - :param inGUIDStr: GUID which you can specify. If None the GUID will be generated - :param inThreadBool: True - execute ActivityItem in new thread; False - in processor thread - :return: {} + :param inDef: Функция Python или синоним (текстовый ключ) + :param inArgList: Список (list) неименованных аргументов к функции + :param inArgDict: Словарь (dict) именованных аргументов к функции + :param inArgGSettingsStr: Текстовое наименование аргумента GSettings (если требуется передавать) + :param inArgLoggerStr: Текстовое наименование аргумента logger (если требуется передавать) + :param inGUIDStr: ГУИД идентификатор активности (ActivityItem). Если ГУИД не указан, то он будет сгенерирован автоматически + :param inThreadBool: True - выполнить ActivityItem в новом потоке; False - выполнить последовательно в общем потоке процессорной очереди + :return: + lActivityItemDict= { + "Def":inDef, # def link or def alias (look gSettings["Processor"]["AliasDefDict"]) + "ArgList":inArgList, # Args list + "ArgDict":inArgDict, # Args dictionary + "ArgGSettings": inArgGSettingsStr, # Name of GSettings attribute: str (ArgDict) or index (for ArgList) + "ArgLogger": inArgLoggerStr, # Name of GSettings attribute: str (ArgDict) or index (for ArgList) + "GUIDStr": inGUIDStr, + "ThreadBool": inThreadBool + } """ return ActivityItemCreate(inDef=inDef, inArgList=inArgList, inArgDict=inArgDict, inArgGSettingsStr=inArgGSettingsStr, inArgLoggerStr=inArgLoggerStr, inGUIDStr=inGUIDStr, inThreadBool=inThreadBool) def ProcessorActivityItemAppend(inGSettings = None, inDef=None, inArgList=None, inArgDict=None, inArgGSettingsStr=None, inArgLoggerStr=None, inActivityItemDict=None): """ - Create and add activity item in processor queue. - + Добавить активность (ActivityItem) в процессорную очередь. + .. code-block:: python # USAGE @@ -1688,14 +1738,16 @@ def ProcessorActivityItemAppend(inGSettings = None, inDef=None, inArgList=None, inActivityItemDict = lActivityItem) # Activity have been already append in the processor queue - :param inGSettings: Global settings dict (singleton) - :param inDef: def link or def alias (look gSettings["Processor"]["AliasDefDict"]) - :param inArgList: Args list for the Def - :param inArgDict: Args dict for the Def - :param inArgGSettingsStr: Name of def argument of the GSettings dict - :param inArgLoggerStr: Name of def argument of the logging object - :param inActivityItemDict: Fill if you already have ActivityItemDict (don't fill inDef, inArgList, inArgDict, inArgGSettingsStr, inArgLoggerStr) - :return ActivityItem GUIDStr + :param inGSettings: Глобальный словарь настроек Оркестратора (синглтон) + :param inDef: Функция Python или синоним (текстовый ключ) + :param inArgList: Список (list) неименованных аргументов к функции + :param inArgDict: Словарь (dict) именованных аргументов к функции + :param inArgGSettingsStr: Текстовое наименование аргумента GSettings (если требуется передавать) + :param inArgLoggerStr: Текстовое наименование аргумента logger (если требуется передавать) + :param inGUIDStr: ГУИД идентификатор активности (ActivityItem). Если ГУИД не указан, то он будет сгенерирован автоматически + :param inThreadBool: True - выполнить ActivityItem в новом потоке; False - выполнить последовательно в общем потоке процессорной очереди + :param inActivityItemDict: Альтернативный вариант заполнения, если уже имеется Активность (ActivityItem). В таком случае не требуется заполнять аргументы inDef, inArgList, inArgDict, inArgGSettingsStr, inArgLoggerStr + :return ГУИД активности (ActivityItem) """ inGSettings = GSettingsGet(inGSettings=inGSettings) # Set the global settings if inActivityItemDict is None: @@ -1727,18 +1779,20 @@ def ProcessorActivityItemAppend(inGSettings = None, inDef=None, inArgList=None, ## Process defs def ProcessIsStarted(inProcessNameWOExeStr): # Check if process is started """ - Check if there is any running process that contains the given name processName. + Проверить, запущен ли процесс, который в наименовании содержит inProcessNameWOExeStr. + !ВНИМАНИЕ! ПРОВЕРЯЕТ ВСЕ ПРОЦЕССЫ ОПЕРАЦИОННОЙ СИСТЕМЫ. И ДРУГИХ ПОЛЬЗОВАТЕЛЬСКИХ СЕССИЙ, ЕСЛИ ОНИ ЗАПУЩЕНЫ НА ЭТОЙ МАШИНЕ. + .. code-block:: python - # USAGE + # ПРИМЕР from pyOpenRPA import Orchestrator lProcessIsStartedBool = Orchestrator.ProcessIsStarted(inProcessNameWOExeStr = "notepad") # lProcessIsStartedBool is True - notepad.exe is running on the Orchestrator machine - :param inProcessNameWOExeStr: Process name WithOut (WO) '.exe' postfix. Example: "notepad" (not "notepad.exe") - :return: True - process is running on the orchestrator machine; False - process is not running on the orchestrator machine + :param inProcessNameWOExeStr: Наименование процесса без расширения .exe (WO = WithOut = Без) Пример: Для проверки процесса блокнота нужно указывать "notepad", не "notepad.exe" + :return: True - Процесс запущен на ОС ; False - Процесс не запущен на ОС, где работает Оркестратор """ #Iterate over the all the running process for proc in psutil.process_iter(): @@ -1752,11 +1806,13 @@ def ProcessIsStarted(inProcessNameWOExeStr): # Check if process is started def ProcessStart(inPathStr, inArgList, inStopProcessNameWOExeStr=None): """ - Start process locally. Extra feature: Use inStopProcessNameWOExeStr to stop the execution if current process is running. + Запуск процесса на сессии Оркестратора, если на ОС не запущен процесс inStopProcessNameWOExeStr. + + !ВНИМАНИЕ! ПРИ ПРОВЕРКЕ РАНЕЕ ЗАПУЩЕННЫХ ПРОЦЕССОВ ПРОВЕРЯЕТ ВСЕ ПРОЦЕССЫ ОПЕРАЦИОННОЙ СИСТЕМЫ. И ДРУГИХ ПОЛЬЗОВАТЕЛЬСКИХ СЕССИЙ, ЕСЛИ ОНИ ЗАПУЩЕНЫ НА ЭТОЙ МАШИНЕ. .. code-block:: python - # USAGE + # ПРИМЕР from pyOpenRPA import Orchestrator Orchestrator.ProcessStart( @@ -1765,10 +1821,9 @@ def ProcessStart(inPathStr, inArgList, inStopProcessNameWOExeStr=None): inStopProcessNameWOExeStr = "notepad") # notepad.exe will be started if no notepad.exe is active on the machine - :param inPathStr: Command to send in CMD - :param inArgList: List of the arguments for the CMD command. Example: ["test.txt"] - :param inStopProcessNameWOExeStr: Trigger: stop execution if process is running. Process name WithOut (WO) '.exe' postfix. Example: "notepad" (not "notepad.exe") - :return: None - nothing is returned. If process will not start -exception will be raised + :param inPathStr: Путь к файлу запускаемого процесса + :param inArgList: Список аргументов, передаваемых в запускаемый процесс. Пример: ["test.txt"] + :param inStopProcessNameWOExeStr: Доп. контроль: Не запускать процесс, если обнаружен запущенный процесс под наименованием inStopProcessNameWOExeStr без расширения .exe (WO = WithOut = Без) """ lStartProcessBool = True if inStopProcessNameWOExeStr is not None: #Check if process running @@ -1789,11 +1844,11 @@ def ProcessStart(inPathStr, inArgList, inStopProcessNameWOExeStr=None): def ProcessStop(inProcessNameWOExeStr, inCloseForceBool, inUserNameStr = "%username%"): """ - Stop process on the orchestrator machine. You can set user session on the machine and set flag about to force close process. + Остановить процесс на ОС, где работает Оркестратор, под учетной записью inUserNameStr. .. code-block:: python - # USAGE + # ПРИМЕР from pyOpenRPA import Orchestrator Orchestrator.ProcessStop( @@ -1802,10 +1857,9 @@ def ProcessStop(inProcessNameWOExeStr, inCloseForceBool, inUserNameStr = "%usern inUserNameStr = "USER_99") # Will close process "notepad.exe" on the user session "USER_99" (!ATTENTION! if process not exists no exceptions will be raised) - :param inProcessNameWOExeStr: Process name WithOut (WO) '.exe' postfix. Example: "notepad" (not "notepad.exe") - :param inCloseForceBool: True - do force close. False - send signal to safe close (!ATTENTION! - Safe close works only in orchestrator session. Win OS doens't allow to send safe close signal between GUI sessions) - :param inUserNameStr: User name which is has current process to close. Default value is close process on the Orchestrator session - :return: None + :param inProcessNameWOExeStr: Наименование процесса без расширения .exe (WO = WithOut = Без). Пример: Для проверки процесса блокнота нужно указывать "notepad", не "notepad.exe" + :param inCloseForceBool: True - принудительно завершить процесс. False - отправить сигнал на безопасное отключение (!ВНИМАНИЕ! - ОС не позволяет отправлять сигнал на безопасное отключение на другую сесиию - только на той, где работает Оркестратор) + :param inUserNameStr: Наименование пользователя, под именем которого искать процесс для остановки. По умолчанию "%username%" - искать процесс на текущей сессии """ # Support input arg if with .exe lProcessNameWExeStr = inProcessNameWOExeStr @@ -1826,30 +1880,32 @@ def ProcessStop(inProcessNameWOExeStr, inCloseForceBool, inUserNameStr = "%usern def ProcessListGet(inProcessNameWOExeList=None): """ - Return process list on the orchestrator machine sorted by Memory Usage. You can determine the list of the processes you are interested - def will return the list about it. + Вернуть список процессов, запущенных на ОС, где работает Оркестратор. В списке отсортировать процессы по количеству используемой оперативной памяти. Также можно указать перечень процессов, которые интересуют - функция будет показывать активные из них. + + !ВНИМАНИЕ! ДЛЯ ПОЛУЧЕНИЯ СПИСКА ВСЕХ ПРОЦЕССОВ ОС НЕОБХОДИМО ЗАПУСКАТЬ ОРКЕСТРАТОР С ПРАВАМИ АДМИНИСТРАТОРА. .. code-block:: python - # USAGE + # ПРИМЕР from pyOpenRPA import Orchestrator lProcessList = Orchestrator.ProcessListGet() # Return the list of the process on the machine. # !ATTENTION! RUn orchestrator as administrator to get all process list on the machine. - :param inProcessNameWOExeList: - :return: { - "ProcessWOExeList": ["notepad","..."], - "ProcessWOExeUpperList": ["NOTEPAD","..."], - "ProcessDetailList": [ - { - 'pid': 412, - 'username': "DESKTOP\\USER", - 'name': 'notepad.exe', - 'vms': 13.77767775, - 'NameWOExeUpperStr': 'NOTEPAD', - 'NameWOExeStr': "'notepad'"}, - {...}] + :param inProcessNameWOExeList: Список процессов, среди которых искать активные. Если параметр не указывать - вернет перечень всех доступных процессов + :return: Сведения о запущенных процессах в следующем формате { + "ProcessWOExeList": ["notepad","..."], + "ProcessWOExeUpperList": ["NOTEPAD","..."], + "ProcessDetailList": [ + { + 'pid': 412, # Идентификатор процесса + 'username': "DESKTOP\\USER", + 'name': 'notepad.exe', + 'vms': 13.77767775, # В Мб + 'NameWOExeUpperStr': 'NOTEPAD', + 'NameWOExeStr': "'notepad'"}, + {...}] """ if inProcessNameWOExeList is None: inProcessNameWOExeList = [] @@ -1884,19 +1940,18 @@ def ProcessListGet(inProcessNameWOExeList=None): def ProcessDefIntervalCall(inDef, inIntervalSecFloat, inIntervalAsyncBool=False, inDefArgList=None, inDefArgDict=None, inDefArgGSettingsNameStr=None, inDefArgLoggerNameStr=None, inExecuteInNewThreadBool=True, inLogger=None, inGSettings = None): """ - Use this procedure if you need to run periodically some def. Set def, args, interval and enjoy :) - - :param inGSettings: global settings - :param inDef: def link, which will be called with interval inIntervalSecFloat - :param inIntervalSecFloat: Interval in seconds between call - :param inIntervalAsyncBool: False - wait interval before next call after the previous iteration result; True - wait interval after previous iteration call - :param inDefArgList: List of the args in def. Default None (empty list) - :param inDefArgDict: Dict of the args in def. Default None (empty dict) - :param inDefArgGSettingsNameStr: Name of the GSettings arg name for def (optional) - :param inDefArgLoggerNameStr: Name of the Logger arg name for def (optional). If Use - please check fill of the inLogger arg. - :param inExecuteInNewThreadBool: True - create new thread for the periodic execution; False - execute in current thread. Default: True - :param inLogger: logging def if some case is appear - :return: + Периодический вызов функции Python. + + :param inDef: Функция Python, которую потребуется периодически вызывать + :param inIntervalSecFloat: Интервал между вызовами функции в сек. + :param inIntervalAsyncBool: False - ожидать интервал inIntervalSecFloat только после окончания выполнения предыдущей итерации; True - Ожидать интервал сразу после запуска итерации + :param inDefArgList: Список (list) неименованных аргументов для передачи в функцию. По умолчанию None + :param inDefArgDict: Словарь (dict) именованных аргументов для передачи в функцию. По умолчанию None + :param inDefArgGSettingsNameStr: Наименование аргумента глобального словаря настроек Оркестратора GSettings (опционально) + :param inDefArgLoggerNameStr: Наименование аргумента логгера Оркестратора (опционально) + :param inExecuteInNewThreadBool: True - периодический вызов выполнять в отдельном потоке (не останавливать выполнение текущего потока); False - Выполнение периодического вызова в текущем потоке, в котором была вызвана функция ProcessDefIntervalCall. По умолчанию: True + :param inLogger: Логгер для фиксации сообщений выполнения функции (опционально) + :param inGSettings: Глобальный словарь настроек Оркестратора (синглтон) """ inGSettings = GSettingsGet(inGSettings=inGSettings) # Set the global settings if inLogger is None: inLogger = OrchestratorLoggerGet() @@ -1965,15 +2020,15 @@ def ProcessDefIntervalCall(inDef, inIntervalSecFloat, inIntervalAsyncBool=False, # Python def - start module function def PythonStart(inModulePathStr, inDefNameStr, inArgList=None, inArgDict=None, inLogger = None): """ - Import module and run def in the Orchestrator process. + Импорт модуля и выполнение функции в процессе Оркестратора. .. note:: - Import module will be each time when PythonStart def will be called. + Импорт модуля inModulePathStr будет происходить каждый раз в вызовом функции PythonStart. .. code-block:: python - # USAGE + # ПРИМЕР from pyOpenRPA import Orchestrator Orchestrator.PythonStart( @@ -1981,12 +2036,11 @@ def PythonStart(inModulePathStr, inDefNameStr, inArgList=None, inArgDict=None, i inDefNameStr="TestDef") # Import module in Orchestrator process and call def "TestDef" from module "ModuleToCall.py" - :param inModulePathStr: Absolute or relative (working directory of the orchestrator process) path to the importing module .py - :param inDefNameStr: Def name in module - :param inArgList: List of the arguments for callable def - :param inArgDict: Dict of the named arguments for callable def - :param inLogger: Logger instance to log some information when PythonStart def is running - :return: None + :param inModulePathStr: Абсолютный или относительный путь (относительно рабочей директории процесса Оркестратора), по которому расположен импортируемый .py файл + :param inDefNameStr: Наименование функции в модуле .py + :param inArgList: Список (list) неименованных аргументов для передачи в функцию. По умолчанию None + :param inArgDict: Словарь (dict) именованных аргументов для передачи в функцию. По умолчанию None + :param inLogger: Логгер для фиксации сообщений выполнения функции (опционально) """ if inLogger is None: inLogger = OrchestratorLoggerGet() if inArgList is None: inArgList=[] @@ -2001,17 +2055,16 @@ def PythonStart(inModulePathStr, inDefNameStr, inArgList=None, inArgDict=None, i # # # # # # # # # # # # # # # # # # # # # # # # Scheduler # # # # # # # # # # # # # # # # # # # # # # # - def SchedulerActivityTimeAddWeekly(inTimeHHMMStr="23:55:", inWeekdayList=None, inActivityList=None, inGSettings = None): """ - Add activity item list in scheduler. You can set weekday list and set time when launch. Activity list will be executed at planned time/day. + Добавить активность по расписанию. Допускается указание времени и дней недели, в которые производить запуск. .. code-block:: python - # USAGE + # ПРИМЕР from pyOpenRPA import Orchestrator - # EXAMPLE 1 + # ВАРИАНТ 1 def TestDef(inArg1Str): pass lActivityItem = Orchestrator.ProcessorActivityItemCreate( @@ -2027,11 +2080,10 @@ def SchedulerActivityTimeAddWeekly(inTimeHHMMStr="23:55:", inWeekdayList=None, i inActivityList = [lActivityItem]) # Activity will be executed at 04:34 Wednesday (2), thursday (3), friday (4) - :param inGSettings: Global settings dict (singleton) - :param inTimeHHMMStr: Activation time from "00:00" to "23:59". Example: "05:29" - :param inWeekdayList: Week day list to initiate activity list. Use int from 0 (monday) to 6 (sunday) as list items. Example: [0,1,2,3,4]. Default value is everyday ([0,1,2,3,4,5,6]) - :param inActivityList: Activity list structure - :return: None + :param inGSettings: Глобальный словарь настроек Оркестратора (синглтон) + :param inTimeHHMMStr: Время запуска активности. Допускаются значения от "00:00" до "23:59". Example: "05:29" + :param inWeekdayList: Список (list) дней недели, в которые выполнять запуск список активностей (ActivityItem list). 0 (понедельник) - 6 (воскресенье). Пример: [0,1,2,3,4]. По умолчанию устанавливается каждый день [0,1,2,3,4,5,6] + :param inActivityList: Список активностей (ActivityItem list) на исполнение """ inGSettings = GSettingsGet(inGSettings=inGSettings) # Set the global settings if inWeekdayList is None: inWeekdayList=[0,1,2,3,4,5,6] @@ -2052,11 +2104,11 @@ def SchedulerActivityTimeAddWeekly(inTimeHHMMStr="23:55:", inWeekdayList=None, i def RDPTemplateCreate(inLoginStr, inPasswordStr, inHostStr="127.0.0.1", inPortInt = 3389, inWidthPXInt = 1680, inHeightPXInt = 1050, inUseBothMonitorBool = False, inDepthBitInt = 32, inSharedDriveList=None, inRedirectClipboardBool=True): """ - Create RDP connect dict item/ Use it connect/reconnect (Orchestrator.RDPSessionConnect) + Создать шаблон подключения RDP (dict). Данный шаблон далее можно использовать в Orchestrator.RDPSessionConnect .. code-block:: python - # USAGE + # ПРИМЕР from pyOpenRPA import Orchestrator lRDPItemDict = Orchestrator.RDPTemplateCreate( @@ -2068,49 +2120,38 @@ def RDPTemplateCreate(inLoginStr, inPasswordStr, inHostStr="127.0.0.1", inPortIn inHeightPXInt = 1050, inUseBothMonitorBool = False, inDepthBitInt = 32, - inSharedDriveList=None) - # lRDPTemplateDict= { # Init the configuration item - # "Host": "127.0.0.1", "Port": "3389", "Login": "USER_99", "Password": "USER_PASS_HERE", - # "Screen": { "Width": 1680, "Height": 1050, "FlagUseAllMonitors": False, "DepthBit": "32" }, - # "SharedDriveList": ["c"], - # "RedirectClipboardBool": True, # True - share clipboard to RDP; False - else - # ###### Will updated in program ############ - # "SessionHex": "77777sdfsdf77777dsfdfsf77777777", # Hex is created when robot runs, example "" - # "SessionIsWindowExistBool": False, "SessionIsWindowResponsibleBool": False, "SessionIsIgnoredBool": False - # } - - :param inLoginStr: User/Robot Login, example "USER_99" - :param inPasswordStr: Password, example "USER_PASS_HERE" - :param inHostStr: Host address, example "77.77.22.22" - :param inPortInt: RDP Port, example "3389" (default) - :param inWidthPXInt: Width of the remote desktop in pixels, example 1680 - :param inHeightPXInt: Height of the remote desktop in pixels, example 1050 - :param inUseBothMonitorBool: True - connect to the RDP with both monitors. False - else case - :param inDepthBitInt: Remote desktop bitness. Available: 32 or 24 or 16 or 15, example 32 - :param inSharedDriveList: Host local disc to connect to the RDP session. Example: ["c", "d"] - :param inRedirectClipboardBool: # True - share clipboard to RDP; False - else + inSharedDriveList=None, + inRedirectClipboardBool=False) + + :param inLoginStr: Логин учетной записи, на которую будет происходить вход по RDP + :param inPasswordStr: Пароль учетной записи, на которую будет происходить вход по RDP. !ВНИМАНИЕ! Пароль нигде не сохраняется - конфиденциальность обеспечена + :param inHostStr: Имя хоста, к которому планируется подключение по RDP. Пример "77.77.22.22" + :param inPortInt: RDP порт, по которому будет происходить подключение. По умолчанию 3389 (стандартный порт RDP) + :param inWidthPXInt: Разрешение ширины RDP графической сессии в пикселях. По умолчанию 1680 + :param inHeightPXInt: Разрешение высоты RDP графической сессии в пикселях. По умолчанию 1050 + :param inUseBothMonitorBool: True - Использовать все подключенные мониторы на RDP сессии; False - Использовать только один монитор на подключенной RDP сессии + :param inDepthBitInt: Глубина цвета на удаленной RDP графической сессии. Допустимые варианты: 32 || 24 || 16 || 15. По умолчанию 32 + :param inSharedDriveList: Перечень общих дисков, доступ к которым предоставить на сторону удаленной RDP сессии. Пример: ["c", "d"] + :param inRedirectClipboardBool: True - Синхронизировать буфер обмена между сессией Оркестратора и удаленной RDP сессией; False - Не синхронизировать буфер обмена. По умолчанию True (в целях обратной совместимости). !ВНИМАНИЕ! Для учетных записей роботов мы рекомендуем не синхронизировать буфер обмена, так как это может привести к ошибкам роботов, которые работают с клавиатурой и буфером обмена :return: { - "Host": inHostStr, # Host address, example "77.77.22.22" - "Port": str(inPortInt), # RDP Port, example "3389" - "Login": inLoginStr, # Login, example "test" - "Password": inPasswordStr, # Password, example "test" + "Host": inHostStr, # Адрес хоста, пример "77.77.22.22" + "Port": str(inPortInt), # RDP порт, пример "3389" + "Login": inLoginStr, # Логин УЗ, пример "test" + "Password": inPasswordStr, # Пароль УЗ, пример "test" "Screen": { - "Width": inWidthPXInt, # Width of the remote desktop in pixels, example 1680 - "Height": inHeightPXInt, # Height of the remote desktop in pixels, example 1050 - # "640x480" or "1680x1050" or "FullScreen". If Resolution not exists set full screen, example - "FlagUseAllMonitors": inUseBothMonitorBool, # True or False, example False - "DepthBit": str(inDepthBitInt) # "32" or "24" or "16" or "15", example "32" + "Width": inWidthPXInt, # Разрешение ширины RDP графической сессии в пикселях. По умолчанию 1680 + "Height": inHeightPXInt, Разрешение высоты RDP графической сессии в пикселях. По умолчанию 1050 + "FlagUseAllMonitors": inUseBothMonitorBool, + "DepthBit": str(inDepthBitInt) }, - "SharedDriveList": inSharedDriveList, # List of the Root sesion hard drives, example ["c"] - "RedirectClipboardBool": True, # True - share clipboard to RDP; False - else - ###### Will updated in program ############ - "SessionHex": "77777sdfsdf77777dsfdfsf77777777", # Hex is created when robot runs, example "" + "SharedDriveList": inSharedDriveList, + "RedirectClipboardBool": True, + ###### PROGRAM VARIABLE ############ + "SessionHex": "77777sdfsdf77777dsfdfsf77777777", "SessionIsWindowExistBool": False, - # Flag if the RDP window is exist, old name "FlagSessionIsActive". Check every n seconds , example False "SessionIsWindowResponsibleBool": False, - # Flag if RDP window is responsible (recieve commands). Check every nn seconds. If window is Responsible - window is Exist too , example False - "SessionIsIgnoredBool": False # Flag to ignore RDP window False - dont ignore, True - ignore, example False + "SessionIsIgnoredBool": False } """ @@ -2144,27 +2185,22 @@ def RDPTemplateCreate(inLoginStr, inPasswordStr, inHostStr="127.0.0.1", inPortIn # TODO Search dublicates in GSettings RDPlist ! # Return list if dublicates def RDPSessionDublicatesResolve(inGSettings): - """ - DEVELOPING Search duplicates in GSettings RDPlist - !def is developing! - - :param inGSettings: Global settings dict (singleton) - :return: - """ pass #for lItemKeyStr in inGSettings["RobotRDPActive"]["RDPList"]: # lItemDict = inGSettings["RobotRDPActive"]["RDPList"][lItemKeyStr] def RDPSessionConnect(inRDPSessionKeyStr, inRDPTemplateDict=None, inHostStr=None, inPortStr=None, inLoginStr=None, inPasswordStr=None, inGSettings = None, inRedirectClipboardBool=True): """ - Create new RDPSession in RobotRDPActive. Attention - activity will be ignored if RDP key is already exists - 2 way of the use - Var 1 (Main stream): inGSettings, inRDPSessionKeyStr, inRDPTemplateDict - Var 2 (Backward compatibility): inGSettings, inRDPSessionKeyStr, inHostStr, inPortStr, inLoginStr, inPasswordStr + Выполнить подключение к RDP и следить за стабильностью соединения со стороны Оркестратора. + !ВНИМАНИЕ! - Подключение будет проигнорировано, если соединение по таком RDP ключу уже было инициализировано ранее. + + 2 способа использования функции: + ВАРИАНТ 1 (ОСНОВНОЙ): inGSettings, inRDPSessionKeyStr, inRDPTemplateDict. Для получения inRDPTemplateDict см. функцию Orchestrator.RDPTemplateCreate + ВАРИАНТ 2 (ОБРАТНАЯ СОВМЕСТИМОСТЬ ДО ВЕРСИИ 1.1.20): inGSettings, inRDPSessionKeyStr, inHostStr, inPortStr, inLoginStr, inPasswordStr .. code-block:: python - # USAGE + # ПРИМЕР (ВАРИАНТ 1) from pyOpenRPA import Orchestrator lRDPItemDict = Orchestrator.RDPTemplateCreate( @@ -2176,15 +2212,15 @@ def RDPSessionConnect(inRDPSessionKeyStr, inRDPTemplateDict=None, inHostStr=None inRDPSessionKeyStr = "RDPKey", inRDPTemplateDict = lRDPItemDict) # Orchestrator will create RDP session by the lRDPItemDict configuration - - :param inGSettings: Global settings dict (singleton) - :param inRDPSessionKeyStr: RDP Session string key - need for the further identification - :param inRDPTemplateDict: RDP configuration dict with settings (see def Orchestrator.RDPTemplateCreate) - :param inHostStr: Backward compatibility from Orchestrator v 1.1.20. Use inRDPTemplateDict - :param inPortStr: Backward compatibility from Orchestrator v 1.1.20. Use inRDPTemplateDict - :param inLoginStr: Backward compatibility from Orchestrator v 1.1.20. Use inRDPTemplateDict - :param inPasswordStr: Backward compatibility from Orchestrator v 1.1.20. Use inRDPTemplateDict - :return: True every time :) + + :param inRDPSessionKeyStr: Ключ RDP сессии - необходим для дальнейшей идентификации + :param inRDPTemplateDict: Конфигурационный словарь (dict) RDP подключения (см. функцию Orchestrator.RDPTemplateCreate) + :param inLoginStr: Логин учетной записи, на которую будет происходить вход по RDP. Обратная совместимость до версии v 1.1.20. Мы рекомендуем использовать inRDPTemplateDict (см. функцию Orchestrator.RDPTemplateCreate) + :param inPasswordStr: Пароль учетной записи, на которую будет происходить вход по RDP. !ВНИМАНИЕ! Пароль нигде не сохраняется - конфиденциальность обеспечена. Обратная совместимость до версии v 1.1.20. Мы рекомендуем использовать inRDPTemplateDict (см. функцию Orchestrator.RDPTemplateCreate) + :param inHostStr: Имя хоста, к которому планируется подключение по RDP. Пример "77.77.22.22". Обратная совместимость до версии v 1.1.20. Мы рекомендуем использовать inRDPTemplateDict (см. функцию Orchestrator.RDPTemplateCreate) + :param inPortInt: RDP порт, по которому будет происходить подключение. По умолчанию 3389 (стандартный порт RDP). Обратная совместимость до версии v 1.1.20. Мы рекомендуем использовать inRDPTemplateDict (см. функцию Orchestrator.RDPTemplateCreate) + :param inGSettings: Глобальный словарь настроек Оркестратора (синглтон) + :param inRedirectClipboardBool: True - Синхронизировать буфер обмена между сессией Оркестратора и удаленной RDP сессией; False - Не синхронизировать буфер обмена. По умолчанию True (в целях обратной совместимости). !ВНИМАНИЕ! Для учетных записей роботов мы рекомендуем не синхронизировать буфер обмена, так как это может привести к ошибкам роботов, которые работают с клавиатурой и буфером обмена """ inGSettings = GSettingsGet(inGSettings=inGSettings) # Set the global settings # Check thread @@ -2217,11 +2253,11 @@ def RDPSessionConnect(inRDPSessionKeyStr, inRDPTemplateDict=None, inHostStr=None def RDPSessionDisconnect(inRDPSessionKeyStr, inBreakTriggerProcessWOExeList = None, inGSettings = None): """ - Disconnect the RDP session and stop monitoring it. + Выполнить отключение RDP сессии и прекратить мониторить его активность. .. code-block:: python - # USAGE + # ПРИМЕР from pyOpenRPA import Orchestrator Orchestrator.RDPSessionDisconnect( @@ -2229,14 +2265,9 @@ def RDPSessionDisconnect(inRDPSessionKeyStr, inBreakTriggerProcessWOExeList = No inRDPSessionKeyStr = "RDPKey") # Orchestrator will disconnect RDP session and will stop to monitoring current RDP - :param inGSettings: Global settings dict (singleton) - :param inRDPSessionKeyStr: RDP Session string key - need for the further identification - :param inBreakTriggerProcessWOExeList: List of the processes, which will stop the execution. Example ["notepad"] - - .. note:: - - Orchestrator look processes on the current machine - :return: True every time + :param inRDPSessionKeyStr: Ключ RDP сессии - необходим для дальнейшей идентификации + :param inBreakTriggerProcessWOExeList: Список процессов, наличие которых в диспетчере задач приведет к прерыванию задачи по остановке RDP соединения. Пример ["notepad"] + :param inGSettings: Глобальный словарь настроек Оркестратора (синглтон) """ inGSettings = GSettingsGet(inGSettings=inGSettings) # Set the global settings if inBreakTriggerProcessWOExeList is None: inBreakTriggerProcessWOExeList = [] @@ -2265,11 +2296,11 @@ def RDPSessionDisconnect(inRDPSessionKeyStr, inBreakTriggerProcessWOExeList = No def RDPSessionReconnect(inRDPSessionKeyStr, inRDPTemplateDict=None, inGSettings = None): """ - Reconnect the RDP session + Выполнить переподключение RDP сессии и продолжить мониторить его активность. .. code-block:: python - # USAGE + # ПРИМЕР from pyOpenRPA import Orchestrator lRDPItemDict = Orchestrator.RDPTemplateCreate( @@ -2282,10 +2313,9 @@ def RDPSessionReconnect(inRDPSessionKeyStr, inRDPTemplateDict=None, inGSettings inRDPTemplateDict = inRDPTemplateDict) # Orchestrator will reconnect RDP session and will continue to monitoring current RDP - :param inGSettings: Global settings dict (singleton) - :param inRDPSessionKeyStr: RDP Session string key - need for the further identification - :param inRDPTemplateDict: RDP configuration dict with settings (see def Orchestrator.RDPTemplateCreate) - :return: + :param inRDPSessionKeyStr: Ключ RDP сессии - необходим для дальнейшей идентификации + :param inRDPTemplateDict: Конфигурационный словарь (dict) RDP подключения (см. функцию Orchestrator.RDPTemplateCreate) + :param inGSettings: Глобальный словарь настроек Оркестратора (синглтон) """ inGSettings = GSettingsGet(inGSettings=inGSettings) # Set the global settings # Check thread @@ -2312,11 +2342,11 @@ def RDPSessionReconnect(inRDPSessionKeyStr, inRDPTemplateDict=None, inGSettings def RDPSessionMonitorStop(inRDPSessionKeyStr, inGSettings = None): """ - Stop monitoring the RDP session by the Orchestrator process. Current def don't kill RDP session - only stop to track it (it can give ) - + Прекратить мониторить активность RDP соединения со стороны Оркестратора. Данная функция не уничтожает активное RDP соединение. + .. code-block:: python - # USAGE + # ПРИМЕР from pyOpenRPA import Orchestrator Orchestrator.RDPSessionMonitorStop( @@ -2324,9 +2354,8 @@ def RDPSessionMonitorStop(inRDPSessionKeyStr, inGSettings = None): inRDPSessionKeyStr = "RDPKey") # Orchestrator will stop the RDP monitoring - :param inGSettings: Global settings dict (singleton) - :param inRDPSessionKeyStr: RDP Session string key - need for the further identification - :return: True every time :> + :param inRDPSessionKeyStr: Ключ RDP сессии - необходим для дальнейшей идентификации + :param inGSettings: Глобальный словарь настроек Оркестратора (синглтон) """ inGSettings = GSettingsGet(inGSettings=inGSettings) # Set the global settings lResult = True @@ -2335,11 +2364,11 @@ def RDPSessionMonitorStop(inRDPSessionKeyStr, inGSettings = None): def RDPSessionLogoff(inRDPSessionKeyStr, inBreakTriggerProcessWOExeList = None, inGSettings = None): """ - Logoff the RDP session from the Orchestrator process (close all apps in session when logoff) + Выполнить отключение (logoff) на RDP сессии и прекратить мониторить активность со стороны Оркестратора. .. code-block:: python - # USAGE + # ПРИМЕР from pyOpenRPA import Orchestrator Orchestrator.RDPSessionLogoff( @@ -2348,10 +2377,11 @@ def RDPSessionLogoff(inRDPSessionKeyStr, inBreakTriggerProcessWOExeList = None, inBreakTriggerProcessWOExeList = ['Notepad']) # Orchestrator will logoff the RDP session - :param inGSettings: Global settings dict (singleton) - :param inRDPSessionKeyStr: RDP Session string key - need for the further identification - :param inBreakTriggerProcessWOExeList: List of the processes, which will stop the execution. Example ["notepad"] - :return: True - logoff is successful + + :param inRDPSessionKeyStr: Ключ RDP сессии - необходим для дальнейшей идентификации + :param inBreakTriggerProcessWOExeList: Список процессов, наличие которых в диспетчере задач приведет к прерыванию задачи по остановке RDP соединения. Пример ["notepad"] + :param inGSettings: Глобальный словарь настроек Оркестратора (синглтон) + :return: True - Отключение прошло успешно; False - были зафиксированы ошибки при отключении. """ inGSettings = GSettingsGet(inGSettings=inGSettings) # Set the global settings if inBreakTriggerProcessWOExeList is None: inBreakTriggerProcessWOExeList = [] @@ -2382,13 +2412,6 @@ def RDPSessionLogoff(inRDPSessionKeyStr, inBreakTriggerProcessWOExeList = None, return lResult def RDPSessionResponsibilityCheck(inRDPSessionKeyStr, inGSettings = None): - """ - DEVELOPING, MAYBE NOT USEFUL Check RDP Session responsibility TODO NEED DEV + TEST - - :param inGSettings: Global settings dict (singleton) - :param inRDPSessionKeyStr: RDP Session string key - need for the further identification - :return: True every time - """ inGSettings = GSettingsGet(inGSettings=inGSettings) # Set the global settings # Check thread if not Core.IsProcessorThread(inGSettings=inGSettings): @@ -2427,11 +2450,13 @@ def RDPSessionResponsibilityCheck(inRDPSessionKeyStr, inGSettings = None): def RDPSessionProcessStartIfNotRunning(inRDPSessionKeyStr, inProcessNameWEXEStr, inFilePathStr, inFlagGetAbsPathBool=True, inGSettings = None): """ - Start process in RDP if it is not running (check by the arg inProcessNameWEXEStr) + Выполнить запуск процесса на RDP сессии через графические UI инструменты (без Агента). + + !ВНИМАНИЕ! Данная функция может работать нестабильно из-за использования графических элементов UI при работе с RDP. Мы рекомендуем использовать конструкцию взаимодействия Оркестратора с Агентом. .. code-block:: python - # USAGE + # ПРИМЕР from pyOpenRPA import Orchestrator Orchestrator.RDPSessionProcessStartIfNotRunning( @@ -2442,12 +2467,11 @@ def RDPSessionProcessStartIfNotRunning(inRDPSessionKeyStr, inProcessNameWEXEStr, inFlagGetAbsPathBool = True) # Orchestrator will start the process in RDP session - :param inGSettings: Global settings dict (singleton) - :param inRDPSessionKeyStr: RDP Session string key - need for the further identification - :param inProcessNameWEXEStr: Process name with extension (.exe). This arg allow to check the process is running. Example: "Notepad.exe" - :param inFilePathStr: Path to run process if it is not running. - :param inFlagGetAbsPathBool: True - get abs path from the relative path in inFilePathStr. False - else case - :return: True every time :) + :param inRDPSessionKeyStr: Ключ RDP сессии - необходим для дальнейшей идентификации + :param inProcessNameWEXEStr: Наименование процесса с расширением .exe (WEXE - WITH EXE - С EXE). Параметр позволяет не допустить повторного запуска процесса, если он уже был запущен. Example: "Notepad.exe" + :param inFilePathStr: Путь к файлу запуска процесса на стороне RDP сессии + :param inFlagGetAbsPathBool: True - Преобразовать относительный путь inFilePathStr в абсолютный с учетом рабочей директории Оркестратора; False - Не выполнять преобразований + :param inGSettings: Глобальный словарь настроек Оркестратора (синглтон) """ inGSettings = GSettingsGet(inGSettings=inGSettings) # Set the global settings # Check thread @@ -2474,11 +2498,13 @@ def RDPSessionProcessStartIfNotRunning(inRDPSessionKeyStr, inProcessNameWEXEStr, def RDPSessionCMDRun(inRDPSessionKeyStr, inCMDStr, inModeStr="CROSSCHECK", inGSettings = None): """ - Send CMD command to the RDP session "RUN" window + Отправить CMD команду на удаленную сесиию через RDP окно (без Агента). + + !ВНИМАНИЕ! Данная функция может работать нестабильно из-за использования графических элементов UI при работе с RDP. Мы рекомендуем использовать конструкцию взаимодействия Оркестратора с Агентом. .. code-block:: python - # USAGE + # ПРИМЕР from pyOpenRPA import Orchestrator lResultDict = Orchestrator.RDPSessionCMDRun( @@ -2486,18 +2512,18 @@ def RDPSessionCMDRun(inRDPSessionKeyStr, inCMDStr, inModeStr="CROSSCHECK", inGSe inRDPSessionKeyStr = "RDPKey", inModeStr = 'LISTEN') # Orchestrator will send CMD to RDP and return the result (see return section) - - :param inGSettings: Global settings dict (singleton) - :param inRDPSessionKeyStr: RDP Session string key - need for the further identification - :param inCMDStr: Any CMD string - :param inModeStr: Variants: - "LISTEN" - Get result of the cmd command in result; - "CROSSCHECK" - Check if the command was successfully sent - "RUN" - Run without crosscheck and get clipboard - :return: # OLD > True - CMD was executed successfully + + :param inRDPSessionKeyStr: Ключ RDP сессии - необходим для дальнейшей идентификации + :param inCMDStr: Команда CMD, которую отправить на удаленную сессию + :param inModeStr: По умолчанию "CROSSCHECK". Варианты: + "LISTEN" - Получить результат выполнения операции. Внимание! необходим общий буфер обмена с сессией Оркестратора! + "CROSSCHECK" - Выполнить проверку, что операция была выполнена (без получения результата отработки CMD команды). Внимание! необходим общий буфер обмена с сессией Оркестратора! + "RUN" - Не получать результат и не выполнять проверку + :param inGSettings: Глобальный словарь настроек Оркестратора (синглтон) + :return: Результат выполнения операции в соответсвии с параметрами инициализации функции. Выходная структура: { - "OutStr": <> # Result string - "IsResponsibleBool": True|False # Flag is RDP is responsible - works only when inModeStr = CROSSCHECK + "OutStr": <> # Результат выполнения CMD (если inModeStr = "LISTEN") + "IsResponsibleBool": True|False # True - RDP приняло команду; False - обратная связь не была получена (если inModeStr = "CROSSCHECK") } """ inGSettings = GSettingsGet(inGSettings=inGSettings) # Set the global settings @@ -2528,11 +2554,13 @@ def RDPSessionCMDRun(inRDPSessionKeyStr, inCMDStr, inModeStr="CROSSCHECK", inGSe def RDPSessionProcessStop(inRDPSessionKeyStr, inProcessNameWEXEStr, inFlagForceCloseBool, inGSettings = None): """ - Send CMD command to the RDP session "RUN" window. + Отправка CMD команды в RDP окне на остановку процесса (без Агента). + + !ВНИМАНИЕ! Данная функция может работать нестабильно из-за использования графических элементов UI при работе с RDP. Мы рекомендуем использовать конструкцию взаимодействия Оркестратора с Агентом. .. code-block:: python - # USAGE + # ПРИМЕР from pyOpenRPA import Orchestrator lResultDict = Orchestrator.RDPSessionProcessStop( @@ -2542,11 +2570,11 @@ def RDPSessionProcessStop(inRDPSessionKeyStr, inProcessNameWEXEStr, inFlagForceC inFlagForceCloseBool = True) # Orchestrator will send CMD to RDP and return the result (see return section) - :param inGSettings: Global settings dict (singleton) - :param inRDPSessionKeyStr: RDP Session string key - need for the further identification - :param inProcessNameWEXEStr: Process name to kill. Example: 'notepad.exe' - :param inFlagForceCloseBool: True - force close the process. False - safe close the process - :return: True every time + + :param inRDPSessionKeyStr: Ключ RDP сессии - необходим для дальнейшей идентификации + :param inProcessNameWEXEStr: Наименование процесса, который требуется выключить с расширением .exe (WEXE - WITH EXE - С EXE). Пример: "Notepad.exe" + :param inFlagForceCloseBool: True - Принудительное отключение. False - Отправка сигнала на безопасное отключение (если процесс поддерживает) + :param inGSettings: Глобальный словарь настроек Оркестратора (синглтон) """ inGSettings = GSettingsGet(inGSettings=inGSettings) # Set the global settings # Check thread @@ -2574,11 +2602,15 @@ def RDPSessionProcessStop(inRDPSessionKeyStr, inProcessNameWEXEStr, inFlagForceC def RDPSessionFileStoredSend(inRDPSessionKeyStr, inHostFilePathStr, inRDPFilePathStr, inGSettings = None): """ - Send file from Orchestrator session to the RDP session using shared drive in RDP (see RDP Configuration Dict, Shared drive) + Отправка файла со стороны Оркестратора на сторону RDP сессии через UI инструменты RDP окна (без Агента). + + !ВНИМАНИЕ! Данная функция может работать нестабильно из-за использования графических элементов UI при работе с RDP. Мы рекомендуем использовать конструкцию взаимодействия Оркестратора с Агентом. + + !ВНИМАНИЕ! Для работы функции требуется открыть доступ по RDP к тем дискам, с которых будет производится копирование файла. .. code-block:: python - # USAGE + # ПРИМЕР from pyOpenRPA import Orchestrator lResultDict = Orchestrator.RDPSessionFileStoredSend( @@ -2588,11 +2620,10 @@ def RDPSessionFileStoredSend(inRDPSessionKeyStr, inHostFilePathStr, inRDPFilePat inRDPFilePathStr = "C:\\RPA\\TESTDIR\\Test.py") # Orchestrator will send CMD to RDP and return the result (see return section) - :param inGSettings: Global settings dict (singleton) - :param inRDPSessionKeyStr: RDP Session string key - need for the further identification - :param inHostFilePathStr: Relative or absolute path to the file location on the Orchestrator side. Example: "TESTDIR\\Test.py" - :param inRDPFilePathStr: !Absolute! path to the destination file location on the RDP side. Example: "C:\\RPA\\TESTDIR\\Test.py" - :return: True every time + :param inRDPSessionKeyStr: Ключ RDP сессии - необходим для дальнейшей идентификации + :param inHostFilePathStr: Откуда взять файл. Относительный или абсолютный путь к файлу на стороне Оркестратора. Пример: "TESTDIR\\Test.py" + :param inRDPFilePathStr: Куда скопировать файл. !Абсолютный! путь на стороне RDP сессии. Пример: "C:\\RPA\\TESTDIR\\Test.py" + :param inGSettings: Глобальный словарь настроек Оркестратора (синглтон) """ inGSettings = GSettingsGet(inGSettings=inGSettings) # Set the global settings # Check thread @@ -2619,11 +2650,15 @@ def RDPSessionFileStoredSend(inRDPSessionKeyStr, inHostFilePathStr, inRDPFilePat def RDPSessionFileStoredRecieve(inRDPSessionKeyStr, inRDPFilePathStr, inHostFilePathStr, inGSettings = None): """ - Recieve file from RDP session to the Orchestrator session using shared drive in RDP (see RDP Configuration Dict, Shared drive) + Получение файла со стороны RDP сессии на сторону Оркестратора через UI инструменты RDP окна (без Агента). + + !ВНИМАНИЕ! Данная функция может работать нестабильно из-за использования графических элементов UI при работе с RDP. Мы рекомендуем использовать конструкцию взаимодействия Оркестратора с Агентом. + + !ВНИМАНИЕ! Для работы функции требуется открыть доступ по RDP к тем дискам, с которых будет производится копирование файла. .. code-block:: python - # USAGE + # ПРИМЕР from pyOpenRPA import Orchestrator lResultDict = Orchestrator.RDPSessionFileStoredRecieve( @@ -2633,11 +2668,10 @@ def RDPSessionFileStoredRecieve(inRDPSessionKeyStr, inRDPFilePathStr, inHostFile inRDPFilePathStr = "C:\\RPA\\TESTDIR\\Test.py") # Orchestrator will send CMD to RDP and return the result (see return section) - :param inGSettings: Global settings dict (singleton) - :param inRDPSessionKeyStr: RDP Session string key - need for the further identification - :param inRDPFilePathStr: !Absolute! path to the destination file location on the RDP side. Example: "C:\\RPA\\TESTDIR\\Test.py" - :param inHostFilePathStr: Relative or absolute path to the file location on the Orchestrator side. Example: "TESTDIR\\Test.py" - :return: True every time + :param inRDPSessionKeyStr: Ключ RDP сессии - необходим для дальнейшей идентификации + :param inRDPFilePathStr: Откуда скопировать файл. !Абсолютный! путь на стороне RDP сессии. Пример: "C:\\RPA\\TESTDIR\\Test.py" + :param inHostFilePathStr: Куда скопировать файл. Относительный или абсолютный путь к файлу на стороне Оркестратора. Пример: "TESTDIR\\Test.py" + :param inGSettings: Глобальный словарь настроек Оркестратора (синглтон) """ inGSettings = GSettingsGet(inGSettings=inGSettings) # Set the global settings # Check thread @@ -2665,13 +2699,8 @@ def RDPSessionFileStoredRecieve(inRDPSessionKeyStr, inRDPFilePathStr, inHostFile # # # # # Start orchestrator # # # # # # # # # # # # # # # # # # # # # # # +#HIDDEN Interval gSettings auto cleaner def to clear some garbage. def GSettingsAutocleaner(inGSettings=None): - """ - HIDDEN Interval gSettings auto cleaner def to clear some garbage. - - :param inGSettings: Global settings dict (singleton) - :return: None - """ inGSettings = GSettingsGet(inGSettings=inGSettings) # Set the global settings while True: time.sleep(inGSettings["Autocleaner"]["IntervalSecFloat"]) # Wait for the next iteration @@ -2700,23 +2729,15 @@ def GSettingsAutocleaner(inGSettings=None): from .. import __version__ # Get version from the package def Start(inDumpRestoreBool = True, inRunAsAdministratorBool = True): - """ - Start the orchestrator threads execution - - :param inDumpRestoreBool: True - restore data from the dumo - :param inRunAsAdministratorBool: True - rerun as admin if not - :return: - """ Orchestrator(inDumpRestoreBool = True, inRunAsAdministratorBool = True) def Orchestrator(inGSettings=None, inDumpRestoreBool = True, inRunAsAdministratorBool = True): """ - Main def to start orchestrator + Инициализация ядра Оркестратора (всех потоков) - :param inGSettings: - :param inDumpRestoreBool: - :param inRunAsAdministratorBool: - :return: + :param inGSettings: Глобальный словарь настроек Оркестратора (синглтон) + :param inDumpRestoreBool: True - Восстановить информацию о RDP сессиях и StorageDict; False - не восстанавливать + :param inRunAsAdministratorBool: True - Проверить права администратратора и обеспечить их; False - Не обеспечивать права администратора """ lL = inGSettings["Logger"] # https://stackoverflow.com/questions/130763/request-uac-elevation-from-within-a-python-script @@ -2801,8 +2822,6 @@ def Orchestrator(inGSettings=None, inDumpRestoreBool = True, inRunAsAdministrato lRobotRDPActiveThread.start() # Start the thread execution. if lL: lL.info("Robot RDP active has been started") #Logging - - # Init autocleaner in another thread lAutocleanerThread = threading.Thread(target= GSettingsAutocleaner, kwargs={"inGSettings":gSettingsDict}) lAutocleanerThread.daemon = True # Run the thread in daemon mode. diff --git a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/pyOpenRPA/Robot/Clipboard.py b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/pyOpenRPA/Robot/Clipboard.py index 12b43186..279e699b 100644 --- a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/pyOpenRPA/Robot/Clipboard.py +++ b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/pyOpenRPA/Robot/Clipboard.py @@ -4,17 +4,42 @@ import win32clipboard #################################### # GUI Module - interaction with Windows clipboard -################ -###ClipboardGet -################ +def Get(): + """ + Получить текстовое содержимое буфера обмена. + + .. code-block:: python + + # Clipboard: Взаимодействие с буфером + from pyOpenRPA.Robot import Clipboard + lClipStr = Clipboard.Get() + + :return: Текстовое содержимое буфера обмена + :rtype: str + """ + return ClipboardGet() + +def Set(inTextStr:str): + """ + Установить текстовое содержимое в буфер обмена. + + .. code-block:: python + + # Clipboard: Взаимодействие с буфером + from pyOpenRPA.Robot import Clipboard + lClipStr = Clipboard.Set(inTextStr="HELLO WORLD") + + :param inTextStr: Текстовое содержимое для установки в буфера обмена + :type inTextStr: str + """ + ClipboardSet(inText=inTextStr) + def ClipboardGet(): win32clipboard.OpenClipboard() lResult = win32clipboard.GetClipboardData(win32clipboard.CF_UNICODETEXT) win32clipboard.CloseClipboard() return lResult -################ -###ClipboardSet -################ + def ClipboardSet(inText): win32clipboard.OpenClipboard() win32clipboard.EmptyClipboard() diff --git a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/pyOpenRPA/Robot/Keyboard.py b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/pyOpenRPA/Robot/Keyboard.py index b6a278fc..d6cbacc5 100644 --- a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/pyOpenRPA/Robot/Keyboard.py +++ b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/pyOpenRPA/Robot/Keyboard.py @@ -1 +1,344 @@ -from keyboard import * \ No newline at end of file +from keyboard import * +import time + +# Настройки модуля Keyboard +WAIT_AFTER_SEC_FLOAT = 0.4 # Время, которое ожидать после выполнения любой операции модуля Keyboard. Настройка является единой для всех участов кода, использующих модуль Keyboard. Если для некоторой функции требуется изменить данное время ожидания, то в отношении этой функции можно применить соответсвующий аргумент. + +# ШЕСТНАДЦАТИРИЧНЫЙ СКАН-КОД В РУССКОЙ РАСКЛАДКЕ (НЕЗАВИСИМО ОТ ВЫБРАННОГО ЯЗЫКА НА КЛАВИАТУРЕ) +# ОТОБРАЖЕНИЕ СКАН КОДОВ НА КЛАВИАТУРЕ https://snipp.ru/handbk/scan-codes + +KEY_RUS_Ф = 0x1E #A +KEY_RUS_И = 0x30 #B +KEY_RUS_С = 0x2E #C +KEY_RUS_В = 0x20 #D +KEY_RUS_У = 0x12 #E +KEY_RUS_А = 0x21 #F +KEY_RUS_П = 0x22 #G +KEY_RUS_Р = 0x23 #H +KEY_RUS_Ш = 0x17 #I +KEY_RUS_О = 0x24 #J +KEY_RUS_Л = 0x25 #K +KEY_RUS_Д = 0x26 #L +KEY_RUS_Ь = 0x32 #M +KEY_RUS_Т = 0x31 #N +KEY_RUS_Щ = 0x18 #O +KEY_RUS_З = 0x19 #P +KEY_RUS_Й = 0x10 #Q +KEY_RUS_К = 0x13 #R +KEY_RUS_Ы = 0x1F #S +KEY_RUS_Е = 0x14 #T +KEY_RUS_Г = 0x16 #U +KEY_RUS_М = 0x2F #V +KEY_RUS_Ц = 0x11 #W +KEY_RUS_Ч = 0x2D #X +KEY_RUS_Н = 0x15 #Y +KEY_RUS_Я = 0x2C #Z +KEY_RUS_Ё = 0x29 #~ +KEY_RUS_Ж = 0x27 #: +KEY_RUS_Б = 0x33 #< +KEY_RUS_Ю = 0x34 #> +KEY_RUS_Х = 0x1A #[ +KEY_RUS_Ъ = 0x1B #] +KEY_RUS_Э = 0x28 #' + +KEY_ENG_A = 0x1E #A +KEY_ENG_B = 0x30 #B +KEY_ENG_C = 0x2E #C +KEY_ENG_D = 0x20 #D +KEY_ENG_E = 0x12 #E +KEY_ENG_F = 0x21 #F +KEY_ENG_G = 0x22 #G +KEY_ENG_H = 0x23 #H +KEY_ENG_I = 0x17 #I +KEY_ENG_J = 0x24 #J +KEY_ENG_K = 0x25 #K +KEY_ENG_L = 0x26 #L +KEY_ENG_M = 0x32 #M +KEY_ENG_N = 0x31 #N +KEY_ENG_O = 0x18 #O +KEY_ENG_P = 0x19 #P +KEY_ENG_Q = 0x10 #Q +KEY_ENG_R = 0x13 #R +KEY_ENG_S = 0x1F #S +KEY_ENG_T = 0x14 #T +KEY_ENG_U = 0x16 #U +KEY_ENG_V = 0x2F #V +KEY_ENG_W = 0x11 #W +KEY_ENG_X = 0x2D #X +KEY_ENG_Y = 0x15 #Y +KEY_ENG_Z = 0x2C #Z + + +KEY_HOT_NUMPAD_0 = 0x52 +KEY_HOT_NUMPAD_1 = 0x4F +KEY_HOT_NUMPAD_2 = 0x50 +KEY_HOT_NUMPAD_3 = 0x51 +KEY_HOT_NUMPAD_4 = 0x4B +KEY_HOT_NUMPAD_5 = 0x4C +KEY_HOT_NUMPAD_6 = 0x4D +KEY_HOT_NUMPAD_7 = 0x47 +KEY_HOT_NUMPAD_8 = 0x48 +KEY_HOT_NUMPAD_9 = 0x49 +KEY_HOT_NUMPAD_ASTERISK = 0x37 #* +KEY_HOT_NUMPAD_PLUS = 0x4E +KEY_HOT_NUMPAD_MINUS = 0x4A +KEY_HOT_NUMPAD_DELETE = 0x53 +KEY_HOT_NUMPAD_SOLIDUS = 0x35 #/ +KEY_HOT_NUMPAD_ENTER = 0x11c + +KEY_HOT_F1 = 0x3B +KEY_HOT_F2 = 0x3C +KEY_HOT_F3 = 0x3D +KEY_HOT_F4 = 0x3E +KEY_HOT_F5 = 0x3F +KEY_HOT_F6 = 0x40 +KEY_HOT_F7 = 0x41 +KEY_HOT_F8 = 0x42 +KEY_HOT_F9 = 0x43 +KEY_HOT_F10 = 0x44 +KEY_HOT_F11 = 0x57 +KEY_HOT_F12 = 0x58 +KEY_HOT_F13 = 0x7C +KEY_HOT_F14 = 0x7D +KEY_HOT_F15 = 0x7E +KEY_HOT_F16 = 0x7F +KEY_HOT_F17 = 0x80 +KEY_HOT_F18 = 0x81 +KEY_HOT_F19 = 0x82 +KEY_HOT_F20 = 0x83 +KEY_HOT_F21 = 0x84 +KEY_HOT_F22 = 0x85 +KEY_HOT_F23 = 0x86 +KEY_HOT_F24 = 0x87 + +KEY_HOT_TILDE = 0x29 #~ +KEY_HOT_COLON = 0x27 #: +KEY_HOT_PLUS = 0x0D #+ +KEY_HOT_MINUS = 0x0C #- +KEY_HOT_LESS_THAN = 0x33 #< , +KEY_HOT_GREATER_THAN = 0x34 #> . +KEY_HOT_SOLIDUS = 0x35 #/ ? +KEY_HOT_SQUARE_BRACKET_LEFT = 0x1A #[ +KEY_HOT_SQUARE_BRACKET_RIGHT = 0x1B #] +KEY_HOT_APOSTROPHE = 0x28 #' " +KEY_HOT_VERTICAL_LINE = 0x2B #| \ + +KEY_HOT_ESC = 0x1 +KEY_HOT_BACKSPACE = 0x0E +KEY_HOT_TAB = 0x0F +KEY_HOT_ENTER = 0x1C +KEY_HOT_CONTEXT_MENU = 0x15D +KEY_HOT_SHIFT_LEFT = 0x2A +KEY_HOT_SHIFT_RIGHT = 0x36 +KEY_HOT_CTRL_LEFT = 0x1D +KEY_HOT_CTRL_RIGHT = 0x11D +KEY_HOT_ALT_LEFT = 0x38 +KEY_HOT_ALT_RIGHT = 0x138 +KEY_HOT_WIN_LEFT = 57435 #OLD AND DONT WORK 0x5B +KEY_HOT_WIN_RIGHT = 57436 #OLD AND DONT WORK 0x5C +KEY_HOT_CAPS_LOCK = 0x3A +KEY_HOT_NUM_LOCK = 0x45 +KEY_HOT_SCROLL_LOCK = 0x46 +KEY_HOT_END = 0x4F +KEY_HOT_HOME = 0x47 +KEY_HOT_SPACE = 0x39 +KEY_HOT_PAGE_UP = 0x49 +KEY_HOT_PAGE_DOWN = 0x51 +KEY_HOT_CLEAR = 0x4C +KEY_HOT_LEFT = 0x4B +KEY_HOT_UP = 0x48 +KEY_HOT_RIGHT = 0x4D +KEY_HOT_DOWN = 0x50 +KEY_HOT_PRINT_SCREEN = 0x137 +KEY_HOT_INSERT = 0x52 +KEY_HOT_DELETE = 0x53 + +KEY_HOT_0 = 0xB +KEY_HOT_1 = 0x2 +KEY_HOT_2 = 0x3 +KEY_HOT_3 = 0x4 +KEY_HOT_4 = 0x5 +KEY_HOT_5 = 0x6 +KEY_HOT_6 = 0x7 +KEY_HOT_7 = 0x8 +KEY_HOT_8 = 0x9 +KEY_HOT_9 = 0xA + +def Write(inTextStr:str, inDelayFloat:float=0, inRestoreStateAfterBool:bool=True, inExactBool:bool=None, inWaitAfterSecFloat:float=WAIT_AFTER_SEC_FLOAT): + """ + Печатает текст, который был передан в переменной inTextStr (поддерживает передачу в одной строке символов разного языка). Не зависит от текущей раскладки клавиатуры! Посылает искусственные клавишные события в ОС, моделируя печать данного текста. Знаки, не доступные на клавиатуре, напечатаны как явный unicode знаки, использующие определенную для ОС функциональность, такие как alt+codepoint. + Чтобы гарантировать текстовую целостность, все в настоящее время нажатые ключи выпущены прежде текст напечатан, и модификаторы восстановлены впоследствии. + + ВНИМАНИЕ! ПЕЧАТАЕТ ЛЮБУЮ СТРОКУ, ДАЖЕ В СОЧЕТАНИИ НЕСКОЛЬКИХ ЯЗЫКОВ ОДНОВРЕМЕННО. ДЛЯ РАБОТЫ С ГОРЯЧИМИ КЛАВИШАМИ ИСПОЛЬЗУЙ ФУНКЦИЮ Send, Up, Down, HotkeyCombination + + .. code-block:: python + + # Keyboard: Взаимодействие с клавиатурой + from pyOpenRPA.Robot import Keyboard + Keyboard.Write("Привет мой милый мир! Hello my dear world!") + + :param inTextStr: Текст, отправляемый на печать. Не зависит от текущей раскладки клавиатуры! + :type inTextStr: str + :param inDelayFloat: Число секунд, которое ожидать между нажатиями. По умолчанию 0 + :type inDelayFloat: float, опциональный + :param inRestoreStateAfterBool: Может использоваться, чтобы восстановить регистр нажатых ключей после того, как текст напечатан, т.е. нажимает ключи, которые были выпущены в начало. + :type inRestoreStateAfterBool: bool, опциональный + :param inExactBool: Печатает все знаки как явный unicode. Необязательный параметр + :type inExactBool: bool, опциональный + :param inWaitAfterSecFloat: Количество секунд, которые ожидать после выполнения операции. По умолчанию установлено в настройках модуля Keyboard (базовое значение 0.4) + :type inWaitAfterSecFloat: float, опциональный + """ + write(text=inTextStr, delay=inDelayFloat, restore_state_after=inRestoreStateAfterBool, exact=inExactBool) + time.sleep(inWaitAfterSecFloat) + +def HotkeyCombination(*inKeyList, inDelaySecFloat = 0.3,inWaitAfterSecFloat:float=WAIT_AFTER_SEC_FLOAT): + """Получает перечень клавиш для одновременного нажатия. Между нажатиями программа ожидания время inDelaySecFloat + ВНИМАНИЕ! НЕ ЗАВИСИТ ОТ ТЕКУЩЕЙ РАСКЛАДКИ КЛАВИАТУРЫ + + .. code-block:: python + + # Keyboard: Взаимодействие с клавиатурой + from pyOpenRPA.Robot import Keyboard + Keyboard.HotkeyCombination(Keyboard.KEY_HOT_CTRL_LEFT,Keyboard.KEY_ENG_A) # Ctrl + a + Keyboard.HotkeyCombination(Keyboard.KEY_HOT_CTRL_LEFT,Keyboard.KEY_ENG_C) # Ctrl + c + Keyboard.HotkeyCombination(Keyboard.KEY_HOT_CTRL_LEFT,Keyboard.KEY_ENG_A) + Keyboard.HotkeyCombination(Keyboard.KEY_HOT_ALT_LEFT,Keyboard.KEY_HOT_TAB, Keyboard.KEY_HOT_TAB) + + :param inKeyList: Список клавиш для одновременного нажатия. Перечень клавиш см. в разделе "Коды клавиш". Пример: KEY_HOT_CTRL_LEFT,KEY_ENG_A + :param inDelaySecFloat: Интервал между нажатиями. Необходим в связи с тем, что операционной системе требуется время на реакцию на нажатие клавиш, по умолчанию: 0.3 + :type inDelaySecFloat: float, опциональный + :param inWaitAfterSecFloat: Количество секунд, которые ожидать после выполнения операции. По умолчанию установлено в настройках модуля Keyboard (базовое значение 0.4) + :type inWaitAfterSecFloat: float, опциональный + """ + for l_key_item in inKeyList: + if l_key_item == inKeyList[-1]: + send(l_key_item) + else: + press(l_key_item) + time.sleep(inDelaySecFloat) + lRevKeyList = list(reversed(inKeyList)) + for l_key_item in lRevKeyList: + if l_key_item == lRevKeyList[0]: + pass + else: + release(l_key_item) + time.sleep(inDelaySecFloat) + time.sleep(inWaitAfterSecFloat) + +def HotkeyCtrlA_CtrlC(inWaitAfterSecFloat:float=0.4) -> None: + """Выполнить выделение текста, после чего скопировать его в буфер обмена + ВНИМАНИЕ! НЕ ЗАВИСИТ ОТ ТЕКУЩЕЙ РАСКЛАДКИ КЛАВИАТУРЫ + + .. code-block:: python + + # Keyboard: Взаимодействие с клавиатурой + from pyOpenRPA.Robot import Keyboard + Keyboard.HotkeyCtrlA_CtrlC() # Отправить команды: выделить все, скопировать в буфер обмена + + :param inWaitAfterSecFloat: Количество секунд, которые ожидать после выполнения операции. По умолчанию установлено в настройках модуля Keyboard (базовое значение 0.4) + :type inWaitAfterSecFloat: float, опциональный + """ + HotkeyCombination(KEY_HOT_CTRL_LEFT,KEY_ENG_A) # Ctrl + a + HotkeyCombination(KEY_HOT_CTRL_LEFT,KEY_ENG_C) # Ctrl + c + time.sleep(inWaitAfterSecFloat) + +def Send(inKeyInt:int, inDoPressBool:bool=True, inDoReleaseBool:bool=True,inWaitAfterSecFloat:float=WAIT_AFTER_SEC_FLOAT) -> None: + """ + Имитация нажатия/отпускания любой физической клавиши. Посылает событие в операционную систему, которые выполняет нажатие и отпускание данной клавиши + + ВНИМАНИЕ! ПРИ ПОПЫТКЕ ПЕЧАТИ ТЕКСТА БУДЕТ УЧИТЫВАТЬ ТЕКУЩУЮ РАСКЛАДКУ КЛАВИАТУРЫ. ДЛЯ ПЕЧАТИ ТЕКСТА ИСПОЛЬЗУЙ Write! + + .. code-block:: python + + # Keyboard: Взаимодействие с клавиатурой + from pyOpenRPA.Robot import Keyboard + Keyboard.Send(Keyboard.KEY_ENG_A) # Нажать клавишу A. Если будет активна русская раскладка, то будет выведена буква ф. + + :param inKeyInt: Перечень клавиш см. в разделе "Коды клавиш". Пример: KEY_HOT_CTRL_LEFT,KEY_ENG_A + :type inKeyInt: int + :param inDoPressBool: Выполнить событие нажатия клавиши, По умолчанию True + :type inDoPressBool: bool, опциональный + :param inDoReleaseBool: Выполнить событие отпускания клавиши, По умолчанию True + :type inDoReleaseBool: bool, опциональный + :param inWaitAfterSecFloat: Количество секунд, которые ожидать после выполнения операции. По умолчанию установлено в настройках модуля Keyboard (базовое значение 0.4) + :type inWaitAfterSecFloat: float, опциональный + """ + send(hotkey=inKeyInt, do_press=inDoPressBool, do_release=inDoReleaseBool) + time.sleep(inWaitAfterSecFloat) + +def Up(inKeyInt:int, inWaitAfterSecFloat:float=WAIT_AFTER_SEC_FLOAT) -> None: + """ + Отпустить (поднять) клавишу. Если клавиша уже была поднята, то ничего не произойдет. + + ВНИМАНИЕ! ПРИ ПОПЫТКЕ ПЕЧАТИ ТЕКСТА БУДЕТ УЧИТЫВАТЬ ТЕКУЩУЮ РАСКЛАДКУ КЛАВИАТУРЫ. ДЛЯ ПЕЧАТИ ТЕКСТА ИСПОЛЬЗУЙ Write! + + .. code-block:: python + + # Keyboard: Взаимодействие с клавиатурой + from pyOpenRPA.Robot import Keyboard + Keyboard.Up(Keyboard.KEY_ENG_A) # Отпустить клавишу A. + + :param inKeyInt: Перечень клавиш см. в разделе "Коды клавиш". Пример: KEY_HOT_CTRL_LEFT, KEY_ENG_A + :type inKeyInt: int + :param inWaitAfterSecFloat: Количество секунд, которые ожидать после выполнения операции. По умолчанию установлено в настройках модуля Keyboard (базовое значение 0.4) + :type inWaitAfterSecFloat: float, опциональный + """ + send(hotkey=inKeyInt, do_press=False, do_release=True) + time.sleep(inWaitAfterSecFloat) + +def Down(inKeyInt:int, inWaitAfterSecFloat:float=WAIT_AFTER_SEC_FLOAT) -> None: + """ + Нажать (опустить) клавишу. Если клавиша уже была опущена, то ничего не произойдет. + + ВНИМАНИЕ! ПРИ ПОПЫТКЕ ПЕЧАТИ ТЕКСТА БУДЕТ УЧИТЫВАТЬ ТЕКУЩУЮ РАСКЛАДКУ КЛАВИАТУРЫ. ДЛЯ ПЕЧАТИ ТЕКСТА ИСПОЛЬЗУЙ Write! + + .. code-block:: python + + # Keyboard: Взаимодействие с клавиатурой + from pyOpenRPA.Robot import Keyboard + Keyboard.Down(Keyboard.KEY_ENG_A) # Отпустить клавишу A. + + :param inKeyInt: Перечень клавиш см. в разделе "Коды клавиш". Пример: KEY_HOT_CTRL_LEFT, KEY_ENG_A + :type inKeyInt: int + :param inWaitAfterSecFloat: Количество секунд, которые ожидать после выполнения операции. По умолчанию установлено в настройках модуля Keyboard (базовое значение 0.4) + :type inWaitAfterSecFloat: float, опциональный + """ + send(hotkey=inKeyInt, do_press=True, do_release=False) + time.sleep(inWaitAfterSecFloat) + +def IsDown(inKeyInt:int) -> bool: + """ + Проверить, опущена ли клавиша. Вернет True если опущена; False если поднята. + + ВНИМАНИЕ! ПРИ ПОПЫТКЕ ПЕЧАТИ ТЕКСТА БУДЕТ УЧИТЫВАТЬ ТЕКУЩУЮ РАСКЛАДКУ КЛАВИАТУРЫ. ДЛЯ ПЕЧАТИ ТЕКСТА ИСПОЛЬЗУЙ Write! + + .. code-block:: python + + # Keyboard: Взаимодействие с клавиатурой + from pyOpenRPA.Robot import Keyboard + lKeyAIsPressedBool = Keyboard.IsDown(Keyboard.KEY_ENG_A) # Проверить, опущена ли клавиша A. + + :param inKeyInt: Перечень клавиш см. в разделе "Коды клавиш". Пример: KEY_HOT_CTRL_LEFT, KEY_ENG_A + :type inKeyInt: int + """ + return is_pressed(inKeyInt) + +def Wait(inKeyInt:int,inWaitAfterSecFloat:float=WAIT_AFTER_SEC_FLOAT): + """Блокирует осуществление программы, пока данная обозначенная клавиша не будет нажата. + ВНИМАНИЕ! НЕ ЗАВИСИТ ОТ ТЕКУЩЕЙ РАСКЛАДКИ КЛАВИАТУРЫ. ОЖИДАЕТ НАЖАТИЕ СООТВЕТСВУЮЩЕЙ ФИЗИЧЕСКОЙ КЛАВИШИ + + .. code-block:: python + + # Keyboard: Взаимодействие с клавиатурой + from pyOpenRPA.Robot import Keyboard + Keyboard.Wait(Keyboard.KEY_ENG_A) # Ждать нажатие клавиши A. + + :param inKeyInt: Перечень клавиш см. в разделе "Коды клавиш". Пример: KEY_HOT_CTRL_LEFT,KEY_ENG_A + :type inKeyInt: int + :param inWaitAfterSecFloat: Количество секунд, которые ожидать после выполнения операции. По умолчанию установлено в настройках модуля Keyboard (базовое значение 0.4) + :type inWaitAfterSecFloat: float, опциональный + """ + wait(hotkey=inKeyInt) + time.sleep(inWaitAfterSecFloat) + +key_to_scan_codes("win") # 2022 06 10 Люблю смотреть скан код клавиши Виндовс :) \ No newline at end of file diff --git a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/pyOpenRPA/Robot/Mouse.py b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/pyOpenRPA/Robot/Mouse.py index 49af0760..e693a900 100644 --- a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/pyOpenRPA/Robot/Mouse.py +++ b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/pyOpenRPA/Robot/Mouse.py @@ -1 +1,173 @@ -from pyautogui import * \ No newline at end of file +from pyautogui import * +import time + +WAIT_AFTER_SEC_FLOAT = 0.4 # Настройка модуля Mouse: Время, которое ожидать после выполнения любой операции модуля Mouse. Настройка является единой для всех участов кода, использующих модуль Mouse. Если для некоторой функции требуется изменить данное время ожидания, то в отношении этой функции можно применить соответсвующий аргумент. + +def Click(inXInt:int=None, inYInt:int=None, inClickCountInt:int=1, inIntervalSecFloat:float=0.0, inButtonStr:str='left', inMoveDurationSecFloat:float=0.0, inWaitAfterSecFloat:float=WAIT_AFTER_SEC_FLOAT): + """Нажатие (вниз) кнопки мыши и затем немедленно выпуск (вверх) её. Допускается следующая параметризация. Если не указаны inXInt и inYInt - клик производится по месту нахождения указателя мыши. + + !ВНИМАНИЕ! Отсчет координат inXInt, inYInt начинается с левого верхнего края рабочей области (экрана). + + .. code-block:: python + + # Mouse: Взаимодействие с мышью + from pyOpenRPA.Robot import Mouse + Mouse.Click(100,150) #Выполнить нажатие левой клавиши мыши на экране по координатам: X(гор) 100px, Y(вер) 150px. + + :param inXInt: Целевая позиция указателя мыши по оси X (горизонтальная ось). + :type inXInt: int, опциональный + :param inYInt: Целевая позиция указателя мыши по оси Y (вертикальная ось). + :type inYInt: int, опциональный + :param inClickCountInt: Количество нажатий (вниз и вверх) кнопкой мыши, По умолчанию 1 + :type inClickCountInt: int, опциональный + :param inIntervalSecFloat: Интервал ожидания в секундах между нажатиями, По умолчанию 0.0 + :type inIntervalSecFloat: float, опциональный + :param inButtonStr: Номер кнопки, которую требуется нажать. Возможные варианты: 'left', 'middle', 'right' или 1, 2, 3. В остальных случаях инициирует исключение ValueError. По умолчанию 'left' + :type inButtonStr: str, опциональный + :param inMoveDurationSecFloat: Время перемещения указателя мыши, По умолчанию 0.0 (моментальное перемещение) + :type inMoveDurationSecFloat: float, опциональный + :param inWaitAfterSecFloat: Количество секунд, которые ожидать после выполнения операции. По умолчанию установлено в настройках модуля Mouse (базовое значение 0.4) + :type inWaitAfterSecFloat: float, опциональный + """ + click(x=inXInt, y=inYInt, clicks=inClickCountInt, interval=inIntervalSecFloat, button=inButtonStr, duration=inMoveDurationSecFloat) + time.sleep(inWaitAfterSecFloat) + +def ClickDouble(inXInt:int=None, inYInt:int=None, inWaitAfterSecFloat:float=WAIT_AFTER_SEC_FLOAT): + """Двойное нажатие левой клавиши мыши. Данное действие аналогично вызову функции (см. ниже). + + !ВНИМАНИЕ! Отсчет координат inXInt, inYInt начинается с левого верхнего края рабочей области (экрана). + + .. code-block:: python + + # Mouse: Взаимодействие с мышью + from pyOpenRPA.Robot import Mouse + Mouse.ClickDouble(100,150) #Выполнить двойное нажатие левой клавиши мыши на экране по координатам: X(гор) 100px, Y(вер) 150px. + + :param inXInt: Целевая позиция указателя мыши по оси X (горизонтальная ось). + :type inXInt: int, опциональный + :param inYInt: Целевая позиция указателя мыши по оси Y (вертикальная ось). + :type inYInt: int, опциональный + :param inButtonStr: Номер кнопки, которую требуется нажать. Возможные варианты: 'left', 'middle', 'right' или 1, 2, 3. В остальных случаях инициирует исключение ValueError. По умолчанию 'left' + :type inButtonStr: str, опциональный + :param inWaitAfterSecFloat: Количество секунд, которые ожидать после выполнения операции. По умолчанию установлено в настройках модуля Mouse (базовое значение 0.4) + :type inWaitAfterSecFloat: float, опциональный + """ + doubleClick(x=inXInt, y=inYInt) + time.sleep(inWaitAfterSecFloat) + +def Down(inXInt:int=None, inYInt:int=None, inButtonStr:str='left', inWaitAfterSecFloat:float=WAIT_AFTER_SEC_FLOAT): + """Переместить указатель по координатам inXInt, inYInt, после чего нажать (вниз) клавишу мыши и не отпускать до выполнения соответсвующей команды (см. Up). Если координаты inXInt, inYInt не переданы - нажатие происходит на тех координатах X/Y, на которых указатель мыши находится. + + !ВНИМАНИЕ! Отсчет координат inXInt, inYInt начинается с левого верхнего края рабочей области (экрана). + + .. code-block:: python + + # Mouse: Взаимодействие с мышью + from pyOpenRPA.Robot import Mouse + Mouse.Down() #Опустить левую клавишу мыши + + :param inXInt: Целевая позиция указателя мыши по оси X (горизонтальная ось). + :type inXInt: int, опциональный + :param inYInt: Целевая позиция указателя мыши по оси Y (вертикальная ось). + :type inYInt: int, опциональный + :param inButtonStr: Номер кнопки, которую требуется нажать. Возможные варианты: 'left', 'middle', 'right' или 1, 2, 3. В остальных случаях инициирует исключение ValueError. По умолчанию 'left' + :type inButtonStr: str, опциональный + :param inWaitAfterSecFloat: Количество секунд, которые ожидать после выполнения операции. По умолчанию установлено в настройках модуля Mouse (базовое значение 0.4) + :type inWaitAfterSecFloat: float, опциональный + """ + mouseDown(x=inXInt, y=inYInt, button = inButtonStr) + time.sleep(inWaitAfterSecFloat) + +def Up(inXInt:int=None, inYInt:int=None, inButtonStr:str='left', inWaitAfterSecFloat:float=WAIT_AFTER_SEC_FLOAT): + """Отпустить (вверх) клавишу мыши. Если координаты inXInt, inYInt не переданы - нажатие происходит на тех координатах X/Y, на которых указатель мыши находится. + + !ВНИМАНИЕ! Отсчет координат inXInt, inYInt начинается с левого верхнего края рабочей области. + + .. code-block:: python + + # Mouse: Взаимодействие с мышью + from pyOpenRPA.Robot import Mouse + Mouse.Up(inButtonStr:str='right') #Поднять правую клавишу мыши + + :param inXInt: Целевая позиция указателя мыши по оси X (горизонтальная ось). + :type inXInt: int, опциональный + :param inYInt: Целевая позиция указателя мыши по оси Y (вертикальная ось). + :type inYInt: int, опциональный + :param inButtonStr: Номер кнопки, которую требуется поднять. Возможные варианты: 'left', 'middle', 'right' или 1, 2, 3. В остальных случаях инициирует исключение ValueError. По умолчанию 'left' + :type inButtonStr: str, опциональный + :param inWaitAfterSecFloat: Количество секунд, которые ожидать после выполнения операции. По умолчанию установлено в настройках модуля Mouse (базовое значение 0.4) + :type inWaitAfterSecFloat: float, опциональный + """ + mouseUp(x=inXInt, y=inYInt, button = inButtonStr) + time.sleep(inWaitAfterSecFloat) + +def MoveTo(inXInt=None, inYInt=None, inMoveDurationSecFloat:float=0.0, inWaitAfterSecFloat:float=WAIT_AFTER_SEC_FLOAT): + """Переместить указатель мыши на позицию inXInt, inYInt за время inMoveDurationSecFloat. + + !ВНИМАНИЕ! Отсчет координат inXInt, inYInt начинается с левого верхнего края рабочей области (экрана). + + .. code-block:: python + + # Mouse: Взаимодействие с мышью + from pyOpenRPA.Robot import Mouse + Mouse.MoveTo(inXInt=100, inYInt=200) #Переместить указатель мыши по координатам: X(гор) 100, Y(вер) 200 + + :param inXInt: Целевая позиция указателя мыши по оси X (горизонтальная ось). + :type inXInt: int, опциональный + :param inYInt: Целевая позиция указателя мыши по оси Y (вертикальная ось). + :type inYInt: int, опциональный + :param inMoveDurationSecFloat: Время перемещения указателя мыши, По умолчанию 0.0 (моментальное перемещение) + :type inMoveDurationSecFloat: float, опциональный + :param inWaitAfterSecFloat: Количество секунд, которые ожидать после выполнения операции. По умолчанию установлено в настройках модуля Mouse (базовое значение 0.4) + :type inWaitAfterSecFloat: float, опциональный + """ + moveTo(x=inXInt, y=inYInt, duration=inMoveDurationSecFloat) + time.sleep(inWaitAfterSecFloat) + +def ScrollVertical(inScrollClickCountInt, inXInt=None, inYInt=None, inWaitAfterSecFloat:float=WAIT_AFTER_SEC_FLOAT): + """Переместить указатель мыши на позицию inXInt, inYInt и выполнить вертикальную прокрутку (скроллинг) колесом мыши на количество щелчков inScrollClickCountInt. + + !ВНИМАНИЕ! Отсчет координат inXInt, inYInt начинается с левого верхнего края рабочей области (экрана). + + .. code-block:: python + + # Mouse: Взаимодействие с мышью + from pyOpenRPA.Robot import Mouse + Mouse.ScrollVertical(100, inXInt=100, inYInt=200) #Крутить колесо мыши вниз на 100 кликов по координатам: X(гор) 100, Y(вер) 200 + Mouse.ScrollVertical(-100) #Крутить колесо мыши вверх на 100 кликов по текущим координатам указателя мыши. + + :param inScrollClickCountInt: Количество щелчок колеса мыши, которое требуется !вертикально! прокрутить. Аргумент может принимать как положительное (прокрутка вниз), так и отрицательное (прокрутка вверх) значения + :type inScrollClickCountInt: int, обязательный + :param inXInt: Целевая позиция указателя мыши по оси X (горизонтальная ось). + :type inXInt: int, опциональный + :param inYInt: Целевая позиция указателя мыши по оси Y (вертикальная ось). + :type inYInt: int, опциональный + :param inWaitAfterSecFloat: Количество секунд, которые ожидать после выполнения операции. По умолчанию установлено в настройках модуля Mouse (базовое значение 0.4) + :type inWaitAfterSecFloat: float, опциональный + """ + vscroll(inScrollClickCountInt, x=inXInt, y=inYInt) + time.sleep(inWaitAfterSecFloat) + +def ScrollHorizontal(inScrollClickCountInt, inXInt=None, inYInt=None, inWaitAfterSecFloat:float=WAIT_AFTER_SEC_FLOAT): + """!ТОЛЬКО ДЛЯ LINUX! Переместить указатель мыши на позицию inXInt, inYInt и выполнить горизонтальную прокрутку (скроллинг) виртуальным колесом мыши на количество щелчков inScrollClickCountInt. + + !ВНИМАНИЕ! Отсчет координат inXInt, inYInt начинается с левого верхнего края рабочей области (экрана). + + .. code-block:: python + + # Mouse: Взаимодействие с мышью + from pyOpenRPA.Robot import Mouse + Mouse.ScrollHorizontal(100, inXInt=100, inYInt=200) #Крутить колесо мыши вниз на 100 кликов по координатам: X(гор) 100, Y(вер) 200 + Mouse.ScrollHorizontal(-100) #Крутить колесо мыши вверх на 100 кликов по текущим координатам указателя мыши. + + :param inScrollClickCountInt: Количество щелчок колеса мыши, которое требуется !горизонтально! прокрутить. Аргумент может принимать как положительное (прокрутка вправо), так и отрицательное (прокрутка влево) значения + :type inScrollClickCountInt: int, обязательный + :param inXInt: Целевая позиция указателя мыши по оси X (горизонтальная ось). + :type inXInt: int, опциональный + :param inYInt: Целевая позиция указателя мыши по оси Y (вертикальная ось). + :type inYInt: int, опциональный + :param inWaitAfterSecFloat: Количество секунд, которые ожидать после выполнения операции. По умолчанию установлено в настройках модуля Mouse (базовое значение 0.4) + :type inWaitAfterSecFloat: float, опциональный + """ + hscroll(inScrollClickCountInt, x=inXInt, y=inYInt) + time.sleep(inWaitAfterSecFloat) diff --git a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/pyOpenRPA/Robot/README.md b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/pyOpenRPA/Robot/README.md index f5f30305..4ae5e05c 100644 --- a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/pyOpenRPA/Robot/README.md +++ b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/pyOpenRPA/Robot/README.md @@ -43,16 +43,5 @@ Resources\WPy64-3720\python-3.7.2.amd64\python.exe ] -# Open RPA Wiki -- [Home](https://gitlab.com/UnicodeLabs/OpenRPA/wikis/home) -- [04. Desktop app access (win32 & ui automation)](https://gitlab.com/UnicodeLabs/OpenRPA/wikis/04.-Desktop-app-access-(win32-&-ui-automation)) - -#Dependencies -* Python 3 x32 [psutil, pywinauto, wmi, PIL, keyboard, pyautogui, win32api (pywin32), selenium, openCV, tesseract, requests, lxml, PyMuPDF] -* Python 3 x64 [psutil, pywinauto, wmi, PIL, keyboard, pyautogui, win32api (pywin32), selenium, openCV, tesseract, requests, lxml, PyMuPDF] -* pywinauto (Windows GUI automation) -* Semantic UI CSS framework -* JsRender by https://www.jsviews.com (switch to Handlebars) -* Handlebars - -Created by Unicode Labs (Ivan Maslov) \ No newline at end of file + +Created by pyOpenRPA LLC (Ivan Maslov) \ No newline at end of file diff --git a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/pyOpenRPA/Robot/UIDesktop.py b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/pyOpenRPA/Robot/UIDesktop.py index e084d515..fa101c2b 100644 --- a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/pyOpenRPA/Robot/UIDesktop.py +++ b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/pyOpenRPA/Robot/UIDesktop.py @@ -29,7 +29,7 @@ import copy #TODO В перспективе нужно реализовать алгоритм определения разрядности не в Robot.py, а в UIDesktop.py, тк начинают появляться функции, на входе в которые еще неизвестна разрядность элемента + селектор может охватить сразу два элемента из 2-х разных разрядностей - обрабатываться это должно непосредственно при выполнении #################################### -#Info: GUI module of the Robot app (OpenRPA - Robot) +#Info: GUI module of the Robot app (pyOpenRPA - Robot) #################################### # GUI Module - interaction with Desktop application @@ -99,19 +99,27 @@ mDefaultPywinautoBackend="win32" # "rich_text" - наименование rich_text # } #] -################ -#return: List of UI Object -#inElement - Входной элемент - показатель, что не требуется выполнять коннект к процессу -#inFlagRaiseException - Флаг True - выкинуть ошибку в случае обнаружении пустого списка -#old name - PywinautoExtElementsGet + +#old:PywinautoExtElementsGet def UIOSelector_Get_UIOList (inSpecificationList,inElement=None,inFlagRaiseException=True): ''' - Get the UIO list by the selector + Получить список UIO объектов по UIO селектору + + .. code-block:: python + + # UIDesktop: Взаимодействие с UI объектами приложений + from pyOpenRPA.Robot import UIDesktop + # 1С: UIO Селектор выбора базы + lDemoBaseUIOSelector = [{"title":"Запуск 1С:Предприятия","class_name":"V8TopLevelFrameTaxiStarter","backend":"uia"},{"title":"DEMO", "depth_start": 5, "depth_end": 5}] + lDemoBaseUIOList = UIDesktop.UIOSelector_Get_UIOList(lDemoBaseUIOSelector) #Получить список UIO объектов, которые удовлетворяют требованиям UIO селектора. В нашем примере либо [], либо [UIO объект] - :param inSpecificationList: UIO Selector - :param inElement: Входной элемент - показатель, что не требуется выполнять коннект к процессу - :param inFlagRaiseException: Флаг True - выкинуть ошибку в случае обнаружении пустого списка - :return: + :param inSpecificationList: UIO Селектор, который определяет критерии поиска UI элементов + :type inSpecificationList: list, обязательный + :param inElement: Родительский элемент, от которого выполнить поиск UIO объектов по заданному UIO селектору. Если аргумент не задан, платформа выполнит поиск UIO объектов среди всех доступных приложений windows, которые запущены на текущей сессии + :type inElement: UIO объект, опциональный + :param inFlagRaiseException: True - формировать ошибку exception, если платформа не обнаружина ни одного UIO объекта по заданному UIO селектору. False - обратный случай. По умолчанию True + :type inFlagRaiseException: bool, опциональный + :return: Список UIO объектов, которые удовлетворяют условиям UIO селектора ''' #Создать копию входного листа, чтобы не менять массив в других верхнеуровневых функциях inSpecificationList=copy.deepcopy(inSpecificationList) @@ -235,20 +243,26 @@ def UIOSelector_Get_UIOList (inSpecificationList,inElement=None,inFlagRaiseExcep raise pywinauto.findwindows.ElementNotFoundError("Robot can't find element by the UIOSelector") return lResultList -################################################################################################# -#Get first (in more than one) UIO (UI Object) -#inSpecificationList - UIOSelector -#inElement - Входной элемент - показатель, что не требуется выполнять коннект к процессу -#inFlagRaiseException - Флаг True - выкинуть ошибку в случае обнаружении пустого списка -#old name - PywinautoExtElementGet +#old:PywinautoExtElementGet def UIOSelector_Get_UIO (inSpecificationList,inElement=None,inFlagRaiseException=True): ''' - Get the pywinauto object by the UIO selector. + Получить список UIO объект по UIO селектору. Если критериям UIO селектора удовлетворяет несколько UIO объектов - вернуть первый из списка + + .. code-block:: python + + # UIDesktop: Взаимодействие с UI объектами приложений + from pyOpenRPA.Robot import UIDesktop + # 1С: UIO Селектор выбора базы + lDemoBaseUIOSelector = [{"title":"Запуск 1С:Предприятия","class_name":"V8TopLevelFrameTaxiStarter","backend":"uia"},{"title":"DEMO", "depth_start": 5, "depth_end": 5}] + lDemoBaseUIOList = UIDesktop.UIOSelector_Get_UIO(lDemoBaseUIOSelector) #Получить 1-й UIO объект, которые удовлетворяет требованиям UIO селектора. В нашем примере либо None, либо UIO объект - :param inSpecificationList: - :param inElement: - :param inFlagRaiseException: - :return: + :param inSpecificationList: UIO Селектор, который определяет критерии поиска UI элементов + :type inSpecificationList: list, обязательный + :param inElement: Родительский элемент, от которого выполнить поиск UIO объектов по заданному UIO селектору. Если аргумент не задан, платформа выполнит поиск UIO объектов среди всех доступных приложений windows, которые запущены на текущей сессии + :type inElement: UIO объект, опциональный + :param inFlagRaiseException: True - формировать ошибку exception, если платформа не обнаружина ни одного UIO объекта по заданному UIO селектору. False - обратный случай. По умолчанию True + :type inFlagRaiseException: bool, опциональный + :return: UIO объект, которые удовлетворяют условиям UIO селектора, или None ''' lResult=None #Получить родительский объект если на вход ничего не поступило @@ -259,17 +273,25 @@ def UIOSelector_Get_UIO (inSpecificationList,inElement=None,inFlagRaiseException if lResult is None and inFlagRaiseException: raise pywinauto.findwindows.ElementNotFoundError("Robot can't find element by the UIOSelector") return lResult -################################################################################################# -#Check if UIO exist (Identified by the UIOSelector) -#!!!!!Safe call is included (you can set activity and UIDesktop will choose the bitness and return the result)!!!!! -#UIOSelector -#old name - - + +#old:- def UIOSelector_Exist_Bool (inUIOSelector): ''' - Check if object is exist by the UIO selector. + Проверить существование хотя бы 1-го UIO объекта по заданному UIO селектору + + !ВНИМАНИЕ! ДАННАЯ ФУНКЦИОНАЛЬНОСТЬ В АВТОМАТИЧЕСКОМ РЕЖИМЕ ПОДДЕРЖИВАЕТ ВСЕ РАЗРЯДНОСТИ ПРИЛОЖЕНИЙ (32|64), КОТОРЫЕ ЗАПУЩЕНЫ В СЕСИИ. PYTHON x64 ИМЕЕТ ВОЗМОЖНОСТЬ ВЗЗАИМОДЕЙСТВИЯ С x32 UIO ОБЪЕКТАМИ, НО МЫ РЕКОМЕНДУЕМ ДОПОЛНИТЕЛЬНО ИСПОЛЬЗОВАТЬ ИНТЕРПРЕТАТОР PYTHON x32 (ПОДРОБНЕЕ СМ. ФУНКЦИЮ Configure()) + + .. code-block:: python + + # UIDesktop: Взаимодействие с UI объектами приложений + from pyOpenRPA.Robot import UIDesktop + # 1С: UIO Селектор выбора базы + lDemoBaseUIOSelector = [{"title":"Запуск 1С:Предприятия","class_name":"V8TopLevelFrameTaxiStarter","backend":"uia"},{"title":"DEMO", "depth_start": 5, "depth_end": 5}] + lDemoBaseUIOExistBool = UIDesktop.UIOSelector_Exist_Bool(lDemoBaseUIOSelector) # Получить булевый результат проверки существования UIO объекта - :param inUIOSelector: - :return: True - Object is exist. False - else case + :param inUIOSelector: UIO Селектор, который определяет критерии поиска UIO объектов + :type inUIOSelector: list, обязательный + :return: True - существует хотя бы 1 UIO объект. False - не существует ни одного UIO объекта по заданному UIO селектору ''' lResult=False #Check the bitness @@ -294,27 +316,34 @@ def UIOSelector_Exist_Bool (inUIOSelector): else: lResult = lPIPEResponseDict["Result"] return lResult -################################################################################################# -#Wait for UIO is appear (at least one of them or all at the same time) -#inSpecificationListList - List of the UIOSelector -#inWaitSecs - Время ожидания объекта в секундах -#inFlagWaitAllInMoment - доп. условие - ожидать появление всех UIOSelector одновременно -#return: [0,1,2] - index of UIOSpecification, which is appear -#old name - - -#####Внимание##### -##Функция ожидания появления элементов (тк элементы могут быть недоступны, неизвестно в каком фреймворке каждый из них может появиться) -def UIOSelectorsSecs_WaitAppear_List (inSpecificationListList,inWaitSecs,inFlagWaitAllInMoment=False): + +#old: - +def UIOSelectorsSecs_WaitAppear_List (inSpecificationListList,inWaitSecs=86400.0,inFlagWaitAllInMoment=False): ''' - Wait for many UI object will appear in GUI for inWaitSecs seconds. + Ожидать появление хотя бы 1-го / всех UIO объектов по заданным UIO селекторам + + !ВНИМАНИЕ! ДАННАЯ ФУНКЦИОНАЛЬНОСТЬ В АВТОМАТИЧЕСКОМ РЕЖИМЕ ПОДДЕРЖИВАЕТ ВСЕ РАЗРЯДНОСТИ ПРИЛОЖЕНИЙ (32|64), КОТОРЫЕ ЗАПУЩЕНЫ В СЕСИИ. PYTHON x64 ИМЕЕТ ВОЗМОЖНОСТЬ ВЗЗАИМОДЕЙСТВИЯ С x32 UIO ОБЪЕКТАМИ, НО МЫ РЕКОМЕНДУЕМ ДОПОЛНИТЕЛЬНО ИСПОЛЬЗОВАТЬ ИНТЕРПРЕТАТОР PYTHON x32 (ПОДРОБНЕЕ СМ. ФУНКЦИЮ Configure()) + + .. code-block:: python - :param inSpecificationListList: UIOSelector list. - Example: [ + # UIDesktop: Взаимодействие с UI объектами приложений + from pyOpenRPA.Robot import UIDesktop + # 1С: UIO Селектор выбора базы + lDemoBaseUIOSelector = [{"title":"Запуск 1С:Предприятия","class_name":"V8TopLevelFrameTaxiStarter","backend":"uia"},{"title":"DEMO", "depth_start": 5, "depth_end": 5}] + lNotepadOKSelector = [{"title":"notepad"},{"title":"OK"}] + lNotepadCancelSelector = [{"title":"notepad"},{"title":"Cancel"}] + lDemoBaseUIOExistList = UIDesktop.UIOSelectorsSecs_WaitAppear_List([lDemoBaseUIOSelector, lNotepadOKSelector, lNotepadCancelSelector]) # Ожидать появление UIO объекта + + :param inSpecificationListList: Список UIO селекторов, которые определяют критерии поиска UIO объектов + Пример: [ [{"title":"notepad"},{"title":"OK"}], [{"title":"notepad"},{"title":"Cancel"}] ] - :param inWaitSecs: Float value (seconds) for wait UI element appear in GUI - :param inFlagWaitAllInMoment: True - Wait all UI objects from the UIOSelector list to be appeared - :return: List of index, which UI object UIO will be appeared. Example: [1] # Appear only UI object with UIO selector: [{"title":"notepad"},{"title":"Cancel"}] + :type inSpecificationListList: list, обязательный + :param inWaitSecs: Количество секунд, которые отвести на ожидание UIO объектов. По умолчанию 24 часа (86400 секунд) + :type inWaitSecs: float, необязательный + :param inFlagWaitAllInMoment: True - Ожидать до того момента, пока не появятся все запрашиваемые UIO объекты на рабочей области + :return: Список индексов, которые указывают на номер входящих UIO селекторов, которые были обнаружены на рабочей области. Пример: [0,2] ''' lResultFlag=False lSecsSleep = 1 #Настроечный параметр @@ -345,29 +374,36 @@ def UIOSelectorsSecs_WaitAppear_List (inSpecificationListList,inWaitSecs,inFlagW lSecsDone=lSecsDone+lSecsSleep time.sleep(lSecsSleep) return lResultList -################################################################################################# -#Wait for UIO is Disappear (at least one of them or all at the same time) -#inSpecificationListList - List of the UIOSelector -#inWaitSecs - Время ожидания пропажи объекта в секундах -#inFlagWaitAllInMoment - доп. условие - ожидать пропажу всех UIOSelector одновременно -#return: [0,1,2] - index of UIOSpecification, which is Disappear -#old name - - -#####Внимание##### -##Функция ожидания пропажи элементов (тк элементы могут быть недоступны, неизвестно в каком фреймворке каждый из них может появиться) -def UIOSelectorsSecs_WaitDisappear_List (inSpecificationListList,inWaitSecs,inFlagWaitAllInMoment=False): + +#old: - +def UIOSelectorsSecs_WaitDisappear_List (inSpecificationListList,inWaitSecs=86400.0,inFlagWaitAllInMoment=False): ''' - Wait for many UI object will disappear in GUI for inWaitSecs seconds. + Ожидать исчезновение хотя бы 1-го / всех UIO объектов по заданным UIO селекторам + + !ВНИМАНИЕ! ДАННАЯ ФУНКЦИОНАЛЬНОСТЬ В АВТОМАТИЧЕСКОМ РЕЖИМЕ ПОДДЕРЖИВАЕТ ВСЕ РАЗРЯДНОСТИ ПРИЛОЖЕНИЙ (32|64), КОТОРЫЕ ЗАПУЩЕНЫ В СЕСИИ. PYTHON x64 ИМЕЕТ ВОЗМОЖНОСТЬ ВЗЗАИМОДЕЙСТВИЯ С x32 UIO ОБЪЕКТАМИ, НО МЫ РЕКОМЕНДУЕМ ДОПОЛНИТЕЛЬНО ИСПОЛЬЗОВАТЬ ИНТЕРПРЕТАТОР PYTHON x32 (ПОДРОБНЕЕ СМ. ФУНКЦИЮ Configure()) + + .. code-block:: python + + # UIDesktop: Взаимодействие с UI объектами приложений + from pyOpenRPA.Robot import UIDesktop + # 1С: UIO Селектор выбора базы + lDemoBaseUIOSelector = [{"title":"Запуск 1С:Предприятия","class_name":"V8TopLevelFrameTaxiStarter","backend":"uia"},{"title":"DEMO", "depth_start": 5, "depth_end": 5}] + lNotepadOKSelector = [{"title":"notepad"},{"title":"OK"}] + lNotepadCancelSelector = [{"title":"notepad"},{"title":"Cancel"}] + lDemoBaseUIOExistList = UIDesktop.UIOSelectorsSecs_WaitDisappear_List([lDemoBaseUIOSelector, lNotepadOKSelector, lNotepadCancelSelector]) # Ожидать исчезновение UIO объектов - :param inSpecificationListList: UIOSelector list. - Example: [ + :param inSpecificationListList: Список UIO селекторов, которые определяют критерии поиска UIO объектов + Пример: [ [{"title":"notepad"},{"title":"OK"}], [{"title":"notepad"},{"title":"Cancel"}] ] - :param inWaitSecs: Float value (seconds) for wait UI element disappear in GUI - :param inFlagWaitAllInMoment: True - Wait all UI objects from the UIOSelector list to be disappeared. - :return: List of index, which UI object UIO will be disappeared. Example: [1] # Disappear only UI object with UIO selector: [{"title":"notepad"},{"title":"Cancel"}] - :return: + :type inSpecificationListList: list, обязательный + :param inWaitSecs: Количество секунд, которые отвести на ожидание исчезновения UIO объектов. По умолчанию 24 часа (86400 секунд) + :type inWaitSecs: float, необязательный + :param inFlagWaitAllInMoment: True - Ожидать до того момента, пока не исчезнут все запрашиваемые UIO объекты на рабочей области + :return: Список индексов, которые указывают на номер входящих UIO селекторов, которые были обнаружены на рабочей области. Пример: [0,2] ''' + lResultFlag=False lSecsSleep = 1 #Настроечный параметр lSecsDone = 0 @@ -397,56 +433,77 @@ def UIOSelectorsSecs_WaitDisappear_List (inSpecificationListList,inWaitSecs,inFl lSecsDone=lSecsDone+lSecsSleep time.sleep(lSecsSleep) return lResultList -################################################################################################# -#Wait for UIO is appear (at least one of them or all at the same time) -#inSpecificationList - UIOSelector -#inWaitSecs - Время ожидания объекта в секундах -#return: Bool - True - UIO is appear -#old name - - + +#old: - def UIOSelectorSecs_WaitAppear_Bool (inSpecificationList,inWaitSecs): ''' - Wait for UI object will appear in GUI for inWaitSecs seconds. + Ожидать появление 1-го UIO объекта по заданному UIO селектору + + !ВНИМАНИЕ! ДАННАЯ ФУНКЦИОНАЛЬНОСТЬ В АВТОМАТИЧЕСКОМ РЕЖИМЕ ПОДДЕРЖИВАЕТ ВСЕ РАЗРЯДНОСТИ ПРИЛОЖЕНИЙ (32|64), КОТОРЫЕ ЗАПУЩЕНЫ В СЕСИИ. PYTHON x64 ИМЕЕТ ВОЗМОЖНОСТЬ ВЗЗАИМОДЕЙСТВИЯ С x32 UIO ОБЪЕКТАМИ, НО МЫ РЕКОМЕНДУЕМ ДОПОЛНИТЕЛЬНО ИСПОЛЬЗОВАТЬ ИНТЕРПРЕТАТОР PYTHON x32 (ПОДРОБНЕЕ СМ. ФУНКЦИЮ Configure()) + + .. code-block:: python + + # UIDesktop: Взаимодействие с UI объектами приложений + from pyOpenRPA.Robot import UIDesktop + # 1С: UIO Селектор выбора базы + lDemoBaseUIOSelector = [{"title":"Запуск 1С:Предприятия","class_name":"V8TopLevelFrameTaxiStarter","backend":"uia"},{"title":"DEMO", "depth_start": 5, "depth_end": 5}] + lDemoBaseUIOExistBool = UIDesktop.UIOSelectorSecs_WaitAppear_Bool(lDemoBaseUIOSelector) # Ожидать появление UIO объекта - :param inSpecificationList: UIOSelector. Example: [{"title":"notepad"},{"title":"OK"}] - :param inWaitSecs: Float value (seconds) for wait UI element appear in GUI - :return: True - UI object will appear. False - else case + :param inSpecificationList: UIO селектор, который определяет критерии поиска UIO объекта + :type inSpecificationList: list, обязательный + :param inWaitSecs: Количество секунд, которые отвести на ожидание UIO объекта. По умолчанию 24 часа (86400 секунд) + :type inWaitSecs: float, необязательный + :return: True - UIO объект был обнаружен. False - обратная ситуациая ''' lWaitAppearList=UIOSelectorsSecs_WaitAppear_List([inSpecificationList],inWaitSecs) lResult=False if len(lWaitAppearList)>0: lResult=True return lResult -################################################################################################# -#Wait for UIO is disappear (at least one of them or all at the same time) -#inSpecificationList - UIOSelector -#inWaitSecs - Время ожидания пропажи объекта в секундах -#return: Bool - True - UIO is Disappear + #old name - - def UIOSelectorSecs_WaitDisappear_Bool (inSpecificationList,inWaitSecs): ''' - Wait for UI object will disappear in GUI for inWaitSecs seconds. + Ожидать исчезновение 1-го UIO объекта по заданному UIO селектору + + !ВНИМАНИЕ! ДАННАЯ ФУНКЦИОНАЛЬНОСТЬ В АВТОМАТИЧЕСКОМ РЕЖИМЕ ПОДДЕРЖИВАЕТ ВСЕ РАЗРЯДНОСТИ ПРИЛОЖЕНИЙ (32|64), КОТОРЫЕ ЗАПУЩЕНЫ В СЕСИИ. PYTHON x64 ИМЕЕТ ВОЗМОЖНОСТЬ ВЗЗАИМОДЕЙСТВИЯ С x32 UIO ОБЪЕКТАМИ, НО МЫ РЕКОМЕНДУЕМ ДОПОЛНИТЕЛЬНО ИСПОЛЬЗОВАТЬ ИНТЕРПРЕТАТОР PYTHON x32 (ПОДРОБНЕЕ СМ. ФУНКЦИЮ Configure()) + + .. code-block:: python + + # UIDesktop: Взаимодействие с UI объектами приложений + from pyOpenRPA.Robot import UIDesktop + # 1С: UIO Селектор выбора базы + lDemoBaseUIOSelector = [{"title":"Запуск 1С:Предприятия","class_name":"V8TopLevelFrameTaxiStarter","backend":"uia"},{"title":"DEMO", "depth_start": 5, "depth_end": 5}] + lDemoBaseUIOExistBool = UIDesktop.UIOSelectorSecs_WaitDisappear_Bool(lDemoBaseUIOSelector) # Ожидать исчезновение UIO объекта - :param inSpecificationList: UIOSelector. - Example: [{"title":"notepad"},{"title":"OK"}] - :param inWaitSecs: Float value (seconds) for wait UI element disappear in GUI - :return: True - UI object will disappear. False - else case + :param inSpecificationList: UIO селектор, который определяет критерии поиска UIO объекта + :type inSpecificationList: list, обязательный + :param inWaitSecs: Количество секунд, которые отвести на исчезновение UIO объекта. По умолчанию 24 часа (86400 секунд) + :type inWaitSecs: float, необязательный + :return: True - UIO объект был обнаружен. False - обратная ситуациая ''' lWaitDisappearList=UIOSelectorsSecs_WaitDisappear_List([inSpecificationList],inWaitSecs) lResult=False if len(lWaitDisappearList)>0: lResult=True return lResult -################################################################################################# -#Get process bitness (32 or 64) -#inSpecificationList - UIOSelector -#old name - None -#return None (if Process not found), int 32, or int 64 + +#old: - def UIOSelector_Get_BitnessInt (inSpecificationList): ''' - Detect process bitness by the UI Object UIO Selector. + Определить разрядность приложения по UIO селектору. Вернуть результат в формате целого числа (64 или 32) + + .. code-block:: python - :param inSpecificationList: UIOSelector. Example: [{"title":"notepad"},{"title":"OK"}] - :return: int 32 or int 64 + # UIDesktop: Взаимодействие с UI объектами приложений + from pyOpenRPA.Robot import UIDesktop + # 1С: UIO Селектор выбора базы + lDemoBaseUIOSelector = [{"title":"Запуск 1С:Предприятия","class_name":"V8TopLevelFrameTaxiStarter","backend":"uia"},{"title":"DEMO", "depth_start": 5, "depth_end": 5}] + lDemoBaseBitInt = UIDesktop.UIOSelector_Get_BitnessInt(lDemoBaseUIOSelector) # Определить разрядность приложения, в котором обнаружен UIO объект по селектору + + :param inSpecificationList: UIO селектор, который определяет критерии поиска UIO объекта + :type inSpecificationList: list, обязательный + :return: None - UIO объект не обнаружен; 64 (int) - разрядность приложения равна 64 битам; 32 (int) - разрядность приложения равна 32 битам ''' lResult=None #Получить объект Application (Для проверки разрядности) @@ -457,18 +514,24 @@ def UIOSelector_Get_BitnessInt (inSpecificationList): else: lResult=32 return lResult -################################################################################################# -#Get process bitness ("32" or "64") -#inSpecificationList - UIOSelector -#old name - None -#return None (if Process not found), int 32, or int 64 + +#old: - def UIOSelector_Get_BitnessStr (inSpecificationList): - ''' - Detect process bitness by the UI Object UIO Selector. + """ + Определить разрядность приложения по UIO селектору. Вернуть результат в формате строки ("64" или "32") - :param inSpecificationList: UIOSelector. Example: [{"title":"notepad"},{"title":"OK"}] - :return: str "32" or str "64" - ''' + .. code-block:: python + + # UIDesktop: Взаимодействие с UI объектами приложений + from pyOpenRPA.Robot import UIDesktop + # 1С: UIO Селектор выбора базы + lDemoBaseUIOSelector = [{"title":"Запуск 1С:Предприятия","class_name":"V8TopLevelFrameTaxiStarter","backend":"uia"},{"title":"DEMO", "depth_start": 5, "depth_end": 5}] + lDemoBaseBitStr = UIDesktop.UIOSelector_Get_BitnessStr(lDemoBaseUIOSelector) # Определить разрядность приложения, в котором обнаружен UIO объект по селектору + + :param inSpecificationList: UIO селектор, который определяет критерии поиска UIO объекта + :type inSpecificationList: list, обязательный + :return: None - UIO объект не обнаружен; "64" (str) - разрядность приложения равна 64 битам; "32" (str) - разрядность приложения равна 32 битам + """ lResult=None #Получить объект Application (Для проверки разрядности) lRootElement=PWASpecification_Get_PWAApplication(inSpecificationList) @@ -478,28 +541,40 @@ def UIOSelector_Get_BitnessStr (inSpecificationList): else: lResult="32" return lResult -################################################################################################# -#Get OS bitness (32 or 64) -#old name - None -#return int 32, or int 64 + +#old: - def Get_OSBitnessInt (): ''' - Detect OS bitness. + Определить разрядность робота, в котором запускается данная функция - :return: int 32 or int 64 + .. code-block:: python + + from pyOpenRPA.Robot import UIDesktop + lRobotBitInt = UIDesktop.Get_OSBitnessInt() # Определить разрядность робота, в котором была вызвана это функция + + :return: 64 (int) - разрядность приложения равна 64 битам; 32 (int) - разрядность приложения равна 32 битам ''' lResult=32 if pywinauto.sysinfo.is_x64_OS(): lResult=64 return lResult -################################################################################################# +#old: - def UIOSelector_SafeOtherGet_Process(inUIOSelector): - ''' - Safe get other process or None if destination app is the other/same bitness + """ + Получить процесс робота другой разрядности (если приложение UIO объекта выполняется в другой разрядности). Функция возвращает None, если разрядность робота совпадает с разрядностью приложения UIO объекта, либо если при инициализации робота не устанавливался интерпретатор другой разрядности. - :param inUIOSelector: UIO Selector of the UI object - :return: None or process (of the other bitness) - ''' + .. code-block:: python + + # UIDesktop: Взаимодействие с UI объектами приложений + from pyOpenRPA.Robot import UIDesktop + # 1С: UIO Селектор выбора базы + lDemoBaseUIOSelector = [{"title":"Запуск 1С:Предприятия","class_name":"V8TopLevelFrameTaxiStarter","backend":"uia"},{"title":"DEMO", "depth_start": 5, "depth_end": 5}] + lOtherBitnessProcess = UIDesktop.UIOSelector_SafeOtherGet_Process(lDemoBaseUIOSelector) # Вернуть процесс робота, схожей разрядности + + :param inUIOSelector: UIO селектор, который определяет критерии поиска UIO объекта + :type inUIOSelector: list, обязательный + :return: Процесс робота схожей разрядности + """ #Default value lResult = None #Go check bitness if selector exists @@ -509,15 +584,44 @@ def UIOSelector_SafeOtherGet_Process(inUIOSelector): if lUIOSelectorAppBitness and Utils.ProcessBitness.mSettingsDict["BitnessProcessCurrent"] != lUIOSelectorAppBitness: lResult = Utils.ProcessBitness.OtherProcessGet() return lResult -################################################################################################## +#old: GetControl def PWASpecification_Get_UIO(inControlSpecificationArray): - ''' - #Backend def selection - attribute "backend" ("win32" || "uia") in 1-st list element - #old name - GetControl + """ + Получить UIO объект по PWA (pywinauto) селектору. (https://pywinauto.readthedocs.io/en/latest/code/pywinauto.findwindows.html). Мы рекомендуем использовать метод UIOSelector_UIO_Get, так как UIO селектор обладает большей функциональностью. - :param inControlSpecificationArray: List of dict, dict in pywinauto.find_windows notation - :return: list of UIO object - ''' + .. code-block:: python + + # UIDesktop: Взаимодействие с UI объектами приложений + from pyOpenRPA.Robot import UIDesktop + # 1С: UIO Селектор выбора базы + lDemoBaseUIOSelector = [{"title":"Запуск 1С:Предприятия","class_name":"V8TopLevelFrameTaxiStarter","backend":"uia"}] + lUIOObject = UIDesktop.PWASpecification_Get_UIO(lDemoBaseUIOSelector) # Получить UIO объект по PWA селектору + + :param inControlSpecificationArray: PWA селектор, который определяет критерии поиска UIO объекта + Допустимые ключи PWA селектора: + + - class_name содержимое атрибута class UIO объекта + - class_name_re содержимое атрибута class UIO объекта, которое удовлетворяет установленному рег. выражению + - process идентификатор процесса, в котором находится UIO объект + - title содержимое атрибута title UIO объекта + - title_re содержимое атрибута title UIO объекта, которое удовлетворяет установленному рег. выражению + - top_level_only признак поиска только на верхнем уровне приложения. По умолчанию True + - visible_only признак поиска только среди видимых UIO объектов. По умолчанию True + - enabled_only признак поиска только среди разблокированных UIO объектов. По умолчанию False + - best_match содержимое атрибута title UIO объекта максимально приближено к заданному + - handle идентификатор handle искомого UIO объекта + - ctrl_index индекс UIO объекта среди всех дочерних объектов в списке родительского + - found_index индекс UIO объекта среди всех обнаруженных + - predicate_func пользовательская функция проверки соответсвия UIO элемента + - active_only признак поиска только среди активных UIO объектов. По умолчанию False + - control_id идентификатор control_id искомого UIO объекта + - control_type тип элемента (применимо, если backend == "uia") + - auto_id идентификатор auto_id искомого UIO объекта (применимо, если backend == "uia") + - framework_id идентификатор framework_id искомого UIO объекта (применимо, если backend == "uia") + - backend вид технологии подключения к поиску UIO объекта ("uia" или "win32") + :type inControlSpecificationArray: list, обязательный + :return: UIO объект + """ #Определение backend lBackend=mDefaultPywinautoBackend if "backend" in inControlSpecificationArray[0]: @@ -563,14 +667,44 @@ def PWASpecification_Get_UIO(inControlSpecificationArray): #Добавить объект в результирующий массив lResultList.append(lTempObject) return lResultList -################################################################################################## + def PWASpecification_Get_PWAApplication(inControlSpecificationArray): - ''' - #Backend selection - attribute "backend" ("win32" || "uia") in 1-st list element + """ + Получить значение атрибута backend по PWA (pywinauto) селектору. Мы рекомендуем использовать метод UIOSelector_UIO_Get, так как UIO селектор обладает большей функциональностью. - :param inControlSpecificationArray: List of dict, dict in pywinauto.find_windows notation - :return: process application object - ''' + .. code-block:: python + + # UIDesktop: Взаимодействие с UI объектами приложений + from pyOpenRPA.Robot import UIDesktop + # 1С: UIO Селектор выбора базы + lDemoBaseUIOSelector = [{"title":"Запуск 1С:Предприятия","class_name":"V8TopLevelFrameTaxiStarter","backend":"uia"}] + lBackendStr = UIDesktop.PWASpecification_Get_PWAApplication(lDemoBaseUIOSelector) # Получить backend по PWA селектору + + :param inControlSpecificationArray: PWA селектор, который определяет критерии поиска UIO объекта + Допустимые ключи PWA селектора: + + - class_name содержимое атрибута class UIO объекта + - class_name_re содержимое атрибута class UIO объекта, которое удовлетворяет установленному рег. выражению + - process идентификатор процесса, в котором находится UIO объект + - title содержимое атрибута title UIO объекта + - title_re содержимое атрибута title UIO объекта, которое удовлетворяет установленному рег. выражению + - top_level_only признак поиска только на верхнем уровне приложения. По умолчанию True + - visible_only признак поиска только среди видимых UIO объектов. По умолчанию True + - enabled_only признак поиска только среди разблокированных UIO объектов. По умолчанию False + - best_match содержимое атрибута title UIO объекта максимально приближено к заданному + - handle идентификатор handle искомого UIO объекта + - ctrl_index индекс UIO объекта среди всех дочерних объектов в списке родительского + - found_index индекс UIO объекта среди всех обнаруженных + - predicate_func пользовательская функция проверки соответсвия UIO элемента + - active_only признак поиска только среди активных UIO объектов. По умолчанию False + - control_id идентификатор control_id искомого UIO объекта + - control_type тип элемента (применимо, если backend == "uia") + - auto_id идентификатор auto_id искомого UIO объекта (применимо, если backend == "uia") + - framework_id идентификатор framework_id искомого UIO объекта (применимо, если backend == "uia") + - backend вид технологии подключения к поиску UIO объекта ("uia" или "win32") + :type inControlSpecificationArray: list, обязательный + :return: "win32" или "uia" + """ inControlSpecificationArray=copy.deepcopy(inControlSpecificationArray) #Определение backend lBackend=mDefaultPywinautoBackend @@ -600,16 +734,23 @@ def PWASpecification_Get_PWAApplication(inControlSpecificationArray): #Скорректировано из-за недопонимания структуры lTempObject=lRPAApplication return lTempObject - -########################################################################################################### +#old: AutomationSearchMouseElement def UIOSelector_SearchChildByMouse_UIO(inElementSpecification): - ''' - UIOSelector (see description on the top of the document) - #old name - AutomationSearchMouseElement + """ + Инициировать визуальный поиск UIO объекта с помощью указателя мыши. При наведении указателя мыши UIO объект выделяется зеленой рамкой. Остановить режим поиска можно с помощью зажима клавиши ctrl left на протяжении нескольких секунд. После этого в веб окне студии будет отображено дерево расположения искомого UIO объекта. - :param inElementSpecification: UIOSelector of the UI Object - :return: pywinauto element wrapper instance or None - ''' + .. code-block:: python + + # UIDesktop: Взаимодействие с UI объектами приложений + from pyOpenRPA.Robot import UIDesktop + # 1С: UIO Селектор выбора базы + lDemoBaseUIOSelector = [{"title":"Запуск 1С:Предприятия","class_name":"V8TopLevelFrameTaxiStarter","backend":"uia"}] + lUIO = UIDesktop.UIOSelector_SearchChildByMouse_UIO(lDemoBaseUIOSelector) # Инициировать поиск дочернего UIO объекта, который расположен внутри lDemoBaseUIOSelector. + + :param inElementSpecification: UIO селектор, который определяет критерии поиска родительского UIO объекта, в котором будет производиться поиск дочернего UIO объекта + :type inElementSpecification: list, обязательный + :return: UIO объект или None (если UIO не был обнаружен) + """ lGUISearchElementSelected=None #Настройка - частота обновления подсвечивания lTimeSleepSeconds=0.4 @@ -647,15 +788,26 @@ def UIOSelector_SearchChildByMouse_UIO(inElementSpecification): #Вернуть результат поиска return lElementFoundedList -#################################################################################################### -#old name - AutomationSearchMouseElementHierarchy +#old: - AutomationSearchMouseElementHierarchy def UIOSelector_SearchChildByMouse_UIOTree(inUIOSelector): - ''' - !!!!Safe call is included (you can set activity and UIDesktop will choose the bitness and return the result)!!!!! + """ + Получить список уровней UIO объекта с указнием всех имеющихся атрибутов по входящему UIO селектору. + + !ВНИМАНИЕ! ДАННАЯ ФУНКЦИОНАЛЬНОСТЬ В АВТОМАТИЧЕСКОМ РЕЖИМЕ ПОДДЕРЖИВАЕТ ВСЕ РАЗРЯДНОСТИ ПРИЛОЖЕНИЙ (32|64), КОТОРЫЕ ЗАПУЩЕНЫ В СЕСИИ. PYTHON x64 ИМЕЕТ ВОЗМОЖНОСТЬ ВЗЗАИМОДЕЙСТВИЯ С x32 UIO ОБЪЕКТАМИ, НО МЫ РЕКОМЕНДУЕМ ДОПОЛНИТЕЛЬНО ИСПОЛЬЗОВАТЬ ИНТЕРПРЕТАТОР PYTHON x32 (ПОДРОБНЕЕ СМ. ФУНКЦИЮ Configure()) + + .. code-block:: python + + # UIDesktop: Взаимодействие с UI объектами приложений + from pyOpenRPA.Robot import UIDesktop + # 1С: UIO Селектор выбора базы + lDemoBaseUIOSelector = [{"title":"Запуск 1С:Предприятия","class_name":"V8TopLevelFrameTaxiStarter","backend":"uia"}] + lBackendStr = UIDesktop.UIOSelector_SearchChildByMouse_UIOTree(lDemoBaseUIOSelector) # Получить список атрибутов всех родительских элементов lDemoBaseUIOSelector. + + :param inUIOSelector: UIO селектор, который определяет UIO объект, для которого будет произведено извлечение всех атрибутов на всех уровнях. + :type inUIOSelector: list, обязательный + :return: list, список атрибутов на каждом уровне UIO объекта + """ - :param inUIOSelector: UIOSelector of the UI Object - :return: ? - ''' lItemInfo = [] #Check the bitness lSafeOtherProcess = UIOSelector_SafeOtherGet_Process(inUIOSelector) @@ -715,10 +867,24 @@ def UIOSelector_SearchChildByMouse_UIOTree(inUIOSelector): lItemInfo = lPIPEResponseDict["Result"] #Вернуть результат return lItemInfo -#################################################################################################### -#inElement- UIO (UI Object) #old name - PywinautoExtElementCtrlIndexGet def UIO_GetCtrlIndex_Int(inElement): + """ + Получить индекс UIO объекта inElement в списке родительского UIO объекта. + + .. code-block:: python + + # UIDesktop: Взаимодействие с UI объектами приложений + from pyOpenRPA.Robot import UIDesktop + # 1С: UIO Селектор выбора базы + lDemoBaseUIOSelector = [{"title":"Запуск 1С:Предприятия","class_name":"V8TopLevelFrameTaxiStarter","backend":"uia"}] + lUIO = UIDesktop.UIOSelector_Get_UIO(lDemoBaseUIOSelector) # Получить UIO объект по UIO селектору. + lUIOIndexInt = UIDesktop.UIO_GetCtrlIndex_Int(lUIO) # Получить индекс UIO объекта в списке у родительского UIO объекта. + + :param inElement: UIO объект, для которого требуется определить индекс в списке родительского UIO объекта. + :type inElement: list, обязательный + :return: int, индекс UIO объекта в списке родительского UIO объекта + """ lResult = None #Выполнить алгоритм, если есть Element if inElement is not None: @@ -747,12 +913,27 @@ def UIO_GetCtrlIndex_Int(inElement): #Вернуть результат return lResult -#################################################################################################### -# Get the UIO Info list for the selected criteria -#!!!!!Safe call is included (you can set activity and UIDesktop will choose the bitness and return the result)!!!!! -#inSpecificationList - UIOSelector -#old name - PywinautoExtElementsGetInfo +#old: - PywinautoExtElementsGetInfo def UIOSelector_Get_UIOInfoList (inUIOSelector, inElement=None): + """ + Техническая функция: Получить список параметров последних уровней UIO селектора по UIO объектам, которые удовлетворяют входящим inUIOSelector, поиск по которым будет производится от уровня inElement. + + !ВНИМАНИЕ! ДАННАЯ ФУНКЦИОНАЛЬНОСТЬ В АВТОМАТИЧЕСКОМ РЕЖИМЕ ПОДДЕРЖИВАЕТ ВСЕ РАЗРЯДНОСТИ ПРИЛОЖЕНИЙ (32|64), КОТОРЫЕ ЗАПУЩЕНЫ В СЕСИИ. PYTHON x64 ИМЕЕТ ВОЗМОЖНОСТЬ ВЗЗАИМОДЕЙСТВИЯ С x32 UIO ОБЪЕКТАМИ, НО МЫ РЕКОМЕНДУЕМ ДОПОЛНИТЕЛЬНО ИСПОЛЬЗОВАТЬ ИНТЕРПРЕТАТОР PYTHON x32 (ПОДРОБНЕЕ СМ. ФУНКЦИЮ Configure()) + + .. code-block:: python + + # UIDesktop: Взаимодействие с UI объектами приложений + from pyOpenRPA.Robot import UIDesktop + # 1С: UIO Селектор выбора базы + lDemoBaseUIOSelector = [{"title":"Запуск 1С:Предприятия","class_name":"V8TopLevelFrameTaxiStarter","backend":"uia"}] + lUIOInfoList = UIDesktop.UIOSelector_Get_UIOInfoList(lDemoBaseUIOSelector) # Получить словарь параметров по UIO селектору. + + :param inUIOSelector: UIO селектор, который определяет UIO объект, для которого будет произведено извлечение всех атрибутов на всех уровнях. + :type inUIOSelector: list, обязательный + :param inElement: UIO объект, от которого выполнить поиск дочерних UIO объектов по UIO селектору inUIOSelector. По умолчанию None - поиск среди всех приложений. + :type inElement: UIO объект, необязательный + :return: dict, пример: {"title":None,"rich_text":None,"process_id":None,"process":None,"handle":None,"class_name":None,"control_type":None,"control_id":None,"rectangle":{"left":None,"top":None,"right":None,"bottom":None}, 'runtime_id':None} + """ #Check the bitness lSafeOtherProcess = UIOSelector_SafeOtherGet_Process(inUIOSelector) if lSafeOtherProcess is None: @@ -778,17 +959,25 @@ def UIOSelector_Get_UIOInfoList (inUIOSelector, inElement=None): lResultList = lPIPEResponseDict["Result"] return lResultList -#################################################################################################### -#Try to restore (maximize) window, if it's was minimized -#(особенность uia backend - он не может прицепиться к окну, если оно свернуто) -#inSpecificationList - UIOSelector -#old name - PywinautoExtTryToRestore +#old: - PywinautoExtTryToRestore def UIOSelector_TryRestore_Dict(inSpecificationList): """ - Try to restore (maximize) window, if it's minimized. (!IMPORTANT! When use UIA framework minimized windows doesn't appear by the UIOSelector. You need to try restore windows and after that try to get UIO) + Восстановить окно приложения на экране по UIO селектору inSpecificationList, если оно было свернуто. Функция обернута в try .. except - ошибок не возникнет. + + !ВНИМАНИЕ! ДАННАЯ ФУНКЦИОНАЛЬНОСТЬ УЖЕ ИСПОЛЬЗУЕТСЯ В РЯДЕ ДРУГИХ ФУНКЦИЙ ТАК КАК АДРЕССАЦИЯ ПО UIA FRAMEWORK НЕДОСТУПНА, ЕСЛИ ПРИЛОЖЕНИЕ СВЕРНУТО. + + !ВНИМАНИЕ! ДАННАЯ ФУНКЦИОНАЛЬНОСТЬ В АВТОМАТИЧЕСКОМ РЕЖИМЕ ПОДДЕРЖИВАЕТ ВСЕ РАЗРЯДНОСТИ ПРИЛОЖЕНИЙ (32|64), КОТОРЫЕ ЗАПУЩЕНЫ В СЕСИИ. PYTHON x64 ИМЕЕТ ВОЗМОЖНОСТЬ ВЗЗАИМОДЕЙСТВИЯ С x32 UIO ОБЪЕКТАМИ, НО МЫ РЕКОМЕНДУЕМ ДОПОЛНИТЕЛЬНО ИСПОЛЬЗОВАТЬ ИНТЕРПРЕТАТОР PYTHON x32 (ПОДРОБНЕЕ СМ. ФУНКЦИЮ Configure()) + + .. code-block:: python + + # UIDesktop: Взаимодействие с UI объектами приложений + from pyOpenRPA.Robot import UIDesktop + # 1С: UIO Селектор выбора базы + lDemoBaseUIOSelector = [{"title":"Запуск 1С:Предприятия","class_name":"V8TopLevelFrameTaxiStarter","backend":"uia"}] + UIDesktop.UIOSelector_TryRestore_Dict(lDemoBaseUIOSelector) # Попытка восстановления свернутого окна по UIO селектору. - :param inSpecificationList: UIOSelector - List of items, which contains condition attributes - :return: + :param inSpecificationList: UIO селектор, который определяет UIO объект, для которого будет произведено извлечение всех атрибутов на всех уровнях. + :type inSpecificationList: list, обязательный """ lResult={} try: @@ -802,17 +991,24 @@ def UIOSelector_TryRestore_Dict(inSpecificationList): except Exception: True==False return lResult -#################################################################################################### -#Get the list of the UI object activities -#!!!!!Safe call is included (you can set activity and UIDesktop will choose the bitness and return the result)!!!!! -#inControlSpecificationArray - UIOSelector -#old name - ElementActionGetList + +#old: - ElementActionGetList def UIOSelector_Get_UIOActivityList (inUIOSelector): """ - Get the list of the UI object activities + Получить список доступных действий/функций по UIO селектору inUIOSelector. Описание возможных активностей см. ниже. + + !ВНИМАНИЕ! ДАННАЯ ФУНКЦИОНАЛЬНОСТЬ В АВТОМАТИЧЕСКОМ РЕЖИМЕ ПОДДЕРЖИВАЕТ ВСЕ РАЗРЯДНОСТИ ПРИЛОЖЕНИЙ (32|64), КОТОРЫЕ ЗАПУЩЕНЫ В СЕСИИ. PYTHON x64 ИМЕЕТ ВОЗМОЖНОСТЬ ВЗЗАИМОДЕЙСТВИЯ С x32 UIO ОБЪЕКТАМИ, НО МЫ РЕКОМЕНДУЕМ ДОПОЛНИТЕЛЬНО ИСПОЛЬЗОВАТЬ ИНТЕРПРЕТАТОР PYTHON x32 (ПОДРОБНЕЕ СМ. ФУНКЦИЮ Configure()) + + .. code-block:: python - :param inUIOSelector: UIOSelector - List of items, which contains condition attributes - :return: + # UIDesktop: Взаимодействие с UI объектами приложений + from pyOpenRPA.Robot import UIDesktop + # 1С: UIO Селектор выбора базы + lDemoBaseUIOSelector = [{"title":"Запуск 1С:Предприятия","class_name":"V8TopLevelFrameTaxiStarter","backend":"uia"}] + lActivityList = UIDesktop.UIOSelector_Get_UIOActivityList(lDemoBaseUIOSelector) # Получить список активностей по UIO селектору. + + :param inUIOSelector: UIO селектор, который определяет UIO объект, для которого будет представлен перечень доступных активностей. + :type inUIOSelector: list, обязательный """ #Check the bitness lSafeOtherProcess = UIOSelector_SafeOtherGet_Process(inUIOSelector) @@ -845,21 +1041,30 @@ def UIOSelector_Get_UIOActivityList (inUIOSelector): lResult = lPIPEResponseDict["Result"] return lResult -#################################################################################################### -#Run the activity in UIO (UI Object) -#!!!!!Safe call is included (you can set activity and UIDesktop will choose the bitness and return the result)!!!!! -#inUIOSelector -#inActionName - UIOActivity (name) from Pywinauto -#old name - ElementRunAction +#old: - ElementRunAction def UIOSelectorUIOActivity_Run_Dict(inUIOSelector, inActionName, inArgumentList=None, inkwArgumentObject=None): """ - Run the activity in UIO (UI Object) + Выполнить активность inActionName над UIO объектом, полученным с помощью UIO селектора inUIOSelector. Описание возможных активностей см. ниже. + + !ВНИМАНИЕ! ДАННАЯ ФУНКЦИОНАЛЬНОСТЬ В АВТОМАТИЧЕСКОМ РЕЖИМЕ ПОДДЕРЖИВАЕТ ВСЕ РАЗРЯДНОСТИ ПРИЛОЖЕНИЙ (32|64), КОТОРЫЕ ЗАПУЩЕНЫ В СЕСИИ. PYTHON x64 ИМЕЕТ ВОЗМОЖНОСТЬ ВЗЗАИМОДЕЙСТВИЯ С x32 UIO ОБЪЕКТАМИ, НО МЫ РЕКОМЕНДУЕМ ДОПОЛНИТЕЛЬНО ИСПОЛЬЗОВАТЬ ИНТЕРПРЕТАТОР PYTHON x32 (ПОДРОБНЕЕ СМ. ФУНКЦИЮ Configure()) - :param inUIOSelector: UIOSelector - List of items, which contains condition attributes - :param inActionName: UIOActivity (name) activity name string from Pywinauto - :param inArgumentList: - :param inkwArgumentObject: - :return: + .. code-block:: python + + # UIDesktop: Взаимодействие с UI объектами приложений + from pyOpenRPA.Robot import UIDesktop + # 1С: UIO Селектор выбора базы + lDemoBaseUIOSelector = [{"title":"Запуск 1С:Предприятия","class_name":"V8TopLevelFrameTaxiStarter","backend":"uia"}] + lActivityResult = UIDesktop.UIOSelectorUIOActivity_Run_Dict(lDemoBaseUIOSelector, "click") # выполнить действие над UIO объектом с помощью UIO селектора. + + :param inUIOSelector: UIO селектор, который определяет UIO объект, для которого будет представлен перечень доступных активностей. + :type inUIOSelector: list, обязательный + :param inActionName: наименование активности, которую требуется выполнить над UIO объектом + :type inActionName: str, обязательный + :param inArgumentList: список передаваемых неименованных аргументов в функцию inActionName + :type inArgumentList: list, необязательный + :param inkwArgumentObject: словарь передаваемых именованных аргументов в функцию inActionName + :type inkwArgumentObject: dict, необязательный + :return: возвращает результат запускаемой функции с наименованием inActionName над UIO объектом """ if inArgumentList is None: inArgumentList=[] # 2021 02 22 Minor fix by Ivan Maslov if inkwArgumentObject is None: inkwArgumentObject={} # 2021 02 22 Minor fix by Ivan Maslov @@ -905,16 +1110,57 @@ def UIOSelectorUIOActivity_Run_Dict(inUIOSelector, inActionName, inArgumentList= lResult = lPIPEResponseDict["Result"] return lResult -#################################################################################################### -#Get the UIO dict of the attributes -#!!!!!Safe call is included (you can set activity and UIDesktop will choose the bitness and return the result)!!!!! #old name - ElementGetInfo def UIOSelector_Get_UIOInfo(inUIOSelector): """ - Get the UIO dict of the attributes + Получить свойства UIO объекта (element_info), по заданному UIO селектору. Ниже представлен перечень возвращаемых свойств. + + Для backend = win32: + + - automation_id (int) + - class_name (str) + - control_id (int) + - control_type (str) + - full_control_type (str) + - enabled (bool) + - handle (int) + - name (str) + - parent (object/UIO) + - process_id (int) + - rectangle (object/rect) + - rich_text (str) + - visible (bool) + + Для backend = uia: - :param inUIOSelector: UIOSelector - List of items, which contains condition attributes - :return: + - automation_id (int) + - class_name (str) + - control_id (int) + - control_type (str) + - enabled (bool) + - framework_id (int) + - handle (int) + - name (str) + - parent (object/UIO) + - process_id (int) + - rectangle (object/rect) + - rich_text (str) + - runtime_id (int) + - visible (bool) + + !ВНИМАНИЕ! ДАННАЯ ФУНКЦИОНАЛЬНОСТЬ В АВТОМАТИЧЕСКОМ РЕЖИМЕ ПОДДЕРЖИВАЕТ ВСЕ РАЗРЯДНОСТИ ПРИЛОЖЕНИЙ (32|64), КОТОРЫЕ ЗАПУЩЕНЫ В СЕСИИ. PYTHON x64 ИМЕЕТ ВОЗМОЖНОСТЬ ВЗЗАИМОДЕЙСТВИЯ С x32 UIO ОБЪЕКТАМИ, НО МЫ РЕКОМЕНДУЕМ ДОПОЛНИТЕЛЬНО ИСПОЛЬЗОВАТЬ ИНТЕРПРЕТАТОР PYTHON x32 (ПОДРОБНЕЕ СМ. ФУНКЦИЮ Configure()) + + .. code-block:: python + + # UIDesktop: Взаимодействие с UI объектами приложений + from pyOpenRPA.Robot import UIDesktop + # 1С: UIO Селектор выбора базы + lDemoBaseUIOSelector = [{"title":"Запуск 1С:Предприятия","class_name":"V8TopLevelFrameTaxiStarter","backend":"uia"}] + lUIOElementInfoDict = UIDesktop.UIOSelector_Get_UIOInfo(lDemoBaseUIOSelector) #Получить свойства над UIO объектом с помощью UIO селектора. + + :param inUIOSelector: UIO селектор, который определяет UIO объект, для которого будет представлен перечень доступных активностей. + :type inUIOSelector: list, обязательный + :return: словарь свойств element_info: Пример {"control_id": ..., "process_id": ...} """ #Check the bitness lSafeOtherProcess = UIOSelector_SafeOtherGet_Process(inUIOSelector) @@ -945,12 +1191,28 @@ def UIOSelector_Get_UIOInfo(inUIOSelector): else: lResultList = lPIPEResponseDict["Result"] return lResultList -#################################################################################################### -#Search child UIO by the: Parent UIO, X, Y -#inHierarchyList: [{"index":<>,"element":<>}] - technical argument for internal purpose -#result -List of dict [{"index":<>,"element":<>}] -- list of element hierarchy specifications -#old name - GUISearchElementByRootXY +#old: - GUISearchElementByRootXY def UIOXY_SearchChild_ListDict(inRootElement,inX,inY,inHierarchyList=None): + """ + Техническая функция: Получить иерархию вложенности UIO объекта по заданным корневому UIO объекту, координатам X и Y. + + .. code-block:: python + + # UIDesktop: Взаимодействие с UI объектами приложений + from pyOpenRPA.Robot import UIDesktop + # 1С: UIO Селектор выбора базы + lDemoBaseUIOSelector = [{"title":"Запуск 1С:Предприятия","class_name":"V8TopLevelFrameTaxiStarter","backend":"uia"}] + lUIO = UIDesktop.UIOSelector_Get_UIO(lDemoBaseUIOSelector) # Получить UIO объект с помощью UIO селектора + lUIOHierarchyList = UIDesktop.UIOXY_SearchChild_ListDict(lUIO, 100, 200) # Получить UIO объект с помощью UIO селектора родительского элемента и координат X / Y + + :param inRootElement: родительский UIO объект, полученный ранее с помощью UIO селектора. + :type inRootElement: object UIO, обязательный + :param inX: родительский UIO объект, полученный ранее с помощью UIO селектора. + :type inX: int, обязательный + :param inY: родительский UIO объект, полученный ранее с помощью UIO селектора. + :type inY: int, обязательный + :return: Список словарей - уровней UIO объектов + """ if inHierarchyList is None: inHierarchyList = [] #Инициализация результирующего значения lResultElement = None @@ -1035,21 +1297,27 @@ def UIOXY_SearchChild_ListDict(inRootElement,inX,inY,inHierarchyList=None): False == False return lResultHierarchyList -################################################################################################### -#Get list of child UIO's by Parent UIOSelector -#!!!!!Safe call is included (you can set activity and UIDesktop will choose the bitness and return the result)!!!!! -#inControlSpecificationArray- UIOSelector -#old name - ElementGetChildElementList +#old: - ElementGetChildElementList def UIOSelector_GetChildList_UIOList(inUIOSelector=None, inBackend=mDefaultPywinautoBackend): """ - Get list of child UIO's by the parent UIOSelector + Получить список дочерних UIO объектов по входящему UIO селектору inUIOSelector. + + !ВНИМАНИЕ! ДАННАЯ ФУНКЦИОНАЛЬНОСТЬ В АВТОМАТИЧЕСКОМ РЕЖИМЕ ПОДДЕРЖИВАЕТ ВСЕ РАЗРЯДНОСТИ ПРИЛОЖЕНИЙ (32|64), КОТОРЫЕ ЗАПУЩЕНЫ В СЕСИИ. PYTHON x64 ИМЕЕТ ВОЗМОЖНОСТЬ ВЗЗАИМОДЕЙСТВИЯ С x32 UIO ОБЪЕКТАМИ, НО МЫ РЕКОМЕНДУЕМ ДОПОЛНИТЕЛЬНО ИСПОЛЬЗОВАТЬ ИНТЕРПРЕТАТОР PYTHON x32 (ПОДРОБНЕЕ СМ. ФУНКЦИЮ Configure()) - :param inUIOSelector: UIOSelector - List of items, which contains condition attributes - :param inBackend: "win32" or "uia" - :return: - """ + .. code-block:: python + # UIDesktop: Взаимодействие с UI объектами приложений + from pyOpenRPA.Robot import UIDesktop + # 1С: UIO Селектор выбора базы + lDemoBaseUIOSelector = [{"title":"Запуск 1С:Предприятия","class_name":"V8TopLevelFrameTaxiStarter","backend":"uia"}] + lUIOList = UIDesktop.UIOSelector_GetChildList_UIOList(lDemoBaseUIOSelector) # Получить список дочерних UIO объектов с помощью UIO селектора + :param inUIOSelector: родительский UIO объект, полученный ранее с помощью UIO селектора. + :type inUIOSelector: list, обязательный + :param inBackend: вид backend "win32" или "uia". По умолчанию mDefaultPywinautoBackend ("win32") + :type inBackend: str, необязательный + :return: список дочерних UIO объектов + """ if inUIOSelector is None: inUIOSelector = [] #mRobotLogger.info(f"File!!!!") #mRobotLogger.info(f"inSelector:{str(inUIOSelector)}, inBackend:{str(inBackend)}") @@ -1099,12 +1367,24 @@ def UIOSelector_GetChildList_UIOList(inUIOSelector=None, inBackend=mDefaultPywin lResultList = lPIPEResponseDict["Result"] return lResultList -#################################################################################################### -#Подготовить массив для обращшения к поиску элемементов -#inControlSpecificationArray - UIOSelector (can be dirty) -#old name 1 - ElementSpecificationArraySearchPrepare -#old name 2 - ElementSpecificationListNormalize +#old1: - ElementSpecificationArraySearchPrepare +#old2: - ElementSpecificationListNormalize def UIOSelector_SearchUIONormalize_UIOSelector (inControlSpecificationArray): + """ + Нормализовать UIO селектор для дальнейшего использования в функциях поиск UIO объекта. Если недопустимых атрибутов не присутствует, то оставить как есть. + + .. code-block:: python + + # UIDesktop: Взаимодействие с UI объектами приложений + from pyOpenRPA.Robot import UIDesktop + # 1С: UIO Селектор выбора базы + lDemoBaseUIOSelectorDitry = [{"title":"Запуск 1С:Предприятия","class_name":"V8TopLevelFrameTaxiStarter","backend":"uia"}] + lDemoBaseUIOSelectorClean = UIDesktop.UIOSelector_SearchUIONormalize_UIOSelector(lDemoBaseUIOSelectorDitry) # Очистить UIO селектор от недопустимых ключей для дальнейшего использования + + :param inControlSpecificationArray: UIO селектор, который определяет UIO объект, для которого будет представлен перечень доступных активностей. + :type inControlSpecificationArray: list, обязательный + :return: нормализованный UIO селектор + """ lResult=[] #Циклический обход for lSpecificationItem in inControlSpecificationArray: @@ -1172,12 +1452,25 @@ def UIOSelector_SearchUIONormalize_UIOSelector (inControlSpecificationArray): lResult.append(lSpecificationItemNew) #Вернуть результат return lResult -#################################################################################################### -#Подготовить массив для обращшения к поиску процесса (отличается от поиска элемента, тк данная функция нужна для нормализации спецификации для подключения к процессу с окнами) -#inControlSpecificationArray - UIOSelector (can be dirty) + #old name 1 - ElementSpecificationArraySearchPrepare #old name 2 - ElementSpecificationListNormalize def UIOSelector_SearchProcessNormalize_UIOSelector (inControlSpecificationArray): + """ + Нормализовать UIO селектор для дальнейшего использования в функциях поиска процесса, в котором находится искомый UIO объект. Если недопустимых атрибутов не присутствует, то оставить как есть. + + .. code-block:: python + + # UIDesktop: Взаимодействие с UI объектами приложений + from pyOpenRPA.Robot import UIDesktop + # 1С: UIO Селектор выбора базы + lDemoBaseUIOSelectorDitry = [{"title":"Запуск 1С:Предприятия","class_name":"V8TopLevelFrameTaxiStarter","backend":"uia"}] + lDemoBaseUIOSelectorClean = UIDesktop.UIOSelector_SearchProcessNormalize_UIOSelector(lDemoBaseUIOSelectorDitry) # Очистить UIO селектор от недопустимых ключей для дальнейшего использования + + :param inControlSpecificationArray: UIO селектор, который определяет UIO объект, для которого будет представлен перечень доступных активностей. + :type inControlSpecificationArray: list, обязательный + :return: нормализованный UIO селектор + """ lResult=[] #Циклический обход for lSpecificationItem in inControlSpecificationArray: @@ -1250,11 +1543,25 @@ def UIOSelector_SearchProcessNormalize_UIOSelector (inControlSpecificationArray) lResult.append(lSpecificationItemNew) #Вернуть результат return lResult -#################################################################################################### -#Transfer UI object element info (pywinauto) to UIOInfo (dict of attributes) -#inElementInfo - UIOEI -#old name - ElementInfoExportObject + +#old: - ElementInfoExportObject def UIOEI_Convert_UIOInfo(inElementInfo): + """ + Техническая функция: Дообогащение словаря с параметрами UIO объекта по заданному UIO.element_info + + .. code-block:: python + + # UIDesktop: Взаимодействие с UI объектами приложений + from pyOpenRPA.Robot import UIDesktop + # 1С: UIO Селектор выбора базы + lDemoBaseUIOSelector = [{"title":"Запуск 1С:Предприятия","class_name":"V8TopLevelFrameTaxiStarter","backend":"uia"}] + lUIO = UIDesktop.UIOSelector_Get_UIO(lDemoBaseUIOSelector) # Получить UIO объект по UIO селектору. + lUIOProcessInfoDict = UIDesktop.UIOEI_Convert_UIOInfo(lUIO.element_info) + + :param inElementInfo: экземпляр класса UIO.element_info, для которого требуется дообогатить словарь с параметрами (в дальнейшем можно использовать как элемент UIO селектора). + :type inElementInfo: object, обязательный + :return: dict, пример: {"title":None,"rich_text":None,"process_id":None,"process":None,"handle":None,"class_name":None,"control_type":None,"control_id":None,"rectangle":{"left":None,"top":None,"right":None,"bottom":None}, 'runtime_id':None} + """ #Подготовить выходную структуру данных lResult = {"title":None,"rich_text":None,"process_id":None,"process":None,"handle":None,"class_name":None,"control_type":None,"control_id":None,"rectangle":{"left":None,"top":None,"right":None,"bottom":None}, 'runtime_id':None} #Проверка name @@ -1322,10 +1629,21 @@ def UIOEI_Convert_UIOInfo(inElementInfo): #Вернуть результат return lResult -################################################################################################### -#Get list of top level -#old name - GetRootElementList +#old: - GetRootElementList def BackendStr_GetTopLevelList_UIOInfo(inBackend=mDefaultPywinautoBackend): + """ + Получить список UIOInfo словарей - процессы, которые запущены в рабочей сессии и готовы для взаимодействия с роботом через backend inBackend + + .. code-block:: python + + # UIDesktop: Взаимодействие с UI объектами приложений + from pyOpenRPA.Robot import UIDesktop + lAppList = UIDesktop.BackendStr_GetTopLevelList_UIOInfo() # Очистить UIO селектор от недопустимых ключей для дальнейшего использования + + :param inBackend: вид backend, который планируется использовать для взаимодействия с UIO объектами + :type inBackend: list, обязательный + :return: список UIOInfo словарей + """ #Получить список объектов lResultList=pywinauto.findwindows.find_elements(top_level_only=True,backend=inBackend) lResultList2=[] @@ -1334,16 +1652,23 @@ def BackendStr_GetTopLevelList_UIOInfo(inBackend=mDefaultPywinautoBackend): lResultList2.append(UIOEI_Convert_UIOInfo(lI)) return lResultList2 -################################################################################################### -#Highlight the UI object -#!!!!!Safe call is included (you can set activity and UIDesktop will choose the bitness and return the result)!!!!! -#old name - ElementDrawOutlineNew +#old: - ElementDrawOutlineNew def UIOSelector_Highlight(inUIOSelector): """ - Highlight (draw outline) the element (in app) by the UIO selector. + Подсветить на несколько секунд на экране зеленой рамкой UIO объект, который соответствует входящему UIO селектору inUIOSelector - :param inUIOSelector: UIOSelector - List of items, which contains condition attributes - :return: + !ВНИМАНИЕ! ДАННАЯ ФУНКЦИОНАЛЬНОСТЬ В АВТОМАТИЧЕСКОМ РЕЖИМЕ ПОДДЕРЖИВАЕТ ВСЕ РАЗРЯДНОСТИ ПРИЛОЖЕНИЙ (32|64), КОТОРЫЕ ЗАПУЩЕНЫ В СЕСИИ. PYTHON x64 ИМЕЕТ ВОЗМОЖНОСТЬ ВЗЗАИМОДЕЙСТВИЯ С x32 UIO ОБЪЕКТАМИ, НО МЫ РЕКОМЕНДУЕМ ДОПОЛНИТЕЛЬНО ИСПОЛЬЗОВАТЬ ИНТЕРПРЕТАТОР PYTHON x32 (ПОДРОБНЕЕ СМ. ФУНКЦИЮ Configure()) + + .. code-block:: python + + # UIDesktop: Взаимодействие с UI объектами приложений + from pyOpenRPA.Robot import UIDesktop + # 1С: UIO Селектор выбора базы + lDemoBaseUIOSelector = [{"title":"Запуск 1С:Предприятия","class_name":"V8TopLevelFrameTaxiStarter","backend":"uia"}] + UIDesktop.UIOSelector_Highlight(lDemoBaseUIOSelector) # Подсветить UIO объект по UIO селектору + + :param inUIOSelector: UIO селектор, который определяет UIO объект, для которого будет представлен перечень доступных активностей. + :type inUIOSelector: list, обязательный """ #Check the bitness lSafeOtherProcess = UIOSelector_SafeOtherGet_Process(inUIOSelector) @@ -1364,17 +1689,23 @@ def UIOSelector_Highlight(inUIOSelector): else: return lPIPEResponseDict["Result"] return True - -################################################################################################### -#inSpecificationArray - UIOSelector -#!!!!!Safe call is included (you can set activity and UIDesktop will choose the bitness and return the result)!!!!! -#old name - ElementDrawOutlineNewFocus +#old: - ElementDrawOutlineNewFocus def UIOSelector_FocusHighlight(inUIOSelector): """ - Set focus and highlight (draw outline) the element (in app) by the UIO selector. + Установить фокус и подсветить на несколько секунд на экране зеленой рамкой UIO объект, который соответствует входящему UIO селектору inUIOSelector + + !ВНИМАНИЕ! ДАННАЯ ФУНКЦИОНАЛЬНОСТЬ В АВТОМАТИЧЕСКОМ РЕЖИМЕ ПОДДЕРЖИВАЕТ ВСЕ РАЗРЯДНОСТИ ПРИЛОЖЕНИЙ (32|64), КОТОРЫЕ ЗАПУЩЕНЫ В СЕСИИ. PYTHON x64 ИМЕЕТ ВОЗМОЖНОСТЬ ВЗЗАИМОДЕЙСТВИЯ С x32 UIO ОБЪЕКТАМИ, НО МЫ РЕКОМЕНДУЕМ ДОПОЛНИТЕЛЬНО ИСПОЛЬЗОВАТЬ ИНТЕРПРЕТАТОР PYTHON x32 (ПОДРОБНЕЕ СМ. ФУНКЦИЮ Configure()) - :param inUIOSelector: UIOSelector - List of items, which contains condition attributes - :return: + .. code-block:: python + + # UIDesktop: Взаимодействие с UI объектами приложений + from pyOpenRPA.Robot import UIDesktop + # 1С: UIO Селектор выбора базы + lDemoBaseUIOSelector = [{"title":"Запуск 1С:Предприятия","class_name":"V8TopLevelFrameTaxiStarter","backend":"uia"}] + UIDesktop.UIOSelector_FocusHighlight(lDemoBaseUIOSelector) # Установить фокус и подсветить UIO объект по UIO селектору + + :param inUIOSelector: UIO селектор, который определяет UIO объект, для которого будет представлен перечень доступных активностей. + :type inUIOSelector: list, обязательный """ #Check the bitness @@ -1397,9 +1728,29 @@ def UIOSelector_FocusHighlight(inUIOSelector): return lPIPEResponseDict["Result"] return True -################################################################################################### -#old name - draw_outline_new +#old: - draw_outline_new def UIO_Highlight(lWrapperObject,colour='green',thickness=2,fill=win32defines.BS_NULL,rect=None,inFlagSetFocus=False): + """ + Выполнить подсветку UIO объекта на экране + + .. code-block:: python + + # UIDesktop: Взаимодействие с UI объектами приложений + from pyOpenRPA.Robot import UIDesktop + # 1С: UIO Селектор выбора базы + lDemoBaseUIOSelector = [{"title":"Запуск 1С:Предприятия","class_name":"V8TopLevelFrameTaxiStarter","backend":"uia"}] + lUIO = UIDesktop.UIOSelector_Get_UIO(lDemoBaseUIOSelector) # Получить UIO объект по UIO селектору + UIDesktop.UIO_Highlight(lUIO) # Подсветить UIO объект по UIO селектору зеленым цветом с толщиной подсветки 2 px. + + :param lWrapperObject: UIO объект, который будет подсвечен + :type lWrapperObject: object UIO, обязательный + :param colour: цвет подсветки UIO объекта. Варианты: 'red', 'green', 'blue'. По умолчанию 'green' + :type colour: str, необязательный + :param thickness: толщина подсветки UIO объекта. По умолчанию 2 + :type thickness: int, необязательный + :param inFlagSetFocus: признак установки фокуса на UIO объект перед подсветкой. По умолчанию False + :type inFlagSetFocus: bool, необязательный + """ if lWrapperObject is not None: """ Draw an outline around the window. @@ -1449,10 +1800,27 @@ def UIO_Highlight(lWrapperObject,colour='green',thickness=2,fill=win32defines.BS # delete the Display context that we created win32functions.DeleteDC(dc) -################################################################################################### -#Аналог подсвечивания + установка фокуса -#old name - draw_outline_new_focus +#old: - draw_outline_new_focus def UIO_FocusHighlight(lWrapperObject,colour='green',thickness=2,fill=win32defines.BS_NULL,rect=None): + """ + Установить фокус и выполнить подсветку UIO объекта на экране + + .. code-block:: python + + # UIDesktop: Взаимодействие с UI объектами приложений + from pyOpenRPA.Robot import UIDesktop + # 1С: UIO Селектор выбора базы + lDemoBaseUIOSelector = [{"title":"Запуск 1С:Предприятия","class_name":"V8TopLevelFrameTaxiStarter","backend":"uia"}] + lUIO = UIDesktop.UIOSelector_Get_UIO(lDemoBaseUIOSelector) # Получить UIO объект по UIO селектору + UIDesktop.UIO_FocusHighlight(lUIO) # Установить фокус и подсветить UIO объект по UIO селектору зеленым цветом с толщиной подсветки 2 px. + + :param lWrapperObject: UIO объект, который будет подсвечен + :type lWrapperObject: object UIO, обязательный + :param colour: цвет подсветки UIO объекта. Варианты: 'red', 'green', 'blue'. По умолчанию 'green' + :type colour: str, необязательный + :param thickness: толщина подсветки UIO объекта. По умолчанию 2 + :type thickness: int, необязательный + """ UIO_Highlight(lWrapperObject,'green',2,win32defines.BS_NULL,None,True) #Определить разрядность процесса diff --git a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/pyOpenRPA/__init__.py b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/pyOpenRPA/__init__.py index 8c4b3aa6..fc97568b 100644 --- a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/pyOpenRPA/__init__.py +++ b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/pyOpenRPA/__init__.py @@ -1,9 +1,9 @@ r""" -The OpenRPA package (from UnicodeLabs) +The pyOpenRPA package """ -__version__ = 'v1.2.12' +__version__ = 'v1.2.13' __all__ = [] -__author__ = 'Ivan Maslov ' +__author__ = 'Ivan Maslov ' #from .Core import Robot \ No newline at end of file diff --git a/Sources/GuideSphinx/01_HowToInstall.rst b/Sources/GuideSphinx/01_HowToInstall.rst index ad09df6c..21abf39c 100644 --- a/Sources/GuideSphinx/01_HowToInstall.rst +++ b/Sources/GuideSphinx/01_HowToInstall.rst @@ -2,25 +2,37 @@ 1. Первый запуск #################################### -Are you ready to install the pyOpenRPA solution on your machine? +Готовы испытать всю мощь перспективных технологий? -Ok, we start. -**Do the following operations:** +Будет очень интересно - начинаем! -- Download the pyOpenRPA package from master branch on GitLab [Download ZIP](https://gitlab.com/UnicodeLabs/OpenRPA/-/archive/master/OpenRPA-master.zip) -- Unzip the package +**Для начала необходимо выполнить следующие действия:** -**Installation has been completed :)** +- Скачать пакет pyOpenRPA c главной страницы https://pyopenrpa.ru/ +- Распаковать пакет куда угодно! + +**ВСЁ - Развертывание pyOpenRPA завершено! :)** ************************************************** -How to check installation +Проверить, что pyOpenRPA развернута корректно? ************************************************** -- Run portable python (built in the pyOpenRPA) +В папке pyOpenRPA запустить интерпретатор Python - - x32 python (GIT\\Resources\\WPy32-3720\\python-3.7.2\\python.exe) - - x64 python (GIT\\Resources\\WPy64-3720\\python-3.7.2.amd64\\python.exe) +- x32 Python (GIT\\Resources\\WPy32-3720\\python-3.7.2\\python.exe) +- x64 Python (GIT\\Resources\\WPy64-3720\\python-3.7.2.amd64\\python.exe) -**The pyOpenRPA has been successfully installed if the portable python 3.7.2 was started without any exceptions (see screenshot).** +**Платформа pyOpenRPA успешно развернута корректно. если интерпретаторы python 3.7.2 были запущены без проблем (см. скриншот).** .. image:: /img/cb5dec8cecafa7d64f6cd14b2672acce.png - :alt: cb5dec8cecafa7d64f6cd14b2672acce.png \ No newline at end of file + :alt: cb5dec8cecafa7d64f6cd14b2672acce.png + +****************************** +Быстрая навигация +****************************** + +- `Сообщество pyOpenRPA (telegram) `_ +- `Сообщество pyOpenRPA (tenchat) `_ +- `Сообщество pyOpenRPA (вконтакте) `_ +- `Презентация pyOpenRPA `_ +- `Портал pyOpenRPA `_ +- `Репозиторий pyOpenRPA `_ \ No newline at end of file diff --git a/Sources/GuideSphinx/03_Copyrights_Contacts.rst b/Sources/GuideSphinx/03_Copyrights_Contacts.rst index f9a277f8..bb91f77f 100644 --- a/Sources/GuideSphinx/03_Copyrights_Contacts.rst +++ b/Sources/GuideSphinx/03_Copyrights_Contacts.rst @@ -80,4 +80,15 @@ pyOpenRPA - роботы Вам помогут! - Handlebars, v4.1.2, лицензия MIT, https://github.com/handlebars-lang/handlebars.js/blob/master/LICENSE - jinja2, v2.11.2, лицензия BSD 3-Clause, https://github.com/pallets/jinja/blob/main/LICENSE.rst - JupiterNotebook v6.1.4, лицензия BSD 3-Clause, https://github.com/jupyter/notebook/blob/main/LICENSE -- schedule, v1.1.0, лицензия MIT, https://github.com/dbader/schedule/blob/master/LICENSE.txt \ No newline at end of file +- schedule, v1.1.0, лицензия MIT, https://github.com/dbader/schedule/blob/master/LICENSE.txt + +****************************** +Быстрая навигация +****************************** + +- `Сообщество pyOpenRPA (telegram) `_ +- `Сообщество pyOpenRPA (tenchat) `_ +- `Сообщество pyOpenRPA (вконтакте) `_ +- `Презентация pyOpenRPA `_ +- `Портал pyOpenRPA `_ +- `Репозиторий pyOpenRPA `_ \ No newline at end of file diff --git a/Sources/GuideSphinx/Agent/02_Defs.rst b/Sources/GuideSphinx/Agent/02_Defs.rst index 64850fbb..8801b5d3 100644 --- a/Sources/GuideSphinx/Agent/02_Defs.rst +++ b/Sources/GuideSphinx/Agent/02_Defs.rst @@ -1,5 +1,5 @@ #################################### -2. Defs +2. Функции #################################### ************************************************** @@ -11,13 +11,3 @@ pyOpenRPA.Agent.__Agent__ .. automodule:: pyOpenRPA.Agent.__Agent__ :members: :autosummary: - - -********** -References -********** - -`reStructuredText`_ - -.. target-notes:: -.. _`reStructuredText`: http://docutils.sourceforge.net/rst.html diff --git a/Sources/GuideSphinx/Orchestrator/01_Orchestrator.rst b/Sources/GuideSphinx/Orchestrator/01_Orchestrator.rst index f15992ed..09d195ee 100644 --- a/Sources/GuideSphinx/Orchestrator/01_Orchestrator.rst +++ b/Sources/GuideSphinx/Orchestrator/01_Orchestrator.rst @@ -1,83 +1,75 @@ +.. _module.orchestrator.dscription: + #################################### -1. Description +1. Описание #################################### -pyOpenRPA Orchestrator is the executable process. +************************************ +Общее +************************************ -The features of the orchestrator is: +Модуль оркестратор - это координирующее звено, которое обеспечивает бесперебойную работа массива роботов. Этот массив может состоять как из одного так и из тысячи роботов RPA. -- Centralized/decentralized user control interface (applicable and for business users and for technical users). Web based, support desktop, tablet, phone. -- Automatized robots control (customized algorithms, robots scheduling) -- Source code mega flexibility: Light Orchestrator architecture is good for own customization +**Основные возможности** -************************************ -Global settings dict concept -************************************ -pyOpenRPA project is complex tool which consist of several executable modules such as Robot, Orchestrator, Studio, +- Запуск / пауза / безопасная остановка / принудительная остановка робота +- Интеллектуальное расписание +- Просмотр состояния графических сессий роботов через панель управления +- Удаленное администрирование сессий оркестратора и робота +- Среда отладки функциональности через панель управления оркестратора +- Консолидированное хранилище логов, доступное для просмотра через панель управления +- Ролевая модель разграничения доступа +- Функциональность очередей для координации роботов -Because of module compexity, we use 1 init arg - inGSettings -inGSettings is a complex dictionary which has all reqired parameters for the module execution. +************************************************************************ +Концепция единого глобального словаря настроек (GSettings) +************************************************************************ -The description of the GSettings you can find in executable module details. +pyOpenRPA - это сложное решение, которое направлено на упрощение жизни пользователей и разработчиков роботов. -************************************ -Orchestrator how to configure -************************************ +Для того, чтобы предлагать рынку гибкое, адаптивное и надежное решение, одним из архитектурных решений был выбран подхъод хранения !ВСЕЙ! конфигурационной информации в едином словаре, который мы называем GSettings. +GSettings - это многоуровневая и иерархичная структура, которая позволяет произвести широкую кастомизацию под свои нужды, и в то же время быть открытой к внедрению новых возможностей. -To init pyOpenRPA Orchestrator instance use script: +Ознакомиться со структурой GSettings можно по ссылке: :ref:`module.orchestrator.gsettings` -from pyOpenRPA import Orchestrator # Import orchestrator main -gSettings = SettingsTemplate.Create(inModeStr="BASIC") # Create GSettings with basic configuration -Orchestrator.Orchestrator(inGSettings=gSettings) # Call the orchestrator def +Мы не рекомендуем вносить изменения напрямую в GSettings, хоть мы и оставляем такую возможность. Для корректировки функциональности Вы можете воспользоваться соответствующей функцией в модуле Оркестратора (см. здесь: :ref:`module.orchestrator.defs`) -gSettings structure +Используя специальные функции модуля Оркестратора вы существенно увеличиваете шансы бесшовного перехода на новые версии pyOpenRPA, если вам это потребуется. ************************************ -Orchestrator architecture +Архитектура ************************************ -Orchestrator has several source code components: - -- User/robot activity consolidated queue single thread (Processor) -- User/robot activity asynchonus many threads (Processor) -- Scheduler single thread (main) -- RDP keep active many thread -- Autocleaner single thread -- GUI keep active single thread -- HTTP web server single thread (create user socket threads) -- +Оркестратор состоит из следующих основных потоков: -Below you can find more information about all of the component. +- Процессорная очередь активностей (ActivityItem) (Processor) +- Функциональность асинхронного исполнения активностей (ActivityItem) (Processor) +- Поток интеллектуального расписания (main) +- Поток контроля активности RDP сессий +- Поток сбора мусорных данных +- Поток контроля графической сессии на учетной записи, где работает Оркестратор +- Поток веб-сервера Оркестратора -*************************** -Component Processor -*************************** -Sync - Append activity list to consolidated processor queue. Execution goes sequency by the activity list order -Async - Create New thread to execute the activity list +Ознакомиться с возможностями и функциями оркестратора можно по ссылке: :ref:`module.orchestrator.defs` -- Activity list -List of the activity item +Дорогие коллеги! -- Activity item +Мы знаем, что с pyOpenRPA вы сможете существенно улучшить качество вашего бизнеса. Платформа роботизации pyOpenRPA - это разработка, которая дает возможность делать виртуальных сотрудников (программных роботов RPA) выгодными, начиная от эффекта всего в **10 тыс. руб.** И управлять ими будете только Вы! -Activity item is universal mechanism to execute different algorythms from any sources. -The core feature of the Activity is to call python defs with args and kwargs. -If you need to init do some activity you can write some python def, then create Activity item with current def. -ATTENTION: In some cases (such as web transmition), when you can't transmit python def as object you can use symbolic names for python defs. It is apply you to init all of you want from the web UI. +Если у вас останутся вопросы, то вы всегда можете обратиться в центр поддержки клиентов pyOpenRPA. Контакты: :ref:`3.-Copyrights-&-Contacts` -?Why i cant transmit python def from the web -Because the WEB space is not the Python executable space. Interaction between it spaces create by JSON protocol. So, we know than JSON apply int, float, str, bool, None, list, dict - that is all. +pyOpenRPA - роботы помогут! -.. note:: +****************************** +Быстрая навигация +****************************** - Example - { - "Def":"DefAliasTest", # def link or def alias (look gSettings["Processor"]["AliasDefDict"]) - "ArgList":[1,2,3], # Args list - "ArgDict":{"ttt":1,"222":2,"dsd":3}, # Args dictionary - "ArgGSettings": None # Name of GSettings attribute: str (ArgDict) or index (for ArgList) - "ArgLogger": None # Name of GSettings attribute: str (ArgDict) or index (for ArgList) - }# Pay attention! Do not left comma symbol after the end of the dict - it can be interpretated like a turple.. +- `Сообщество pyOpenRPA (telegram) `_ +- `Сообщество pyOpenRPA (tenchat) `_ +- `Сообщество pyOpenRPA (вконтакте) `_ +- `Презентация pyOpenRPA `_ +- `Портал pyOpenRPA `_ +- `Репозиторий pyOpenRPA `_ \ No newline at end of file diff --git a/Sources/GuideSphinx/Orchestrator/02_Defs.rst b/Sources/GuideSphinx/Orchestrator/02_Defs.rst index 9b804f54..4c3b7646 100644 --- a/Sources/GuideSphinx/Orchestrator/02_Defs.rst +++ b/Sources/GuideSphinx/Orchestrator/02_Defs.rst @@ -1,20 +1,26 @@ +.. _module.orchestrator.defs: + #################################### 2. Функции #################################### +************************************************** +Общее +************************************************** + Раздел содержит всю необходимую информацию о функциях pyOpenRPA.Orchestrator При необходимости вы всегда можете обратиться в центр поддержки клиентов pyOpenRPA. Контакты: :ref:`3.-Copyrights-&-Contacts` ************************************************** -Что такое активность (ActivityItem) +Что такое активность (ActivityItem)? ************************************************** Архитектура pyOpenRPA позволяет обмениваться сообщениями о выполнении функций через механизм активностей (ActivityItem). На стороне Агента и Оркестратора реализована процессорная очередь, которая последовательно выполняет поставленные активности. Результат этих активностей сообщается инициатору (см. функции группы Agent... в Оркестраторе) ************************************************** -pyOpenRPA.Orchestrator.__Orchestrator__ +Функции ************************************************** .. code-block:: python @@ -29,50 +35,50 @@ pyOpenRPA.Orchestrator.__Orchestrator__ -Группа функций Agent... -###################### +**Группа функций Agent...** + Взаимодействие между Оркестратором и Агентом, который развертнут на других графических сессиях, где будет происходить запуск робота. -Группа функций GSettings... -###################### +**Группа функций GSettings...** + Вспомогательные функции для работы с глобальным словарем настроек Оркестратора -Группа функций Storage... -###################### +**Группа функций Storage...** + Функции для взаимодействия со специальным хранилищем переменных, предназначенного для хранения информации от роботов. !ВНИМАНИЕ! Данное хранилище сохраняется при перезагрузке Оркестратора из панели управления. -Группа функций OS... -###################### +**Группа функций OS...** + Функции взаимодействия с командной строкой на сессии, где запущен Оркестратор. -Группа функций Process... -###################### +**Группа функций Process...** + Запуск / остановка процессов на сессии Оркестратора. -Группа функций Processor... -###################### +**Группа функций Processor...** + Функции взаимодействия с процессорной очередью. Если требуется выполнить синхронизацию нескольких разных задач, то можно их отправлять в процессорную очередь. -Группа функций Python... -###################### +**Группа функций Python...** + Функции взаимодействия с Python модулями. -Группа функций RDPSession... -###################### +**Группа функций RDPSession...** + Запуск, отключение, перезапуск, отправка CMD команд, раскрыть на весь экран на RDP сессию -Группа функций Web... -###################### +**Группа функций Web...** + Управление веб-сервером Оркестратора. -Группа функций UAC... -###################### +**Группа функций UAC...** + Управление ролевой моделью доступа пользователей к панели управления Оркестратора. Актуально для подключения бизнес-пользователей. -Группа функций Scheduler... -###################### +**Группа функций Scheduler...** + Установка расписания на различные активности. @@ -81,10 +87,13 @@ pyOpenRPA.Orchestrator.__Orchestrator__ :autosummary: -************************************************** -pyOpenRPA.Orchestrator.Web.Basic -************************************************** +****************************** +Быстрая навигация +****************************** -.. automodule:: pyOpenRPA.Orchestrator.Web.Basic - :members: - :autosummary: \ No newline at end of file +- `Сообщество pyOpenRPA (telegram) `_ +- `Сообщество pyOpenRPA (tenchat) `_ +- `Сообщество pyOpenRPA (вконтакте) `_ +- `Презентация pyOpenRPA `_ +- `Портал pyOpenRPA `_ +- `Репозиторий pyOpenRPA `_ diff --git a/Sources/GuideSphinx/Orchestrator/03_gSettingsTemplate.rst b/Sources/GuideSphinx/Orchestrator/03_gSettingsTemplate.rst index 4efe8d47..f67a6ee5 100644 --- a/Sources/GuideSphinx/Orchestrator/03_gSettingsTemplate.rst +++ b/Sources/GuideSphinx/Orchestrator/03_gSettingsTemplate.rst @@ -1,9 +1,29 @@ -.. _gSettingsTemplate: -************************ -3. gSettings Template -************************ +.. _module.orchestrator.gsettings: -gSettings structure +############################################# +3. Настройки GSettings (шаблон) +############################################# + +****************************** +Общее +****************************** +Ниже представлена структура единого глобального словаря настроек GSettings + +****************************** +Структура +****************************** .. include:: ../../pyOpenRPA/Orchestrator/SettingsTemplate.py - :literal: \ No newline at end of file + :literal: + + +****************************** +Быстрая навигация +****************************** + +- `Сообщество pyOpenRPA (telegram) `_ +- `Сообщество pyOpenRPA (tenchat) `_ +- `Сообщество pyOpenRPA (вконтакте) `_ +- `Презентация pyOpenRPA `_ +- `Портал pyOpenRPA `_ +- `Репозиторий pyOpenRPA `_ \ No newline at end of file diff --git a/Sources/GuideSphinx/Orchestrator/04_HowToUse.rst b/Sources/GuideSphinx/Orchestrator/04_HowToUse.rst index 392bc9cf..c92f98b6 100644 --- a/Sources/GuideSphinx/Orchestrator/04_HowToUse.rst +++ b/Sources/GuideSphinx/Orchestrator/04_HowToUse.rst @@ -1,8 +1,17 @@ -************************ -4. How to use -************************ +################################# +4. Как использовать? +################################# -You need to run orchestrator process? +****************************** +Как запустить? +****************************** + +Хотите выполнить запуск Оркестратора? + +**Для этого достаточно (выбрать одно):** + +- запустить .cmd файл, расположенный в папке pyOpenRPA по адресу: Orchestrator\pyOpenRPA.Orchestrator_x64.cmd +- в свой .py скрипт добавить следующий код (см. ниже) .. code-block:: python @@ -13,7 +22,23 @@ You need to run orchestrator process? Orchestrator.Orchestrator(inGSettings=gSettings) -If you need more configurations - so you can see here: +****************************** +Параметры настройки +****************************** + +Также вы можете выполнить более тонкую настройку параметров Оркестратора. Ниже пример такой настройки: .. include:: ../../../Orchestrator/OrchestratorSettings.py :literal: + + +****************************** +Быстрая навигация +****************************** + +- `Сообщество pyOpenRPA (telegram) `_ +- `Сообщество pyOpenRPA (tenchat) `_ +- `Сообщество pyOpenRPA (вконтакте) `_ +- `Презентация pyOpenRPA `_ +- `Портал pyOpenRPA `_ +- `Репозиторий pyOpenRPA `_ \ No newline at end of file diff --git a/Sources/GuideSphinx/Orchestrator/05_UAC.rst b/Sources/GuideSphinx/Orchestrator/05_UAC.rst index e7f5e58a..334a47a1 100644 --- a/Sources/GuideSphinx/Orchestrator/05_UAC.rst +++ b/Sources/GuideSphinx/Orchestrator/05_UAC.rst @@ -1,21 +1,23 @@ #################################### -5. UAC - User Access Control +5. Права доступа пользователей UAC #################################### ***************** -About +Описание ***************** -Orchestrator has mega feature - user access control (UAC). This feature allow you to manipulate access of the web UI for the all users! +Оркестратор обладает уникальным и гибким механизмом контроля и распределения прав доступа пользователей (UAC - User Access Control). Концепция pyOpenRPA заключается в том, что настройка доступа должна быть максимально функциональной, но при этом удобной в использовании. -If you need to give admin rights - you don't customize UAC dict. +Если требуется дать все права доступа - не нужно ничего редактировать - они будут по умолчанию. -If you need to give some little rights for user only for one robot in orchestrator web panel - you can set the following properties in UAC dict. +Если нужно внести корректировки - вы можете указать лишь те ключи доступа, которые потребуются пользователю. -To work with UAC you can use defs ``Orchestrator.UAC`` group. +Также UAC механизм распределения прав доступа отлично интегрируется со сторонними системами безопасности, которые уже используются в компаниях, например Active Directory и другие. -!!!ATTENTION!!! +Функции по работе с UAC представлены в группе ``Orchestrator.UAC`` в разделе описания функций: :ref:`module.orchestrator.defs`. -Need practice example to work with UAC! - too hard to understand +Если у вас останутся вопросы, то вы всегда можете обратиться в центр поддержки клиентов pyOpenRPA. Контакты: :ref:`3.-Copyrights-&-Contacts` + +pyOpenRPA - роботы помогут! *************************************************** UAC Dict for Orchestrator WEB UI rights @@ -55,4 +57,16 @@ UAC Dict for pyOpenRPA Orchestrator WEB UI rights. "ActivityListExecuteBool": True, # Execute activity at the current thread "ActivityListAppendProcessorQueueBool": True # Append activity to the processor queue } - } \ No newline at end of file + } + + +****************************** +Быстрая навигация +****************************** + +- `Сообщество pyOpenRPA (telegram) `_ +- `Сообщество pyOpenRPA (tenchat) `_ +- `Сообщество pyOpenRPA (вконтакте) `_ +- `Презентация pyOpenRPA `_ +- `Портал pyOpenRPA `_ +- `Репозиторий pyOpenRPA `_ \ No newline at end of file diff --git a/Sources/GuideSphinx/Orchestrator/06_Defs Managers.rst b/Sources/GuideSphinx/Orchestrator/06_Defs Managers.rst deleted file mode 100644 index 060b8528..00000000 --- a/Sources/GuideSphinx/Orchestrator/06_Defs Managers.rst +++ /dev/null @@ -1,52 +0,0 @@ -#################################### -6. Defs Managers -#################################### - -************************************************** -Process (General) -************************************************** - -.. code-block:: python - - # EXAMPLE - from pyOpenRPA.Orchestrator import Orchestrator - lProcess = Orchestrator.Managers.Process(inAgentHostNameStr="PC-DESKTOP",inAgentUserNameStr="ND", inProcessNameWOExeStr="notepad",inStartCMDStr="notepad") - - -.. automodule:: pyOpenRPA.Orchestrator.Managers.Process - :members: - :autosummary: - - -************************************************** -Process (Details) -************************************************** - -.. automodule:: pyOpenRPA.Orchestrator.Managers.Process - :members: - :autosummary: - - -************************************************** -ControlPanel (General) -************************************************** - -.. code-block:: python - - # EXAMPLE - from pyOpenRPA.Orchestrator import Orchestrator - lCP = Orchestrator.Managers.ControlPanel(inControlPanelNameStr="TestTTT",inRefreshHTMLJinja2TemplatePathStr="ControlPanel\\test.html", inJinja2TemplateRefreshBool = True) - - -.. automodule:: pyOpenRPA.Orchestrator.Managers.ControlPanel - :members: - :autosummary: - - -************************************************** -ControlPanel (Details) -************************************************** - -.. automodule:: pyOpenRPA.Orchestrator.Managers.ControlPanel - :members: - :autosummary: diff --git a/Sources/GuideSphinx/Robot/01_Robot.rst b/Sources/GuideSphinx/Robot/01_Robot.rst index 301b1c1f..1e591111 100644 --- a/Sources/GuideSphinx/Robot/01_Robot.rst +++ b/Sources/GuideSphinx/Robot/01_Robot.rst @@ -1,30 +1,45 @@ .. _module.robot.description: -************************ +#################################### 1. Описание -************************ +#################################### +****************************** +Общее +****************************** Модуль обеспечивает всю необходимую функциональность для создания любого программного робота RPA. Модуль робота поставляется в качестве библиотеки Python, что позволяет с легкостью интегрировать его в другие проекты перспективных технологий. **Содержит** -- Уровень доступа к элементам локального приложения (win32, UI automation), и веб приложения +- **Уровень доступа к элементам локального приложения (win32, UI automation), и веб приложения** - UIDesktop: инструменты взаимодействия с элементами локального приложения (взаимодействие с ОС через протоколы win32, UI automation). Перейти к описанию функций: :ref:`module.robot.uidesktop` - UIWeb: инструменты взаимодействия с элементами веб приложения. Перейти к описанию функций: :ref:`module.robot.uiweb` -- Уровень доступа к текстовым каналам передачи данных (клавиатура, буфер обмена) +- **Уровень доступа к текстовым каналам передачи данных (клавиатура, буфер обмена)** - Keyboard: инструменты взаимодействия с клавиатурой. Перейти к описанию функций: :ref:`module.robot.keyboard` - Clipboard: инструменты взаимодействия с буфером обмена. Перейти к описанию функций: :ref:`module.robot.clipboard` -- Уровень доступа к графическим каналам передачи данных (мышь, экран) +- **Уровень доступа к графическим каналам передачи данных (мышь, экран)** - Mouse: инструменты взаимодействия с мышью. Перейти к описанию функций: :ref:`module.robot.mouse` - Image: инструменты взаимодействия с эраном рабочего стола. Перейти к описанию функций: :ref:`module.robot.image` -Ниже преставлен пример использования инструментов робота. +Дорогие коллеги! + +Мы знаем, что с pyOpenRPA вы сможете существенно улучшить качество вашего бизнеса. Платформа роботизации pyOpenRPA - это разработка, которая дает возможность делать виртуальных сотрудников (программных роботов RPA) выгодными, начиная от эффекта всего в **10 тыс. руб.** И управлять ими будете только Вы! + +Если у вас останутся вопросы, то вы всегда можете обратиться в центр поддержки клиентов pyOpenRPA. Контакты: :ref:`3.-Copyrights-&-Contacts` + +pyOpenRPA - роботы помогут! + +****************************** +Примеры +****************************** + +**Ниже преставлен пример использования инструментов робота.** .. code-block:: python @@ -110,4 +125,15 @@ Mouse.mouseDown(x-30,y+90) Mouse.moveTo(x+40,y+130) Mouse.moveTo(x+105,y+90) - Mouse.mouseUp() \ No newline at end of file + Mouse.mouseUp() + +****************************** +Быстрая навигация +****************************** + +- `Сообщество pyOpenRPA (telegram) `_ +- `Сообщество pyOpenRPA (tenchat) `_ +- `Сообщество pyOpenRPA (вконтакте) `_ +- `Презентация pyOpenRPA `_ +- `Портал pyOpenRPA `_ +- `Репозиторий pyOpenRPA `_ \ No newline at end of file diff --git a/Sources/GuideSphinx/Robot/02_uidesktop.rst b/Sources/GuideSphinx/Robot/02_uidesktop.rst index 7482f590..7ef19ae8 100644 --- a/Sources/GuideSphinx/Robot/02_uidesktop.rst +++ b/Sources/GuideSphinx/Robot/02_uidesktop.rst @@ -1,276 +1,185 @@ .. _module.robot.uidesktop: #################################### -2. UIDesktop +2. Функции UIDesktop #################################### ************************ Общее ************************ +Здесь представлено описание всех функций, которые используются для взаимодействия с UI интерфейсами локальных приложений. -Here you can find the functions description for interaction with desktop GUI applications +**Функции в модуле UIDesktop именуются по следующему принципу:** +<Входящий аргумент>_<действие>_<исходящий аргумент - если присутствует> +**Термины и определения:** -************************ -UIO объект -************************ - -************************ -UIO селектор -************************ - +- **UIO:** Объект пользовательского интерфейса +- **UIOSelector:** Селектор (адрес) одного и/или более UIO объектов. Селектор представлен в формате списка (list) словарей (dict) атрибутивных критериев. -************************************************ -UIO свойства и методы (общие) -************************************************ +************************************************** +Описание функций +************************************************** -- process_id() -Return the ID of process that owns this window -- window_text() -Window text of the element -Quite a few contorls have other text that is visible, for example Edit controls usually have an empty string for window_text but still have text displayed in the edit window. - -- windowclasses= [] - -- writable_props -Build the list of the default properties to be written. - -Derived classes may override or extend this list depending on how much control they need. -- rectangle() -Return the rectangle of element: {"top", "left", "right", "bottom"} -The rectangle() is the rectangle of the element on the screen. Coordinates are given from the top left of the screen. -This method returns a RECT structure, Which has attributes - top, left, right, bottom. and has methods width() and height(). See win32structures.RECT for more information. +.. automodule:: pyOpenRPA.Robot.UIDesktop + :members: + :autosummary: -- right_click_input(coords=(None, None)) -Right click at the specified coords +************************ +Селектор UIO +************************ -- click_input(button='left', coords=(None, None), button_down=True, button_up=True, double=False, wheel_dist=0, use_log=True, pressed='', absolute=False, key_down=True, key_up=True) -Click at the specified coordinates -button The mouse button to click. One of ‘left’, ‘right’, ‘middle’ or ‘x’ (Default: ‘left’, ‘move’ is a special case) -coords The coordinates to click at.(Default: the center of the control) -double Whether to perform a double click or not (Default: False) -wheel_dist The distance to move the mouse wheel (default: 0) -NOTES: -This is different from click method in that it requires the control to be visible on the screen but performs a more realistic ‘click’ simulation. -This method is also vulnerable if the mouse is moved by the user as that could easily move the mouse off the control before the click_input has finished. - -- double_click_input(button='left', coords=(None, None)) -Double click at the specified coordinates - -- press_mouse_input(button='left', coords=(None, None), pressed='', absolute=True, key_down=True, key_up=True) -Press a mouse button using SendInput - -- press_mouse_input(button='left', coords=(None, None), pressed='', absolute=True, key_down=True, key_up=True) -Press a mouse button using SendInput - -- drag_mouse_input(dst=(0, 0), src=None, button='left', pressed='', absolute=True) -Click on src, drag it and drop on dst -dst is a destination wrapper object or just coordinates. -src is a source wrapper object or coordinates. If src is None the self is used as a source object. -button is a mouse button to hold during the drag. It can be “left”, “right”, “middle” or “x” -pressed is a key on the keyboard to press during the drag. -absolute specifies whether to use absolute coordinates for the mouse pointer locations - -- wheel_mouse_input(coords=(None, None), wheel_dist=1, pressed='') -Do mouse wheel - -- draw_outline(colour='green', thickness=2, fill=, rect=None) -Draw an outline around the window. -colour can be either an integer or one of ‘red’, ‘green’, ‘blue’ (default ‘green’) -thickness thickness of rectangle (default 2) -fill how to fill in the rectangle (default BS_NULL) -rect the coordinates of the rectangle to draw (defaults to the rectangle of the control) - -- element_info -Read-only property to get ElementInfo object - -- from_point(x, y) -Get wrapper object for element at specified screen coordinates (x, y) - -- get_properties() -Return the properties of the control as a dictionary. - -- is_child(parent) -Return True if this element is a child of ‘parent’. -An element is a child of another element when it is a direct of the other element. An element is a direct descendant of a given element if the parent element is the the chain of parent elements for the child element. - -- is_dialog() -Return True if the control is a top level window - -- is_enabled() -Whether the element is enabled or not -Checks that both the top level parent (probably dialog) that owns this element and the element itself are both enabled. -If you want to wait for an element to become enabled (or wait for it to become disabled) use Application.wait('visible') or Application.wait_not('visible'). -If you want to raise an exception immediately if an element is not enabled then you can use the BaseWrapper.verify_enabled(). BaseWrapper.VerifyReady() raises if the window is not both visible and enabled. - - -- is_visible() -Whether the element is visible or not -Checks that both the top level parent (probably dialog) that owns this element and the element itself are both visible. -If you want to wait for an element to become visible (or wait for it to become hidden) use Application.wait('visible') or Application.wait_not('visible'). -If you want to raise an exception immediately if an element is not visible then you can use the BaseWrapper.verify_visible(). BaseWrapper.verify_actionable() raises if the element is not both visible and enabled. - -- parent() -Return the parent of this element -Note that the parent of a control is not necesarily a dialog or other main window. A group box may be the parent of some radio buttons for example. -To get the main (or top level) window then use BaseWrapper.top_level_parent(). - -- root() -Return wrapper for root element (desktop) - -- set_focus() -Set the focus to this element - -- texts() -Return the text for each item of this control -It is a list of strings for the control. It is frequently overridden to extract all strings from a control with multiple items. -It is always a list with one or more strings: -The first element is the window text of the control -Subsequent elements contain the text of any items of the control (e.g. items in a listbox/combobox, tabs in a tabcontrol) - -- type_keys(keys, pause=None, with_spaces=False, with_tabs=False, with_newlines=False, turn_off_numlock=True, set_foreground=True, vk_packet=True) -Type keys to the element using keyboard.send_keys -Ограниченная функциональность. Для более полной функциональности рекомендуем ознакомится с pyOpenPRA.Robot.Keyboard -This uses the re-written keyboard python module where you can find documentation on what to use for the keys. - -- was_maximized() -Indicate whether the window was maximized before minimizing or not - -************************************************************* -UIO свойства и методы (дополнение для win32 элементов) -************************************************************* -Кнопка (Button || CheckBox || RadioButton || GroupBox) - -- check() -Check a checkbox - -- get_check_state() -Return the check state of the checkbox -The check state is represented by an integer 0 - unchecked 1 - checked 2 - indeterminate -The following constants are defined in the win32defines module BST_UNCHECKED = 0 BST_CHECKED = 1 BST_INDETERMINATE = 2 - -- click(button='left', pressed='', coords=(0, 0), double=False, absolute=False) -Click the Button control -- is_checked() -Return True if checked, False if not checked, None if indeterminate -- is_dialog() -Buttons are never dialogs so return False -- set_check_indeterminate() -Set the checkbox to indeterminate -- uncheck() -Uncheck a checkbox -- friendly_class_name() -Return the friendly class name of the button - -Windows controls with the class “Button” can look like different controls based on their style. They can look like the following controls: - -Buttons, this method returns “Button” -CheckBoxes, this method returns “CheckBox” -RadioButtons, this method returns “RadioButton” -GroupBoxes, this method returns “GroupBox” - - -Поле выбора нескольких значений из списка (ComboBox) - -- dropped_rect() -Get the dropped rectangle of the combobox -- friendlyclassname= 'ComboBox' -- get_properties() -Return the properties of the control as a dictionary -item_count() -Return the number of items in the combobox -- item_data(item) -Returns the item data associated with the item if any -- item_texts() -Return the text of the items of the combobox -- select(item) -Select the ComboBox item -item can be either a 0 based index of the item to select or it can be the string that you want to select -- selected_index() -Return the selected index -- selected_text() -Return the selected text -- texts() -Return the text of the items in the combobox -- windowclasses= ['ComboBox', 'WindowsForms\\d*\\.COMBOBOX\\..*', '.*ComboBox'] - -Поле ввода (Edit) - -- friendlyclassname= 'Edit' -- get_line(line_index) -Return the line specified -- line_count() -Return how many lines there are in the Edit -- line_length(line_index) -Return how many characters there are in the line -- select(start=0, end=None) -Set the edit selection of the edit control -- selection_indices() -The start and end indices of the current selection -- set_edit_text(text, pos_start=None, pos_end=None) -Set the text of the edit control -- set_text(text, pos_start=None, pos_end=None) -Set the text of the edit control -- set_window_text(text, append=False) -Override set_window_text for edit controls because it should not be used for Edit controls. -Edit Controls should either use set_edit_text() or type_keys() to modify the contents of the edit control. -- text_block() -Get the text of the edit control -- texts() -Get the text of the edit control -- windowclasses= ['Edit', '.*Edit', 'TMemo', 'WindowsForms\\d*\\.EDIT\\..*', 'ThunderTextBox', 'ThunderRT6TextBox'] - - -Поле выбора 1-го значения из списка (ListBox) - -- friendlyclassname= 'ListBox' -- get_item_focus() -Return the index of current selection in a ListBox -- is_single_selection() -Check whether the listbox has single selection mode. -- item_count() -Return the number of items in the ListBox -- item_data(i) -Return the item_data if any associted with the item -- item_rect(item) -Return the rect of the item -- item_texts() -Return the text of the items of the listbox -- select(item, select=True) -Select the ListBox item -item can be either a 0 based index of the item to select or it can be the string that you want to select -- selected_indices() -The currently selected indices of the listbox -- set_item_focus(item) -Set the ListBox focus to the item at index -- texts() -Return the texts of the control -- windowclasses= ['ListBox', 'WindowsForms\\d*\\.LISTBOX\\..*', '.*ListBox'] - -Выпадающее меню (PopupMenu) - -- friendlyclassname= 'PopupMenu' -- is_dialog() -Return whether it is a dialog -- windowclasses= ['#32768'] - -Текст (Static) +Селектор UIO - адрес одного и/или более UIO объектов. Селектор представлен в формате списка (list) словарей (dict) атрибутивных критериев. Поддерживает формат JSON, что позволяет обеспечить удобство форматирования и передачи через web интерфейс студии / оркестратора. + +UIO селектор — это список характеристических словарей (спецификаций UIO). Данные спецификации UIO содержат условия, с помощью которых библиотека pyOpenRPA определит UIO, удовлетворяющий условиям, заданным в спецификации UIO. Индекс спецификации UIO в списке UIO селектора харакетризует уровень вложенности целевого UIO. Говоря другим языком, UIO селектор — это перечень условий, под которые может попасть 0, 1 или n UIO. + +Ниже приведен перечень атрибутов — условий, которые можно использовать в спецификациях UIO: + +**Формат селектора:** + +[ + { + + "depth_start" :: [int, начинается с 1] :: глубина, с которой начинается поиск (по умолчанию 1), + + "depth_end" :: [int, начинается с 1] :: глубина, до которой ведется поиск (по умолчанию 1), + + "ctrl_index" || "index" :: [int, начинается с 0] :: индекс UIO в списке у родительского UIO, + + "title" :: [str] :: идентичное наименование атрибута *title* искомого объекта UIO, + + "title_re" :: [str] :: регулярное выражение (python диалект) для отбора UIO, у которого атрибут *title* должен удовлетворять условию данного регулярного выражения, + + "rich_text" :: [str] :: идентичное наименование атрибута *rich_text* искомого объекта UIO, + + "rich_text_re" :: [str] :: регулярное выражение (python диалект) для отбора UIO, у которого атрибут *rich_text* должен удовлетворять условию данного регулярного выражения, + + "class_name" :: [str] :: идентичное наименование атрибута *class_name* искомого объекта UIO, + + "class_name_re" :: [str] :: регулярное выражение (python диалект) для отбора UIO, у которого атрибут *class_name* должен удовлетворять условию данного регулярного выражения, + + "friendly_class_name" :: [str] :: идентичное наименование атрибута *friendly_class_name* искомого объекта UIO, + + "friendly_class_name_re" :: [str] :: регулярное выражение (python диалект) для отбора UIO, у которого атрибут *friendly_class_name* должен удовлетворять условию данного регулярного выражения, + + "control_type" :: [str] :: идентичное наименование атрибута *control_type* искомого объекта UIO, + + "control_type_re" :: [str] :: регулярное выражение (python диалект) для отбора UIO, у которого атрибут *control_type* должен удовлетворять условию данного регулярного выражения, + + "is_enabled" :: [bool] :: признак, что UIO доступен для выполнения действий, + + "is_visible" :: [bool] :: признак, что UIO отображается на экране, + + "backend" :: [str, "win32" || "uia"] :: вид способа адресации к UIO (по умолчанию "win32"). Внимание! Данный атрибут может быть указан только для первого элемента списка UIO селектора. Для остальных элементов списка данный атрибут будет проигнорирован. + + }, + { ... спецификация UIO следующего уровня иерархии } +] + +**Пример UIO селектора:** +[ + {"class_name":"CalcFrame", "backend":"win32"}, # Спецификация UIO 1-го уровня вложенности + {"title":"Hex", "depth_start":3, "depth_end": 3} # Спецификация UIO 1+3-го уровня вложенности (так как установлены атрибуты depth_start|depth_stop, определяющие глубину поиска UIO) +] + + +**UIO объект - свойства и методы (общие)** + +- process_id(): Возвращает идентификатор процесса, которому принадлежит это окно +- window_text(): Текст окна элемента. Довольно много элементов управления имеют другой текст, который виден, например, элементы управления редактированием обычно имеют пустую строку для window_text, но все равно имеют текст, отображаемый в окне редактирования. +- rectangle(): Возвращает прямоугольник элемента: {"сверху", "слева", "справа", "снизу"} Прямоугольник() - это прямоугольник элемента на экране. Координаты указаны в левом верхнем углу экрана. Этот метод возвращает прямоугольную структуру, которая имеет атрибуты - top, left, right, bottom. и имеет методы width() и height(). См. раздел win32structures.Прямую кишку для получения дополнительной информации. +- right_click_input(coords=(None, None)): Щелкните правой кнопкой мыши на указанных координатах +- click_input(button='left', coords=(None, None), button_down=True, button_up=True, double=False, wheel_dist=0, use_log=True, pressed='', absolute=False, key_down=True, key_up=True): Щелкните по указанным координатам кнопкой мыши, чтобы щелкнуть. Один из "влево", "вправо", "посередине" или "x" (по умолчанию: "влево", "переместить" - это особый случай) определяет координаты, по которым нужно щелкнуть.(По умолчанию: центр элемента управления) дважды Укажите, следует ли выполнять двойной щелчок или нет (по умолчанию: False) wheel_dist Расстояние для перемещения колеса мыши (по умолчанию: 0) Внимание: Этот метод отличается от метода щелчка тем, что он требует, чтобы элемент управления был виден на экране, но выполняет более реалистичную симуляцию щелчка. Этот метод также уязвим, если пользователь перемещает мышь, поскольку это может легко переместить мышь с элемента управления до завершения click_input. +- double_click_input(button='left', coords=(None, None)): Дважды щелкните по указанным координатам +- press_mouse_input(button='left', coords=(None, None), pressed='', absolute=True, key_down=True, key_up=True): Нажмите кнопку мыши с помощью SendInput +- drag_mouse_input(dst=(0, 0), src=None, button='left', pressed='', absolute=True): Нажмите на src, перетащите его и перетащите на dst dst - это объект-оболочка назначения или просто координаты. src - это исходный объект-оболочка или координаты. Если src равен None, self используется в качестве исходного объекта. кнопка - это кнопка мыши, которую нужно удерживать во время перетаскивания. Это может быть “влево”, “вправо”, “посередине” или “x”. Нажата клавиша на клавиатуре, которую нужно нажимать во время перетаскивания. абсолютные указывает, следует ли использовать абсолютные координаты для расположения указателя мыши +- wheel_mouse_input(coords=(None, None), wheel_dist=1, pressed=''): Прокрутить колесо мыши +- draw_outline(colour='green', thickness=2, fill=, rect=None): Нарисуйте контур вокруг окна. цвет может быть либо целым числом, либо одним из "красного", "зеленого", "синего" (по умолчанию "зеленый") толщина толщина прямоугольника (по умолчанию 2) заливка как заполнить прямоугольник (по умолчанию BS_NULL) укажите координаты прямоугольника для рисования (по умолчанию используется прямоугольник элемента управления) +- element_info: Свойство, доступное только для чтения, для получения объекта ElementInfo +- from_point(x, y): Получить объект-оболочку для элемента в заданных координатах экрана (x, y) +- get_properties(): Возвращает свойства элемента управления в виде словаря. +- is_child(parent): Возвращает значение True, если этот элемент является дочерним элементом ‘parent’. Элемент является дочерним элементом другого элемента, когда он является прямым элементом другого элемента. Элемент является прямым потомком данного элемента, если родительский элемент является цепочкой родительских элементов для дочернего элемента. +- is_dialog(): Возвращает значение True, если элемент управления является окном верхнего уровня +- is_enabled(): Независимо от того, включен элемент или нет. Проверяет, что как родительский элемент верхнего уровня (возможно, диалоговое окно), которому принадлежит этот элемент, так и сам элемент включены.Если вы хотите дождаться, пока элемент станет включенным (или дождаться, пока он станет отключенным), используйте Application.wait('visible') или Application.wait_not('visible').Если вы хотите немедленно вызвать исключение, если элемент не включен, вы можете использовать BaseWrapper.verify_enabled(). Функция BaseWrapper.Verify Ready() вызывается, если окно одновременно не видно и не включено. +- is_visible(): Является ли элемент видимым или нет. Проверяет, видны ли как родительский элемент верхнего уровня (возможно, диалоговое окно), которому принадлежит этот элемент, так и сам элемент. Если вы хотите дождаться, пока элемент станет видимым (или дождаться, пока он станет скрытым), используйте Application.wait('visible') или Application.wait_not('visible'). Если вы хотите немедленно вызвать исключение, если элемент не виден, вы можете использовать BaseWrapper.verify_visible(). Базовая оболочка.verify_actible() вызывается, если элемент одновременно не виден и не включен. +- parent(): Возвращает родительский элемент этого элемента Обратите внимание, что родительским элементом элемента управления не обязательно является диалоговое окно или другое главное окно. Например, поле группы может быть родительским для некоторых переключателей. Чтобы получить главное (или окно верхнего уровня), затем используйте BaseWrapper.top_level_parent(). +- root(): Возвращаемая оболочка для корневого элемента (рабочий стол) +- set_focus(): Установить фокус на этот элемент +- texts(): Возвращает текст для каждого элемента этого элемента управления Это список строк для элемента управления. Часто переопределяется извлечение всех строк из элемента управления с несколькими элементами. Это всегда список с одной или несколькими строками: Первый элемент - это текст окна элемента управления Последующие элементы содержат текст любых элементов элемента управления (например, элементы в listbox/combobox, вкладки в tabcontrol) +- type_keys(keys, pause=None, with_spaces=False, with_tabs=False, with_newlines=False, turn_off_numlock=True, set_foreground=True, vk_packet=True): Введите ключи для элемента с помощью клавиатуры.send_keys. Ограниченная функциональность. Для более полной функциональности рекомендуем ознакомится с pyOpenPRA.Robot.Keyboard +- was_maximized(): Проверить, было ли окно развернуто перед сворачиванием или нет + +**UIO свойства и методы (дополнение к базовым методам для win32 элементов)** + +**Кнопка (Button || CheckBox || RadioButton || GroupBox)** + +- check(): Установить флажок +- uncheck(): Снять флажок +- get_check_state(): Вернуть состояние проверки флажка. Состояние проверки представлено целым числом 0 - непроверено 1 - проверено 2 - неопределенно. Следующие константы определены в модуле win32defines BST_UNCHECKED = 0 BST_CHECKED = 1 BST_INDETERMINATE = 2 +- click(button='left', pressed='', coords=(0, 0), double=False, absolute=False): Клик на кнопку управления +- is_checked(): Возвращает True, если флажок установлен, False, если флажок не установлен, None, если значение не определено +- is_dialog(): Кнопки никогда не являются диалоговыми окнами, поэтому возвращайте значение False +- set_check_indeterminate(): Установить флажок в положение неопределенный +- friendly_class_name(): Возвращает имя класса кнопки. Они могут выглядеть следующим образом: Кнопки, этот метод возвращает “Button”; Флажки, этот метод возвращает “флажок”; RadioButtons, этот метод возвращает “RadioButton”; GroupBoxes, этот метод возвращает “GroupBox” + +**Поле выбора нескольких значений из списка (ComboBox)** + +- friendlyclassname = 'ComboBox' +- windowclasses = ['ComboBox', 'WindowsForms\\d*\\.COMBOBOX\\..*', '.*ComboBox'] +- dropped_rect(): Получить выпадающий прямоугольник в поле со списком +- get_properties(): Возвращает свойства элемента управления в виде словаря +- item_count(): Возвращает количество элементов в поле со списком +- item_data(item): Возвращает данные элемента, связанные с элементом, если таковые имеются +- item_texts(): Возвращает текст элементов выпадающего списка +- select(item): Выбрать элемент со списком элемент может быть либо индексом элемента для выбора на основе 0, либо строкой, которую вы хотите выбрать +- selected_index(): Возвращает выбранный индекс +- selected_text():Возвращает выделенный текст +- texts(): Возвращает текст элементов в выпадающем списке + +**Поле ввода (Edit)** + +- friendlyclassname = 'Edit' +- windowclasses = ['Edit', '.*Edit', 'TMemo', 'WindowsForms\\d*\\.EDIT\\..*', 'ThunderTextBox', 'ThunderRT6TextBox'] +- get_line(line_index): Возвращает указанную строку +- line_count(): Возвращает, сколько строк есть в редактировании +- line_length(line_index): Возвращает количество символов в строке +- select(start=0, end=None): Установите выбор редактирования элемента управления редактированием +- selection_indices(): Начальный и конечный индексы текущего выбора +- set_edit_text(text, pos_start=None, pos_end=None): Задать текст элемента управления редактированием +- set_text(text, pos_start=None, pos_end=None): Задать текст элемента управления редактированием +- set_window_text(text, append=False): Переопределите set_window_text для элементов управления редактированием, поскольку он не должен использоваться для элементов управления редактированием. Элементы управления редактированием должны использовать либо set_edit_text(), либо type_keys() для изменения содержимого элемента управления редактированием. +- text_block(): Получить текст элемента управления редактированием +- texts(): Получить текст элемента управления редактированием + +**Поле выбора 1-го значения из списка (ListBox)** + +- friendlyclassname = 'ListBox' +- windowclasses = ['ListBox', 'WindowsForms\\d*\\.LISTBOX\\..*', '.*ListBox'] +- get_item_focus(): Возвращает индекс текущего выбора в списке +- is_single_selection(): Проверить, имеет ли поле списка режим одиночного выбора +- item_count(): Возвращает количество элементов в списке +- item_data(i): Возвращает item_data, если таковые имеются, связанные с элементом +- item_texts(): Возвращает текст элементов списка +- select(item, select=True): Выбрать элемент списка элемент может быть либо индексом элемента для выбора на основе 0, либо строкой, которую вы хотите выбрать +- selected_indices(): Выбранные в данный момент индексы списка +- set_item_focus(item): Установить фокус по элементу +- texts(): Получить текст элемента управления редактированием + +**Выпадающее меню (PopupMenu)** + +- friendlyclassname = 'PopupMenu' +- windowclasses = ['#32768'] +- is_dialog(): Возвращает, является ли это диалогом + +**Текст (Static)** - friendlyclassname= 'Static' - windowclasses= ['Static', 'WindowsForms\\d*\\.STATIC\\..*', 'TPanel', '.*StaticText'] -************************************************************* -UIO свойства и методы (дополнение для uia элементов) -************************************************************* - - - -************************************************ -Инициализация 2-х разрядностей для UIO -************************************************ +**Инициализация 2-х разрядностей для UIO** pyOpenRPA позволяет обеспечить максимальную совместимость со всеми приложениями, которые выполняются на компьютере. Мы рекомендуем разрабатывать робота под интерпретатором Python x64. В дополнение к нему Вы можете подключить Python x32 (см. ниже пример подключения). Если планируемый робот не будет взаимодействовать через pyOpenRPA.Robot.UIDesktop с другой разрядность, то эту настройку можно не применять. @@ -289,16 +198,13 @@ pyOpenRPA позволяет обеспечить максимальную со # Теперь при вызове функций pyOpenRPA.Robot.UIDesktop платформа pyOpenRPA будет отслеживать разрядность приложения и отправлять соответсвующий вызов на идентичную разрядность. -.. automodule:: pyOpenRPA.Robot.UIDesktop - :members: - :autosummary: - - -********** -Ссылки -********** - -`reStructuredText`_ +****************************** +Быстрая навигация +****************************** -.. target-notes:: -.. _`reStructuredText`: http://docutils.sourceforge.net/rst.html +- `Сообщество pyOpenRPA (telegram) `_ +- `Сообщество pyOpenRPA (tenchat) `_ +- `Сообщество pyOpenRPA (вконтакте) `_ +- `Презентация pyOpenRPA `_ +- `Портал pyOpenRPA `_ +- `Репозиторий pyOpenRPA `_ diff --git a/Sources/GuideSphinx/Robot/03_uiweb.rst b/Sources/GuideSphinx/Robot/03_uiweb.rst index 80946577..fe8905ca 100644 --- a/Sources/GuideSphinx/Robot/03_uiweb.rst +++ b/Sources/GuideSphinx/Robot/03_uiweb.rst @@ -1,38 +1,31 @@ .. _module.robot.uiweb: #################################### -3. UIWeb +3. Функции UIWeb #################################### -Here you can find the functions description for interaction with desktop GUI applications +************************ +Общее +************************ -How to use both x32 and x64 python processes (it can be helpfully, if another app GUI is on another bitness than your app) +Документация к модулю будет опубликована в Июле 2022. По всем вопросам роботизации WEB приложений обращайтесь в центр поддержки клиентов pyOpenRPA. -.. code-block:: python - from pyOpenRPA.Robot import UIDesktop - #Section for robot init - lPyOpenRPA_SettingsDict = { - "Python32FullPath": "..\\Resources\\WPy32-3720\\python-3.7.2\\python.exe", #Set from user: "..\\Resources\\WPy32-3720\\python-3.7.2\\OpenRPARobotGUIx32.exe" - "Python64FullPath": "..\\Resources\\WPy64-3720\\python-3.7.2.amd64\\python.exe", #Set from user - "Python32ProcessName": "pyOpenRPA_UIDesktopX32.exe", #Config set once - "Python64ProcessName": "pyOpenRPA_UIDesktopX64.exe" #Config set once - } - # Init the pyOpenRPA configuration - UIDesktop.Utils.ProcessBitness.SettingsInit(lPyOpenRPA_SettingsDict) - # Now you can use pyOpenRPA with both bitness. +Дорогие коллеги! +Мы знаем, что с pyOpenRPA вы сможете существенно улучшить качество вашего бизнеса. Платформа роботизации pyOpenRPA - это разработка, которая дает возможность делать виртуальных сотрудников (программных роботов RPA) выгодными, начиная от эффекта всего в **10 тыс. руб.** И управлять ими будете только Вы! -.. automodule:: pyOpenRPA.Robot.UIDesktop - :members: - :autosummary: +Если у вас останутся вопросы, то вы всегда можете обратиться в центр поддержки клиентов pyOpenRPA. Контакты: :ref:`3.-Copyrights-&-Contacts` +pyOpenRPA - роботы помогут! -********** -References -********** +****************************** +Быстрая навигация +****************************** -`reStructuredText`_ - -.. target-notes:: -.. _`reStructuredText`: http://docutils.sourceforge.net/rst.html +- `Сообщество pyOpenRPA (telegram) `_ +- `Сообщество pyOpenRPA (tenchat) `_ +- `Сообщество pyOpenRPA (вконтакте) `_ +- `Презентация pyOpenRPA `_ +- `Портал pyOpenRPA `_ +- `Репозиторий pyOpenRPA `_ diff --git a/Sources/GuideSphinx/Robot/04_keyboard.rst b/Sources/GuideSphinx/Robot/04_keyboard.rst index 3b9ef7b4..2c754580 100644 --- a/Sources/GuideSphinx/Robot/04_keyboard.rst +++ b/Sources/GuideSphinx/Robot/04_keyboard.rst @@ -1,9 +1,13 @@ .. _module.robot.keyboard: #################################### -4. Keyboard +4. Функции Keyboard #################################### +************************ +Общее +************************ + Клавиатура - это главный текстовый инструмент, который обладает 100% точностью передачи данных. С его помощью можно отправлять сообщения, ожидать нажатия и выполнять различные комбинации клавиш. На этой странице представлена вся необходимая информация по управлению клавиатурой со стороны программного робота RPA. В отличие от многих RPA платформ, pyOpenRPA обладает функциями, которые не зависят от текущей раскладки клавиатуры. За счет этого надежность и стабильность программного робота существенно возрастает. @@ -29,7 +33,7 @@ Коды клавиш см. ниже ************************************************** -Описание методов +Описание функций ************************************************** @@ -215,3 +219,15 @@ # Пример использования функции send from pyOpenRPA.Robot import Keyboard Keyboard.send(57) + +****************************** +Быстрая навигация +****************************** + +- `Сообщество pyOpenRPA (telegram) `_ +- `Сообщество pyOpenRPA (tenchat) `_ +- `Сообщество pyOpenRPA (вконтакте) `_ +- `Презентация pyOpenRPA `_ +- `Портал pyOpenRPA `_ +- `Репозиторий pyOpenRPA `_ + diff --git a/Sources/GuideSphinx/Robot/05_clipboard.rst b/Sources/GuideSphinx/Robot/05_clipboard.rst index d733784a..641979c3 100644 --- a/Sources/GuideSphinx/Robot/05_clipboard.rst +++ b/Sources/GuideSphinx/Robot/05_clipboard.rst @@ -1,38 +1,24 @@ .. _module.robot.clipboard: #################################### -5. Clipboard +5. Функции Clipboard #################################### -Here you can find the functions description for interaction with desktop GUI applications +************************************************** +Описание функций +************************************************** -How to use both x32 and x64 python processes (it can be helpfully, if another app GUI is on another bitness than your app) - -.. code-block:: python - - from pyOpenRPA.Robot import UIDesktop - #Section for robot init - lPyOpenRPA_SettingsDict = { - "Python32FullPath": "..\\Resources\\WPy32-3720\\python-3.7.2\\python.exe", #Set from user: "..\\Resources\\WPy32-3720\\python-3.7.2\\OpenRPARobotGUIx32.exe" - "Python64FullPath": "..\\Resources\\WPy64-3720\\python-3.7.2.amd64\\python.exe", #Set from user - "Python32ProcessName": "pyOpenRPA_UIDesktopX32.exe", #Config set once - "Python64ProcessName": "pyOpenRPA_UIDesktopX64.exe" #Config set once - } - # Init the pyOpenRPA configuration - UIDesktop.Utils.ProcessBitness.SettingsInit(lPyOpenRPA_SettingsDict) - # Now you can use pyOpenRPA with both bitness. - - -.. automodule:: pyOpenRPA.Robot.UIDesktop +.. automodule:: pyOpenRPA.Robot.Clipboard :members: :autosummary: +****************************** +Быстрая навигация +****************************** -********** -References -********** - -`reStructuredText`_ - -.. target-notes:: -.. _`reStructuredText`: http://docutils.sourceforge.net/rst.html +- `Сообщество pyOpenRPA (telegram) `_ +- `Сообщество pyOpenRPA (tenchat) `_ +- `Сообщество pyOpenRPA (вконтакте) `_ +- `Презентация pyOpenRPA `_ +- `Портал pyOpenRPA `_ +- `Репозиторий pyOpenRPA `_ diff --git a/Sources/GuideSphinx/Robot/06_mouse.rst b/Sources/GuideSphinx/Robot/06_mouse.rst index dab54f67..2574f755 100644 --- a/Sources/GuideSphinx/Robot/06_mouse.rst +++ b/Sources/GuideSphinx/Robot/06_mouse.rst @@ -1,38 +1,29 @@ .. _module.robot.mouse: #################################### -6. Mouse +6. Функции Mouse #################################### -Here you can find the functions description for interaction with desktop GUI applications - -How to use both x32 and x64 python processes (it can be helpfully, if another app GUI is on another bitness than your app) - -.. code-block:: python - - from pyOpenRPA.Robot import UIDesktop - #Section for robot init - lPyOpenRPA_SettingsDict = { - "Python32FullPath": "..\\Resources\\WPy32-3720\\python-3.7.2\\python.exe", #Set from user: "..\\Resources\\WPy32-3720\\python-3.7.2\\OpenRPARobotGUIx32.exe" - "Python64FullPath": "..\\Resources\\WPy64-3720\\python-3.7.2.amd64\\python.exe", #Set from user - "Python32ProcessName": "pyOpenRPA_UIDesktopX32.exe", #Config set once - "Python64ProcessName": "pyOpenRPA_UIDesktopX64.exe" #Config set once - } - # Init the pyOpenRPA configuration - UIDesktop.Utils.ProcessBitness.SettingsInit(lPyOpenRPA_SettingsDict) - # Now you can use pyOpenRPA with both bitness. +************************************************** +Общее +************************************************** +************************************************** +Описание функций +************************************************** .. automodule:: pyOpenRPA.Robot.Mouse :members: :autosummary: -********** -References -********** - -`reStructuredText`_ +****************************** +Быстрая навигация +****************************** -.. target-notes:: -.. _`reStructuredText`: http://docutils.sourceforge.net/rst.html +- `Сообщество pyOpenRPA (telegram) `_ +- `Сообщество pyOpenRPA (tenchat) `_ +- `Сообщество pyOpenRPA (вконтакте) `_ +- `Презентация pyOpenRPA `_ +- `Портал pyOpenRPA `_ +- `Репозиторий pyOpenRPA `_ diff --git a/Sources/GuideSphinx/Robot/07_image.rst b/Sources/GuideSphinx/Robot/07_image.rst index 3a0959e7..0cf05269 100644 --- a/Sources/GuideSphinx/Robot/07_image.rst +++ b/Sources/GuideSphinx/Robot/07_image.rst @@ -1,38 +1,30 @@ .. _module.robot.image: #################################### -7. Image +7. Функции Image #################################### -Here you can find the functions description for interaction with desktop GUI applications +************************ +Общее +************************ -How to use both x32 and x64 python processes (it can be helpfully, if another app GUI is on another bitness than your app) +Документация к модулю будет опубликована в Июле 2022. По всем вопросам роботизации WEB приложений обращайтесь в центр поддержки клиентов pyOpenRPA. -.. code-block:: python +Дорогие коллеги! - from pyOpenRPA.Robot import UIDesktop - #Section for robot init - lPyOpenRPA_SettingsDict = { - "Python32FullPath": "..\\Resources\\WPy32-3720\\python-3.7.2\\python.exe", #Set from user: "..\\Resources\\WPy32-3720\\python-3.7.2\\OpenRPARobotGUIx32.exe" - "Python64FullPath": "..\\Resources\\WPy64-3720\\python-3.7.2.amd64\\python.exe", #Set from user - "Python32ProcessName": "pyOpenRPA_UIDesktopX32.exe", #Config set once - "Python64ProcessName": "pyOpenRPA_UIDesktopX64.exe" #Config set once - } - # Init the pyOpenRPA configuration - UIDesktop.Utils.ProcessBitness.SettingsInit(lPyOpenRPA_SettingsDict) - # Now you can use pyOpenRPA with both bitness. +Мы знаем, что с pyOpenRPA вы сможете существенно улучшить качество вашего бизнеса. Платформа роботизации pyOpenRPA - это разработка, которая дает возможность делать виртуальных сотрудников (программных роботов RPA) выгодными, начиная от эффекта всего в **10 тыс. руб.** И управлять ими будете только Вы! +Если у вас останутся вопросы, то вы всегда можете обратиться в центр поддержки клиентов pyOpenRPA. Контакты: :ref:`3.-Copyrights-&-Contacts` -.. automodule:: pyOpenRPA.Robot.UIDesktop - :members: - :autosummary: +pyOpenRPA - роботы помогут! +****************************** +Быстрая навигация +****************************** -********** -References -********** - -`reStructuredText`_ - -.. target-notes:: -.. _`reStructuredText`: http://docutils.sourceforge.net/rst.html +- `Сообщество pyOpenRPA (telegram) `_ +- `Сообщество pyOpenRPA (tenchat) `_ +- `Сообщество pyOpenRPA (вконтакте) `_ +- `Презентация pyOpenRPA `_ +- `Портал pyOpenRPA `_ +- `Репозиторий pyOpenRPA `_ \ No newline at end of file diff --git a/Sources/GuideSphinx/Robot/08_HowToUse.rst b/Sources/GuideSphinx/Robot/08_HowToUse.rst index 5259e73b..5c23544e 100644 --- a/Sources/GuideSphinx/Robot/08_HowToUse.rst +++ b/Sources/GuideSphinx/Robot/08_HowToUse.rst @@ -2,225 +2,85 @@ 8. Как использовать? #################################### -The Robot tool is the main module for production process automation. It has no graphic/console interface. All low-level actions to OS are perfoming by the Robot tool in pyOpenRPA. +Модуль РОБОТ - это ключевое звено, которое отвечает за продуктивную роботизацию процесса. Данный модуль не имеет графический или консольный интерфейс - он подключается в качестве библиотеки в проект робота, что позволяет выполнять операции максимально быстро. А также позволяет с легкостью интегрировать робота в другие проекты. ************************************************** -How to execute RPA script +Как запустить скрипт робота? ************************************************** -You can use the robot by the several ways: -- In Python script -- In Studio script (n/a) +Запустить скрипт робота можно 2-мя способами: +- Скрипт Python (файл .py) +- Скрипт в Студии pyOpenRPA -Create python script + +Скрипт Python (файл .py) ############################################ -In order to use robot just add Robot tool folder in work directory and add line "import GUI" in your script. +Чтобы начать использовать модуль робота достаточно выполнить в файле скрипта соответсвующие команды импорта: .. code-block:: python import sys sys.path.append('../../') - import selenium # [Web app access](https://gitlab.com/UnicodeLabs/OpenRPA/wikis/05.1.-Theory-&-practice:-Web-app-access-(Chrome,-Firefox,-Opera))
- import GUI # [Win32 & UI Automation access](https://gitlab.com/UnicodeLabs/OpenRPA/wikis/05.2.-Theory-&-practice:-Desktop-app-UI-access-(win32-and-UI-automation-dlls))
- import pyautogui #[Screen capture/recognition](https://gitlab.com/UnicodeLabs/OpenRPA/wikis/05.4.-Theory-&-practice:-Screen-capture-&-image-recognition) [#Mouse manipulation](https://gitlab.com/UnicodeLabs/OpenRPA/wikis/05.3.-Theory-&-practice:-Keyboard-&-mouse-manipulation)
- import cv2 # [Computer vision](https://gitlab.com/UnicodeLabs/OpenRPA/wikis/05.4.-Theory-&-practice:-Screen-capture-&-image-recognition)
- import keyboard #[Keyboard manipulation](https://gitlab.com/UnicodeLabs/OpenRPA/wikis/05.3.-Theory-&-practice:-Keyboard-&-mouse-manipulation)
- -Execute python script -############################################ + from pyOpenRPA.Robot import UIDesktop # Взаимодействие с UI объектами приложений + from pyOpenRPA.Robot import UIWeb # Взаимодействие с UI объектами веб приложений + from pyOpenRPA.Robot import Keyboard # Взаимодействие с клавиатурой + from pyOpenRPA.Robot import Clipboard # Взаимодействие с буфером обмена + from pyOpenRPA.Robot import Mouse # Взаимодействие с мышью + from pyOpenRPA.Robot import Image # Взаимодействие с графической сессией ОС -The pyOpenRPA is fully portable solution. It contains own python enviroment both 32 and 64 bit versions. So, you can execute your python script in several ways: -- Execute in python x32 (\OpenRPA\Resources\WPy32-3720\python-3.7.2) -- Execute in python x64 (\OpenRPA\Resources\WPy64-3720\python-3.7.2.amd64) -- Execute from .cmd file +Описание каждого из этих модулей представлены в разделе "МОДУЛЬ РОБОТ" -Execute in the Python x32 +Execute python script ############################################ -To execute your python script in x32 bit version just write in command line from x32 python directory: +pyOpenRPA - это максимально инкапсулированная платформа программной роботизаии RPA. Все необходимые зависимости находятся внутри нее, что позволяет копировать робота между ЭВМ максимально просто. -.. code-block:: python +Вы можете запустить скрипт робота RPA следующими способами: - cd "\OpenRPA\Resources\WPy32-3720\python-3.7.2" - python.exe "path to your python script.py" +- Запустить из интерпретатора Python x32 (Resources\WPy32-3720\python-3.7.2\python.exe) +- Запустить из интерпретатора Python x64 (Resources\WPy64-3720\python-3.7.2.amd64\python.exe) +- Запустить из под .cmd файла -Execute in the Python x64 +Запустить из интерпретатора Python x32 ############################################ - -To execute your python script in x32 bit version just write in command line from x32 python directory: +Для запуска срипта из интерпретатора Python x32 необходимо открыть командную строку (cmd), и выполнить следующие команды: .. code-block:: python - cd "\OpenRPA\Resources\WPy64-3720\python-3.7.2.amd64" - python.exe "path to your python script.py" + cd "Resources\WPy32-3720\python-3.7.2" # Установить рабочую директорию там, где находится интерпретатор Python + python.exe "path to your python script.py" # Запустить интерпретатор Python с файлом скрипта робота "path to your python script.py" -Execute from .cmd file +Запустить из интерпретатора Python x64 ############################################ - -In order to simplify the execution process you can write several code lines in file with the .cmd extension: +Для запуска срипта из интерпретатора Python x64 необходимо открыть командную строку (cmd), и выполнить следующие команды: .. code-block:: python - cd %~dp0 - copy /Y ..\Resources\WPy32-3720\python-3.7.2\python.exe ..\Resources\WPy32-3720\python-3.7.2\OpenRPAOrchestrator.exe - .\..\Resources\WPy32-3720\python-3.7.2\OpenRPAOrchestrator.exe orchestratorMain.py - pause >nul - - -Use in studio script (n/a) -############################################ -.. code-block:: python - - import sys - sys.path.append('../../') - import GUI - import keyboard - import subprocess - import time - - #Highlight the UI Object in Folder explorer - GUI.UIOSelector_FocusHighlight([{"class_name":"CabinetWClass","backend":"uia"},{"ctrl_index":2},{"ctrl_index":0},{"ctrl_index":2},{"ctrl_index":0}]) - - #Wait 2 seconds - time.sleep(3) - - #Loop: get child element of UI List - for lItem in GUI.UIOSelector_Get_UIO([{"class_name":"CabinetWClass","backend":"uia"},{"ctrl_index":2},{"ctrl_index":0},{"ctrl_index":2},{"ctrl_index":0}]).children(): - print(str(lItem)) - - - -Here you can find the docs and examples of the OpenRPA desktop (GUI) app access. - -**************************************************************************************************** -Desktop app UI access (win32 and UI automation dlls) -**************************************************************************************************** - -Definitions -############################################ - -- **UIO** - UI Object (class of pywinauto UI object) [pywinauto.base_wrapper] -- **UIOSelector** - List of dict (key attributes) -- **PWA** - PyWinAuto -- **PWASpecification** - List of dict (key attributes in pywinauto.find_window notation) -- **UIOTree** - Recursive Dict of Dict ... (UI Parent -> Child hierarchy) -- **UIOInfo** - Dict of UIO attributes -- **UIOActivity** - Activity of the UIO (UI object) from the Pywinauto module -- **UIOEI** - UI Object info object - - -What is UIO? -############################################ -UIO is a User Interface Object (pyOpenRPA terminology). For maximum compatibility, this instance is inherited from the object model developed in the [pywinauto library (click to get a list of available class functions)](https://pywinauto.readthedocs.io/en/latest/code/pywinauto.base_wrapper.html). - -This approach allows us to implement useful functionality that has already been successfully developed in other libraries, and Supplement it with the missing functionality. In our case, the missing functionality is the ability to dynamically access UIO objects using UIO selectors. + cd "Resources\WPy32-3720\python-3.7.2.amd64" # Установить рабочую директорию там, где находится интерпретатор Python + python.exe "path to your python script.py" # Запустить интерпретатор Python с файлом скрипта робота "path to your python script.py" - -UIOSelector structure & example +Запустить из под .cmd файла ############################################ -UIOSelector is the list of condition items for the UIO in GUI. Each item has condition attributes for detect applicable UIO. Here is the description of the available condition attributes in item. - -**Desciption** - -.. code-block:: python - - [ - { - "depth_start" :: [int, start from 1] :: the depth index, where to start check the condition list (default 1), - "depth_end" :: [int, start from 1] :: the depth index, where to stop check the condition list (default 1), - "ctrl_index" || "index" :: [int, starts from 0] :: the index of the UIO in parent UIO child list, - "title" :: [str] :: the condition for the UIO attribute *title*, - "title_re" :: [str] :: regular expression (python ver) for the condition for the UIO attribute *title*, - "rich_text" :: [str] :: the condition for the UIO attribute *rich_text*, - "rich_text_re" :: [str] :: regular expression (python ver) for the condition for the UIO attribute *rich_text*, - "class_name" :: [str] :: the condition for the UIO attribute *class_name*, - "class_name_re" :: [str] :: regular expression (python ver) for the condition for the UIO attribute *class_name*, - "friendly_class_name" :: [str] :: the condition for the UIO attribute *friendly_class_name*, - "friendly_class_name_re" :: [str] :: regular expression (python ver) for the condition for the UIO attribute *friendly_class_name*, - "control_type" :: [str] :: the condition for the UIO attribute *control_type*, - "control_type_re" :: [str] :: regular expression (python ver) for the condition for the UIO attribute *control_type*, - "is_enabled" :: [bool] :: the condition for the UIO attribute *is_enabled*. If UI object is enabled on GUI, - "is_visible" :: [bool] :: the condition for the UIO attribute *is_visible*. If UI object is visible on GUI, - "backend" :: [str, "win32" || "uia"] :: the method of UIO extraction (default "win32"). ATTENTION! Current option can be only for the first item of the UIO selector. For the next items this option will be implemented from the first item. - }, - { ... specification next level UIO } - ] -**The UIO selector example** +Упростить процесс запуска и свести инициализацию робота к одному нажатию можно с помощью средстве command shell и .cmd файла. -.. code-block:: python - - [ - {"class_name":"CalcFrame", "backend":"win32"}, # 1-st level UIO specification - {"title":"Hex", "depth_start":3, "depth_end": 3} # 3-rd level specification (because of attribute depth_start|depth_stop) - ] - -The UIDesktop module (OpenRPA/Robot/UIDesktop.py) -######################################################################################## -The UIDesktop is extension of the pywinauto module which provide access to the desktop apps by the **win32** and **ui automation** dll frameworks (big thx to the Microsoft :) ). +Для этого достаточно выбрать рабочую директорию робота, там создать текстовый .cmd файл, и прописать в нем следующий код: .. code-block:: python - # EXAMPLE 1 - from pyOpenRPA.Robot import UIDesktop - - UIDesktop.UIOSelector_Get_UIO( - inSpecificationList=[ - {"title":"notepad.exe"},{"title":"OK"}], - inElement=None, - inFlagRaiseException=True) - - -The UIDesktop module (OpenRPA/Robot/UIDesktop.py) -######################################################################################## -The UIDesktop is extension of the pywinauto module which provide access to the desktop apps by the **win32** and **ui automation** dll frameworks (big thx to the Microsoft :) ). - -*Naming convention: \\_\\_\*
- - -**************************************************************************************************** -Theory & practice. WEB app UI access (selenium) -**************************************************************************************************** - -About -############################################### -The pyOpenRPA support web app manipulation (by the Selenium lib). -More docs about selenium you can find here (https://selenium-python.readthedocs.io/) - -How to use -############################################### -To start use selenium just import selenium modules in the robot tool. Here is the example of the usage. - -.. code-block:: python - - from selenium import webdriver - from selenium.webdriver.common.keys import Keys - - driver = webdriver.Chrome() - driver.get("http://www.python.org") - assert "Python" in driver.title - elem = driver.find_element_by_name("q") - elem.clear() - elem.send_keys("pycon") - elem.send_keys(Keys.RETURN) - assert "No results found." not in driver.page_source - driver.close() - -**************************************************************************************************** -Theory & practice. Keyboard & mouse manipulation -**************************************************************************************************** - - -**************************************************************************************************** -Theory & practice. Screen capture & image recognition -**************************************************************************************************** - -How to automate image recognition on PC -########################################### - -Here you can find any ways you need to use in your business case: -- Find the exact match on the screen with the other image -- Use text recognition module (OCR) -- Use computer vision (CV) to identify the objects on screen/image/video -- Use artificial intelligence (AI) to make custom identification/classification/text recognition \ No newline at end of file + cd %~dp0 # Установить рабочую директорую там, где находится этот .cmd файл + copy /Y ..\Resources\WPy32-3720\python-3.7.2\python.exe ..\Resources\WPy32-3720\python-3.7.2\OpenRPAOrchestrator.exe # Выполнить компирование python.exe на другое наименование, чтобы изменить наименование процесса робота в диспетчере задач (без этой операции все роботы будут отображаться в диспетчере задач как python.exe) + .\..\Resources\WPy32-3720\python-3.7.2\OpenRPAOrchestrator.exe orchestratorMain.py # Выполнить инициализацию скрипта робота RPA + pause >nul # Не закрывать окно консоли после завершения работы скрипта робота + +****************************** +Быстрая навигация +****************************** + +- `Сообщество pyOpenRPA (telegram) `_ +- `Сообщество pyOpenRPA (tenchat) `_ +- `Сообщество pyOpenRPA (вконтакте) `_ +- `Презентация pyOpenRPA `_ +- `Портал pyOpenRPA `_ +- `Репозиторий pyOpenRPA `_ \ No newline at end of file diff --git a/Sources/GuideSphinx/Robot/09_Dependencies.rst b/Sources/GuideSphinx/Robot/09_Dependencies.rst deleted file mode 100644 index ce74f304..00000000 --- a/Sources/GuideSphinx/Robot/09_Dependencies.rst +++ /dev/null @@ -1,10 +0,0 @@ -#################################### -9. Зависимости -#################################### - -Python 3 x32 [psutil, pywinauto, wmi, PIL, keyboard, pyautogui, win32api (pywin32), selenium, openCV, tesseract, requests, lxml, PyMuPDF] -Python 3 x64 [psutil, pywinauto, wmi, PIL, keyboard, pyautogui, win32api (pywin32), selenium, openCV, tesseract, requests, lxml, PyMuPDF] -pywinauto (Windows GUI automation) -Semantic UI CSS framework -JsRender by https://www.jsviews.com (switch to Handlebars) -Handlebars \ No newline at end of file diff --git a/Sources/GuideSphinx/Studio/01_Studio.rst b/Sources/GuideSphinx/Studio/01_Studio.rst index 45c773bb..fdfbf0c9 100644 --- a/Sources/GuideSphinx/Studio/01_Studio.rst +++ b/Sources/GuideSphinx/Studio/01_Studio.rst @@ -1,7 +1,32 @@ .. _module.studio.description: -************************ +#################################### 1. Описание +#################################### + +************************ +Общее ************************ -pyOpenRPA Studio is the executable process. +Модуль студии обеспечивает всю необходимую функциональность взаимодействия с UI объектами различных приложений, запущенных в сессии. + +В разделе :ref:`module.studio.how-to-use` вы найдете практическое руководство по работе с пользовательским интерфейсом студии, которая отрывается в веб браузере. + +Дорогие коллеги! + +Мы знаем, что с pyOpenRPA вы сможете существенно улучшить качество вашего бизнеса. Платформа роботизации pyOpenRPA - это разработка, которая дает возможность делать виртуальных сотрудников (программных роботов RPA) выгодными, начиная от эффекта всего в **10 тыс. руб.** И управлять ими будете только Вы! + +Если у вас останутся вопросы, то вы всегда можете обратиться в центр поддержки клиентов pyOpenRPA. Контакты: :ref:`3.-Copyrights-&-Contacts` + +pyOpenRPA - роботы помогут! + +****************************** +Быстрая навигация +****************************** + +- `Сообщество pyOpenRPA (telegram) `_ +- `Сообщество pyOpenRPA (tenchat) `_ +- `Сообщество pyOpenRPA (вконтакте) `_ +- `Презентация pyOpenRPA `_ +- `Портал pyOpenRPA `_ +- `Репозиторий pyOpenRPA `_ \ No newline at end of file diff --git a/Sources/GuideSphinx/Studio/02_HowToUse.rst b/Sources/GuideSphinx/Studio/02_HowToUse.rst index 96761ba8..fb0c6678 100644 --- a/Sources/GuideSphinx/Studio/02_HowToUse.rst +++ b/Sources/GuideSphinx/Studio/02_HowToUse.rst @@ -1,126 +1,148 @@ +.. _module.studio.how-to-use: + #################################### 2. Как использовать? #################################### -Content -======= - -- `How to run <#how-to-run>`__ -- `UI Description <#ui-description>`__ -- `How to extract UI tree <#how-to-extract-ui-tree>`__ -- `How to search UI object by mouse - hover <#how-to-search-ui-object-by-mouse-hover>`__ -- `How to extract UI object - properties <#how-to-extract-ui-object-properties>`__ - -How to run -========== - -- For OS x32 -- Run (double click): OpenRPA\_32.cmd (for OS x32) -- For OS x64 -- Run (double click): OpenRPA\_64.cmd (for OS x64) -- Wait text "running server" in console. Default browser will be open - automatically -- **Attention!** The studio tool does not support the Internet explorer - (any version) for GUI rendering (lol) +.. _general: + +************************ +Общее +************************ + +- `Как запустить? <#how-to-run>`__ +- `Описание UI студии <#ui-description>`__ +- `Извлечь UI дерево <#how-to-extract-ui-tree>`__ +- `Поиск UI объекта по наведению мыши <#how-to-search-ui-object-by-mouse-hover>`__ +- `Извлечь свойства UI объекта <#how-to-extract-ui-object-properties>`__ + +.. _how-to-run: + +************************ +Как запустить? +************************ + +- Запустить файл Studio\pyOpenRPA.Studio_x64.cmd +- Ожидать текст в окне консоли: "running server". Браузер, установленный по умолчанию откроется автоматически +- **!ВНИМАНИЕ!** Студия поддерживает все версии браузеров, кроме Internet Explorer. .. image:: /img/504b98f76747f63900a2943532a946bb.png :alt: 504b98f76747f63900a2943532a946bb.png +.. _ui-description: -UI Description -============== +************************ +Описание UI студии +************************ -**The studio tool GUI contains of:** +**Интерфейс (UI) студии состоит из следующих компонентов:** -1. UI tree viewer -2. Selected UI object hierarchy list -3. Selected UI object property list -4. UIO selector editor -5. UIO action panel -6. Another Python activity panel -7. Action/activity list +1. Обозреватель UI дерева +2. Обозреватель иерархии выбранного UI объекта +3. Обозреватель свойств выбранного уровня UI объекта +4. Редактор UIO селектора +5. Панель активностей над UIO объектом +6. Панель других Python активностей +7. Список активностей -*Look it on the GUI screenshots are listed below* +*Ниже представлены скриншоты студии* -GUI Screenshot 1 +Скриншот 1 ---------------- .. image:: /img/d3d6ad14a7e50843bd89d2b14a092fee.png :alt: 504b98f76747f63900a2943532a946bb.png -GUI Screenshot 2 +Скриншот 2 ---------------- .. image:: /img/65b7d51c0a5b21e6b27dc23d4062d3ca.png :alt: 65b7d51c0a5b21e6b27dc23d4062d3ca.png -How to extract UI tree -====================== +.. _how-to-extract-ui-tree: + +************************ +Извлечь UI дерево +************************ -In order to extract the UI tree do the following: in ``UI tree viewer`` -choose the object you are interested and click the button "Expand". ## +Чтобы извлечь дерево пользовательского интерфейса выполните следующие действия: в ``UI Tree viewer`` выбрать интересующий UI объект и нажать кнопку ``Expand``. -Action: Click the button "Expand" +Действие: Нажать по кнопке "Expand" --------------------------------------- .. image:: /img/6effc376ff6ea928840674bd744caced.png :alt: 6effc376ff6ea928840674bd744caced.png -Result +Итог --------------------------------------- .. image:: /img/18b9ab36126c8c32168bf5bbb9330701.png :alt: 18b9ab36126c8c32168bf5bbb9330701.png -How to search UI object by mouse hover + --------------------------------------- -In order to search UI object do the -following: in ``UI tree viewer`` choose the parent object, where you are -want to search UI object, and click the button "Mouse search". The mouse -search mode will start. Turn mouse on the UI object you are interested -and wait when the studio will highlight the UI object. After the -hightlight hold the "Ctrl" key and wait 3 seconds. The interested UI -object will be shown in ``UI tree viewer``. - -Action: Click the button "Mouse search" + +.. _how-to-search-ui-object-by-mouse-hover: + +*********************************** +Поиск UI объекта по наведению мыши +*********************************** + +Чтобы выполнить поиск UI объекта пользовательского интерфейса, необходимо в ``UI tree viewer`` выбрать родительский UI объект, в котором вы хотите выполнить поиск, и нажать кнопку ``Mouse search``. + +Будет активирован режим поиск UI объекта по курсору мыши. Наведите курсор мыши на интересующий вас объект пользовательского интерфейса и дождитесь, когда студия выделит объект пользовательского интерфейса. После выделения цветов удерживайте клавишу "Ctrl" и подождите 3 секунды. Интересующий UI объект будет показан в ``UI tree viewer``. + +Действие: Нажать кнопку "Mouse search" --------------------------------------- .. image:: /img/84d7e4de0c840631f87cf7b325b53ad8.png :alt: 84d7e4de0c840631f87cf7b325b53ad8.png -Action: Turn mouse on the UI object you are interested and hold the "Ctrl" key for 3 seconds --------------------------------------------------------------------------------------------- +Действие: Навести курсор мыши на UI объект, который интересует и зажать клавишу "Ctrl" на 3 секунды +-------------------------------------------------------------------------------------------------------------- .. image:: /img/b7c38d622bf5b7afa5b26d1686d7302a.png :alt: b7c38d622bf5b7afa5b26d1686d7302a.png -Result: The interested UI object will be shown in ``UI tree viewer`` +Итог: Интересующий UI объект будет отображен в ``UI tree viewer`` -------------------------------------------------------------------- .. image:: /img/629bbf4db2c01b9c640194230949fcd2.png :alt: 629bbf4db2c01b9c640194230949fcd2.png -How to extract UI object properties -=================================== +.. _how-to-extract-ui-object-properties: + +*********************************** +Извлечь свойства UI объекта +*********************************** -In order to extract UI object properties do the following: in -``Selected UI object hierarchy list`` choose the UI object you are -interested and click it. The UI object property list will be shown in -``Selected UI object property list`` +Чтобы извлечь свойства UI объекта, необходимо в +``Selected UI object hierarchy list`` выбрать интересующий UI объект и щелкнуть по нему. Список свойств UI объекта будет отображен в ``Selected UI object property list`` -Action: Choose the UI object you are interested and click it +Действие: Choose the UI object you are interested and click it ------------------------------------------------------------------------------ .. image:: /img/2c27be5bdde20b5d062cbb40e74eaec5.png :alt: 2c27be5bdde20b5d062cbb40e74eaec5.png -Result: The UI object property list will be shown in ``Selected UI object property list`` +Итог: Свойства UI объекта будут отображены в ``Selected UI object property list`` ----------------------------------------------------------------------------------------- .. image:: /img/f235ae29099a713e0246cd574ac3a17c.png :alt: f235ae29099a713e0246cd574ac3a17c.png + +****************************** +Быстрая навигация +****************************** + +- `Сообщество pyOpenRPA (telegram) `_ +- `Сообщество pyOpenRPA (tenchat) `_ +- `Сообщество pyOpenRPA (вконтакте) `_ +- `Презентация pyOpenRPA `_ +- `Портал pyOpenRPA `_ +- `Репозиторий pyOpenRPA `_ + + diff --git a/Sources/GuideSphinx/Tools/02_Defs.rst b/Sources/GuideSphinx/Tools/02_Defs.rst index e118c2ac..ca56fb6e 100644 --- a/Sources/GuideSphinx/Tools/02_Defs.rst +++ b/Sources/GuideSphinx/Tools/02_Defs.rst @@ -1,5 +1,5 @@ #################################### -2. Defs StopSafe +2. Функции StopSafe #################################### How to use StopSafe on the robot side diff --git a/Sources/GuideSphinx/index.rst b/Sources/GuideSphinx/index.rst index ba45c743..440bd076 100644 --- a/Sources/GuideSphinx/index.rst +++ b/Sources/GuideSphinx/index.rst @@ -51,9 +51,9 @@ pyOpenRPA - роботы помогут! **Для коммерческого использования:** -* Вариант 1: Подписка на премиальную техническую поддержку от вендора (ежемесячно от 66 900 руб. без НДС) -* Вариант 2: Покупка бессрочной лицензии на текущую версию pyOpenRPA и ниже (разовый платеж 299 000 руб. без НДС) -* Вариант 3: Покупка бессрочной лицензии на 1-го робота, который будет использовать текущую версию pyOpenPRA и ниже (разовый платеж 99 000 руб. без НДС) +* **Вариант 1:** Подписка на премиальную техническую поддержку от вендора (ежемесячно от 66 900 руб. без НДС) +* **Вариант 2:** Покупка бессрочной лицензии на текущую версию pyOpenRPA и ниже (разовый платеж 299 000 руб. без НДС) +* **Вариант 3:** Покупка бессрочной лицензии на 1-го робота, который будет использовать текущую версию pyOpenPRA и ниже (разовый платеж 99 000 руб. без НДС) Используя ПО pyOpenRPA Вы осознаете свою ответственность в случаях нарушения лицензионного законодательства и совершения неправомерных действий. @@ -244,4 +244,17 @@ Wiki структура :caption: ИНСТРУМЕНТЫ :glob: - Tools/* \ No newline at end of file + Tools/* + + + +****************************** +Быстрая навигация +****************************** + +- `Сообщество pyOpenRPA (telegram) `_ +- `Сообщество pyOpenRPA (tenchat) `_ +- `Сообщество pyOpenRPA (вконтакте) `_ +- `Презентация pyOpenRPA `_ +- `Портал pyOpenRPA `_ +- `Репозиторий pyOpenRPA `_ \ No newline at end of file diff --git a/Sources/GuideSphinx/make_RUS_Guide_PDF.cmd b/Sources/GuideSphinx/make_RUS_Guide_PDF.cmd new file mode 100644 index 00000000..31cfd772 --- /dev/null +++ b/Sources/GuideSphinx/make_RUS_Guide_PDF.cmd @@ -0,0 +1 @@ +"C:\Abs\Archive\scopeSrcUL\pyOpenRPA\Resources\wkhtmltopdf\bin\wkhtmltopdf.exe" --javascript-delay 5000 --load-error-handling ignore --enable-local-file-access C:\Abs\Archive\scopeSrcUL\pyOpenRPA\Wiki\RUS_Guide\html\index.html C:\Abs\Archive\scopeSrcUL\pyOpenRPA\Wiki\RUS_Guide\html\01_HowToInstall.html C:\Abs\Archive\scopeSrcUL\pyOpenRPA\Wiki\RUS_Guide\html\03_Copyrights_Contacts.html C:\Abs\Archive\scopeSrcUL\pyOpenRPA\Wiki\RUS_Guide\html\Robot\01_Robot.html C:\Abs\Archive\scopeSrcUL\pyOpenRPA\Wiki\RUS_Guide\html\Robot\02_uidesktop.html C:\Abs\Archive\scopeSrcUL\pyOpenRPA\Wiki\RUS_Guide\html\Robot\03_uiweb.html C:\Abs\Archive\scopeSrcUL\pyOpenRPA\Wiki\RUS_Guide\html\Robot\04_keyboard.html C:\Abs\Archive\scopeSrcUL\pyOpenRPA\Wiki\RUS_Guide\html\Robot\05_clipboard.html C:\Abs\Archive\scopeSrcUL\pyOpenRPA\Wiki\RUS_Guide\html\Robot\06_mouse.html C:\Abs\Archive\scopeSrcUL\pyOpenRPA\Wiki\RUS_Guide\html\Robot\07_image.html C:\Abs\Archive\scopeSrcUL\pyOpenRPA\Wiki\RUS_Guide\html\Robot\08_HowToUse.html C:\Abs\Archive\scopeSrcUL\pyOpenRPA\Wiki\RUS_Guide\html\Studio\01_Studio.html C:\Abs\Archive\scopeSrcUL\pyOpenRPA\Wiki\RUS_Guide\html\Studio\02_HowToUse.html C:\Abs\Archive\scopeSrcUL\pyOpenRPA\Wiki\RUS_Guide\html\Orchestrator\01_Orchestrator.html C:\Abs\Archive\scopeSrcUL\pyOpenRPA\Wiki\RUS_Guide\html\Orchestrator\02_Defs.html C:\Abs\Archive\scopeSrcUL\pyOpenRPA\Wiki\RUS_Guide\html\Orchestrator\03_gSettingsTemplate.html C:\Abs\Archive\scopeSrcUL\pyOpenRPA\Wiki\RUS_Guide\html\Orchestrator\04_HowToUse.html C:\Abs\Archive\scopeSrcUL\pyOpenRPA\Wiki\RUS_Guide\html\Orchestrator\05_UAC.html C:\Abs\Archive\scopeSrcUL\pyOpenRPA\Wiki\RUS_Guide\pdf\pyOpenRPA_Guide_RUS.pdf \ No newline at end of file diff --git a/Sources/pyOpenRPA/Robot/Clipboard.py b/Sources/pyOpenRPA/Robot/Clipboard.py index 12b43186..279e699b 100644 --- a/Sources/pyOpenRPA/Robot/Clipboard.py +++ b/Sources/pyOpenRPA/Robot/Clipboard.py @@ -4,17 +4,42 @@ import win32clipboard #################################### # GUI Module - interaction with Windows clipboard -################ -###ClipboardGet -################ +def Get(): + """ + Получить текстовое содержимое буфера обмена. + + .. code-block:: python + + # Clipboard: Взаимодействие с буфером + from pyOpenRPA.Robot import Clipboard + lClipStr = Clipboard.Get() + + :return: Текстовое содержимое буфера обмена + :rtype: str + """ + return ClipboardGet() + +def Set(inTextStr:str): + """ + Установить текстовое содержимое в буфер обмена. + + .. code-block:: python + + # Clipboard: Взаимодействие с буфером + from pyOpenRPA.Robot import Clipboard + lClipStr = Clipboard.Set(inTextStr="HELLO WORLD") + + :param inTextStr: Текстовое содержимое для установки в буфера обмена + :type inTextStr: str + """ + ClipboardSet(inText=inTextStr) + def ClipboardGet(): win32clipboard.OpenClipboard() lResult = win32clipboard.GetClipboardData(win32clipboard.CF_UNICODETEXT) win32clipboard.CloseClipboard() return lResult -################ -###ClipboardSet -################ + def ClipboardSet(inText): win32clipboard.OpenClipboard() win32clipboard.EmptyClipboard() diff --git a/Sources/pyOpenRPA/__init__.py b/Sources/pyOpenRPA/__init__.py index 8e4a392b..fc97568b 100644 --- a/Sources/pyOpenRPA/__init__.py +++ b/Sources/pyOpenRPA/__init__.py @@ -3,7 +3,7 @@ r""" The pyOpenRPA package """ -__version__ = 'v1.2.12' +__version__ = 'v1.2.13' __all__ = [] __author__ = 'Ivan Maslov ' #from .Core import Robot \ No newline at end of file diff --git a/Wiki/RUS_Guide/doctrees/01_HowToInstall.doctree b/Wiki/RUS_Guide/doctrees/01_HowToInstall.doctree index bf882b7da48ace9ac62516b6bc9d495142bda8cf..de69ee25d781e582b9e77627c22a27a98cc3132f 100644 GIT binary patch literal 12531 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 literal 20878 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 D-w|E{ diff --git a/Wiki/RUS_Guide/doctrees/Agent/02_Defs.doctree b/Wiki/RUS_Guide/doctrees/Agent/02_Defs.doctree index 992c9a173fb8c8ae354fb40a2a3298a820372dde..fa002a6841f8df400794fcb6c42c504df8d362ac 100644 GIT binary patch delta 1080 zcmZvbOH30%7{{4zpD9IJpo(o}HI1NFS{k_EfrFkZX*ihph%H@Y+i3$VY_~j2M2PY@ ztPwJ+AsiKr;eau7fT)C+7{n-~m?l0Bni39PB*thIqru&l$ADZW^Z$PT@0HB_nWIMT zQJNn0ts8HKHG@@VZ#kVDTfCN>PCj1jPfjJLB&Z8W&>*VMu$_X0B=LXCqX~}+aHs~j zP|AH0^-#~YDGmCp=0V>&zle*pv)WA=!lR}JK*%S1zN{QMXMx@6mO&V zZGa+jBPF-V-06dDWbTTyk))Q=8IlekJx|hc*Q<4kQ|_lEsq?1DyydE54M=2mt@PF6 z2Pcl_WhJik^%j7e3c-az5oE8ZFc`zpkkPOy1K1ODZ_xnq#7t;@#Dv;I`{lbHpKbbP z07ID$g~0$?ul`@Y*6GcGvnEjpZXo4jytnP zFi5zJsOF&_uTJdM?-G7JDH(y7ai`p;&|0Mf)6YlMJ3^OVMm4#x?ntk6MJj_Dkw%>< z8of_BRde}hE#>je<>%x;04ZqqLx(@n0Ii~h=GoRJ<`P?7O}AH+d&?`lQlGR@VK)kG zF}Yk@cpn-Xv!a2wRy}knMH3BZW!!DC$I?m{$7u@MvH+zQnp`YApbSL^B$0|XR!9sy zBtLzpER{FEc%A$fIQY)10uDU-~Gu)qmv=UJgU~a}OPgg5{KCQs;5mrEHgAM)uSfZ~t%MQCp{y7bL z@##WALNtXrPH5o-wqBk|>43V@POE5U5(2j!1tc_+4grAZrNhTmVqPo5$JzR3HXdgp W@@(?j7J+A4;$e<&Cd265vhyEWhm>Cc delta 6598 zcmcgxU2GKB70%kbYp?n9uA?>JzhPs6>EZz!@*}shKmsDNV1f&3p<|iZ-SN&$XJ@zb z<6tT6f@l+0y-L#FX;no?p@~qUP(`65wQAF(jUOrqtz>9;>QkCFQB^5YrK%xPDtgY0 zXLf81&CAS#FFP~$o^!r)zH`pKm!Dp0{rqZc;%xlK-}>7R6Z2czMpfO?P80N+sg(qs zd#XP7$e!WdkB;tw&xTl2hj+7&vZE|tEkCk{Q=}rNONKC9=S$z@EA-ffgS6QCZum;F zH#X3h<0AK~aM2v1i``k9CjO9&LepmZqqW6YG@5R$|949intJT7Wg3xS>aoiYeil9^ zd$Ie)i16Ir6l;wpM$h*BBz#Qv3j-wl_&~d*v1d`v~j-<7Y|S8D`|T_{jfb$P4=-1 zgKN3pgp1|t^rd{eedo3A_GmO+ykf24-U%1ea2 zWco_1ceGJgh;L$I ztJo{%#lAwuEQ(KVUz$$3PHVzf4b3bWrY4l}bb5N)Q7{Cj)s*Hbg(IuCME(%v;c+%g zI#({Xd_$aXUCSg}V9dv0*NaR;<*R}ve*%(75|o&lWRW4!FzRDFcb01<(~uOMb#3ZQ2X|4|@#J&l0 zya?zrGqswb)(l~KHJGr>#TXk|A?pshcH=41DwX$GyqE(|48q@5_#2wCNSrr~8W=(n zAXX|{IBz!`_yLxKT6`bP|8LX$rd{%Fcw30kV;6HpH&_n_;s?l5q}?+*5E0i@3|K

-YiC6{uJZ~;+jv>4+>jo{bHhlrkO=S>_>t#QF0G|JVlYCD-ff)J<-OF%@dD7w2c_|;7+0N7HtIWQRR0;q+ z4LlWV+S80C)D^xYjEymeW_gu4!s|+HmidYV4{X(W*lVg%sa6(%T{^3oNcWioaPE?sB5Ueet*8i9-jGVo*d$24-NWIP z#pa9UoKunT8wZ&wpz<>=gzu*5zw!?qbIR(LDlaKUZR|cO0(pnv-4Z$;z!n?F+6@s;KgrS~*Rt#U zrh?6c^5t#x%}o2gmr#3OAs%34FmVIS)B}uf@>QpwUhCfq4XT;!Bwohr(`J6)#VNkB z_rEvV68nq&)E}Q|Z49lFQcx&9hIHZOgJ2ar+`$LaX*W_?hi>WA5$}Ue+ORsiUxwsg z!W!Ae;ZK-y@8R$UK3>M*1P+rpplo@=VHi!4LIK7c+}vU-c0^1#%O{+r6V9@EXUV)N zGB^h{h-)43;tuh!T!3fr=0r!OBKBpT( zb-F6(I$sg!Kt~VVb*XJ{mh3p8LMS9vC^NcQ)D6ji#$8h({g?JC9>1xrR2lDGn9 zS%ns)_6|qBjO%3;2W%knCLFLqY;~w%l678d#r=RokRWq(I)7s@=d9vM8hiZm=^l~j z!j03h7W&Z5t=$Q-zRqj9;CW8BVA61go_nsR@%@P!Qg;y&k1O>}-j_o+1OKOEVpjH$~7nvDeQHt=N z0FL0MGE~uk7Pq8>^(xHs_b_SUa?qxQw*p2jT>igSExfgwSr4yb*GfGr8B_Eb(=wfb y`ZjRL<3h~iLj2Ig!K1JRbAzAtIU(jf9t29$(tbD#)T2{3yOT2Vkf+AY!T$lvC}eK{ diff --git a/Wiki/RUS_Guide/doctrees/Orchestrator/01_Orchestrator.doctree b/Wiki/RUS_Guide/doctrees/Orchestrator/01_Orchestrator.doctree index 79801fef6655c69eb80456039ee3bbda5ad5e2f4..76b0b6913e972f2cd72215582d7437096ddfb8c9 100644 GIT binary patch literal 25294 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 diff --git a/Wiki/RUS_Guide/doctrees/Orchestrator/02_Defs.doctree b/Wiki/RUS_Guide/doctrees/Orchestrator/02_Defs.doctree index 0222e3dbbb4aaf59db706780d531e71bce25f9b4..2de72328b272527fd4c249737238e808a322bf1e 100644 GIT binary patch literal 855824 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

Ly!EYfqK@VBmMmJh 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

1{+5@9wdn1&x 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

n05mh*h{lhNM?Q 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 E11&TkjQ{`u delta 1865 zcmb7E&u<$=6s~_IHIRt9B?@hW$4)?@YBxVPAUPp45>;sfj+6%Vlv=a)*t5=h*X+)i zRBB{Ug#==X6wPozLR^Y^fQmz-_CP2?YMXz8e*sP$xbnvK?z%}DwTG4b<~_f8-}k<6 z9^Oj)`cFLddGfp454KW`krBf{rP>w3nB~;`RnlnMn2{}YHFK=y_fA>wRHkE(-h1sG z1BLY{_=BQ@Yl@~ta+Pc_C6ze1OwPqG$C7d=aq9f>sEN-!US`}Q-7Zt&z}%PW3$>{x zX^JjTMCauXznnQ%pgEeS*`)zEd6ULyV%tpp{Zpz4;YV^Nby~VVuVybpK`bcHf8Zva zd%M?6VCn3j#h21)AmRq*jJnB1sb}v*Rs6%RC^rsu9#mi04 zHEq(s%qj!hA(*2YL0dxzsO+3{4#KObX3Os%5z|*Svzav|5>{naVR{0#IRf7(d?(>J z<&mmY>7-{Ar*F_t_e~YTyttpZXW)E_T(!5ObnlKXi<8eLJ-~QaNrd_q^#4YSVp$9T z8tz$2AeCK;L%Ji& ze#HU(;1!wM9cyd(-hsMgR7av!WI_X;3mh12rfaakp{TE*w=zBVIP^_)7u~T*lABR~ zdP4rVJq!*>Zx8?RZ!Av#+8+4xc4AKKH@>1{^gg}EMcTm)!mc-oudP@=6+3d|D|)}k zX-4a3Om01yXh+t1|H4Mow#pVm4eYJ+CL&J7N1s{XG0qT1rj4C-WLplIL);-7O;Tp0 z0zWOMLL6oU`+cE4ZynSqQUPecJ^^Ec5D@T>>NyCw899KCh3fC%!;uGU(jvB6ii@PC zK#9Stiz~%T#fwTLH3*#<@Llee;UUWd|Me{N-m`+3c)bg>PtnE-0XU_i4); zk$&|%Q2(Hxi^aWM+zh!0SfHC&qYk diff --git a/Wiki/RUS_Guide/doctrees/Orchestrator/04_HowToUse.doctree b/Wiki/RUS_Guide/doctrees/Orchestrator/04_HowToUse.doctree index 755c16c0c9370fa8e90ebb7162efde2c4eb35d09..71757177b27d9507fa14648683fd974ade9723a8 100644 GIT binary patch literal 15453 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 W6z@%oCDi&gQlGJ=A*&vgOaBW{XhVVk delta 1453 zcma)6O-~d-5M{r>K~OwMP(d5yOJpaoAjWkCH8BwpNKg(QjOm?is4=tC%k&H%31&4> z;-O6-Gh$+l@#?|EgcC;(B>n)s>D8P52CJ9dWj82#tgh;M?^VC9@5`@l#vVssHgs;p zp2r)9b#jw05tkEBumI}r2cXI5UAF87ejuyU8$W*LHL2yOL+2fu1FSgrBzP3`LQHnu z;~udY%cxe4XA|xiz=Z2impdfqaDxdkwhPewztzuzVtW{XQ=mf#{IPIPV?VUQd1#x6 z;bFs8kG2{Kjrt!4+Wb!qxALiCvQ8!OM#M`)yi9Xse2%P?m}a@dh{5eSbKXOqCbtEN z6Tu4=2DOP`i~w_3vc&t}*Sr3Fe^1FQ^19=v!hOd}GMXxwUfDX<^sOmo;1MlII@&(c zeH$h{=z|nW4wY(^$|_~le~}>9>NQQ*$tv|+;La*>Sk9sbOD4(qBI=o>!s3f0Wn!Rb z3&B;-HVvL(7EKG?@kad*iL+r?@V_SFd00^MgVrf%n?kH+*;3JPaZpd_gNa?hpseqJ z8l+y`P?Lwz7-@@Tarj21n+_=j2_>O4`NB!zpbQ1I*m13rBK6NSw&bB3P277wkTHkN znVCRF%*Y9BGHJQ;67ENOttWwg+zYo2n@t~4D)$b7Vt@6fH zEdqIt8OZi5H7%DX4}ehe-zc_)hYXEYsKY=d{OO^-4)mmKNIAlNz;dR==P}hb5yo`+ zEBPBk=dUa4Zeu38mtk;PZ32RGuLr&qcX?cG6bc>q8l8Bmb_phmt7a=Zd@&q`Ut8}- zUPtoq8Fqx!Y?@{6N{$I!D)4zq08uS>5PTE2(h;#DT$X*1#Z5xzD~F3tP>ZYl&5Lof z?4PwW=m8tolJL^PHC<1AbF^{sg)&LfLA?{|w{+-xGf~!hcp+3%_i- Vlb64QBL2}-Uu^-5`j=9jzX6?@`+NWZ diff --git a/Wiki/RUS_Guide/doctrees/Orchestrator/05_UAC.doctree b/Wiki/RUS_Guide/doctrees/Orchestrator/05_UAC.doctree index 2fafd1aaa639256443451c64d94845d07acb0d59..6687a26709f5ef0f95e513a48e5760cb12a8c16d 100644 GIT binary patch literal 16181 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 delta 2515 zcmcguT~8ZF6pd|cVgiX!8-rpXW0N#|1gjvCq=*tIMG-{)kr$Jw2Q z(57|r5VfjS742*vDz%aF9*G2s`qoxz^8>2>gT550KcR}$J7d;1BG9T2d9gfq?>%$Q zJ$Ghz_ml7DqW4<9{wn=t^s|MY@eEp?nMEUL*&#NX(KO;XXqH*rW`<8&Z}~LtwdBYh z?hD^LHhU)#iiBQ`&g7ZPYn2JFwi2^pQuRJvv^7c`Zez}DM6rWRQo^W6Fn4VN3|z?o z*BEFu2511t4Q5b|>P|fq8wOiP8_Y$VAro7A#WgS|K`ARDP6=8kd9*x_im;blR-sDm z;G_a_FO^X85TgbmL1H(n)AL28$s(j6g_ZO*kW?^r3)y;!atAsjH5Zt5i6hN*I5YJR ziE^)?YdjOkdh5Rf{c-P`0IIziOZ1(5ue$jn9EX_%89L_%324aJe>UyOz==*8IfmAm{Q+9nIaREsUs58p2Ng)sL946HhadyWR##EUW^Scs-vCW`>3@guANcqE zkNp7}ZDgN6dRLz&sV;szeLKWOsJ}=2JlZm3%b1&o{aOP84bXZ>75+6oBA#?c#b`(3 z+L=@;HIvKDWpne3S@<6e-Jy6LjBWzR7b4X?CU!d$)#{mmDhAfb!~~jOgVA~i zI|f@rlR7Lirdmw9maee^F>v0=*zS~=AMX#-J#l+{q)PW{470R1tK9Ey0$dx-jAcg0 zY8y7q*wHya`ygQ4I|ZjVZx9oMzwpkei#aJ3T$B<52USD`8b-tb@i}xWQS~BvVa%^L zp1uYK3`hfPQq&8+d_3yAbcp_ah(y9`W_+McN2ofOBLUl+`y^H_b}xD7j_z?F>9~}- z$Z}Wc#0i=#pA}Ds(YrCwyq5>cFf1XXa`KFQYa(UEJ_O zeFs3+i{IHhm#$t5ht1Fqe&b=JdIL5qzb$v%qL0hhgjXW f>nJkDEyl?T5OqX)>eo<2{5drgQ$(=nynf*yng(hV diff --git a/Wiki/RUS_Guide/doctrees/Orchestrator/06_Defs Managers.doctree b/Wiki/RUS_Guide/doctrees/Orchestrator/06_Defs Managers.doctree deleted file mode 100644 index 88349b6bb7785f3d975e8c5703fda29d9f60b765..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 667929 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%0AynHnz zvUs^P7W`>!@!kTEsVv@G@p~sNUcCAbGmb!*rw(qna`hh@JGHI5#P1BG^HCYPc)_0- zl&(=Oc)!{bS#L4u%S<8LfT$X+;BB zFLlYjl`p>IL{S*GpNfNCZQOda2^qJyL67Y=Zl6RbJ>!q`m!Em8oE6f;6_Wf<>|?467L z`1;}}ianm(?{3KX&kl<(SsF=J@*JoNRtQ^6AoLENC}s&L2W}Akc%)f^?I@fmHed*5 zB_l%^TFHkP^vbN{Uj_t&kze?B(a6*N{)SNpnAQShDl7S7{N70``6U=eBdXx z?h|fT+UI)DM&`4Lcs}yTA6Wq zz@)xPG<3h(D_&zk*|0_Z`~;+7`<&p5YM0dL`#Xe&+p7&oxquB%JKn#m11&;^wC+W< z3Ta^c{@o3#{&g>^vHtxps);G%i)!Q#KP$djHA)LFs?ovyB23oHoRQi4cSVW|AGMYi zN~$%dBG{3^s(i_X3;fglSJiZNM7x6mYWfV`eX9O-L}UH?h&G4F8a^fVmwz6gQH|3A z+34^I$rfLoJ%s0pD`zJFOn11A6c6G3KrwBZ%hKIy|F(rQX3oHW&Ku{$Y2Epi$P3uq^YB!baf97#KLGv+M1ZIOzCQq_dVOgi{`7m6g$j#`5SqAPi(LDjLXD zyR^$cDx|JeNj!gvA&INrB_U^lx^Uva`aFL({O;^P=XLfdU5aH}&iYh*+_CCLDYOPpdt+U6n zjUu@l4=pWNX`8YT7_R3b5L~Xq;lf<0{s*Y4qx zgRt`ot6VBh%9TZx-4J=!zMn>n-Jc#aV+Oyq!i9H&WuutmGWgk#$E#xSD8G{Te5k8@ zCGRrQNz^NOqV(V^c`dw>huD+lO|*@Mb_^!eZHpl(sw(C@mH*ii|JQXhTbK~m`KxeOg+yGS*tm=cWeH;KM!rzWGOQ1V5&RY!_ zg7GpkL?T|+t|b0S9#?WaI-qaFPK0x_Pw=O4sQf=+5-KO)r}29yoq(H!lZz;=)Skfe zTlNH!@l%J)pB36)@OiB`A1vT1kx7B;vk&*ls7j*Odu+Q;D0C*)(;2b6BNk6|T3>G>GwY9QONuj9f1r5c+h zOZOn~&Pk5=1p?3L!6pTEB>mz%uJ?>y;&wtnI_m&xut+b&9|`n+U(ZTJLa`S!bSO8@ z9k#HqKt3|tH*ZHU;m#%GuM^|<%?B;)1Hi)0CtPV6$2MRHW?>^k7+TmbHRzRv+4*Wn zWMOlmC-~FY!oC$CQ(4$=$M2oAurEgIk{;i-`l-un>Jw8Rwh|i3%bV^C6E+#(Bd4~i zH_B?2%*F3>T7&Mf)8I8NKH~PmgblB04cWPiisfv5&E|4R8*87>8*<~@`yjLm@&ElB zkjqS^aJ!0`-R~C--G_U}>_%Fs&ZwW+0)5!l$QQyrTG0=y_b2&I^Psblyot3m>mphAR>oWG${Fb&1eeU5@%bmV0H`^kxth)-=c`NKbp zC8|+cASWF>Avxo#vp~Ej&76+`7SnH#&s0p?x1U>3wZ}%w6WKzk>D&kre<^-^GX~eO z93md$cD?D&LPv|c0K)AP<c zInY~SwCNrh)a0tI@y0mV)mvkaGNG;UzW|fAduzNCq4c)KbRCe5)*ZMc47SEs7G}CN)M(xw2DRiy>Et^|hDCBz+H1b_~_jnfv-Xz z5nXHp$;_CYJH}XqBP$yA&JA=v(fR&_K*g~5sx>j`q#P0 zS^vpg=8)YJGc=z% zbCD~j-fmD2pG(T{Kg16HxofJ@SP7nHWP}_nf*L~EaM!4KN1*zeZ8vr z2)X{|kt=*nOQ#){#{wyWs!Lw1$YJb=#uB7jACtNf4ohi^HLX1_r^TRE_PqQR=&y84 z_LEMcJTIcO``!+*zz+=13t~nVFVUt5a5p()_1qY8;VNMJN?Zko`^uw8)eieet~3Ch zE#S+bYJvrP&_{9r_(%#!vjnO#^Pbea;Vmp)@!SS0%orT&r)+PT26?^lCiug=wjz;If)s4HmE-@beX0;5KpIXt@Q) z#dg3oQ7rKCRUju1ue$xFbLDwv<_&~`B(9(bfc!E_qOU0A8^DJFPOzKr6Aj%j^+d8O zXBXlEdO{|~VLm3{7!Q2)qxFjdJ9PgQk5=Yk^U&&i0s9C$q&Bvb2^sJC{8z_D48ZF8 zl5!V^>vH_4iu_1=5+)e5_qDF7?~(@2kCsR)W#(!=ApGX<|L3aye+7+07ux&~J_1kE z{=vwdX$87sBm3q~QV>ZP^xJ&h(zFQZfRy>6nSDxlw({;Koo^@qH|g%7&1g&Fy+bn; zV;W%CuTW$lxe#FfvPUUFlT+sw_K}PH2t6g~<%iZQi(MCX~1kK(H{x4lxw`i_3j7Is-aEZb?JpNAe$ z%&=vw(gEb;cC~cBFJ@3KteMMRIqi0k^ZB`s3u!k5a&#KqHy4bYK4w-DZ|{d;C^Y_Ko%3%bL2AtV#%weu zpG8(0=AYSQg9o3ii-+ub9qyN^Svw#-4XXEtZNwD2CNA0!B#?wGaOU+BLvjxOkT#mp z=0ElN_4V2wim=xq3=3V!em(&P4{k1GF@h_C`67=+IK{$%R*FmClV?9~4zoR`c@jT? zl?M+(2|NP0V6vr2cvYbW$(`Hm>l%eB+?4=noP|+vG+>4&TW!qv@ug>S8(H#4@a3T@ z5^PF#{%6M^NDd3kgt{awfIAE4CvY_!Y%WeG9e|lK$9ih-TZ20$QToD`XDr}#TknIx zDKExoJAp37j582}8bkui`+YvCs?Yn~!Z<k7e%KDWvcisd5r)`ZsORB? zJLuNBU8>i!SDte~E1$$^z;Ce|ScvPY# zV&}xNz9UKnkqB4a6oa@}u6n(et3>H!_Yfy0>~;|d;A+H0GOoTMhBzUv)=EvD-`#J} zD~tD_(hY_#g8KP85TJnBEg@Aq9J~CK0qD$L_ykmqvlpb~gH`NeSH8AAQ+d3`Oy%<| za(z22R~uf8;DS4OLysSmw*^Fh4JVesY|S`dHNYApIASdk!Sx)+lAyVb$%9q;Mm&hd z_C11##zC|{!z5^cZ~j=L1kYZT;jB7|qs>?jC5jMVd*WypF(H4kT~8N8JHs@vm zNys*0Ts&7GC1HTg!>02b?4y?hZ0ErQgL`1D-}MEgfw5=%5>@{?&o=E}<=JKxoicUmGu2zg`fZ=E@#n(Oyu$@T>(wzX?4M`{WY6`7seD=+%{&nm_`&Y3K8#xX8 z+^K-3)9mwJ#h6<5q4P||KKnnw_JyRg{0wPeEQY?N>R-o4w0{*Jv60j8(f?II(`i2X ziDFDGAJKUxwEo*<`JZi+#Tld2sKo%KCmzl%bIFni&6s2XQ4NTIXmF_*BHYSs@q zXf%Mf+*%K@GE2T}*|fUHd!{XbQC1-639QnLbE*Me7)cQ?iAbvFDHa^#R%D{!7~e7o zG8qTQu7F9XgJV}?Nyma?8yJ^dQYzH(w)%7tvKJ%_D)CX%g~`4UoI^N!Om)f(zp<9` z0W@vu8M#DAd|bO}o&OuXgCcPC@0v4Lts-aC65^w)LAL9F(aaVpcb%{x z+k|N7ex)aZY#v*N540T-U^c#o4}BMclEmEh3LGVjxp~NS{to*H$J}0jK(ISwU0<|C zl}L$MP>#<>990YKdR37huWtvOBns2rs%RiP&^T|iAkrfB8-x&w3Ix^|eA{3d-!$56~Od{my{$Y_xYWaW1hEj9J2&M0}XWOSbmTCH5EUaPFaG?XayZdDW(B*Wg{LI(*1w;c$v2 zUoT@}VYvzq?d)*uT%BFYKiZh6@bedys=cdFZq)qEYIY5eY%E{M0;>cNI2NgPWx+E% zxvHJ5+g8cm?N!Obi#}Bvn1u&)nDjk}5f39m2RUDb#QC+wPO)^+kq< zt^|;uiV;kbL-+}VvyZt2rcD6(FEI#`<2zq~x}gB_A4vyMQA1JM^#C$LA}_~iLk)O> z1dx9hgBs)=cJ}hur0O#~fPBh|@J>!PIbvDiWYR$tD~Qq*v0ou%Q=YvB6hFJBsixLB^*q~$76+Qrzd$CX_K0xS;1MKZ3wG=?|{xf*=uvab)>8N)t! zi2yZgxozA(kee7?Ne>Z&!C5O$*!4V`q3r-u4Rm&4rxtb%d zOk(X(xS}8jCh_EQ_-ti&)XK$1ogP~3cYOB~1l^6yFB1GLC`qCWuZ+P?EbH#pvaTqt zbpuIas%}??2X@8zCu7%o3_%jI>m@#KCvq$JJ*`@)1_k7(bynYMU7mz~oa2;GQ6nc*qODp!Ml0`Ib*`$u! zug2gfmUX_QWgStv9b@xt$BoBUo#`J~4rh>zX!z)3YLn4J5s|` zobS>N$YXF#f&T{3e&Oz==IydSfEa_No)Ml3IL7yN$W3W*#r%R7ooiH6p8aQ2s)VN|M z;jEDqH_PFL0&tl(vnslCNx(2LgV{pj0T!0ObfswMPW43ol8WF<^w^04eU*he^#sdsMYeho}8QC8CRq=E6N-8ZTF*PYs>{ez<`bUQa2*_Q#6 z@OJJy6wt_SxJ2<*GIspw&f67ZYV&RAJfqbcmkBKIYmySgm(Ip7cbC$(h{$A8&xgXO z95En)s>r{_KA&`QpQg~7ULNp>s(&5((Ee5I!$$VaJt6!2OaV=&+2_ZKF}3VN=b4Iq z_W$JpN32XJh8B?q#$xD1RsT9ZqW!D*h>e_vkIqy;(`i0hsTfnsM|7SE`6#|ROVLs4 zSYL`x!nHZ9m|v%HdS%R*TvD_280DNho*wf`1(4eGm_3RHK1_BeJ!S#~p&~t|5eKb0 zJ;tL&C_QEf25M`13__0kca|PQZAucqzYI!nBM_G!WvynvLPXc z{+eAJTfW+Yf1%=X^&*H8*t|-(yh6_A&>pz0{tSg)m^#k;fyuznbtnEv-~j3C$z2-Z z+<#%H=t}0v12Jn}a+ZA*;p}7kxM`Dl@<8PiD}rfO zK3gMJ`B)hZbWFFQ?d{s?g)6L8BSYJ_Y~8wk9sGVe|9xcB;O5H)H^Qeg$fuE^!Hd?z zUuSxMc~#DWkAvH`lOE3Izk9`an*xcabLhn#U|upk4XVQe?d2(YYrL0d2|JfsK#0UW zRg`fm25W{bcU&`xmb+fwu+S~vVI&IO@(s0E!p5Q7cflmoq1)TBq+_Am%Y7lPA;@Ui z2#+YQE!x>?x)AP#EroD>0Hh1$Rx~qfdq`JY5Yz8;C#HKJaEYv@qgNRB3bL5)J))ue zXb;771B?`o?Vb?L9^7xFt0F`R~ATeRA*TcT^8SJB%W4+&n2_}m5K1v!G2U&iq z>R%URq5Z3ZENtX7L6#Y(hi5Bqd^-{A{j&-Kx+C6np3(Y{%L*3j{RSmScVfLKD-f!U zAU%sTFlL|ARsHMOhxV^xA2xCt_PJOAO{dvstzt|A45wnB{U7UflFo9BG%)6)J*xh7 zd_?o;*u-UiwJd#CQ6dT{FAeK+jeyYFVcg;_imE)pamTbHFkkDyg9uRmlZ=A1klN!Q0V zD$^#Id3p?jQGWb0#A@&=BY8Lkv#pUkgCt{ zVCK~^^NnSND@X@XtRPAcfM6!Vl8hO)#~>#mGfbag=Idh+7t2+z(Q=h2Js8Y%5Esd~ z`qeSS330VnYVu&_a}0WA(G66(hS7~9NmUbjA;n3-j~jr_?1hg()i`@W3T8^Xu%&EM zBuo|dH`tF4W2Xu1M>rm805L;0LYxTMdTO&!61VRXg_5|jE)ZxOO8Ns#LLEx_GnRBL zlypVNqrSab7$3K*Luua=UfXgk$%7zWFzKIkb8BZb3GYweG_-wm`;eWxs94U{S3|Zf z{NUd=Us8fkg;Jf|nlAhn-3mJ`KGSqHa_y5H`xu#?Pl;kZ*q!%2MCrmZ7n zBH6w@Ti`Kas9^he8aSVm2a4hoW?hNwE`M>>)(kG)fI{{4KN(7XSrNq zA*z*>Al(U3y*laSUO}NXJ&x$A`q!}!?O(+{Y~(cT^Iiosoo1hRE5_8a51nT!_Syd- zs?Q{y<)=skV=?q~RsT9ZqW!D*h>e_vkA9+nrqg`%L&ca{KBDtX#YaokmK{@gJ`5fa zsLC~1=(}Hi9eP$m^);U~Fy@;RRQ>DthW4-G8#c0U)^muZOXnJXg_)K5XS_-QQOmr; zMu?BZou(L7%RO|qskn!cUfBOCwpmEo2J3K+kw5uSHsK@S(ChaqyEtQ7Yo#_s2o2j)Qx&2*tq{z(8${ zgCpeVon>)wy2&N+)R1Ti&j@E9^Ds@Dlz|h@4%^|fESDpCKLQMeQU;ci4!{&rrVNPE zuBQwjB=XXXwncy^NXo#`F{qK^X-AT(&+wFibusgeWrYh!2T`mbN)LdP0fZ$PGpvb0 zPC{mwJ}CpG7{tYLm80bzFq*Ex5)*u)NM}BkV z(rAtO1blauhg?R?It+amb{B~&{bS4|VmYj-0#) zv4qq)#dEokTjtA+5XGr15^w1x)HvN_D4SC;sJcB*0G#~(@64rkdsZ2&qmv44-)jxn(l zXW1+|$4|oOcX)eq!i1X`VAAE@yv=aN?M_z! zFS=dbl`S%i!k;AZ##&>Ye#R>P=tFl-dv7sbp4=JA(rz}0hVBn~BJC!Y^THW8&okpE z9zij!F0><2*Dn`{PMDYDQOLOl`v~XdOzc-iXNHS1p+ZWe=}bOO9WW47D%uE2g)}gZ zQQe^GUl*gI{i|YBY-E3oir@6FI95pRm-X|^KPsS+Rj8bg^R}5Y;K^F}=iIm$JoH|0 z;O6;(Q}NNW3MH+r$5fyXl}l7@xXGX{^b7k-l1_9zX<)3{u2A)_Vg0*>PLL~ML{v9mX%^LuzjBQ2A4Z?4JSAJ=BMo&RU=;ujkEHc zaYsA^AHic1JF+d0JPY<8d~EW&fAn{%M!zmNx_fl3QK^)x^^w{Hc&V;yljCR*g)Q@ly2KO0nHuxupvGdN3Qa@b>9SxNbcQ=Vxjw*^Z^@&Vk+v zqfO^p&?}0xjQirCRi|ZmvsqwtrQm4GbB9H>ttoPBJ!J#BInj(cI)l$8aW98dTGU?`NMu!M8~_JT4; zL6mkqM*$&`S823{0-hkQ?4x2(gS^A;Xg{1(eTL^KTo^OoSXMZnbP&Y~qVxdBQ9xLd zF~fN=$Vtcy(NITvEQy z9?Le0b$n!Ox_i5%>GsW9Apje79`ieAgxrXdFRbaBfrt{V*))SOongJpPBb+NFz=pCvZ# z1M5QiG{tNB^tV4?2WKD zWu$O$`%sxZxRcQTQK%!LDbEn7Nf@a1aO#|neS`zmh5g2zWTM@=G~y*N`$R$Nb)E9Heena51kKQ|rm6^Ndz{Ts*MY^aYe4 z-HA=VDe2^HrqG(krr)LNU&lVQe--<%k<+lxJql<#%|8FG7*oqWbe^f$XaC2hA4xjP zuaO4EV(15|{&jpr`&aQ18#xUhJ*|MI(|q(h#h6+?qVr6}M;X{zN7-ad>-o@lxW7KP z0D_K?!cLV}tP5QAfeb!A8AI9|#!W z&%;A#9-a#zFTn38mLWV}qh}THp-Fp>oonFx?*rEMvQ@R~jVi?QX}Rr{T8)}bUVo>f zoPnco5z~c{g*SCT@UahB=TB}*7)dht-!wh|v{Wp<)%5mV6~g?i;uaZ;`3^_wl!{d_%2w}GKgNW@I z+gZwu=;?RtAs7$Va4%2MTl~E|OAsPc0U;8dNdUru>>0jdux8kD$2F5^x$ET(%g*7u z?L^r*+?^wquyJvCsa`!}(m&S^gJkU@V5dsp?MU_UsbkY54lG#{R%D&V>5(yGa!Jh+2b6Q}c;djB3Lv$K1FIAb ze3)Lw?wR%k)=Wkno z!sK?Y1ww$6;N|!uQINkEcQS;!S2I*}CDdPwSr^EV%w1VQIQ!UMXWE4NZ;3&W9Itp8 z)D4CD-$*(D6G0j37o}Yf^&=$mij3CL+->)U7}Ox|uu%W&NY!U}sQ;re^NnSN50eg} zSV5E?0HJ<_B^fjPM+|ZjGQ;!<^*c?V;6XI&E)a2pK z*BJE5;vJ}T4dWdXq-uwcexGo@e*c6BVfMnYP&Lk8I2hi9_a%yB0~0iVW2jyoSje2& zaIFI*`<8OHm4`%+I#};x*236y}!IFXTit8ZQDr?XY=2^;?3ofZS}*RA_Q2eTxUCm<=!oQ zJsre_oy+r)trP5AGETq2nqkWw*G!`2u9r6~yvcVMiNc$F(s) zEWEkZ7Y5n}SN)Z%cDexPi&_eBvZ2$3IK^WGWUcerv@@dA-Fx=Szzb&Ui2KJ_baSU@ z=zgt-qML$g!tu=|D#qp!PIaMhxR4mL ztLk4DT%i4{f(vZqG{J?BDxmSXZx_IIsQk9oHr<2&Va1r*-~ydzw2tGFfyFpoN|5fv zI3G(oxo=TuO=FxtQT4B5AKJf)eb~rp*ynEwXgbY4e^QL8Wgj}vRP3|=W1P!goKOs% zL>d^2p;fB>b$mqoSMd=WISn6Oq=2T=d~~5=Of4VLc_!qe`06aisnoF@kM~`tLW1tL z?vkQ`k5b)<_w5CtposVFjDuDk@AGI8iuaAdKy8ipA>`;TVevj{Uy+DV9!k(Oj*a)d zYCSpfOGA0og+L;Jr&-xCxUU<$2H83s1ST6HeycYeDMn`kMgT|2H`v_QY?~bl8G_Ht z2dpdLG>El3Z z8OqpVhh2sL5wip(SK$W{%s#fohzKo8uEI&~iK2e60c!~OH|R(69AhE3nCui&xWp{s z5VL~rFuv*PA_Rir-7W$F>+GR~>n!7Z(tshD9}F47&<}Q(L9fgY##cikKNuIrf}I_t)GDOw|+B?4y^xUeAXKCh~fnLK+xvH_uh| zuiI|Y{#DyeHgcNn<`xAszD-OAyj~j=V`{gXbe{41N9Of9nG&QsUaxA>$(1Oyre3eT zs{VECL;F{;4;wiR`@CHNO{dxCR>hcF_M!7k#XkGr>vez9S>8(;7>l9LsruLP5$#{a zM{MLYeDpm9G@a(7Z!5;s@)4b9LOzPG&b(fS0627;F6r2gd%fllDzu%>>orHwz(=X> zc)gAV>?yonhr~gv_Ii1=2zkB!0y~wqdc6>G$?HY!E8?s88w_RS^|}phMJv~+R_#)q zyS2(=#I04KdG7<(pyvR?hw5_Kl5m8vI#xDUFYGGRC(Ybl*1B@(6c`T2UWO?*B&TK> zAOC#%5%O@BaRc>^uEF`#-ghuaAG%9``p^R&tn@Pg`_Kbk=8khVun+9)&%_^zJZL?* z5g{zOieaJ~?z5M~tYyi4wjROkV{-JM`)s4mfhV?zU3Q;cm2i<|oXZUug1OI-Aq?GT z7aH`++-H0>Byyi|sV?}_*nRd|fK2T^djpnq%zd`S?{TPCFSb)YWpiF@4m2`yIu}}A zHJ7$J(X18cgIcK)o!70mYu*L?V5YDFzO;9UhVH&z@})7(347CyR`3HiSCnN!ToRAk zzX^OL^r(4=cJ9JHdfB7)5KJ(UN9_}&f$>&$O4Yw^D@*%VZDrZWX|}RIQb6O|Aa%f_ z_LO2w?N*k~Gk$N%JZc}K1nG`PZNY^J*=G)EV9Y+ps`}Tl5A9#YK5XPP?6X1vO{dvs zxnfK$`_Or&VxRr*QQMkymK#X}V?KJhs(&3H(f(C@#70iTM|A}>o#vy8VoWU`(Rn81 zqxkB~qo&lcY3|B+mtuaM#_2m^#^eSZyDLLE=ZMFSruyW>UtAm}-T z7x5!;(5k(N9xXy%#3l^XRxct#E_o5DO-WofZ-){iFXAb%t)rQ6Zbk@se!y^{^r-clWTf3Tb@#r#Q+H22ICby78}{wp zcQfC=ES?G%30jct%b#NyTXL!W5#j7(o0SNcn)CSl@J+(s4}Fso*EWZ@-gw>j;5a(6 z^W|E-l%25gJ@0I35?t0bxVB}ReO;qag;Y(*+bsNl_Pzv6uA*8v5lA5H2?VeQyaK`m z$OOV7MuLVc7|2E@5Rl}BPS2g`zUk>6dPx`rSzVA;QO6w>{oS5C6&Ic;;DX9iQJA;_ zJ{EC#4}Gprp9?DgIknxo_tved+qZjq(i6Tf%*?Ir)H$clId#sdssX517#!s%G1;a& z@Vxiz=nw)yilQKb4qFI27oxP|mt7zv@{){KvcMDM zj@p9^s6pOgmtE{ns_x>KT`V!o*T@QsNe6MPAWA2}WfurbGGh{@rn<2W(wFi)@`>>yq(4WwB=1a>q53Xu0d<4U1Cp9Y&%k zCEqoQC2Sp~d>kgBj#55_C2fmRt`d=)^2iD}q?Izq|IEZ8N;Yh|_~iAGSw#0Ji!i=; z66}h|HYt2pH5RZ=*1+az<61Zp2iNF`MzJqEPl_x4{{lQ>x4yXJi=6`aqiEQ8uuCGB zf}x^e%Y(vf!nd^1g5ZXB=CY*teS8MA$ap?}y&2d?G+j8}$SRIq5~p_Cv> z_6bW<#%ci+a*vW!moGn6QE&kcB%R!46k6N!0TosMI`*OctJsH)9GH8;ha+CAfTrE- zbE9HRE&I@UredFok7nMUbe10>4Xnk`=T-gd_=xte;v+V48a{eR0ZqI4=mEu;T0Wxl zOvOi;;M13joUP?@(OK-^qn9dC6ncz=FB%RoANCRuunYLV^A$6=n`&Y3J8#%x_ zdm>J#znTHP0*k@#P(QtX7UIel{+t?fa$`!NK>ew1|k3S6d z(rm?`TJA9-VZ%&6xYC%un5!K4EjZm%RU=;pjkEHk(RbAk9|2V3$gVu{o`M$<-QCKD(k~sl20a79E22Rm~2%>?!7AIk(NJ z=JGB`TfFPnC0G2wd(ZHMM;XpA)#{ZJFL(V?2krxQ2HZh-DH@-IUWkx$nb{??5pvhN z1DFsb`6uv40`Fu`7y3#FU*FCU(UGi*uNou*E=3k4`7*-U!#pZeCadCc1A^qB=f|LK zB&*_4(gD~X%B%`e+VQLkghXDC@zx3O1j(xSkpVTxJ1nc>`=shFo>j5;is)WJ*7ZhK z*pqY+#|ol!5@b~%EXkN*x&b)}nPKW=RV*|h&d61LTCNhMyR#}h#6>c$KG8s&gk1f> zpvwf)2bZ~n*?O^tw=?4Y6fDoxS-8HjmWL1J5w}7OQg}pyJ@z)A-StSWiiBGuE42mv zXwZ_E;kLTYRy08&<8Z!HE)_@R%A(2+xE~UXQ?Q4#MX);|g%Qk6e=z2|2_z;q<-6Hr zK%SAaFV=FlD1GxJ#Gx>E8pdxbYs?-`kzq7ufe>apzX`Ezu$^~j7)7oD-Tj=-Bz`mqgvf_N zLL{3%>guuHyt8>Me>D6%7XBRv|9Ur%fp8#uh7VY*8MfSU%_LgxdU?Y#jQDOlQHBwB zJ&7f3oniD4OhTPu^gS$TTZYm3Qqn~~_@~lcBKpE65{z)vbooW^56@x3k~T0e39Txe z!-m4JTdvpo-Q0>|Ia^zdFKSJS^rNSNfn*IHzxcRoouwcBTr_Nar)$!WD7!_oj}8nm z5qGObz6*5`5%(f5twdxkoom8a8H@zB0L_?YT(@oE!C~XoHTkNCWH0 zZjY*eU1XQ`58j#SPAE#rMh--F6DF4|R6rx^$96>A`V?bYU^rflayi0slV(tYDA`BK zHzL`bjMV}tR3#v>qySY>aDiT!baEF^Xl-+oa;pAy>_huku@4(LF!zM)Gpc~5-Rx6W zjHzWGI?q(>Gx51ewzgC5anKKnhVt<zmCwX{~$SWU&yDnC;1~di*2e=njj|~JRv#F)mf^Ua{H1d)$DbO zX*Vr2h}C4yXMD9`Om4@rR5RtA+n#FnuL>Zwsb(KmGzeg_GpS~OgI%s7)$IS7pjD@u z`Lu|nnmq{vwKUZXA;+KvOEsh0b&`_v6qKNA#guAxabfzjX_0KRDtL|HSu2dn;jb9l z!$;fvXx@%|A(sbdcM0BbD-4ygMZ6zmgkFA)zxp|6vXcKty4PeL) zxs_@k^LEhGHb{FTBf|srN?#U$kSmu4s`7=~;QAUAumI%vOuT>x!;1J+7Y!w1uQa8u zP@BMvxZOyfP^1ej=KT7}9558g+nYu@fX$RLZ%>qVJZ}#nk(Xn=s$qv(Y+*aI{59NnS>~_(l$zP?O;`Py1wz=C@h6CF z!8g`EUG+~PArhZ42f~4*tNy`a&9LQ;YbMch*UKB0 zuF9QEiPBZM`&ukv>vYxUofns`dJL9m(^dWXG!A6W?D=pvHXLCojtReg<6!RR?qy~3 zpioK@o|Vt!_oI?Ne`5Z~^Jmt#=JyR=oza^=h<|ACcf_6EWo|87C|2k37@VR+=rr#X zmaTQY@`) zpai~>7kX=uB=p+Sy?HG^fv@3z1M;ndy5S4a${ZvfAhRqct->V<#;shB!|ZRFsSCzHv!zrjN4SBrt?8`Pen-mn;M2NBJQucH6CaNBK^Wrw9#!J(VOo{Xa zpIYNZO;3WWu9>U{Uy6~<=X(`GsW<OwXxTd;vLyaY3!!_KO4te(rwI}29fhM-gNkX zV}WHOPHb|R=;3aZHYBe2Ho73^HXH>*pX5As?T10c!2dVT^ZBFEYtR1~kB;EmYwE*V zJ>ES43F>0tptl$}2qnQoQ12EBeEdQ`r&UsMZle`l`6l7_aIzV1r^Q4;^Lr(%PI2>~ zMH3%4dbEEFKzO}He_w}sRC34n*Vq%peRb^o=OA%D1`Vo;j=ghW2?lOk^H#tY?_BsF zw)+sYD=XT`;)CT=<=+Q&eFK@H2sNm0$sKUQ2`lO)c)Pt^QrU7d&KI`aEWe(_=kiw= zZEvV=W6$krQ4gs)05fG&CH5o@2A2MUwG|4_%enp{Lt13kpSV>?W zksAy!+X$1RxX$E0V)O>Pqz8Oa>D+#|R)Z@Gs?Jt$7DIJKx8l<9#5autENpmuEIP)l zgG%e^^<6mr2us!y;4-+B*O`m%SC$GjJf{{nhHpA9zar<3;3A>k??JX?`b1YW>5N=zJtpSiaq@jKVQh%;@8D ztOEnl7xJJ!TutX<9avG2(Fc(QTv{yTG71qH7LD<-2c1`97lhBOlo$DRd(b4%0|!sT zrUd*@-eI;_*zSfqS`QneawT^C0LQ}v0=at4CA=Zw<|HRO2y=$d*&1BKM|$Cy!Gud# z($(yC*nAAa18(Kg+jLSA|29)>f>dP<$H%> z?I6q3H5b!o9Qk-4O@@#rkH$?{(-X;rorq2Be4^ijo7lHb$2|u82R9JJT}#lAcEn;g z%Q_3~W_$AqwzFPfQ%O}};!Q1WX4u+BH?*r-Id*t+yPRptbW`FR-Tec-`DPy3?p~;{ z+3dEv7bsfF_G;XA_cCagWV`Eq0n9~tCwqFroh-$o*w1#Yp-8rntLYk@+c-igNnl4S zZ)lIwZfJq)Gal_Qe*c5p7c}ZCFfcRf&ogia-^QLxVU6F$zE0?@j$5yMF-<0r{B8A3 zi2RKA8VkguL%q9~z>OAIKu-Z>KRsuor(hXn(*%lXAfO!3sz~Z;g*J&*(u&rM8dgRx zVd|sVY4DXJZT~_#=ne(J>~zq-DO%d-pu3@6Djl>ip$-D%O%Vn3QMy`Mr+{dO`elj= z=sPelQ$Qawumx8@AE2|%mhqmlm{j)*_a`i{fWn=UR?juf z3HK`kVwQWG5=(gA&>-e@LA7@3`7+>pdV{8vX7dYUh@+P+=&PGSjuXNN8y#NW*57P|H!u7*H zO#0#QI2SVK_xK9Fe18c7mhl!_0M-5SeUSwgP`*>r=&9bEe6IzhsuTi9Ed8Xm1}Pu) zFJ06gD8dqcEtBvPsHvvO`F?h^-;k&uR1n%u)NfU^v=Q}}L%UR>eo;cBUqb2>G5-IB zkOriEtGrLNL;W&G;eG=Q%!K=;2KL~>{bCAhyzzhME*ZSyD{vQu-dBt7LXu{@cUX|K z`_s5%L;{r@h=fIZc=Xq`k-nO!q18n!oi6FAgm#`1Ti4W})-`sxqNR=0KOWkplKM-Vmij)vr-;};gwV(=_Gvx+f=99cBIu8a{eunU=VJc= z3PQZt-$i#6?9|#W3car&*C9zW-Wm&XcE5r=-vSG$ASqMp*GqE>@-+bkX~+~!tf&nA z>D1;cI}2D?neJdJ&M>2vV~DHRRt+FH-k0he1tHl!UqNU)**;Iv(nhwQ3GGtJ_N3Vb z5>ls#gnt1c4M_M_Wf#y6^~)Ru`gt%g6X-`9*nIm+Sb3XYVJX_WV|m}prrd%&F3tzfU1Tv zhMwn|Q#BDk5D0j3D?)R!1)C;TG8+_1CN&IU^|Csk0@8NR7Yx6JLM3Gv1-_W4GIAwgnbY)Kh}#d7(K`zg;C}$#phOZYtm=^=8hP zU)(M@!Xp2IpvZ5*RQW=fqv$y#_|I0*+fMK=Qna)Y{41edD#8Ea<^(^%>l6|FXAs)7 zQ1sId^~)Va|D`Z6+fAHm;14ePPo}WOi~i&BItFs17QK0l-F(G(8}1yd(pO+O*IU>3 zRX_#7&UhmhAa}pDKWu>oQ~{K5dY))b1zZ^tz5H3&FfH%~1GjK3a5DuyUJD!+j0%fu1v$gVmitovI|x?Bd%yyu?w9i4u)qRJc}f^P z&6|_*;qU>y6|xBrwz=)rTZ@^@bS`p zZbZ6ESG~?{#1;Fpy%&MXc*nsH3nz~E0=#I7-nM^?MH3W+bPjs-_<~Sh4{zJ2x5CEP zi`=$-?8($o!2?z zpSFFRYTj65kHSFw!&Ga?gF4=4U?~1v3VqY2*Skyl*7!QJhLsnEvZT-pt8QgYb{KBJ zuABs$O4b6uY+MWREcO{Z=#|>KY%LFeFJ4nFxmcHcT)KK$@Eg@48{jF@a=ixkXs;-i zv$e&io_w-svZOM!tdOh8{qQ88mF!AwsU6F0^1dj~Y(@^>v2wUt;D3sRL2kY+;o`7* zmW=U&cQ1?qJnD&tjjwmbqXYB>Chs8`g}t`>3XWv^20=1hEwD-XHvYLlPKF1=Wbm%S zKJXPO?+JMh;)Ne}1Wf!Lgy81H5InAd;I}da_e686kp(+by; zrX?2zr}cRSl-gmYH3FkM5X&G7dFs=>o z;{m~XqzcR{{5d$GrxoyNC-igDz}o<<%Jptz`eHs9{1)v0&#L|}Q}KB}d<4D2`gi62 z_e5>WhoFB1N7?HF#cH}dJW69uwLUUZuGF?v;Z45U<@It6UeLS=7ukS3c)Vf8g|mK< zg>3>AvGxy`4t#E*ufa(krJAHpWIUHNuqM?>s{VDPV*Mv0)gsj>O^}KXo{CgQA`N0q zH5Jt~kGm&*{=Hv?2OTxnCZlFn)xVCKtp5Nt_W+ZX^CtN{$dP5$7){WU4xNgYTu91x zwTgmV8nSwPa^cUxdA?RPPaUmpOh&7>sruK^iuE6$l~G83P&G;u)S`o@q88maX*N76 z(vjsVo+t|Mk~k#|wSt7bSA`NCVLzXYun(yE*AbTWA0X^=P8Dkqe+|yy5!DDy5S0#` zkf`SBzoFKsznPSFF&p>xO$fSm_n%Uwe|s_>SQR)Iaq0M7;7oWGzIZ);@6MaYKktBt z0shz=!p+}QxXHt)fj0^z_5Wu@1KC*fot$13x(U2*TE`E8_e^gh<=`|Jf@|>`CvTx| zZCCv#N*AoHz*Ab)S|tlFQ7r&B7(Ve^UBKKAV~xGwb=1PZnD=_Hp`>?a(6jb1SW161 zLAxhBty&rLt_R3)k{7|xz{Z|#MSUWAE(|1|SLZLOdpF_C>|bNO8HbtSHQ)z<9EbiK zvOy1{J$b=p2!=wx1ng$t05!QONr~Jmz4F+KmpPekZbesO^?ApyC+K_u{;+beAl)#y z)HUuDLdc`p`~y#OzF}jbmXAKfh%dwCvLy!}#vaDU(cpu4)7r_xQ=Z!kwb4EY_Loi- zmc~H62=60ibK78HIPkVw6|zCZgL6CbZb>|zSk0H~#Q_H%!6v=HkJ13VkqtFU?O>M#5#>QdB1yv;gc|tHID}wXDo&uu2tDI9kJ6QA=fF#lzzk3} z;#O(}w@P1z1X5K%_Q4Z;1AWdpbs%hw43mRbCM$&A_>dlBf{Op%Im}_p7Flp^+2Zug z67UPKk=OX!=oPmB&t<~7v!dwHsQ_7MDKHFQYtv zPP06}SAgfeFGkde_f_dr;|)x&!YZIyV@^I>Wn7J~l){^^?14q#i&^uXlehG5Si5fB z@@4S*Dg5^>tCy^~aLFq8w2*w-(!XTIa`@|1|1ZDFY4CB$`VFLq)A{ebm|3{rltDZx z35Z;%C2QoP{}PJ+jqoGvh?H#}RNvnKAVGaIS#tp3y`Qx59+9ADCfnnYPrcqxrEiUW z1Y+q7#DmV>FhVpFo>-hKSMnhyL2>iAxk+$7{-!2> zGzgSq;oouauXpp9SKkLVCfnhEDA^vvMK2^9iVD|asE4Vjph7TyC>-FvzyLUxbru8M zO9$WY#o?ssr#x zlFbd*5gC{$hd!_~*zbfBR=c%)d7!%JgcB&!T*)_o-cdLlRRDYQTK=BC;eUhP9jI&2 zTlrC_*JDwyt9NB@;^<`#l(_ec^Y6~zid)oMB+|id^{K81{`Z~lj&7(|Mv5-j^NUVd zbQW$wtMy@s1C5?dGXwIsaYSAG1#nl)g8$@3z3?J9KaH@>9d&A?H@*$xr_@VRR`4T?! zPBDgK`S&72($4Ds4Fel^Dh#F&;DUw~)YbLBcbtq$8+3eI4*Q1rK`xh(VmmGE`@5jR&D#1=Kk>v3Q+TPP0z*ziRB z#%!U66C*z9QkLwtVMcgE1k8}WoqlPdw6aQpJ*QkQZiedgFM8P(?u8K>WQXmy#bnf8 z%cdl44v>QVgxiGkj>5x}!C_d^cxm3vZNvGHzi{V1RLKq_)^ODTp2{O5fQDXS$m65- zP?z}gv!x*y2u$fb2#A9jfv=|kx+%LAvY`;oP|?Zdv8LaS4N1nvq1Z}t3jDs9KvnMj zXP0o`XiIT>KUgUbI{}{raRTA?KhU1cjI_eJioqCc=sc>xZIs|M2v54|760}}2 z3&A^D;Nj@d80-*&b{v6HN_sY?Vi;jYMg}2Ff*6RKi$4bPNP;0G^tS0<2R<1*{vaH^`2YJnSr3D@USq zdV){CaefOs=i9OUjBFIz`7yM{9_6jxSTJVx zT2j0tTPcm*l>evqeAp{_)4+vIB1ztK_^pxjBw&EP;yl>YFl$MKW{|GcxsB)a&huHI zF=G?Fw1b?U@n{Y0MwaZzZ-$;&>U_??0=URAb^bCsczpW*JZqzx^K^n1{)YAg2zti5 z%>r!P4Nf8Uc#j22d`jw>1P?)MrW8*g#n~&M)Ep*TrsP6gY8)%W*;y~CYRYlK5`1OL zy5_vTuhgTzc8U1@rh;yE;`{50mNw%1`_L}6_)dC-L!XQRlqz`MYYHvTuh8YBk>0e1 zeqrL_tzSS-OnQIOzyVx(-%SUPm)^VRdo#?*xQjyXYqftMNi*Iv7UY~_TJ0|uC_$}8 zIb6SZn$v3RB~L28a0e$`Xw7P!Kqs+U?lO97Mf=7LYrRX_HWb%_a}*~n2LLv9zrxo6o}o^&>H%MjaqRD^u)B{5e81+T5&EN zJYFlBUj$_e$XwBv^%o)9QpzL*L{J<>@0P*<^X zzZjPLp@uDmA*=)337Iz?7SamWC^*ATE4)I{(nc%14%(&G3M*}oC9`}nNh^ei zJ{5Jt4njJeZlE>vf&g{HtiB{`a0k<2vElRlm#$T zOb2|z0wt&eD1G##Z%zl?7$bi%NS)Yc9T9NQ3zht#h&ViA=7+=;af_|(hbpWKE>!{F zA{2;)q8cM4{2x`Ygq`sJp`xXY@c%iqOD+7Dr566cD^pSKf0s}V+2l$>pKk znn~SIZr!HMitPnUi;`QX9Xl+K&u?MpoX_`@`wYqETNDJflg$l9OB>nzZfKWUHYeU< z22d~s<@0L^wLm`44(D!emeZsT$34O(h~pR~eXuOYrL{c<~ba zxpWJxN+0KJuB+n9_OBsu8Sg#|z^0gN|B?ktP_|QA>Diz;*`5!`c1#a$TD)T81d^TE z@JvdyVC1k|U)i#*IlJ#G^%xTBzfw@rPN@HvqNR;c|37G#TBs*ZmXa|r1!ekA39-`2 zblQi0F{4c1`ywIJpEU3Ym+6mD@Zx1U3v2~tdKDI~xWYtJ!=;Z-gK5 zBe~GewLl3a?&hDiigj5DGl~ztr$Km$`_}a4Hw^gkzPWA zdxe5vc7ppHMN1pOeF3yfEx1ol>cppWpMoO$Y(gdw*++-X@Gw6I%<_3kvpn2{E`f|k z2hlHQl<7GDhS}*aHn0zu>1R^-<7N76*-o$G;Y=aSRYkrOzY>ATcvn~eGR5rjx&=y5 zic{L?$=;k4XAc6CRZEXuCf= z(DTCNTS$t(UqLWCDgGWsOB*TvZ_qBa6kpVo6sHK7f};GLgjPC_H?5&xkSK@02t6@5 z{5Asva5?-II(WPsK7nw%;skBQe@PRfT_)jFOtASQA(&3S(;E7Pi}L*lAR&|Qzc+9Jm+!x!gU8GFV^+Z(E{5wy zI8R&E^(Fer2yVvfgCD#7DFJ`Vi54h9iB74fXN=|~Iy*efg%sZA(u^ri);2VbmE_DH z-nwzZ5`1OLy5?NIuhe5mYHw7~%}#3fD_Yt}?XA!*wLzZPA1-5H3R>iA39)n%o7T`T zOqAF)=!r?}RR#{=5_=^bJYHfym+om*mpyS7)>ZN4^UVlc#=FS^uqkG7zuE#ND4!{< z^lZ?ae69s8ZV<7dySq|}>rh{@(z`UVP=saskR*pfAh&e-V%fxx7g7YDRxpU2BKU-& zrHvxE7uuy(1m`ttzDN0QDq8X%Bec`$1zJNd5Ku2X1U)gm@DT$;aJ}$BI(WQZa7AwHP(H*Oubl*qO(nh);4((D)_m`%S?u3q0QKs)jD5jI? zw1$2Gqf9>mdSWvDIR-Z1GW}VTOkYE7eSWKJm0kkd^hK+D0jz65xA)yHE^xi?ZhrxJ zOArki?>_BZhM-FR{OWQaY zUr2|j#_$&dIkl8mkljw33@BRKXp<_mORY^3AE;HLVhVbXE+bUaX%t#RzrazWyb5|^ z8fCMA6}U!uIUPKHmvDZp==ZO?rtg)}YrJ(=YV%dl(mwsY$E`U1jQ1{!sZTLY@^%Z9 zpeCW*pl7t^Gzq(=EwtvF%Xe3F601j4dmefLcxnYkGyTI_Q;>v))T9#>}pZ>d|~V#=ryDjj=H2-H`Q|$Ep4>IJZP6%D=co# zO~o)f6@6553AuFofY#72RMZDAhMt%{m}B4pt`82PgU9QGjct14hOdFP_3vwn^@tXD zW6%O6Q%qB=wm=DL3d$vV25e4K1f(~4=cvi}2DXjW5&oG0&=KiJ32O&DGti2T`I^8p z1FXN0QW#Yb%x{C7|luQ9XvXmBBT(E zBZTh{A-8r09;#EG)?L*~K*FMYIo={q9;a+(zryFo*?%9=TS$(7UqMbgIXhJw>BK2p$kKHE;0w)Rfus{h) zeM%)g12iY~H-&^P^$s>+qcb@`+Q-`I;@pBX4n6V1xirDQ>yA2ra1{OvWA)u zw9=MLsz?wW6hsJbx>+ zOD)e6-&ZWAKLtH8*Aq&CBtI-_!asHGhXc3o92H}=3-*UQ5lMIYRg7Z)BT$ct{cA`Q zv!Q+!g*0C5&y5)B7{(QLdR(zD#J`9@WxRVV0GeV#{PPwlK_O0Qq$huKLR@mrpeRjY z){5r7IOhUjLt)r0*K7T5Zbh-2t@$$jtr>id9R8E8=@E{7DxzBhQCQ4FShj`TbAbR z)GH%J_guHuJJ0DIzi0f;o!5_las0DR!VUktvBn;Sfm6ovGuG6`vIy|j0Kkp!<`!+r zZmn+0R&x2mc6U=XR~~Vzm0Z2JX=D_BEmcOcn<{R#T(9KZ>ZTndqi38p|I`;QJQ<2> z`EqIgseLc(TiBN!9ysH)O~u02P1Qopoj;PzZOaZpeF5&KwJ-oA8&$H9Z?p-_9Vo6; zH}UrXM@AP7lygvAC=EGqEsAK@C%40A14+9+-j4s2F*cSz5(waZ22dHKL9ch0^sO;h z)wq{kYUe#6SKTkzKfOIJ_))AX;!nB^R~BK3H3XV?8<8=R_c)9Pq}e1Ib}?ywE8`X) z#MQ14j-lU#G31pHS%lad_YM==H+Sd)^xT<|Dsvl0TsnT&&g*u*3fI>7y*qCn|GYE) z1^i=k$h5ddA@ICBj2e(5u)w?l7zYS>m7+m#-B;Yf+USTo=2fAa#y;@pKzTS@D2;h_ z{ID;4aIY9C7IKB!*iEDy&X^9tQ)!Kpw+xpD>P5G@K&+Dm@;X_-*U19L;$w}yptr)n zSmO{C(~mV~kkNBv`M;oyco^UxHNn3p09P6Ft_N6g+84pk0RK|P_eHgL5%ic1i$Cus zoa^yo9{Tk@=G_d{z1OdU|26QpcOaB7`sa{0dKg0x4Rr~W;0gpu@CK+Elmz)2|GO~{ zWUN!myUsRu)Tt4vivkG095gMqwr;J3z%VHc$Q zz?ioTzu%AFm&0#2;V_>@oTH3m8j!=9Qv01p_reR8)NAEdD8GfV%8!!3tSEZ;nh8QS z|7-^o7U7ECpt{&ss>rz}@J;XqQ5OHn=xSyPE()2lcvv)S?CcIb9zYzC?5T8xk09@t zh%3@#9T-?F|2;Sf!}C_!6ZKg*dqtsItIl)g;{lW%g<{dk7K`N_M448>{70L`flUQ$0t)3))!AOi zIs@*YLsKe=8w!4{)OzvgSg%D zYFmL)13kT6sTTi^D*PlHcO)^Aw8%sHL^ z#)|mtI|zY5a-)Mlz%ug^E;D#%(t;s=>oY{y5SKL`3hGB`)qaa!e?Y79)xd4YprIe` zpY0I1^cVbTy+arS$W%Loci{K<9Rk&MX?$brsRBYz=_*h*ON(x{(u!Tesi}7fF9@0p zVF+Qju%=vc$tnwN7v?DD#8;!TOso?kj6MN4w^It-L}c5CkBNqjN4jbI5I{Zi2Bz9Z z_=xiEL7YXm5qk>SD)teyFi5lqpdXzE(QPCK=7cs9bO7s}#D5sZ=4`@t63W@PeJAlt z1(4dE#D6Io$Z}8GiA|)#Eu#?&svX78Ow&;BD10JCb`&3i9$USm*kf~GM?qHwG0Q#z zqgm}J93s2P-T*ecH8gnO20aoAaf%??MfQWaqF7qq;Q$vX@VWRSk)7Pt0+0}94#P<& z?Bx@YUF_`TUIep;$yu|#ED7GZjgX*ae*-_9m5?7Y-is_CW(FNXY-!NFz@k@X&~b7l zGU)i?69}|6=mr5Yl|kp>_jVd|7yHJ~hDu=wqJnGO9n=fZg2?A-sm;1$qVhWer^={f z?_Q!U5~|NlJ53EC(1?L|EzrPDnsLp|47{sE!^RWcX5dATn%-ONqsw~(Vvh9Kc0=cV zFjQDJY7L!R6%8hVq4Rv>LQ$DJ?=($DZSMG_ikLe)pvP95J9ix=h%3LRNX-L0n|K2N+7Y=F+;!h?8;(2q(fU-|(4b!d;e6!q{Ok zBTEfrZ|1Um48iPSGSF;-U35%a{gLhJUhr+BT_eC+_NqlrLW^Pa+qCf^Dn~&&b(epaggy%P9VegHSk==B6wD;24T2(m*XL-$#d1AE)?s9*rcZed783GPZ13p zk9Mg|3Pe(Q9gnvp9NSI&NlucRt8UAxJ|kB>FjSROHS#@3&{aT}uzv7nLM~e%KM1wN z-!Shdx5g!eH3-L+v5(sTA=LoCH0#+Cy;omVk$V zE(@~h>x0p(JOtMR0;EkoGfJIau=eITwX##)QK;qe_!~?4a9GL*_y(#YZmuv`a0i@R zxeh7IkiksjDTCQUu}X8Xwn9d87J7h6g_6{w21f@SNXjZeo-awnpWB!Wpa|jX%?I3q zL2x4eNEFoRZUd8WS1&_~GOE+-S)@U|4^p459lwK~G1__U&YL+C%pQ*x38Iiqz)O+o z?ZP^X5zZc_E@FHN-s6!({a){&&0;;3+`L&Q-$aZmwJ!pvn8a-Y*Z8 ztksA`%(y@DJvi%24YT(C3WL1X`y2etEWQtux`9bV7fieQOxCO)v z*$8nWWb3KT9D7_qQ{Y+OhW+n1m{#{CE7`PRHK4czfT*Y@sDbXU|CO%$qHo zc>*jZ?*d0m_vTP@_3M8SVui@M*_YXJ9^bdHXz&4|VdKFr@w_pNs=RGUkCpn^@f<|d z!~}m&fuX_{ly+Cwr)V$oCbE;;2YPJvPVPK}66_pyq?9rP zv9oner_f<^_+tfCBm@w*R#j<1_mN$G5akiWa>x`-CH(bD`d- zVMiGFniS};wog6+kg4pG+wprl?UVEIJr&4xrRUgMkmUBl)HcdIF1`bx6-q0sG){O< zxm;Ylp;C9%w`0hyxcRbQ;G+;Z#Dw_@pxDlM4w*3biiX{CJ4OIY)aVEtRhXk70zt7C z2<^mH>-7R5j{}0;abkr(2g&s?U_C6Ew9$v}lLp=f>Bf!5^u>HI_$}D~FI4?srV2gw z)4MfT|MHC*X3;%|q@xU>AGP z!Q+J!XIU1A8&?b~i*;U|g;snH_a1_l6J&-SnpIF(ce}}KMFV+O9Xf0wZZ`=mD@9P@ zKok6GQ`DzU#1y>?sMTsyv=5>5O;O4a#8CMH@`jBm`eQ1<7vOCgPK7ESdcSa=L!VOM z9|y|drQ3m~>Il8>!~q+2xKJWzwHeQ<)ISfuaCAWj{ z)!x-}6hh2f3fut3`V#z+!1L78rK*ywgR>bjIuic42$!c__@f`;>|r9^Xt6gw7*x~f zJYVJxX6r?gC5)O5*5m4IWg9FxNc|O8DmdAyGn_5eVdptNa;w4ujJ1kTAX$hI3Y_nh zOT|&SvZ%77T-gRo6a+=K2&-?tLxhMJj4Z#9*FJ1WFwcGXvtVjs4sJ8xQTE<1hPujt z$`I)!E}$Yx-#iKND6r9(jL?C|LF~yQC*Jtso5=wKNl~k@%_J@j%gy9EQnk&Ig|}OP z&i3JBP&L7-?&PHg^vc2xLf|ub2Y~=y{wUHcf%?pNAF^Nw#>>bMiFjGNl04=Z;Yu!% zV}x6XfK-2rlBI47@t?iTDie{SA42VnTB-RpCbG z6IrZiFbRAj;wn3NRViE|i%j6FT_QelA}*1i0vc!ouDY>WVjRulRo+exxmb>#;kg9F= zG~H(bI`cGr392So)tz*)?DjOlHLPQxJ->%EOQ1b7-na!rFi#UQL?T|+t|abh;z}-& zr->WhfjS^7_z)qI;3r+~>sp60)CY!ovW?cFf5)K3a&>dOC3|Ub>6Wp{A zNq|z)f1h|e=_gWd8$#G@IKMO;{_b&VCH=~ zj^ZLrt;h;vR1N1($@TaWgZO6Pb8xNYRP)qbt+0hcXzMGyT-CphTCD#dwfq}wBNr(W ziE)i;lqRS}2Tw>Xb9Lq`^u?3+0sxr$3hQu3Hop^szUo2Z($RY&6fb_fS268?S5JPp zskJYDyvr~&=WBK@T{-o(pG&`20i^Z>!xt0{0toHQx%B-5YFKrA;d3Uy)ecghED;Ck z0nlTs9i%@*D18ShT?E8IdJvSL$~PWg__FLBt)itwJd&7ILjG#KE3j|YMtm&e_c&Ohu>? z?^j5_jQ2DnBe&7x!zgr%+|zA#8e!&N_{u*GjT^CekT& z-q)V+-1W(+opR#UjsRqEp=ON7ZI)k;8=vy0pxPS)e9BTao)h^FkNMti5e*yTUF3Ts zgm1+eejh*H2M|@nrI%*&|0(E2XXqumA~M-?pC302%~^wO{*_a2`{sXK0i<^G{~bjG z*>djCxiN7^hqR0pDN^4uL9g}z__T?50B(jJTkQdO8lm((0CXjgP1Eb4#L5G30>K03 z4GmSY!w&4m$!44Hw0p(-gY(2IJxQ7fap?UMA3}I;j z?`zR3JNm#^0~ZWd7BClcfQ&3xnK7k_E;b!Qu)z;yA5lY`Wq&z_^ zk1bGQWgQ-~3a%F}lpq~_m|hN$-CC}bPzErslOyjI@wIPNSI7hJGYCV*`xFC(i+!^_ z*tG(HkmeIUX(rq#ydTC6FJ*aUN=D&V5zHPYXN2m~5QTOClvvps z+iA=aJW$|_B9{$8#z(eT*bYba;OHE=5{LvetJ&=?Jsn5yKN&1$hcG+Dy#n5nuJ$?0 zNahH+-)I=Fjdix7#R3m5kUyY%ID$v=OvqQ^)w-gE!;^duYXF42^0p$bGTvnjWoD5D zC@0Surg4&1Qz^hZJ^!(kf{vR&*JxX8mN~@N|D^K zygggQlbYp9`s+e4YqKb?fy~wPnHhejG~J)|dUr|R8pkRu@=#a3%1dIO z8&5oLuj{G^bx6$j2Y}U@avA=IXgFm^8n{k2sWtE8%X*Nku^GBN(i^`GsGt+F;#=TFgh;jcF=&{wt{T@RBG%vt3)YRdPWuVT*azk@TojM2Zg7> z)k(BKa0yW&=UTH!$Op7kG;I8^>+Ax8=~e`ud@OkvBElv{bqvB#;bp5;9XUkh-XO{pL}9!XN@5j;{IJRz>W&#Nxw%diX$~kSzq|bA@ zE8$wpcz0Sb1asjaLs+_S-fz(>bK&sSz{Nw*d<^p@vpc!i6#QxJ!g&fHQ`w!r!0+*P zCsh+^Y|j3GvBvJ3Ye}&2^wf6eQA(97U{u+jhp48*wTikhXoLP85N@|k3E7~35e*w% z^2)IqmFWYLKBl}`dBFC>*r6F1Dy(9(cIe@X2J*V^kR2+XYgdv-5t%&HG!L~c>QgCV zi~cXLdaG^G(-2DE7Nv|q?2|qjYw;j4m*rCG-*IUN(EEs~> zp~w)HcIZVGy)rwLuZBc+C>NQ6KdtT1w*zDEDY! zGR6$0AgZj;If}_}jiM|Qnt}L1KLyCPQwt#*^y8vozP)$P&IDhp@-zy!E$6Z$IT4Y6u2 z1Ee-()ocXk?f><5zHPY6?ePob_qA# z&V&ms<2`7>5X^8zhOjhTzhKcTGhF#<;IhHWaOKii@Taxm`V2s(GF+d<@9i{P@nSg4 z+yP4qU7|9m-QhR+`*z@7u|>? z(3U><>*L2e22nLJmg;FRR9InXJ#VKd8ps-^Lzb$1EgC0^!c6TmL9aGbecD9K)cv5x zR-37-5lY`orR+d#ivys<%1nJ9E_WwauT&tJn%kjp7Y5p)EGJQZd(jy!*PUFpBrI1} z$I0euh3$pfsGWVvj;>a5?4$8k^euQR`q6y+v+2im%a@6K#t(H2PI{*~LVDlr0@VBN z_F<);0oXv2iR||$<_AWAnrM+9W=#|;Kn?oR5*}Gh<3;wjWckh7VRQB#? z@q0V%-Irlpi@d?x5_32G<7CTybC&}a^C;G8xKv@~Pzf9~=akFE#VfMKs`ibteZ*9` zc`SViTF2iCQQz7+zF#zKJk%|&Tt)_!8~4Nnq+wf@@FQ4}_s&?o@FQ4qJx)J(1S{}4 zNW`B2Ey7Ag`()W;q=EI5WxrMRf7wj5Baek!rjCPuy_?5Sb@jtXFg95K!AGz*RO&9D z&z|Iu;4J>38l{Oxu;}3NVvKL|*pp?CP+SD4HMdYwtvMCJ4hmQ0Q;Ze_r#p9BLZZzk z4XlZFtg3$<(OCZhqU}Xw4WAPGD>#pZs&Sei8y!9&+0511+hxAE@*W0))6Hr<#oJ{U zD5fp1hBjVbzS=M}XK;3XxpL}lzrK7#0i<@HKCEaEKxk*)E;~4)rB!(`o(XvMHr*#p zWSjmK;L=ua({Dm3{cSp32xOc7Ra_G`@0Z;leDQ#D|743H65_sE;OSEs;O~=1pYSKN?V>bMiFjGNlK6XOT*-0IqrMS4<;=}K!JpP{ zy!kL+l^gFA{N7GC-fH37B1)?jzPyF$-!yw(WS799i+|VbfZ$BHNgDnfRDGx@r*RStKrcF}&_*Z0Wrm?SdoU+~a_Vh& z65OBwQtKqRR?%P*I0@#em%qwWaJ6X$YEOYrpNOa6Z0NDoo`PEuO5amJR|DBhy%b8U zJOy+o0S{T^$nHM$*cog!U|-QIPHFp(oh5E31f=&Vge~KJl7Yxop-Fr9bge`r6#F-y zViO+j{u+#}6M)EL%ufCaf(f?);g8+n?j^fKxcdi;wQN^f#`~@XLohoT8N$*|{-Q;% zEZogk0|(j4PUb>S@Taw%{47AGvXl21ZnK?yE?SqZI(oe@{c~rlWEDx^3c9Zrqr>VX zc>0LLy`eDd!qZ3nZf-@foUJWhQ!Z(P-h1rJ^2n|6zNk;(cWk*H4df+w^GocR^ z4I2-3j|q*mP#MpsHbEbP`d%*(OP!~}9N0GT7vWQ<<-LEH>tYWOSO zk&6lKek^WBzL3kqV@V}AXIU63Ws7+Ba)jN%i^nio;2hfQC^;Bx!;_d$8w;XM;8-TW zkR5U>)jmcYhXmqbA5KPw`+BKa7&5N_gj~5a0FOB>5vM}I8VfuPRVqsndkhNVtrs*9 zh`rJbfI@8oyLu8NHJE4DcJW-8v4rg4&fdA9TH|ep7sg;S4F`!${MEEbjw=xsq zFw#j}CW0v4or%yyCIVtl-r&cZ#8fI}yh98m#TE1vtN;*s2a~Fvc0If&c1I*9>A(wH zkfJkGcB}NA7BmbBCAfj1lmnaL5_Z0=I^yOEgQHFj+#zT_P(6)S0@3SWKNRtz2Cyxv zpo3-gjb;S#y3;ot(FP&jc(#WNq~vIJXl&oAsUg$?v2K?eaA~zXmXJ>3mWL?4mM1)Q z43}c=jn2aY+=-Y;#`&L%1{#j>abnS>+TEA{d-&*NCv%c_d zm+yM#jWyuP*oEnzNk1#>TPm)`=0Kl3Lv$f?w2YW1Q6O8Pq%cfpe%kA_q8lGO+fAL_Q?}*cYhN&wbkzKO$ep$ z?xu@@II zxy^jEdS_rCQ7_Y~Rx%;uy+9u3VKD=+x&d$0>}Xw%A5~EhNvmOkVIy9fLA#PP@P2WK zv{I%o;se5O!Tv8*_5TNG9JxE{=kO6Wc(i}8T&FvsuGq+dxsyCW;&Xe1uUne303DFB zAT*aNpb7XF(&Z?A0c3Dv?~&0(RAR3|8}VV7)39P#3nT{>g$yTWSmp;?PHCd#ps+a9 zagbD(6O?n1TolCVSklSeLZP+gpbx0}*KrW-U&TRen2xjJ*oE0t~F(Dk0eK+8vkJS_~eQSaqZoz^sB=>Uy=K&lUy;pQoK z%!^y3#~Q}vQk(hYl{0UqrzD^RqE)j7e#cJ%)K= zF4?}pC+FOLw^oDu(yGo@NF#&ly-|BH#SV%K_{jv45C>ij*Z~Z%3jUBbo$*@%>elP& zw*3@guQJ0zN1_F6pZ4;N-!ZPy+7&E|_d- z6rL8SLK5bB_wst70v8oPx@BPioDP_Y$yOUPfdXli+*p=;6MT87iUgYyFTe*32$KE& zC8$gM{X1sSB zP=iQd`MK{PRrUF~YZ)gfkC~FB5DR5|t-eoF!rosh#sE@!6jYROML`%&6iKQFGlnNpd zuKGU%;*4DN2Q62L($UT#PE5GbK_Gyu5f{n0`nLw+M7UZjHF+NPTP=EJ0UcDj;n;+1 z<|6=)LIeV4cO9wP=HO&sMZbwdc$mF#B2+cm3zG4CGP@go|z^ui_v!avBbrQ;n{d3E-du z6~k&dh)y*X2Tgns?TnLAGzcKRGf})T&`XLa-mNBR)lod37Lh34l`v3Cqj(58`XD}ssdzoi#wB5vtDpoo zAjT-(nd|ABMdBs$3KUsYIZi@nv*+rUe66X zRgoYb@yp(1fe;oRdo^O)U@u7FvE!I~*iR?xg*-DFB%9|fhj^GH-+*jeU4Y-PZ2^q( zt`MV`^0qSG+b!_INQ!t#L{dFZu>csiA`=C`_?AJC$vOb`HJF4t0QLC zp__FVpL+7i*-(+by;rX?2zr6{7pDa2v zO+}boOlfd_rz*hJl5K&aLBjdLqa+cz&bT(fkMLBnT#qmC@aN!!&R4*vozS_Yf%TPM zm#F&JUFpU8Pj;o(kZP1BuJodV$D2-ei;Pe~Qn)H&?azost8rR|z6MEkt!k3G2S=_- zMyfZc`qz<)^`DGXx2i^If>dd zP;(Ek2RUz&--8^vQ#D2tw4_5Pq@}q!i#IAQk;xcu{G9@wvaU#!tJ0o$*_yZWIrSV3D9KBpD z-bgn9ByRO1D8bE|Dc*ST40xhu`4u^L1k+^c-F-Z1w$BkK3P-|`NH|T1PrvwS(*B9U z-a-vdER>wBu9GG2##G!YJmFM>54kKHD{cb=a;Gvsb#m&}Sr{wPNt7PHLoC*!M!V@)20Pn_# zj}f7Uyt802fbVS){zw!N?z$a6Sza$>c<4x2c&$M&p+sPA-c<-^5AzI6nNyRV0YP%q z<_xGC2@4OB4&q{gqO{{-VT43pj`6k{@B|49=M1QkVkVc7s=Ihtc+4ASx}M$8vfgW9V6@hOv}2WwAu+IiK#X^GCZ&=&OaHu{=`6#gzUO9;P6Cl1=puj z%~c8`@KUG5v*Z~tjN+I0$3c8HOk5K)k2&T7EEjT|GL8#<6;vP$H+x6aOCWFhjSP1H z=^#!6i_$Zjo~MAf(R?33dW0ky>Gw6DCL!rBkM*+>9gL5~@h9T&=~viy)64n;55x_? z`?8RFObW@X?O6u=7+L2`E$fKV4H%wpIc|KmYES>bayWxz zEO)vAr4g3XZYg-q)Mg7A#u99BM{1d1vyxP8^OXWM3xu%E^yP?c!)98_nc`1j3x5;$ z@J9=LR*9AYnO_wmbA09nkdJKhuD6&KBM8na5kd4E!7`q>gCtSL6L(q)BwJ@ZeG(?2 z&UpF^mb5eDX$?#GpznMyTvD%<(l3zrSM{$uVN3f5vpI5SHXAvR)ROSd?AcdDXDb`^i9)DkY^!6K z2PlTMKytjs;$neibNzzSq%+6;Pft3zQ%D1A4qB?}U&leTe-#I@k<)O{B?@RJfP*en z46EfJI@MGhH1Ws%uSz=0D@X%tR(hSPe;q5){#C5RMoz;@w<(~R09LwHF|3xA=u{K3 zlDRrdzfmgNK>AHW8UIbi{3ZacUpEZPMK())QBJ$8VaDp_hkknD{<5b8#WdkoFRd?~Ml3~MqjjT{09mKJMD4hgZB?wD0 zW*9UeCm}OTovf0#8xUvYs<&vlN|bgmp+ji@4&TL%xJbs;w-|^M;cBhae z8dSQLahjt^)iwvt9swR6u3YNV(?arT zOaGD;%i*t6{lEMwr@_Z1>o<@dPUpY-#d!Y#iIsEc#jRa_qC5?lgV^upDf(-?n`a3- zmnV^}6YN|v-eVSPhAnqoGl`bFUf!^;=`WiJXu zy!s(wWfi<#ytL?ME9t|tFH9Yt9npZ-@-VHqnx#`$M;r^(wp%IOyT{_Rj%e6;xQpVn z0d`cyYo8m>9^C(to+rh<$W({B|WwFzo)&dh?f)2G${yjjH~2 zArsoaDrCY&P7^X2RzM>=d)gGgEhvVyKytilc`?jRi99)dSx8gu}wG#$q7k}jTIr> z#U^OgAzYspkq~YM25M;t7a>Qt84KZ36O#nOj)W52FBn6(4%yHVw@)!!t)a&UE*hv+ z3U1XY!hVk*>Tj4UilyU?0P0|SU&0>=w)Z_M94jpV%_BUN|t z0OdCf^EI-<*GLC(tRPA!L4XorNyZFcF(4-)GfbTTc$ z{*{3^5w6xsO&*|plSQvAVu4E6GGcKxsoLfM_W-lBMRZaGS6rhwgVsqKP zNLY{TZ?GR#5DcL)^Yg6dvNnxs8WxqNm1hJg+JZf-@foUJW_L|FL2zpq(Y zf=`7~joeo*JP@6VBwYiHVYjHblYvE&ULhJb9_g}3lFzxSP*O(2Nj#RMts_Jm2`0Tk z;4xt^$tQsKdh8<_OsaQ;uL%x97n2_r0|~1eaCY+BzF$_Z*6^JGNKWBsRTTxX`9Z)$ zqNvktq=B`g_tUEWb&g)zzsk|eMh?t9;fa!OD4+>=(9qvFP#(?};KBCS!m}t1-=%i* z-XVXa{i(sPDTdWLdg)Z-H6|A=Eb4SCrAcR^PQOYzx&NZj+D4uJs_I|IL9~Ar2eFaU zaL|EQN7u^)aL~SrVYM7Yr<#g`CO+!4FzGD&NCRtO^ioy-I##0nt5}JRoQ9PyQb02S zth8P+td^DNR8z6iT(ya((q;#Ss&Z8p`5x3`qe*8~Ck?Dw=QXPSb*w}CSFsKoIlwx5 z5tEnB^^tkkja@y~o8Jq}9eSY}D-F*0Jqn1LW*;_!RdDT{ih;EZL?@hzff)70UO>e; zvnc0a9nLiJry%yeoOBZRkOtQL@}R1J9ly~2Rs6z64)Dt!upf%!7E%_R?avg@G|eld ze=AOTQZcNSQ|MF^a*DY+3veqp0O3uH2sP_AwC_-oS9ukz9bHVew18{Q|<- z!+cItCKuo}1_a5Wx_+n|$pyH9bN~jCG8aIUc03mVA(5A6yg33qL2?1EHJ}E0haFbF znpEAza{)eOn6Hr)K2AD_V+Bz<3334tmSoKEF#~cEGQ-r#1^BT6aYnBCk(R4O>F!(r z4{?!*H-+**6~cpXJ~vk`4OE$DAaH4T#COE3!^n4Gcaccb zUf1Y1cSa7IPCAH_TcY$Za{IGlDgvBFY!$E#v7cnr`DbgXbG+|(A=kZ^>m_(ct31f= z@fHcOD$>Xv8b%fQlfVEW$bz&4IZ;axQF_GE*eM8r8k$N#6znS*QF;xNi!2$fp~2H< zuCyRE%jiHm)iR@FkW_7R`pl38LRk9D0AkxDAtzVQnljg0KpvHv!F%M?RkXx!rk8z7zvsu>|_TRX6`4t%Z7iHiFcPrboMTQFa zlcdo&i=9&zp3GlP=*+d*_W*my(lLH%aYrUgqPa^nZ2YV%l4uP4tIDT2&W@jW48*p& z&}>B2J|GaCFw4fLkoPU@BbsG1JfV!vj1FaPgp@HuRt>8gh_t9uXqcg*DhgupCxC%O z*)@-m2G&ug->Ul8MVV;-swfj1IWYHx*)@Az8=Y;yeczt!n(2yRwNWNI)p&)R-n}w0{)`v60ho&?*Hq6Tm?) zQw*!+AUf4l95nISHRYtU+(sH$v(nY7{&lQG`&Y3N8#xUty+r}d1hCQ@6~k&-iB2^Y zD?P7J(%O0|p>&9<4Hrx5!k}RK_oNg3G-+VXOuj3}#zlxjK$U$yOmO$~S0-ENz z3CFfdp!lI;SS>dhk+5Orv}ruQs4;ypr#So;B=4V9BVPuMv+}gjC(#cd!Qo*X*_B7$ z1GXT1Z1Q_>^nI?2S`yyn;n5p&s`ZhPa;3JVIt)&x%j@NuTOGRzff|s3O1QYp)mc7? z($sBxR>cV_+~gtqAwn63gyR(rWFksA&J&qc@f|R$6j>F=nxIu@Rrs`sWL10y25MLr2rx+k4@+ytjP{0$!6a7j9YLItWioq*L)m=Qr z;FE^=8d>3X(m@<6h|)=rVt}wDV}_3!kdu%ZrcR2%BL>77x#|a6t`eoYQw%)BMKZ4b zu7NlSx%$Pb4KaqZ`PSMu$>2ipW$s|MUaa9`<$Nd8>jiQS)O%>=IaU`6>x_8d_qaZ~ z2a?TpBlA70Wj;}QjLifEXbr3CU|C}S$q4%Qqy*KfK^_3V!lG9elSM1aGA27fs0sq4A}^AB4q2S%>v-uU{4eP=est6KW+9evZE?$y`Rh;-1QgyD3lD*fA15hNf?3laq7Jn`-n!M3lqkjWTKtA+u=@_eWK{| zr$_^97yVaN{p(!xw11V0o{b!I(eqWUxNMe0ri1+QhyohfUTV{g;y+Lft98-Ssm5zF zE+JU-`Qwx(orymGJ?Z5BLZP+2+hNuX3J%qA5ba;ZL2TqS9ONjVnE(#zQ4Fi)AUf4l z9HfgrzxC#6)2HEoRLKW0dT61<II|X>gq`O*-9|kOtOL=>k>%I-a8at9Xiy z9Kb-roR}d6G!wv6ImNJAo}yDt#ZwvBLC0BXOb-Syc|fo}XQJ@uAosj3>BL@58d!7B zJ5>GaxQF(y;vP0~V9tA@;=wlZ{D5j? zUF6v~av<`&CvF-zuhBn(7=KJPeiN~03Rc1uWv;IbQDLU&Lhgqv8U&EpnTrhG57wC?>{u&sl zr6G5O9Nk?kBt&}?l;GCe7;?XyIuI5tsn^Q%n*Kii@H)M;pS-QUwOEE=e3hOm zz$YBtE8JWiUsmsPHk6%;TdP+fa?eg3_@z$0>XLWW=_m_v6fR{tFtQM7-phcv;Llls zKN9%zdb-RXL3m{;LqbQw`Ij12ndHsA7~$+;-is*{&fji8kR0$h2kJ(``4!Rum}1Is zz9{W@I3FRA*J8ZVM{jHuR&UvW8sr@o&M%UxyLdSNHp6_4tZ*yoAdVG8=_Cl}BP_|7 z;hhHLBxHuE6VCsZ0dYpIx?jsxqI7pS-$Ps^C+a%E9v zN4c^MjL1G`MYag`;e3Y}pJFg#Acpb=!tM{2F%bSN3_KDm`J(}OM$Z17ma|3an9#?Ni2)vM$Ziu4&dr=-rv8B&1N%FKsJk$Q6- z5Z7*Da91)*y}4R6Y>anH>J8^URRYfJC^v8irK(6sR$^e@B9N6Z8OO)6_eSg^nvAom zl`P3DYGt-W+i!dLFibE}zRd?n1MAr2XI1^{Vw1FgRcw-t9EeRO3>bY&0gY^vwJG1` ze#Nlbz$Be&yvE{Uf#uu0m(oPZLDDr1#`{8~x?-6zPM3><%k0-lC-*dk);8bf8CCx} z4x;_5IEam$hJy}%b#%Q<00-@_7*@+cbgHR1NSANZo-~`&lFssE(!g36oules$4az+ z6)Ulk)3DOT3TP&Pl{P4b)v^+uYC={rS7%89N@bfSDd0NA{3ZacR~v@qBAX=zD5u@_ zq=4HLKx$t%c#on%0GXXh3V1W<1VvK7yG+oklLCBNM3MrofPq??6o8PU=Z7T)Q2UYu zdar~M+!Pp-0?s9yHK#D>j8w`ww+c7OR-J6Iu-%1lf1XD4iNCj+-R_e6Oqp|du$Udf zy6zQ)YON{`=C`arVHbGc0YZQS-~s%RzyZ+HmAe{3-ES~dbR>-bq+wl1uE@s_&K|b! znKEJgXAB6EV-f!Wbt7T?Ka&pPVz;8S<6(S+L|&2cY8rTggz^7qKn?N^3*-NuRNckH z_%C>k-oQ7q!t+T7ajYOpCqWn=VM)deM;VZlkQt^<7=Nt+aYn8>U&~dZbaxovLtG@| z>X#Xa6X9yD)a0Sd-&hDv7Rx}TYZ=RUl*-s2!#ltHN;H15^-1YlWA^xM<9CjKZs!f- zckgWMyng(So!1MOj-p7IZp3r?8ViK5(B+MYZG*kAJ9G&TJroD~hG}jF+;`nKi#fL8 zf(A(BE#+J%4@n#~u-*sD#bS8}X7NG+_{QDpqFM8ulehG5Si5fB@@4S*Dg5^>tCy^~ zaLFq8w2*w-(!XTIa`@|1|1ZDFY4CB$`VFLq)A{dyF}_jn^unGZ0$8bBV>^a<{(XCm zE)QM4BP2xPFZ~{* zq04oFsL*=1S}RxF^uf!8se_l|f`77dIbf}f6?OIs{Qm^X%BnSfRd8fm1qlqHN_`ndLfiG6f)^m6)ZqnkCYFZ&;W5pcoS#-0vT z^{)#U(Ee2c12%G+fWZqC&;*>Z?YXP|`HEpJkQ}eHxN!L63}DZU_g6}j&O|R?mUME< zNCRsQx=7W(j)Q3bDh^^Jr{SQY0-6cnpuA#OEeFx5rsAN9k6ykp=`3$14Xjz|J*xh7 ztVH`)u@W0O4J&;{0nG%k(kB(eYFUX+H6bgRtF!2(QrWgWjQ6+-3A(erKUOpd5UVp` zykCRlSA_8%HbJWn%y1GO}ahmfONh=uW}p+y2cKY$Xnk&R)ztKjJ?IHgM? zbks9I0(&Pp*+IBa8=L{z8l2rFn;U-ZHk<-R9{~pT2FN$qvsYc0o#W_-&-416jc|a& z*^zfkPPqbSe&I%7uVV507=KBph}H|!qs{aq1nm+b3O zc)A?n=W@bcF24KfAOwQp8yy4!Ozs5<*BRWcXu%N7y@d>6>E1frqF3hL;;SK%dy5NW z!JpRdtxEthwR>wbmbBBowL0KBK%t)Aw{>c2-`18WRNdp)ssc^z^bX&|KX_bhAI}9WcSL+STrE#z+I}E#!w) z{p+@nw13qWl8u~Z3we(M8rjHbQ#SrxieW8~Y~B+xf7UIOCY|wTJ&|;BKc>*ydPIM% z>R-n}w0{)`v60ho&>pXgu9pempl4M`m^l;on8$7&%O3~-dN+@ujr=$2;-phe#X%GA z&pJ+lT3A3p$37Z!WJnUs(R}=~=|@PMIhtFlALI}K}Da*TZ%!R%q1mfeoARXW$4*eiC}F?N5# zMV9ftYQYf9F@_9b=@|Q@MX$^;##cik#~7FDfb|Y3s=MhlpAWZF z@9yWGd(QdZd+xo_$;C>UR@t_4Z$+2gtkK4RtTQ93mByU7w?fG%1F`umqKu9c=ZKOYmmdYk2Fk!=UzMzG6v8*SK8`+&WJbKm0 z10#=&d~w$`yRO=Gqr@@?jxpi9a+BF3B%)1Br_qUjzkZ^QP%SASG&arf}>H$W`csegkqX#dLB5@;ql_r&K-*hpXD)nE#rVcOS25YE(1oU^hQ6 z1kPc=N4d+{i4cXTFJwD$fiEOah|Ba%jC#BoBbTy-?|$0JXn$vt>`Mx^)NM-6^|Oft zsm&2yh+1>VlyE!JrLR?`GMcv|^JB)T0=R2;nmT^R{yWk8M0=J0z%s<%9=KIke%ST^ zFJHGkAZl)9d*D7zYdlM@o!P6rS5s~1_5kl{u!fV;LhMyu!^cF+L4JWMxXnXFxlE*_ zl`~Km<(-4Ol6LM1-rBf(mCxwP591(SzK(-L&7Qs|e5K(fO>4%0gZ`kYHk5;SS6kws zvEQpa?A-~4(ZMW3Y+-b)uKX}o;^pgDNz~j5E1jlk%^0xK>onDdvJ&rVORSXgz8=|U z43tU*V~IiUM(PBT|8>S#k2dxv?bszOLu~FD(v=^^J-mD!_lTN3+%tn{!o}{7qz4_} zM?eWY(kpnc)wE~S{KG4-XP1ZjhDzCb!E9JxJ{KE;v+yBPNLQu z3=~O+jX0hpyKGNiB6Sb`6-ww2xgU7Bu>n$eiPjm2kA zL{uw{AhG+e?RLj^|6kNJGIaO<_nHhIVvf)5|8^J{n%)2Bqgt!q{ddQrY4?9KDr)QQ zKee3ZmbmVQ!#TFS{AR=u`i{Kr<}o-V@{IrYE#Bdw^%{JGsE-;-p%-uEn!!7 zM>=0~UbetRI79g&f8`iY5hKQ`SK&n|TsxJ{gZ%KZxls{B&6K^9RvyTt;_ZsRtwDuO`juI8ag+vGNJ zHY)%oh}Lbwi5+*h32KQtAA=1PvK*^0$CgKshImJ~O)OKT^@#pPvchGofFM?I zVkdyx1hpj@GZZ6;laLv9AGe7+BM2ACRUZoFDkpZzZNeg2B;)E^BL*iSSAWdAa6wi|XyC<$A!ZsPUb(;#|E$y&Zy-gCf{-pmr^hH&_!N)<8q=rXc$T!oE=1FB zifudp9qoy-ou^!gnl9&@db?%40!xm|_1Ib4E;enlp)}d$_z2 zE<_S-CvqW@OHa-ej_pEp8v3huAv%L%I_W~RN^!&3fF-Kdul78(We=i{_}esQZW-i~ zM1~SkVq<>DEY)ip%*fOd1Cx8Y-QC(f&Rr zk}IW6-yI{2oe(k|8YT2Da*1nYsf=dtq8la*8w=xI>pRkM@1rX~9sgot=vLwmmLc|* z?G3u}!?tXB`B-q7Zus^dMa`Zq+l0O&cWPRrE}eGh8ov)|s*OS9VC5)9iSRzE@-fkJ zkm6CqTs8%_d8nv!F%ld8x+w1)eKcw3zRFu0*ZXKhSAG}=@$z*XBx?5bJs}7EQq!6- z;GkzU)rN8q?`lgNH1^&{v)`Lg812O}#1=+}>dFseC0@Rcl|;?0u+kz;YsP?;7HFys zWhLI#mRM;_ypPr;?bvxNLu~GOv#$Iw?&0O@xJT6N;hx0aM>S1*M$JD7ypPJ7dP5l~ zk`8gbkKU`RIn4VgvgTyoM<3PIKML<7-mI2p)Dhv(NT=mr5tv0<;~^=$I{y(JA;PY> zeu!nT;turVy7I#YT9oe{PQr+?YctpnZ!ezG)iR3V{8T4~b?XEJTKJMK(2?|m8zBNAJw(W-Vf9j~8~u|u@942K zcfW2&E}zL^IlG9r)AC!3=>lExQRY`u(?4CWveJ&CK^t=Px*AebL~|BAwT3o$F4^SH zYjA91HRHW^?a~&SkSP_jRrNY-tb`3ZZ9&WF)pe&mv~fsJWbw^HDwR9UU0dY_T(;`6+s%}9pRa`l_h z@Bvmp5Gy#b6TmZ%+LDYJ8WF@v$PBxWXWnBGgp1^=uZMD#6FcRZXAv!uarIXt1}7m` z?_QpHFGLV8lCyss%GplrMD%@gtlf#~nMc%1HWz*!F`NnK!X1HYd#c0g_H+U6s#{BD z)flXlh8PUZ7xC0`k&aqjB%WNVmdy;^YFUHJ1;J#FM+pM6!&kt`1$ty07`h6qslrr( zs9P)PA&x{TmLKC1tC1e})R47CvGo{|!eI#JCGd)yn-^`=HJHe$aR@6Q$dqtmuaZuy z<3>lP-}d;o1)!5ClZ@>Tj2NmWwhuL&r9)~q#$*y6YJ|IDdZ?{qNjvP2dVUOo2*|jG zs2u?rryNq*Qdln**V46mbwjPvJLQl%u^mzed_pAJA+{E9NQt)Mkn+RsW(x~iUX%jV|N>Tj-HdHHNcd$5I09Ox30%pNjFODFIKe| zWzAYTU#K?B+Tu`*5=By8+gXqrf^e6V}=KjcWo0EgJ z(?B~M??%-!q&>&n+8c7~?3v}^ zTCP-VPat0>O$^6ciMS51!^9QDun0IoD z*?Z-yD5!BgHDP0}+y3VGdIqb^*Nb~-vZV|jnxk71@H|7Ju0mE!_mVObK*}bX?2TLY zD|uYtvIVp**?o9w;Hx8F*mdp5!@KM^Bx{BBH4+Om*VGzmqVRyyqRB>VFl$Xx*q(Fz z@yqB6A+y?d{PA4+UM?f89}rFWCBd^~D%bVacE5pIPen{9qUtcxeLqIJ>SQCi!cCz5 zdnJK=qQcMLxew)TC$in7WCvw_F-c~AuPQ_OPV74^jgza@`VcN=8a|yL70BHsNo8;8 z!hdQGy$-!(q0!shyJbNaUFw28b_35vSBwldHjFZ}HgE)&ZSX74UUJUATh=B9=2PC^ zJ-G+G9~>d?A31wgrc~IG&(?B{Rb4cM_hShE&NzQmWnAnl;~Tzqe9Qa0CpY5#piKB$ zUunSVyHus5aat0A?HRVyFWqcx){n&IOE$By*t}&kw>Elm&fRJD+BUa>kKZ%0*Y-K> z>Yp@7=com`GLYF4$2OX6iJshV?LErF4Kg1Vf#R^FVMR-APQ&>$SYo~=r zRf=T^ht5xe6%XU>4i+4XMj=q=*$HzwM!Izgbs=S46r=gn^wZaX2v_ zM-vW-QQl)n$K`u)dG-t_g=%Bf9yI&!MTWm=Od;z`OuDox1FW;~#X1`S<@-4D{g)=6 znnUvUTJtJQpc^J=pUA^mSW8`y*Ebax3RzypX zrOv$&t_SgNsvY^$nHNmqe1zsktVIv$I{OvW0dBa%$!LFnGFp-1fT`!9^F+Ygc|w=G{y+?J>PyrQ(_1+^{PwX0Yi zpEqLKc+NB)qHPLGX?f1lgd~K{4v6(q^!uQwf9WXnl*@=FgGOFk;>_l^S#rzMzvE)c zB0(EZm*+?4mEtB&QZF%nr|DZLF@DW^7x%o!f9uK*JMSUNPj=p8)-9SL9mRPMUU{$y zAjNUWNFNolc*~WEZj5n^E^x_L4sK`~@2DQ7qes{&p2Jy&*r#|F>&g!sRZ+fYRQF=4 zRrXH&^7dniuAWhhE3dw#aXkpL&~E|gMiQ5Esp(|*{GYx3yg=8_u<=@-Y`n6%^25eU zlk8ak{ChYjpO_~g<(s7p$tSVl@ z^(-&c>4RrE;RY6u3+lF-wTAtge!izsUF<9lELJzY7R&Q3i&ZnbVef?%ihQ+D=KQ*O0jOB?j>9ixendKU=9R51 z=4xh=v$T=BwF8>#i{A z`sMHfTiE$`467ens!BW5D?u{FEH6_yd%YJv4$-!9kaon_69pVFu%DT9k$ozfJ8Om` zFz}(h>&z) zmnvpfv&U}w)K3e$)|;2r;p*b%Bi3V|7Ix8%Mk|YhB~3fuWDdw!(M+CciIW`-qZFH# zF4JVkSBj*V$n48PtmWj_A^ck)gQ-#FV;(syFOyMq1cLQ@t{i?lTIDb|Kn~a|r9VHccyi~r z$iIx42sHf%hM6cJoj+JFX6VN1zAi2+mcx|TREB&oiI^Jz1%zSR#uDBB|Bd(mucPgM zcToS~^Rn86Pghpw^D_JW(5%AeMW#~r>Sj6LQ2IVd8z!#FiYA|zyc;uf)m7n91|Ueb z06fsc{9JRjTDcbr4gf|vx1O1aA9 zhTQ;C(2G%1GqOi$4bIkh&GwRUooFfSIwC`9_l*2EAl0AiSmm2181UUz3B>=(rXu zO*lU(7!bHm_N-P(7pp_4lXcHZZ%^ZWt4h8M$Xd$sBVQOr!obuQ{vH-S*MNp`PK;Wo zfa10hg0YW}3Q9faq^sl*?IDMU{Q%%|Y>eShO|LWHw%~HT#-O*q&Hi$naTC>>60n0B zaC9Xlneq6Ru@S&B7x`{G=j2M5R%%Uz%W0~6n(S2N9R$WGY>tZQNwA%$&+2xOJVw`G zcpuCJ^AOc3Bx=)SZ7Q+#8Otq*&N|+m$kcCZj(4IApW|ImE`jG=mHWKOY2mQw=)Lcn zbcS@t6Ea)lc$XcEM({y(z45kmw9nEAo$If~HQN}tzDQ$*#dFi!q{*qma%C;svyPrc zK6jlx+D*^;GHhMue8<+9xdYz0&Ki5KiiGtC2RsgVP3+-#eF%DN?*9P$dJ_fd}B*3Q3WI=SECKkyOYrS+mRO!gVA z+V6b8oJB$FZlX2EyRDb)4mv9~Wql%g(3!*PN2wLuee+|{SuAmellUao8P0A?so*^^ zDiFsxZ;VdL9zwZ3Mml$@hf5K1IX#D!m&CZZhU@hJY}SH@e{VpM($tVjS7U2b#=cFQ zyIsp;TR`hOK@cel4-Kf()iBH)`IUxe;+Z2q*W`?2j{Fh%S~f?{AH6veL>E$obWULR zwo0DibAFyZ2UdxkRq8Q;x!f#~Q8eLF7S9zfQOG}j#s?e$`;!Rvk#@7Z+y<-Ko#pj~3u zS1i{>ST58kq07gwQGR7qRRy503!S2joP4Q}x_yf2ObsK&Q%t98a>h|itC6o|#k8qC zipe)FQ;?ZK<~}yEbPrY!POqt2X*OvkG4)awPZus+NFDW~JYny@HiBuSIy!|nAy^$P zOtMoT=S8wiu4>v&9Y|TV7>%D&O_#->5~(IW#NpgCI@R=Ut_5^^K(qnW!V+vikrE#1 zqBUAdKqX!3PPNakowki(<#P5N8c?TCBi*6lpLiPSHcier8tD_r*Rn=x0V)O2WeO_M zT`{+?QH3@-3{Xi&Dpf&sbJ(Oy#vv3hEnMo5&iXQH6*}vE5o{%O)_ZtEgLT%~ZQ6d8 z6RK_HxteYlbvtD}8KcWnn(o^%s6?8MGe$VijZV{vT}J6AAXf`oQE~pVq;69-NU(sc zUhg4x8T}dC+X%k`+tShMP0r3P*MqY8F`*?u|TTm5Dd9cMZb^W8mWq&=gkRGMUDeXxzdV{lAI`Kx2rr?6)mK0 zr>x`gXKFoAF1~8~1Q}#ME(VoI6>-K0=eg0TqC5v(Qa-@9svQad#Y8Khi#u1fU+rw@ zK>y?%+D9qdr)M^3hBuy`S*ytzN6)+&`C7(AD@MOcr_y3d#gK|w#YQrjis5;}r#q>b zGRhVz=9~zIkt${dZ%(j^xsI!Z@%2)bb8BKW##L_bAcCi?x5ps%6wbOP29-#;ah43{ z_R%S~E2V}}oMPJpwloDsE4<>^Hpj07w`x7VTT}NsI>^a;h_*hTio8$5B=J<_y_%eH zROFYCuVodvwiOkrA==ay7PE)%W@DO6S@JyL;)9gsw@|iFmLH8^9jPqu;>`(Gmdi(j zpZrH9_K^J@u`%oh6CcMluI=^*oEu6QOlclX?x+>{b>VC?4e~hkAsid1@P>EC$XOM8- z8=Xq3`#^_0g5MT(APb9DN`qt548L0HcNB(fYJ2-F=h^{H_4qW?*EEa}PcuEN$r(p8 zJ&t@WYo=9g06UWMQ%Hv)od?-?CR0s3Pq=s>)$|jTEmYGNBG^W%rqA-`1goaCj%sSp z{Ty=2w7pzcMg57$kh1;|g9KA5>OW&piBuG4lyDv#or8f`HXanEr$+n7OU)fw|=@0#0HxZiWS6Wv# zNk(6fI!Z06yo{(;_!L-O!)x&n+hv-ZaTM59$k(z0ySR-C%r{I^0FD8;AvU~FVi8Az zdAe{RL~84OC{L&@D}r;R+SZ#` z_p^@G^vMc)KkH~s29*e|g)-*vXW55`PIbIFUNHx=rA#CD7ml}6mJ!t({nJ|RST#MZ z^-GLh`<~X~_norWwcbcgbzj%wJi;uFUkj0;eO*g)n`KY*b(RN?+==IluNrxPD}-HF z?YdDK%DO1;#JVtosML#RaCsv%?It9J&KI5W-|EOO-^@9eGTN&hxnL~9(^4&7+0J^@ zV?BR}d)=ohErg^GlpjM8-L(FSg0Hv!8=KCM=`V)~Zbl@y;-{)HDRV-_UM)6(rCSb~vV#y%~3|4P#_8#TohWAnTrH~8O zcTk;mCjMp59AXcWG_2+H{k!yi1^#sdRr5J|kC_@J-umk1vbdF3+%Hvc15@@F+GrZL zaQR6<;{q*Y`*)MlfD9x9vzQ{ExIe*TBm@-ZxoT2_3j*&l6-py8-YZys6MJ4sV^N@l z=bVhY1v$GY^?!FU^Sdaf8ts->^k=UVDpR-Z>7i_Hop~PNYdIF zf!M}S1{LXyp{?{i*ch^STU%Tt%&Pj)x8C1Iqo_l7l(xEbxHM2a_(>tJTl0LcRd5w` z^O|Dlm9xTr2uuJ7Rx4K}~h-56&)3g>FYop#9OK7$C`Z z9)$=^mdTlI*0a7o?;56Ok@-;N+66oRm_2g=Z2=wo)QHCv0wX<7@w`j<+O0PKxv1IYC`a)wzE}zL6 zJMx8sF<=_$a@j0q%`82eK9t5o=~-A&?BRB--s>PvkeU!|9Te?wDbphRemK1QD!_RL z{nrAV*{qNtfaAoTn7rFgW9?C7#tfvoRTC)G@MbV;W&}YLm__^$6D$0YCG9ZGdVP$h z3sydr=n|imXRIj|O~!*5Wd6e)84;PX&h-&HO5CNavtzVa05fWFB4URQwFG8T^hgOE zo=E^Rsi_QG7Z{b#=zS{NtdsU(JW2rH^PbsCI!I zNr9H`h?!iVC3oPh+ldFp1}#0NX=Er`dQ_7^CBk^3C9i*Z6QgNh($}JTqlZcEST(_< zx1+?4z@(?CsV+?7Ji=hoI}j5KCSBv)1=8A6DaJ*mx{*m2jna0rQpsmcc$MU~ znr4nbW&i0i+SsGAnRhmeYgOASikNU=8cW(?Y<6~xrVDJg z97z)}^bA7PQquAtj;ymqWXigb3Qgc%htohYS}d>`wKx&6Lx);oGbwSVNkHYpwN6q4&4?ZyOseI7(kgud?AWKi|L97KV>J{2>$ zKws{dTldoNj}7|zo~DtZ=xaoiK_$X?qOZe(rnSyN?un?5=z*6zOijS+W|Y_w;PpFd zstde0dobX23u0mcuZi(ymk^l~qcM)Gwx-_&DyFRePY_e;_Gs|6I|ygSXaD2!+1TT* zgE2gQL9L1$1$P}lBiStkX!LH_gu-15BD$&KuD@YCw7BaSR!9);a$+YO?xL2drc$U~ z&2ZOz*3-~ADqRnWD`G-{{aDftY-81l`6H~`SUrHb+4J&Lw>@}&TZq)X1ibYZ56vM z3^v|m=fk0!{sm@%-1L!-3BZ8c*D<8=CWEx}1#tU{lhOXo9BwsAgT=Jc0QCCMD^g=Ol6A>Z}fSQhsDb^taT ztQRx1pe+4Ow-rk}j2!;QNvTq~mLJMrE}mem&c%Z-g|jn!+H zuRQA_V}n`2O7#Y_MvKz89j#>SC{?!M1Xe9)kZf?)q)UTF8mF@0<61S+aAqx3uO4wvLO3-Lru;uG%j>f~5r&2q+g}8s2 zVaqiU-BhuqfwWp|c`hp?2wOU_6AoKa%hX923OE?HJUfD13brJ!hzWO2W=T7YEiaGJ zbb&2*AZY@I-arQ#4IIEV2h;Te&fqe2=5E3+=G-I>Hfise57dVURPei)Vfs;5(ijzb*OR74D9IC zZdki!InL9zakp~S=pT7*YF5igYk_{h!s&MSKIH+L1`#9Avo$e}@@8P`hZsXua0DMF zkS4kSTir^qssOSjVinNro{1AA#c)+H}nbjG}62!EH#v_ z^%~1)-;hDFa(b)j;4(n6d=aN&(go~QW+lWLr`jFKY@G%Q0#^0WpG2@~_YuX6pI$2n zG%mPmEwOn#Ty-9`vs;MEml>|gMs!ofRi`4Y7FS)$3JJnhPV9ukRn#(d28NpF3|DQ5 zAeVxxh$~`(gOx04hjGl`oFivz3pKejlMa5=g(4 z_2C#D5WtK&kcjr7BQJrOlt+nxnN*4nJ!1p2Z=n-9VD=<^?<6oYmE~c6iF9Y)0lr}L z7%i-YfpE?K!=!{V;k01(d*ovpuko0yVI@XA3)~%+S(;$si5!u^FzheE?(qbL1U>@8 zKI>%MeFxs-ZQJEOM#=`ld*^FYtmp9ze=L-}`pG+F{|n0dZKqI3`&Uf{70tGx5aOK-$AUt|3AgqyBF!y8Q{p zu_NgARBEb=ZaKd&H1Z6wP7u0PUh3=g8@}RzLZ_>7X0){mB!R)UlKvzx*t)H!*<@qH zJ45wJ&2BBl1*F!cs7PltW$Amc(Inam+boyy zU1A!vUtsTz<%mk&tTwhZdaV2Kw6vXXni#$}SKGM2eQ_I&CtoWA4JbYhqo3wFE8Lp! zRp-3X<@p})aY~Cm|qZu znkVnlWKczqOlFi%_tvaTmy8XNQEvzkVR9tgTmlR+iIc$z2Pdt4$#gvLbq zR8;TuCWN@w2&?D_S_nxefpmlB@>orq-G-GSX(;}Kev=!@^MBA9_n7?C5JG_S68>8uh zEnbbJ@!2A#Z_a5k>KCM=`V)~Zbl~I?u$+`qh=peoXhw=4B>B@eQ>4(7*#4Tx7tPA{k8yPCz@=}Q{#;ukzfH*xSh#$qDE6z!_CYtc!lw5#b)Y)HI6a=g{a!Pa>n<80?p`%ZrgAU8wB2tQ&3{DN2rZc#M!FBjNJj?G zq$0V(?V$d9C4nO(eeOfK+sXdBNy!e%{9=+YW3MWC`cCXSEnTmbs`a5ET+n(tcR|bD zB}rv(>B4_%4lI?ZKi8y(Ol-|vve4-5?cK7Vt7~<-Nd7N)9;(9LFm=x>;2b|4VklKI zIkO6{n_8*DIsa~1n;4i+d4Koh9`Jq$^q;k7WlDt|`D`uMSk*;Cct3{lUl`|)s*H<$ zWqiZej&FH?_vA*rACw7S>njadeV3}FGfqn)Fg?R|`lXwV&H9npe92}u7Mr(h7SC(s zek5CEuWfTH`1n2Jlz&dU`X`sr=BNd_GLS8oy{HjsJ-Od9W5J$T9$o~BH%y<=k$V~} z@jFdUHJt*^?b#J`Fk7N`c^lT>kk4IXu=k`2?0t{`_ahhbnS8BrJ&VSXn_}aJ+~4hm zNk+I~O`AS#+8S#*Li_bea(Z}!Osm{eyOF?RQ1#b*md~?~&`%2psAsRbd&>fshwNiw z&Y_gW3-{WjD!&lLp**eq?t$Wlst1cb7r|nbM_mbW`ta4Z^yK%HkN%;lPu$50ni z*3tMAWmZs+{~65}JvL%waeEw2%*WA$XJSzBF{I=2J-9r329!dzv1$(@`Mt>Sn5JOs zOiViOUd~zgVx5hE@_iinzOKoqa)DTa&E1K#t`RFp)Z(_zN>vUTJtJQpd3fZ3U03hA z+8Fsf%XMmt^mA?@TwlW%LTi;JbT0!XJU3so(kIDveUa_V zQmL@ytaPEulB_Qclxo7@VEN?xQD2?uzWZm-WKhtM8btndSe)sOZN%oWV3S-}{|f5B zz;1Oi+TWjy2BA2E@T5x7MTvBgBz(eL-toEIAv5R4;FVfAKHu?=k2OqXu$_!&)ZTba z3W2k{AH8k4K5<*bww%i=N?SbcFx$1pbjRln8=@Ys@693Frm&RO-&FdAB*el+K&+Rd z9|lGJ+9h=N>w}sM8qsTs-LLnvut8Zys55g?;TL8L| z+|Qd%cF+IW+fPH+&#>|8W*K6SSFf)8u<;V*d&Vnr7M`Z7WfY^uD^ECD(aD9kfmScR zX_hO_#5$0(Zoz+BDlJ5kdG;$V8F>hX@Y`u2dgLp+ZXEfN0qYn)w)o`W79DNEoFOmP zWKflkyAohk(Rj~FL7hH$Rt9ch@wIeiE8JD=*Yxw%@9JX5wpzSaSr}W)QD3FHST(a7 z_Fh z-?A^QSK&X<L$m93lJ^XS6o?x+w_c+4Rbr(7I6zJPU}?rx)$LoJq0D=&b>;# zNNMn1SkdUInkJ57@{3y+;9r?iF-sS?(p7yp@{`G>i(5@PWNEMmKM+k@dAz<}wQzP? zbJT^i-0W~D)qvGN6EB{XjEs9ClvlPAhds~TAUeU0gNh^-vrtN-#gQfRH)0n=OpkSRq0{_@T?YP(#u`gJj|Odq30>>W)rL?&*g6W@ zy0KC>oh{}`*Dr?`*b2|bF|2-!scLTm61lZE&Mk_CEE~!mjn^Wp(h5 zn~zwJeOlPH3CG`876(h3cD~6Rkg=kfJkt^b^WO`xM_J3suQmkYl> zW7;%wbn#~-9n6&*JX^}?N_xmuL|t7K9)&x?i`fG3Ko7e&CReMKd&T83`5|@<=b7oM zdCta->qJ@S@boB>qXjMz)C2DBDOn^sTiypsa)f~#c+VKDF8acA_j(JH`)KQ+-5^|g z;GBb!meI4!GKXOnw;O1Q;oy>*3Hz23kTKa6B&a|Wod`qmsEFYkNVT+)g;?`9(h-b3 zWH^!7OlPzF-kqYk126~#uA-o|MNSww9G+otF7Ck%rpRG>j4XDwDVMhhD}p$_adLW;2!OI zXI%$QWe#<0v6(y7wea*o6G8Zr`)+JOvE}*{8&2%|@1qD{ms#xnxsRPPiBcBN6TDj_ zR?e+6P`2`ixm+l@FjWi;;!M<0XQ-`5s7`I^4FI4(^jNm>2T zHdBt>nM;8xtru}B$XU;A{R%jSX`Qt|t4t*3Ft_!x-LYoHrmRZzSTo<#A!-Hp zJuOCOk*E8JJ^ZJwRB?=nW&Ie`!;+{{!9_7D_&3UxvNlC0WhWBX$4KYS@NnTl-lGSy z@{-sT*Klk@N1mOe-XOY686)I#|4BaQ=h<^$jL2D~di>Aj z)`*Ov2`6)fOB8Z-{|-tQ0`~3*_L1huM|p#S&5>grMCGs3KI%WMl zMuTb9bhlj&WX9~zVo-^65FgfXjv1W}y0%%~`_={8C3bzqa$ST~LX8r-eEb^aS4LG; z0Q$PnDay#nmkO!drVmcK0T2@S(+M}3!^->m37cN{#9W6k4LLE(yU>d28{vM@{l3lMOFi)~fu4+1iI*_tXkJ0!k z)%1oKR3g>Hhd7*jMyHzI&9#7T>xcGzT3C4vC{n^BU9?6^38bGMb!mG*SimTGmJ{K&2qMOhF}rO8sn9p^Xj$RML@3RZ!g=HtCXa z2*pbampY`gu0yRtXKjvPE2*8zN!_OGi(mn{N4cp(Y%cmUwzm;}1-7N5)yWx#=eaqQ zlIt)&UG=Dj1LEnbuWE9}(N#|%U(33xh0Vn#f=nqXQc_=L!?2)3#5vkLD@nT zJs80?QWbrHHz!0DIW8`(xhBbpa(27Qb5+s*qi(0HKga0ulq&i|3@VW-;*1f_bE8v5 zc@Daye1J<;I}`wliB>=tcdlx`+S$;7{>eGCk5aZz&m8`#(XP_HLX$I&p6Nlpmi5ev z(XY~}w3t#cq+$+XBbiLa@I2wuom5O8$`&f-zzBwsDrSG)oM07m9ajnC>zpd**2HLx ztK7~ff~TytF^D~-+|G+ZB~osjCBwOWbjs~YsbLgfSP2PQQ*)XEqZM9pY@6d(f?Kr? z-|eS^oV+`9|of;;I2gPcdoN-j-waC}9id@@@iqtUA)D{-oA1|{pO{Oe)o^bI& z%JLSJEtKU@1nWp;Y4PR+E6e4h!B74Z5^}z@r!ZGpeVRI)vhI!1*(qgpPYf!Nvf?Ze z&TXSpR##}WgE%eIHW@9-i&j;Iv22WAQJEga(J30pX?L)$HlLRIo`yT(X{jeQIpb)l zr;)E^Ew!diT1pJTl#*gf>RW6`lPM{lCtPfhl6nzk3nle05u78H)MLCk!Afd@#|1El z19r+oDb{GqtAF0I zqScJE2j$J!Hhss|A^qwFdr%#$PR=3hL3wNOsgzy~2gFk;$7^!NQ7NxSzLr%=OM6g0 zf=n$C(gNYJY&est6P_nrERZ@`g|dY@IXZ%Cq&hKpbAr{$DhKnle#}}>IWw?!Su!lISZ;Mg?7ua^29g&~{T-hRuu zc0f}-KFxH4h7savrnhTy#?ed-d208>yPE;LQnEO=}(1)ShcO2S=x( zY_1y=Lzerj0%$lWy9Gz}uyUp1k{ehW5B0ZtRB{xR#aP9xp-cVpOfznOXX8| zztFH%Jcai&P0lz9?*-&*S>atUdW9ECoGDmFucf|~eo7~k^hf$+b);#=~TH%x8UUTywvz-o#K_${vd|1OdW^}sh zT>;v_cY3m|qS#k9*ID{Qzt>HK=J}P@l}(b-*Q1V7ODZoTsuey3_C^h_#ZzE!(BzDx zz|KX!mKE5=ZB$^sVVVMPObES}4KI{f#F1d0E?fwa+S-ir1ZX=Yf^($WI*~UaSZyUc z-P_`k;3{<>WnC7d@zmcx;fgoW-(rj`B+q$&!%6AN^YC=^_$0r}FgRV)ABBFJVyCC z-(!?+`{O=F*`vOr&~&Y#dNmz!XpiN25U}~OL&3()5stOR?jQORv1_cyVC1W1;$grq zIvMTfCgUTLO(P&)mGr!QINQ0)mMK>6YkmGm&vSgfNC;5ni+6}dG;$&IalLPAGHB+R zd};7sVkQ?aU%3NseUo^Ay-wNjm#<#bG|~!t`RezY3@Q;^+hWXLzOoMwo$3wc<}Qwu zQ`YlQz0p64<&IU;qgW51#P&Uk#V;sj?_$lq58%yx7mM=$%X1$iBq^;4 zIoB!Ls~x#uEW&e5E#9%tdemb*e~5Aeq#`YZq*uOpyZPFPZd!ju!Pi^=jnFy_X|2D} zzvy)~BEWC(14hEhtPryE@CNzKh7TS%v2DCO(r&#h(QZ}01)DiE)vCyGLIk;pC@;8N z5$op3l-12jjlZSugbYg~qIj`EIlCPvc*Ltl!d@flh$_z_p) ze76BkpO61vh5wJm|2rDL1o;k!`5NTM;>HF>UeFgr-UWNS}JrGEZ5>L!^ zb6K3r$m?7qsB7_F-K4bn0>~;%zt4m8 z-ZAU39#X#9CwTOFKw+MH9W|zW;KiXr&IiVOWx?lTPX(W0f4`G)w;W`Tec$EY!KpFu zn_@i{zCRYaQ~l%}t;a!hzbO)G<9|bwK^4hzP{kY5kH$i;6DQ+iY19kM1<|C1=OBc}eI_j4OjJb}wug_-)FMwNl4 zzG5i9SuV#ghw;G6V~us`Djr+K{jwRnTuQGJx)ZajPu@W?`Z?;Yhg zW3c>^A=Fg3Sd&2&C6XD0sc=EeNdB@sBY&15e!do?s3^f(5&}2}FFrKD@cjZ4s zEb7dKolzarn+xu+HJJ;iqr{Gw3m>4S0(T2@fwK!U7tTOTpt;ba*b8I2mG^0C6^=KH z#^nTX4_z=MUA|iiQ8teExa0T(EPwdH^1o}o{Y?30>(*?A9@Is71>@IHxnD4ZFXyHL^Z_mIGM(UCoDG!Z62b?R=UY|%enf}Vh1t8_g70I9DNm*ZFNjtnK`nMQO7i{qtB#qA&5zBTU z2_xO?2cp?hkdEq4M7q#{lZ&EqQcC$1o=Gf)D!t|)kUU&SP!L|QE-`5r4I2$MLmCnoQ<(^z{HnK1*Y zZq)<|wUwE9KN3L@1sM@P#5C_8VM#lTjQ0F&Y*wCzqzPDg#+p*mWITvL=0Dt#5s@kD zU@A1hCP~UVAV!M?mZBCXB6jFdODrWtkCf2inFN-Sn#v(yY%Fy;I-$c-XVUjhVyTPd zHOq2Ot<50nq?SRHchR(|xsCBDqG-ynowbA-dUO#EF4!pCD-X&noQw9&~pN!_LW zBcR(?QCt*>-koumE`id11s#fWwrMh`8eNX0z&TrECKouz9e8VycwlUB&U-YC48=LN zCWA_Z@x(b^cj+cZ(*T?sqI#nTIPO?A0i3lcu_FNI6Vy}};BX#c0Ox$f!~!_iIG0ki z_GX81QK@cZ(nX`R-K0-^OmWEhNajP*@s+i2~l)8Q* zG{uqF)>nvvxcWj6QY!6eST#9Mv^32efu|mF8Ex$G)Cel~i)&TzD0u1#YG=0)qtSS3 zLOJ0-7tu`>H$8~7THN#>tdJnwgfn_DX5CLBBr7L zI7`}LRCU1TVl(u9NSc75XAmBil9vB)2TDYytoc-EB2;x`j1~)2MJ-N5?9ic>s7eYT zDWJnM2~;K3qeH;hsOmg)LWio>(f3ZGs*O?t!)3qCfa>Iy0oBo-T`9Gt;aJM^I+1`; zo^KA1G6XdUBFAG-X?F_*HQ;2le>N$d)D)7B8+f`BMD}arQ1CRY$)KulIfw#0)ng_X z;K?0xt46~=HsI+FO(R3W(+4#fR3eNgcseX-TI-z2J`mLrJ#KP`sR=i2L5Ur~P5(qq zb#W7C4~Coi5fckHO^mmngvgv2jd5hP^(~@e%KBG9OsSfqvD5A#oEe{e!{xKFhfPnT za=)NfMUDcS{+-&{Ed=Px3^x5KqMIsgdJJi`u;~R>NDyptVkaDIqL!(qQm9$XVAJm+ z$fdw0;)HWkgC zWiwO5-f+28t>y;`Sg*_15Yob4Az#ElDh9j2Hebt^ioIPMD`vWu$AVtIW~8f#&E|{g z%CNzXS`C<)biHaK?zk!z|BPy`RH^mOpU;t~d+EU*@)NfF9)0-Hhh6V7>r@)ClywUI zNdQf|tsl}9IDFL%WIjP;j*xn69xOuIh;-6jm6$2fJP4hI646TCAk}7gCV^(FN5DJ^5$MLr`~x&6**b2!Qkcxq4>ZvnB6HN}wc zl^Be8+%G|sK)%CHM*I0mD#$bgGHw{S0do6=M<@oqNs~df#pG}b3~a|tE-!l7YmnQA_Tn$!#h>={8W z1q~Bd#6$rvu%sPE!>7h*x;V6UGSMYIL&w`hJljX?D3O=4md9wZ*hHijCn9#}P)o=q z1(1}|;h6;FlG@QBU~I^B89JeZTy^^1Nyz1WTu?lm+UDKF*R+hd76zMKvdQ6qOaExD zz+3uAM{zT_bt48sl^4M*EbVgvx8C7ow0|@C;g)=Pm*Wc0H5g;!uKACkwqJFJqOA{W zGN`&q?pe=Xst=otX#s+OYs%c~>+WML%gGz+)L|aEiPJJENdL*hxda&h= zR}yM*#d2fgT4VLve`y;KRC48L_J!`LIjJ-^tjR#XA0Ai`-#3j0q?V<@BW z%RnZSTj^mD-Bc0b^B4~;B0QKC5`+ky*a?RSsb#8#7i#e{M0h|1xfDc5ToDtb{4WR# zu8DEGP4flL!k|5Hq&dnFI?SA19;4|35iTXV#AoOYbXd>8AyacOT`%CADN{$Tf~gwC zQVp>+voeIe!)&hs_eG>{N=Ax9R`r=V>Dd=$hAlspP^xX((6}Ij{{vA zqke&qsQyHx3mrI#kfb<~;x;^!KuA*6Ipm0qkluk#=n&G4^u3b^>0$>$oV#J|n&mh% z+UDKC*R~9i7U;JKoc4xeqyw5dD7CyM#?iVAC4B_MS7&^%%9XaYKuLEv8SP(A?oB~C z2;=5|`4C8*2qt|&lR;J0awr8%dLU+U0h8R3x9%q<7#o=Ml%|oPFzMek8B`*SCrmmb ze7ftl1HT*99X(ER2dfDu-HH-Bf|LG0O?7b+XA*{!K8ToDIH~U7Bz7ue2*)tkEh|~v zWo!&qN<&7KZPOW5b}LJX1E)eB55w_Kxc-mkErFn+bgkD|Mq70ZOO?}GO$Sf`OXZ6= z^N}uKdoU}d<~Y^vNM>v1gP>E&nn8aOth#pZMxvPU({w=~AdImGM6W>QezB|y7zGf` zqjq)+arrXyvFwfLrV5CrA*~h=9nT600z^*igabs>GIa)qn#c?g9T!0^1rQNe#I))U zVo5s;h%S!NbODIogro@=dNvu|Ms2w4+<~clam1dje1!DdMs*~Rekm&#qXPm_Q3n#y zK6K_1FO;1Nb! zfk7f4UVV+nzzi!f>h;y`u*}k63Qy!raE3S^0CUEh))J-&#QA9_!Un_@jLDEMQcn$=Ib+QxxiAA_CQ9HYZ=!#xd9;ZiJcSUqa zT|fRP(rVX_pJ0UqtsnDPuR-af8C#ouJfbN?Td_V!w2iqw_)jcphu3ER5~JyYEnY&> z_-ql=S!L#zqS;cAj_OZDy3m1>ORI8HN+A}WN#G7CmK}1$URqs*{_1eYiS#`fcldQt zZay4=UWNaU#s5898pL6uZP|Oc%0SzO>7QhLcsmt@iQeF}ZLdrrU9C2(<#4aF-Wb%h zx86+*!JDQ4+w|<&y}ia;DrUh77sd9ESxpUMV6tjjqhu_CDoG2^R%o_c)(v+}x1s1NN-92!cqw<9_hsnoYi* zxoX#*kd%-QyA)NkT^Y{pc3 z{L0`VmNW=U;!wpZ@y-n4Pne2hMq<5^Z`eoS9lt`Y)ECkKno-+aA_4Hvv!|b~&;UO) zo%PN%-xOsw(45mM)mpz<&KF8sQN-b^_CPUgDzQZ)cOu1-pxxH>)JT4Fqg#sGj2`Pl zn5Oo@nNqO^?{DV(y$EN_K!9q)lybzLr^XvSBEbUik}F|yUAa_l4xd!HSEJ4oRLNrR zODC2W4W)~4gs4U z)GOeuTEF^%{EK3tx|74F|U25_3ViP&cbCWA4Ak zo-MrSOBLjw4d)QET1yX=@naueO+U)shM!&HXT4IuuYGH!Oh0+eQ*5=7d(u8|uvDty zRG+DQUNzm`w~AXsi}j)Yo#aQ-z?c21wMxF+4^R6cbf${JQv3^~DErb+2gUoDTt;J2 zm&ibZnthl9ISa4-{(`yPEHqZ_VRz-y1?T5p_5tS3Jg8Jl*XmW7XfJ!OtT|BMit_e@ zr+*QL3XuYLln&v`Y`Dl|OzKYKdV9Zov0Mk+79od`s$tKr*9I58Zc#Ole|LK$`|+qz zsnVZI7qbPk0t!=8@t}sif2m&clyb|e#nae-_Fk;GhJCm%iLWf{|AO1?{dfg#V`T1b zZ-g(iJ(oID1;uhgCpGMS3+dw4Iye@j&zcQ;k4n8^A5<|jxSF*;YqFO=i?vmUE)&nz9-j^uYbpV1NQm~$^ z*EdnH_#gzQP_W0r2==DnK?)wB;P!b4K0?8&LlLZ_VEbVRuAtx}uRw4&1xKV198JNC z6ud;io!tmNM#09z5nN2cE((4?!9N^<;6@7Ga3q2=D0rTN7bv*XK=3gNHXeoGA_{iR zNALp*K6*5QPf)P=7zAkwK6fmF2PxQh0fGZ5$h{iD5Ct205nM>YeJ3FJJO#5)Mz9|R zXPt^*6$P(+J%S@C*yl6^b14`+9lnny(I(FbzqGZ^W$~Um4$p_H~s~2Ga*(tq(Jj^c5YiA2iCt zYoP+xuUp!?wvx#~g5qdhsnWYz7&*NnADMB}Va5?T#B!av4wSJdxZn~5n<@An1y51% z@y!VCrC`Sv1aF~W;hPbhNWtt&5$s37Llk_4f}f`m{F;LOG6)W$;KnS1n<&^~A{d}x z&LDyVDEK-B-=yI5tq7J;@FxoXLcu3;2tGr>oAL-YQ!vLuZ~z5gr{EhDoL)e%jDopC z2o9m(UyBI7L&1?{1h1mt@(O~tQSfgy1V5(WpLZa5jDpnV2n-6gzXib+6ny?|2p*!~ z9oHbRDcJdT1Xoh}pZiUR8f1SJZl--uu)1)JZ6AWgyQn-Hw0fXS8HZpOd9M!}aU zxV3@c4hnwxK?J|0;F%90c#eYF?Ffb`*l`Dfw@~o*411 z1Ye=x8~=#lTNHffqX@o7!B0Mh;8_YT`#6H_6p)N#<~_5+gQp2u>Cw~Vo8vo8mT?fV zj!uv!o-1l*IbmGHVh!8_LT#nsfzKfLA_bqk55fHuoPIxoWfUxZ0Kr)l&{LrnJtb<< z<2M#Pj$_fqzZP8#Y|*V$7TsE9(ZOAd4)$8)nr@Nnxs=sAosB*Jm ziVs&|y7WWsRbd#qz+f*S+MJvC#qW9c!cDmPX^`&hFjU=1?%*8uX8Vl!9Ny3GbulFJ zr>vvC9FAH^LROLP2wytZ+$N5(`q7EBy_Y}%d)hOYcci`7iuLQ)t|wcZ!zTtCVc-x% zTD1p(-ELMs%Wu&VL*3q2wX2w_-#3#7ejr-`J>y@<_Lb?lO`(3_>0oKVx*8fN6&zEI zB|X^p(MdhqQ{rq{E6a4Cr+na)Ki;wANEyKzDeR zc9_|P#!0UQQ~1ol3s>Un21K(Q1@X~X zVuUJCnF(HlOM$&>=aj0oH82Y|)GABnuUoce>FO2p7mBz|u;rb&O&eCMpTCgRMJ+^| zM2(c0-|Cq#s=b;WviF7qCMYBWoq|EoP`Gn-C$Lrz_#!w7P%Ud22VUFgC0_d(G1G=*l;`b;ay8YU%2> zZFw9rT%5<@M0_d>sA}#syW}>>%eoKValAfa9MzdaW7+b|IXuD4IjZwBXY8%Tk48{j z&YZh^GiOQ}PbuRGs*Jhs`xJvtG3W$kP_NGWY=i_>bskA!=)9BHx5-*$1-aJZe3UD! zMT(iM*5bD#C@yv0zxs6El(h(vGOiY{cjo*!VjR_(Lu1+U%u%ex$eA++*5b)0cVunR zQ>>TbFGWyX&YVB`X3m8@)0@{8X-}VV(>W$qOO2snfF9EbZC67j2A)O9ZdYfo5tGjdpOr?uL1^F=Ft5`UOM`XThO;#Ta0Cr`ob^DIcNX1ROU zZotAI;G2JWkYl(ju2`L}m#^c~=}mPeah6x%Gn&q+>xFew?B$2poie^b@=H=5p9}eGEQ6&TM zDkQ_VZ)ruR9_ivpR*f z;(<7aIc&kPi9Csz2ZNPGIbwvV28=L0q&-NL4e;;cpk;@b-8^zz8~|>^R+Fb#?=)K; zF*b4xm$G#3vfGqsOCs6?o}E&m2~?<;PuEBAsj3c$SD_Bx|A{uK16GhLbl#3~g|MKQ zDRqz|$BL9S6fs0nlvokzn$&@H3UX+a!4Kgu5~K`Hg$oH&2B+X3qgDn~gHQ%1pd7C< zFzo{!*I%zg0=ar_{lw4X4(R4W|5mu5zg^NZ_1=S}h1}W}~=%OUWry|lt ikivTGW|v_VYMAyu4#zO3-mWY;stccPk}36p-v1vRutv=Q diff --git a/Wiki/RUS_Guide/doctrees/Robot/01_Robot.doctree b/Wiki/RUS_Guide/doctrees/Robot/01_Robot.doctree index f4711a8279d42a879241edecffb35ae540544a2b..ad87f52b20f0c9a62d7c4a5ad475d57c4ff1284f 100644 GIT binary patch literal 30086 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 Mr=!U%E(|384-}!h#{d8T delta 2701 zcmai0ZERCz6z1NwUE6(igYLWQZRy6ktsTQJw$5!Dz{p^HM3jJp+^%=rzUz8Nd+!Va z8JJ0s-08x({#znqqWBSH+>jU(3`7Dk5ebQje>56@n5Yr-7cu_vytmxjHgw}hKkj+Y zd(QKm=RN1Wr~YJ4eahHR*xo(5XUX2j>Q~v1%IrfTCl10a+vOb)17cA0kCvmQU1Y>E zB`(I`f}@|=2ERHsGCN_{I?g_Zt6S;6D%0OZ{b8zn#5TvSS_S{q2SIXYY;Jdi(>*mc z4EWt%xLxIhBd%K&vG7UlxYjA!Rn7EtX=3>SP3+BEV4=e85D#NqiDn9#nJUmSiKqlK zi0GhOJ4K=|Rt_`y;NlzlZ&lB-%p8O~i;M=>J^l8xxcO}i*9v!{E(q1OG3Vf}w+p6f z!&T}->Q(472h93b`1=`~MUYxgP#~@({yUBU2>e@nn~CYS>N;5a4K&QdeAovy-bw}_ z5^aDnuLJtM;Wc-aI4^oA;X0(ahGKmW`eFeC&FzP1+%=!6u8c5|kf!)#S`&XnT;0rN z81{N=6|qe;(N$yi8;_u))@u}<-9Sgz+f+wfNu>l?Q<;cHLnI0aPMRS&x?zGUEe6I! z{}?4^R(9`w#?W%X&=GdDT!7xjFY^^v7f`+hEbU^`c{iy>XOSbweks~UYu9c{=0UR) zS4*k}n_Irfha`U8+4>~o4CLJBVUw>1%X!$hts!EVN>W9Es!=cBZ z8ZU(^W1{*w&{U-EYD~PZ2pP4!Y$2oal4f-9w~$qsnJ_ecfwq*0lLlB(*Y9u_N{2OQ z-{+z|x?NJT0-SX9>u-e`3wlUBYPj9+cojxER5v+~8!^K<3y`I;7tM;-sTsM}M*ZOLys(x!$_5H3UOX~*2b)~4H)Usp| zFtomyLqedV`zC7rS9dk*yq8Dk11_3t>MafbJqFnW16gr169>E#i{c^N87*$+Muc*& z2pqNiVSzK`zPN(il*=LwKxtTQ40n^<+LFhE4o_>WhvDkbYw*I*@k+80hcNvM6PaaT#Gc z#g7XE1Kf)p!%X?{wOk4y_$`qDzE z!)arEOcCqot?m=s4Ojd*fs1fZ4(+gBadK}b$fsvdI)Tckg#?#X;#oNmvt^ypC9S)t(Y&gp@W~rrIb6 zJb#;a@7}RnQyp1J$>1R{YNXmyh)f%0sS=zK-`H;)XGN`=kR&-R$pTDfzhP|fl-$+Q nY2Y9MbT-@MA=enp$p@KNOw4wQ`6YbfphxK~&qWs?u7v&v@$h0M diff --git a/Wiki/RUS_Guide/doctrees/Robot/02_Defs.doctree b/Wiki/RUS_Guide/doctrees/Robot/02_Defs.doctree deleted file mode 100644 index 480e5de9f66b3358c9a14cbb52853c06e927ed3c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 139906 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 =&Ye*V$i*nf|3G#$<+ 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 literal 140456 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 VFg-;~E5Z&@wbC5M1>6`N`2RyZl_UTF diff --git a/Wiki/RUS_Guide/doctrees/Robot/03_uiweb.doctree b/Wiki/RUS_Guide/doctrees/Robot/03_uiweb.doctree index aaccfbaf508fd03c345393a6553000b4869bfb8c..8f31eab254d3a5bb42e44aba8a6e52b7f1a33303 100644 GIT binary patch literal 11743 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 Tgj-#=Ogl;7bm@fa6mtIqaq--m literal 140416 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 Zs{qNs^b|3x2&+TYN^=kW>Hw diff --git a/Wiki/RUS_Guide/doctrees/Robot/05_clipboard.doctree b/Wiki/RUS_Guide/doctrees/Robot/05_clipboard.doctree index 9c9e210f86927fd3c5eac05bc5535a370a4ca5e5..ecdde6b8190efdedb08497a517cb1cdfc3353544 100644 GIT binary patch literal 19848 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 diff --git a/Wiki/RUS_Guide/doctrees/Robot/06_mouse.doctree b/Wiki/RUS_Guide/doctrees/Robot/06_mouse.doctree index 6b2a2f34cfea76490c0adb41c3cb49e521656305..601ef9163ccf76f0639afef4a788afa3551646e1 100644 GIT binary patch literal 123032 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 R!=mZ^G`@L31{|6Q+Yc>D? literal 140416 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 G1OFfCnS_!6 diff --git a/Wiki/RUS_Guide/doctrees/Robot/07_image.doctree b/Wiki/RUS_Guide/doctrees/Robot/07_image.doctree index 0d35bf3f5829f5875ed099e6146718945129339e..b3a07a6cca50d7dbe837b5b70f5b0e2d73b3c49e 100644 GIT binary patch literal 11743 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 Ru3M&^ByhTP!gUI{{{ebH+$I13 literal 140416 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

P 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 literal 34955 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 TW|o#U-$HGHO7{6rTFw6fT!bx_ diff --git a/Wiki/RUS_Guide/doctrees/Studio/01_Studio.doctree b/Wiki/RUS_Guide/doctrees/Studio/01_Studio.doctree index 1ae92b0078823daf1abdc82aff9324345625343f..a4aab303a3403aab230cf01be266da66f2731dab 100644 GIT binary patch literal 13094 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 delta 1166 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 GRQ?+}cKQwg diff --git a/Wiki/RUS_Guide/doctrees/Tools/02_Defs.doctree b/Wiki/RUS_Guide/doctrees/Tools/02_Defs.doctree index abcf297bdf6cf859f0620ac7b057b114cd3c1dbe..ba1d4c2cbd6da56eeb154d5233c25b3c1ffa44d5 100644 GIT binary patch delta 4173 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%0DU?J1C#R>Vl;i;a4a`vdgN~ za*$m5yP1<=jlzZWhO`Bo4Sz#sevq41w*Zu8qdUdD@Nr?$GL-7d0)(4TZ+F`e$h*s1 zN2YAghvqg z#+bh!wR)Q!Py$F&`p8b)t)Lzb@1Wy4gix#a^#qfG5KWpCtSWE^U}Pj{2KZ0_?G;_b zWe`PXJN5Muom7PcWr@xcXORx{645XUPwlBsLeQMfeo2{KnUjmg_6pG3#Zqe^4M2kb zF!z@lfGHNQZA{{03z?7`ms$9w0T!b%?D7^aJvVdu^eiu7{x#0SAwwo`Dg6(^WFc;5 zI#?tL4gH~g_II(w^@SaMR6>@Q?gV4#^cUJ=q(|}4VJlf$b_HBP{r5nzRhYXFOF+^N z=rOii4v5O@ij4swqOQOt#${@nAk%wL-W%Y296>k3Z^>~_PkEUvCy(t~HAPs=&5qI= zPcZ$o{Uuf@(HMGivC2@6u9Ma4G4~gX8^;&V(|#B6+*l}cas}4VBgKnEES9p&3Ve_x zU@WmE^%oo9{ZI{rUpkP{^4ogjytRO+WYdfBQQerzZpSGhoY~El`Oe6vIb2ta0rA;D z^|ZsH6lr%rmbMqJ#XaN5n}83C4|0aF3NHB);Ky(n!Wntg_`xmf{hmUT&wx$-*4rU# zmpe>T+aLLrGIpXGkLj!-xjSbtB{g&oi!?WYkVJ)1RJps*u%C%hC019Q8Yx8R+6cHe zFeC^2;QZhJ`FAH;h(SuG3>8d>nc3l}Pg|Wtwg^CyM0~A}j2H!ufL^emOu;G}k+!6p5;;Z77QToNFuI{r zaBKT#!63VZ+1|Z@6HHMjv;0=hAV@o1EpagJ{!Qd(IC^tTb!^)sh+$0C63uWn9X1lv z;$T6Tf+UAO`DwlE6)NRGM7@vW+&J60s?U{BMNdu6^AUU@B}OS|`$9GyHJ~FY9CK-% z)Be+Hgkv0A6RXxj*3cDHe!kM#g2a>7&%)g}NCjQ)Z4B`D;q-B*w~m1W&4Qyd=>)dehG;AFMk4yHEj zfMyYF9|_Ouldd~T1h2k(;an}2us@jVZ88K;;C?Uien9gC7s;YP;y$z&EDs89f)quH zMU~z7W)+=K?m`rBx4y21T0NB-X}3Te{ACT#FG~z6|pwH zc9bkmFe7!xMqEEW;`)h6cMVJu1%?dz2Gm4GA&Kc za$K?LzXGyBQ3$3P5R=?#4}G{9NI^Fq#FOH`;0FACFL!vuIfn-}Ivos-$-590>q3pj z{rHjYk%y7hs*r4_Sv&?)+`DobeqDdxdTewfu#>-xqa-sLSppns83U;57&@l<5Q0)vkaOmNnJ=iEpUHc1gGFgm#Gc>1G^&mhJt1L8~gsnQI4I zQwWxeAI?+bKm`J;P@U=pT9t|gVAOHM;mkp+r07%jlmrKPZ-gD8FX{kxe2hiolBR>I z+=2YQ-Zg-q8}yfu5vD(wruPTJFN3cLK2wI!b)eEcE5vW%P$&Z!wnD}%GSSop0ZGYk zl3FmHcqpaJ&BmP#$Pv!$W^6ap7O7G!adGMh<+ZJOzDnU`red z{p^eeL4JNeX~2jV&vk|y0EqEKS;b~Dvrf;03N&Jw+HDk!h0(C7JxVDU1e$lli7dIb z;0G|(a1ZE07J+!Sf3?`^Z^E9thJU@DZwgUnGO4%B32M+^h5ZQTG2djN%4;i#O)gLr zFWrt}99p=-#uXlSG+Q$agd5LHW*`G}WH}A;=X{^!fr-xmN@OAO(-NFB+|go)YOq<_ zx$-awTAdVD2GMm^l%!fC!``7AdYuYt96Py_=#bti#?#3ft_w2?2nR#G7hjN3`831i zpwSklKpg~bakS)&UYP1SxHu9V#^CJ-6oMo74q8{PR$D0rv*BSOF06vD;ERV-Eb_6r z<)9ihQeT6y!vII2G#|raLBW=_NVPTd=o5#&(}f1C2n2s?Ig!J@Av}cw~wqqA^`K!1I992a4xyo4!1FerMe7fa=SO+jH8m zH@u#|Qx?d=v3pcl&^z6HeF%z|8FwIf_k!0W*%OlfLqSvP7lzAIe0v|b97X67ZqWS0 z+hB{*tCmCs@If0ROal1ye{FV@yg-cn9wgbAOen|g_xC z!AJhS%7TD)$N{*H2?3@3S&0oPM^j;bkWp~{{uS&sJB8$tk!6fpl`x#FVJTYV_78JL z@dVjyhK+fp|7~0n((#dciO0DZ-L!J9#wWt?%qOCB zTG<;;YaDv*utyAe#Bh0e$DyjZx?$Q79ZYj*2pYyJno}h{X)e8I7ck<`fz+tF;c<;l z_OlD;8+*nR$kwvF(7n9Yf>V1(V#{#7v$WA1`fKCpbl3Kv7ehN24Kok~f@^C;Wm!*5 z2L=-XlJE?3)FU5Mvpyi~Cmme!ig~J9)6v++eoJRY6Yuzhx?vYiz4ZATU$85(ui3il&Gfq(tGggO(}ahLm8M7arBEGQE9_ z^3+Z--Sm$UbI)AsENyOdlIKziDMk?l$K?cJxCa!yuY>c03I{||x#1t3?;+|Cyn)_X zgn^c}4~k;}3<2m~^9arWJAMqCmg!yi#SYfaI@eSbDCu4O!twAspbG;avh6m5Spe+6rjJo^|Ll;`lLWXOr1S z6hTLfNLIaDhLP9GT*Gbl2nbX4Gy53Xfb=2G+&#pP^$*2~VO{dcCsR$Eb<@-1?sM2I zKIfb%xo;J?Iv$>^g{z$aC{yO7%L&q#h$Z8p2M!?FIPA^kQSPy5Vh8A=-~dP&sjJU6 z7wwE3=}w@XD{kUm*(}_aPdzLM7p5+)TnVtHTMdug6G)GmV+LIh1+w$`W&MdTrFHta z;t3oF69Rw)vPgZoGH=w~yJ}f08QOOHi}q7rBA*+X#=5fOgws>hiDLA3Nb*^gi;SQz zq676s4@o)PlXA9kRjFI^Y_Rv$Q$Q~`KmGzp@IG%r z0vDGOTBLQDQY_x5jTz=5G!C;HY;&pY4e!O$dr1~*_FG?HzEsI3@^aC=Cbf*4Eha_d zGV7V4hS4Cj{BdX)>L-a)O|=a@$Z1k|H)y7kAvpg)Psf-RR`tqTHP0SZC+ORPlFd%4*ZT$xm|=Y$s8m8G4lyz=)&(`Psr@W^-L)%}sQ9@h`|WtI-@g(G zQzAb$E|zsxk)crY4rion0J_1|A^I6^gn{~pImVP7@DKCYTkLt|m2i52A9LP7OyF2S zPcxdC!-EAg&2=w<^PMb);O@sAwo#s9rHU=aDe}6(*G$RdWA$hJ#lz{$oi|O*ea^{l zBLcA=ieJM*<@%Db;)VX;O3^}A-i?AyV$p)KyXbuc}eEtf5icHFAq!9kRy=4W-8f#4e27n_X%`#)KJKk`^s!h%R$pihSNpIrxQs2ddLoy(5^$)E1wye5# ze$E2+HOKJqb${s?PXl)+?Vk5$fRvALct2w#{551!Q)vX85@YiclfxA_BD!Qo9fdD*6T9!(I21cvYrDkDowm>D z9W{=LOi({_*p&Quax0jl?D2M0#gEO=yDqif>3*y2DMBFDzktw(L}w5iKZP7hj|Iqp z@IokQ8Jq_)6%~}-Zb)jS6%`5woP4K7AkF(7nxee+S(Mg;7r`tEY(0%2R< z8B+9V4K{dOdsxtPmTr4{3tL0C6`Y$)vQJ%yq5Xp{cO;U>vk%_Qa(@#7nz4$mfuX*%*@&p>RgU=JB&Hy?|Pwnnt zJbApN$<4~PvIYLoXvr4P`Q^@rr6`X>n((*Lb1o+GT}V50ie`qjasS|99VDE!&@x_a zYQ2VZiXLw)rm4=^jQ>di&mRe=t(5?e#6C9GjN4sqyp&8Con3FD%xYMc>xn-%J970= zZHj068_%$;%gkWVAH+TJ0}B4?yFuD=cda{I83AgF6sntB>fn`5iJt?xz`oS+?gtLF zI|WYc&b>eU_=Xg71*0TSng{J~pzAB9eh|`-I5vGgG6U+P=GDId*Vi1$1%!7$>~czw zL^2LjWg42kcP38$AH|^69d=NaY^k$OX#yN;$T1wRP8L75fT2Shlr1t2W(PcAp5-lg z0UgrF50P;PTWophkjj}ZOJvs%f%C=3>xWX3;cs{r^!g!3_G-A#awK136i=zGns+vR zuTgU9zTiHR>hnN()9XQL94A;yqtZtpYKde@2rc7a1qejsw2^9*fW_KD3!aSzwymrA~YgtG~mm&4E; z$H4Z$qy^#95xVrdChbMdeMze6LWfq$VGwV^s*$BNu0*0$0wLsGXBlPw22x${cSG_S zq;X07-R{0(rVtVH-Nm+hS7xHd`d>_+nL9o6sDlk^`PhBrR_3K%j-umlK$HmYF_j^hznAA}Id4dqJ|Lg2AL8RKEQUT3@lP6UGv zn1H~gHnZ$#3ebT90bVpL{Hff4I6J?`lQ>6I+9Zi$;97&sF;w3$ipN(F-kbU24F-dN zmqg=Mj>D%WRK7sm#OOXzhPKddG8n|P$~UMKw*&7R@kgGkhfc_S6eES3B?j3)=-Gc$ zD>*?V#>P~5Ubz0`1{uBR1)0Pa2MQB#%6*#rF!)4d;DmxJTwsm%=$KDV%0HSlWGiH} z--NU9C=Cgrp4J{sgpsdGMs76Rybz6>ZNVIf;V=VX8)*S#Ppr;1@o))5+qAl2`W$SG zapgDuJj4(J>i}Ii!E8?fG8z+J;4<$cNXEYw;OXIq7G%?_4>5S)iiHSv<^z`JB*=Ci zhl~D*32bpm?X|te$MhT>a{{+ODdfqpvjNvO--oo!0o=eOw%ZE60lPp5razc`Ov59% z7{Vre&Rb?!d5t?9FrbQ5Llfv zfop(^(YW~dRJJ;L-yu*xBh_wpy~NC1?gA>2(}A(mM##UrL`~HTv&d?IWrb@);>){k zG9eL>eC;}I_2&_g z$0s8t(ZPSP3oKyGs9idRx}@Tar+5!35Z=Py-{AKL%!hDm`z_Ry(w%?7wOjb_-{3TZ zOMLA0?SFwn`#oe!co)C_kyehk@$UoN{MGiqA@=fZmY;fm`$JHyx3~Y9Exot>%k5ty zAvAk>T~G4+EhP8U1LzN5*vvm-_Wb-yHo`9O=NEY8CR+P{apzqQbu)-F^#WwV0Z0}ruQ}mj2Y<_LhgPt?)J(6#ivB$1x;_D-{NtwRtTY_8FzyMV_%3QuJg%wn~*w9-Y26-_lrgEgQ6j_lo9 zSY!75yKpML>y>E8%={5x_*0jy`|ke${E*we~Y4UL_#PiW18Xpwd3%=0_2ysmTQw;v~Ys{fp zMxT(X)-9+VSUu7wvdIcY;~PKe-0K ztufX$q)1|?m%A@QQ>N>n4uCpSow7mxh?}c{u4b=)mECJx7+;euj34%wa|*_p9}BD~<1sj7+O>%l{L^YM_8 z5D#SaAefybEdGeW?m{Pki*IhfFCp*gJ z;vNCTsiQ0glNx~?4(dxCfTm=n^n{ZS@PvzvjxUb@jkK{;FPYLHAKv45A!9+yR7(6F z(3laa5p>B;7--Q=oDzxFOzeSE^BJ@SDE#c1DAsL3{Q!lNDs^ZE=-an7?Lh9_tkG=h zmm#OWQcg#p>ZIZ~DGED5*72XonpElDv=v$B;Dc@gs|PA~zOjM){LPJPU{dp8jaYFE zlh&?3qams#pa4O0tYz{F?z~GyM>Y&wrfdk9MZgbK^a4jHmPw^dFD zs{r11*kcp?d;whgThk6^MbT%!t(^Lqz$9T7U5DA>-e=W7!?m z4CkV!C(gBoSIF)I+DA?-yn^m~owf1&&BOoYsho=OsjThuN1mFz=yR$TkAe4V&iutp zBY%tMF@Ft1$}c?Lh>Q#$&n44)XrQ`C72%O9>NaB+o^~o9EaaxjR!(UnwVYg}>Q2L~ z2u7C@m+ldtEcaSa&J4k|zy!xR@<+lZ4)<^h^0z~NcE)%YZ%NTc`H-&~M8r$Pf#~A+ z(c{O8qsNQm$BQ%FHSkZ%-D{K%TbsSKOnKHHHUKfM6crt6iI{P?dC7rVbFRNmFrk%) zgPa(mLPbxL&yDbeS-p{ zIRKA9q)uo~DPHO6d@t}|KuK(kKb75ieqm;Q@drOhw1!X#F&uV@`zmG~{AwID*z~z`GiT48nmzj%q1>Z39#RV}1_pH8GTw~gw^En3%Ng?Bxh6z; zZHEX=E#@x~3JON|C=8bAB#7P@B@KEjMZUc;ixW=_BKaX|qUtCBJxR4hV7Hh7ioxPo zvh&rnNDBt?QtabBzF?1nhra{SkVF>6jC2sSm^iHn-o;&>ThM#H8Pk@VW94{_QU{$- zO2un^QeEet;;(cA+BjN{9CzatYf6(9bZ>ZCEG4s~g3GMg)FcW!#jns^ z5U5Ql!JzNoD~CPxBClp>n$WOQ>x2X>6w`*Az7Tb661h-F$>Vs?$j$ZjK0>d%YwJ+9 zw9JU1ib&)W^srYb>5Q8~6UeJpWvJ&#mPxu&)L^e2MuoM6(cy#DhxWwj)Vzl=)m?oY zoKjHTnnjNuic>nFOa#i8Qyx&itn zE7R&?$}uu}fYc$VsIzWRRI^b$@r<)QdM`Bvv4=w4 zy>dS|=rA3#SeG4S!_v4=$^ub?JuEi^@FAr;m;sb{k9g!`O1Nx}=n3N9_NSmYCgU_S_OpfHw zZ1q%60o6l$3H+Yq+@vNq#)(opHR z(C!ELM6(61pfe7E-)YMD6%7=xqZxdFP|iUl4{yKz=r~=E0ww0u$1nNA6{VE1V!nf< z{-%rRQ9wdQL+W?k0rniIQ`1Bx?^uyCpYzYJA-Chw3KSgBQA2h@u9sGOmH8Rm1>^%k zq6;B2-?Vj?se#;T1p;4(13>9B?M=-Q2V`173#d*L_~kjbQ|gF$2@G+T-@5D6spPxJ zqQR2{M;A#)$xGGP7(l_zyodW#{`o+BNEfTl5{K5i?L(8rQ^$@oW&r1FWLDVH5@hYN?L(e; zp}EG%nS~#oo1MFGfx=Xh?3)kr=MbqJ9y|m>O0yjKjzhWUvmSeKb%>{qJ=y%;_rCXC z{QHhZ2_5&Zwm+(lAc$64F^KK#!L3(a>*0BOwBbi{sGPa|C2Y@iR7d8RJVPk8N8JHR zbs)9(gHpJ6rnUb3+}zCkDY2Bu@_HScfQ#!iGkO~n@O%a* zw&lp@OdV>NxVY)ZNtcOkDEX-h4qMX3F8~UgLLN+P;W_)j+n;=j&g& z2!@soxuw9z+#cA&sCCb83@5jL532mG|#B)Ud5H+>hK@PaBMP->f+{7)^`5HfV^!QW7 zw+sHs*G{82e<xolnesw)B$T!IpmanYYX zHKROY7R*5yRmLcPSlE#NDK{92VcuQ>ZCa-sAlX`NOA*nHY%T(CZ1bU*yUW&YH(;0e z){zDHSe{w~nt8F+I{`5ix@laY=Gk9e=qx>hG;i{1_1C6{TWd>HQBTQ&&d2eV(~pNp zF}p+$uhOO9PRIj|)h*q&P`L6vh=;5=b7~EFCS!=3RP5~EUJ5ORE`V?-WS6b;HzgO{ zfm}s3AJd^z0mLf8D(@^cQYP}iL~o(vW&Rbj1iM-n^Z+?Da;6GIgRnIr<-nmxLP1`2R{T zVaq2IEhqiauz-%$j&h^*UWK8Ol90NJohb?V5RkZ6C&7`WR`m^ZsBr1 zCYEWeiEU4^VRv60t$if8*A0>fQG>kSsu&M%h~d<_!;j&<3xM#tTd8&l2~;Ogc1tb# zuudTRE`TTmJK-~xy8x8c+y%*4{M7ZfOL=uV-JfPkwitqYXW+(MK~ zPmE)Aq$Q)OiwBx^5U9UAA~S519d3%=sT$loJ=76#!|lU~Ki(T<%)rj<#FUY!)9u;{oybqBQ89r1FC!#) z3k2l)JJ6~9)T229_Mh;d760I=aKtNHSB$HK>GuXb0r)YPf5^`j)>1}_6pwH{_I9d9 zq{Z$(j7)|-+?T)vZ-9`uHMXS&nljeMO4DGu1|4Vs%KiFZi+Q(qN*IM{J*jQl- zY`;8|v`!#>dGplJo%jC0*io>~VO5x(!B=BTd{DJE;YLh3Udp9tTiv*rB=BBbOuZZy z7n}9SMiagYNsQTpp*-Pe&Eef7TB%VG*-rbBkIC>JeLIH2Hxs7@FS7Or-jb#hP+uTu z#I`-$l0i5|6O#CMsTKs~m5!G`7|>c(nO5B_Guu@?p%*Zd76Q-AkSpIpxTwzJ;rC;3 zQq+ze*jrrn!bZ&vj^+^|!9aooZtSaAIi< zwshLUiegE^n9&keIDXaJ9N0su(}d34aU?)JxQ3T+w;I5G?<`PmF0NS0glv+mO=ud=SF)k(CA?uGd zReK3+Wk)LMIa}L%=r()b`m{?~hgVm+y^gthX4g5RN_2{!CMYmHBU;opQ7ua%@51l= zBmS=@R6()y%8-U?l85(13tYg}R(AvBU&adGtO%&e_-?{!# ziRWM9Ume2GsX~m?o{uo1rx^A+opqXG5oLpdCtYd#33}t?SKyYig_~qPhV`AWqnLxLbj7-YeVU=pK|JX;y{Ly)!ifrB;skxMnI30}W~N+d}`qnC{j`x#kj z1ILH+hX2`z=2>82;Fur>YXA$Kdx-k>`FAhNBa&E#y^}cN+@Q78xzu9m zd7=-*LN&oJwgGtbnXw(G@rDNYHMkawQ%jgDKM44G2|Bt?Ia^uxjqYlvsrG=RJ>+{` zpkra#SYTsOT!$kDS4?0tU;P^F`PehiIRGI$7BC?hmhiD z3)e<3rr#GLKYEZnjU^SlTy@3vdMl>qLJ3kWTiZ(vjWJK5rg7qY9s2Hyg2 zf*M<(Ep2dkM_iem)qZ;uWO;dWO^mndsn}x*#=tgMHJ2nB64P~q;}G0B1hb2S*6`hi z0c25UgLxa~398+1(5WUAPNIsI`tBMXUrCWgMP2R@0yW?WWp4D*qPNH7WK8V_qsfS2 zlxCm1yh(iwPouj(g9=Wr;&Tksr)TTJSi^C6J6G zmwNrBE0dGOx^^xO8BQ`cx8KLW?>(|T)h0C4Ee{ldN3yg6Qw;-$bA9q<&GoGY#rV=g zld2L+=aG}puq?q-Z0o{>(tD*&B20xM^a(|T1hXoqX9ukyVCm?Cv7Rb1Q8+@lPtM&i z^@n@4GJadrpux9cI%tRD^K~d!sbu{NNW={*`@-A4FLC(Fad2mfYSU_p=sr7 z<%ejKAZ#!?oPL>TlK@1+7F{NBAkYVT$YC4W=Mk`d7&>d5qmtGdMlJS&@tHoDwK!o$ zVUNO8c%3Kh%_E88Y-%D&C`E8*8^uXGnql#Uur-Oy`Wp`fp>I#AMx|f>vY0>aOnZCh?1c;UB+(+QJFrNU%#PMz;BTlynWa7)-Gmer@ zLGDT`zD6X=)Pbf``KWMCtdvvo#o0{? zYMk!(*P}vMYVb)E=_GUTgl7&+m&}@Os^SQSVjutE=>>T1vBAMU-y}8A~dKU}YLdpPGE~sgkF3eumB;pLlZOsp=9XM+yy{4?#fOjKmu>Npb6~PEH$*DzO`d z`Y&GSwAVUAoZ4diI9QvFmCb>DdlKK42VLEPgQ(^bIFvAFP{T)IuMQn2YlyDju;WW1 zCOLO>9Y_KZ$Pg0um(c>bOrZt5OMAM4cEF=CC;&22aTr1HgR~CPP81cX-c(Igw$^!|@viCW&0wJE)fiKJiY;fu24KSHR&Gp9~WGbFxvW_G?f_uLGS zd-|jnE#M#?P~ssXKrCB~KWW&}ofO+3ty*%HWmn|);{0>Z;gO3pogoXBJPTTG(gB?| zlC@Gx$#=@ggbp8eb=7zhjJe&pW<`&Edt7~(;d?O3q4Mtp4Ngi;ao#~T;cw!5(HA?n z4wBMXMj&C_hel%Afm z%c!u=SEUHU+vgA~&_fhTs0jkug*juC7i_LI9A51Y+V1Of{o#h#&tu2G*F1{0)4JS$Ng~m=y#6B?c;vMAI0Q8jo{xi z{k1OCD=uSB;)%V!vGR1+_llq@40#1s$@a+sGP-5F@H{-5sH8d3>#kqww+3xFbu-gN z*bzz! zTDo5gucc?|VOPhX%pCe-3j%GL61b|97ogvNHJ6RVEAU^5LJiNpx)=TL$EFT8eH@@b zLk_$`vZENuO@K57Hu%s!lCd<4nlvKWD8zDD`bu&jaxlI7GYk@E*Yb*pJ4HOKIqTCQ z)nYa2cOTrM$zt)S(iNK=8$EN4l`Z9Jb1;jwfDWG0Fm&n0pFzI;JXwA;^#^m(|2@az z)s~)XtHD2#hruRe4{}DaXngN`h~#V@KaT%P%(6QmlR{m@YBWt?DEL$}m^1)h8(Fai z)Q)R3b4mii8XEvfPLjA5{d={u8xF^2N}m8$@#JD9-^aV3VmO}w%Q_yiaA{i^pYd~> z+i$t4bSTylpiY7b2FP8bd*yVI-2x1~JdWw;{Tkx-3AD;FKun!xJRup&VLibXBSuB5 z2>N0~%)=TLsAxW_=ZDCwl~K;<5C676Rp+rpa=0#aRL&(f;9?LarMhRv2jUKFQ?{Oo z`}(Mk*Z{EscY~(~8XQvBta&FXR3VG$gFdVDn$JGLy4Vv)$xuIi#7^kT{x_hp#D+k7 z`pyJMMwvmkL*od!*bQ<3B|+JR_FyS6^%O}sEgM88*z(EZ$>YUOeo`Rh6TgprSHHhA z8pNKo%1Z(2OC$mlvY4(U*M<4UBjJP@SPaaW9s~lkkkrfDf6fsNM#^vio*(}Z#_Mx9 z*~0LA(nf<#r;Vk4od`1iC~;1jITH=sV9fmzSi?rUoFlT9phft+#hns57PtXMX){V# zBOoLkX>?(z*K~;3&KLxij7l2C5e6ly9e1A>T1bHUU85KGG{n)HPEM2>0D`AOLYf>V z4t~(VC1%A{;OcU3Xqs{g7AOhoXx^JdX9>-D(UY>d-2EvZAuR=Hb0q;eY=YKJu{j1uoT--EP1uodGfhOdpeRw3 zxowcDO9po2U6M4kz{nlODdbe1M@_awKy8&WvpxPaNSV>*P_CDbOhX$8DVBIPCDmzr zB&bH>tr;{VPEe!sJfRIQvW43pZvTQbKW&IvT}uslUQTWKFA@bYsGO_XTZ0Qr0~Dr1 zbNO;=`l9gaDbjiy_xsqxFOb~(b=4@1qhwq$$vIVW&;BoFx`W3Q1bIo zBd&4=7`Vu1_O>UXc*lUzUw}A&IDh_nF3>ef1WUb^u9drN)RF|eNxV3bcQ>Y=Vs3u+ z+4<=+#gC@vPfb64dZw`J_B)$T!|6tz>s&*NIDGgSwwLk0KDLL;_+p=N0Te6m&%b_Z z_yROp{i`$Apu?g10F9Y0qP92xIP!1@uba#tw4}5} zmlifvYnE@pUIBt^N;Ro8y_}qAGyNsg;;3gmTDw1KXY~&x$wa9}@MHdBPIK{Wjr$WOC=G-IJ%r)%ueXI@=7IC4V_-q$#Dn654)`5@c zc_fQfpCaG)b!OgGmsFNdO)64<9VA`A}tmj|uYdQ9!n z?B207;qn@B5Wqnhl&&(sV9>vWMM2a-vJ8#5_=pkdW1a^+joEpkF(SgnK1d})w9aK5lDi8+I0g`JE;nV7&A&0Z_*mflyafJEk zfD%2;DaN7p?qUQed7=cML&yr*u)?@>^x_ng-eDDq*R^8U|Nb84QA5p${*P$p#WO36_arJ28k$qi&BCCz&}kv9U(w#YM7tBvHSuDwAaWEv zTCX0XLB$dY>O1y7zTyogZmUm*wuG`??4 z&qEZ(H3_EF54kK4QkgK%y9913NT@pU<{nZ)*VG}Dr;fCa?Vx9xja~KEfR8(pb5L6WpuVIHCoQhV8C4V zn}Yh|z3p4@p<-P%6=Or4g#^MKG&-mq38B);QSD){Va5+Pj0!k&3Vi6gM>JDa$4 zmP>;_uEGC3sJ^GEkg%?;T?(O1O^H}rv z(Y;MLs2jjn+NtBx_yfn!$yvJ>Ga)AP2Bwhsw8c=DeN~kM%zcrTL#%{HQ;q!_s{=Pf zwh}E>?bf(jm8N0Bbj&0j@k-V|yit<=v?aB3%cK zfm(3B!kPd;g?f$pX=myuCN>rI4VVO--#jK`XsCqeft{EgX1|!HWDfHu9>a@TJ;Qgv z`)0}j8b@_DVP^W$J{V&!Q0#kHbFKpWxlJAO2-P&rqx9mFR`&*;V!+3X4&9-hU+ti6 zt|2E-;J$)0REEU3KUmJNiW#-oK8k>Xd|Ee)oZ|}PIIUIa!I5qd7xOkZRo-yzwY!%U!sI(acrh7kSV5oQCS~wF=hCf@u74{k2!Wi?F1|XS%3x# z!#F9?)JX*i0zgVHhUcyI<7l0^c932OvH$(mby!I+b$i{7n9vNJ*R~yuw4q53y8h9r zbo?h|Re@UA11U!7KbDkCxRU^Hu7F@~(x14nfuNI78_-`_d_Z@Nu|4kaz~cogQU~r_ zsk-Zk|A{|{zVo#twP}b-fZBmh^KOem{Yh`h32TEOA|#Uv7HK)!`-ZW?+NVqdDfGW@ zMSf^95-BMAN2~vl`wRe*b*zF0b-)CGM8vQx=ol||lqQ5QLw4;@b$`%wO^(;X0|Su^ z3W5d9sdh%SrqXEW@rBl44WU2T zy!Vqx6r%{+Od3ft?G1%KQz~2!00FJupwr$mlb&os&fLdkYZlP(B}8tXCOi*GNVE#_ z3+RF=%gmg7lCTz!x6dc)j8n9xmJKi`yF=IL2pi1PIEh!zSxA-(Eeq8gz}t9}Ojss& ztsL1>V=tleT-gG_DP(Fky2{ZM!K@vo^GUJ=1b<-YnB)xqiE@!c>lCV@(L}&|k1i;C zgcdbf=nQ}pa)G70d=HA$omHdlu)%^4cZQTP(UPUnM*}dlYJOTg8onSRHlq~(iz^u( zfEf7b6{I^sBnFhGIWa31-C6+!(h`~;l13&t<(qvDAmY3@t=boDS$LQM6@M+yeL$ZD z8Z%hnZw($Lbl^$Z%0726Do;>&U_&p-3Z>G2>K#F`{LP)gj|$R{0sWt7Q#7>9hIaQg zs1I&RxS_}GjiiK_`A`L&bvSsBNF;xVB98FwPP-e}3DA}upR1(!K9HI~c`H&=#7SRC z!D%NDkZ7{g1I2-e!ua%uFQW7u#h|}bmMeEhrn8CMK6M<)OVcz6z((k|aq%#-{T^kNG?P^l z_5w?>*7qW-akN=K>T8cOM{~XZ|Fie5L2{kvnV5N#M9AyA*Nzo$4tt`YVFFEDXv#b0 zPz3^@2$M~q0MH~dL?(@yGeDb->DlfckYkD!NR&$Qk`iT_v}j4B2+8ZMtQ8BQ2=OAC zs$71hQmIC5Qu&+waBV7;ADdLFlCAxd=Xu}ndd_#cdoTb9P(8MYnRCALUElA$UshAc zPj=JuJM57^C6Pj^LF0Q51@!z0fMR4Hn-C;MaN3T0PpwOZyHE|}e3u-7pPaMSDlHeq z38i5D^&E$?M3Mu~rop4N6s!@-IVn3G1;yEi*8`7DiE--OF+utP59bwPiHFMQu5Ml` zi4`%TLI}ZINC8eUeC8*c^6`KxsgZv1nUk)Wk5c3qyhOqk1hU;wvP@wIM4r0-oIM;0 zy76Ug__%_t1mo~)K*>_X5%V$@7%pB+qpa2y*oS8M*JI6H9bx5 z!GmX8D=5+3?{v?)dC@r^xr!EZvYcMeYV_SkMIVwhqu6yFh>D{Cr_^dtK}_CuHf@l@-i$2pJ+HsI+C3 zRia9pOog1#9ark;#PbmUQT-u!XQuwBbjPRXHC2PgX)(x8PKR*`Z+}iShhJfT;KDDc zb}^cf=if_S_v-I2dwC5qGga`D;ZZq2A+ZS{5rB2-itD-iqQ^F|QeK&TJu0vru-^FW zl&N-&6BXl9;h;yNoRK0v^b1E2MvBNW2IFdad7w>aOf<;C72A%ZieM@3E-zQ0icyLa ztm6tBwCWw1%Qkg?#u7GT-ik1R+O;-@f-WZ@!`r8S9$m@&EVGyYI3rAv)et%ES_ck{S~ey$wTpqEN{}5w_pW?t z-C0FR-Y50-gn8T8BfrXc4W`CXE8|x|^*`{@%!qDyo(4*>A8Mos8U_JzWHNke8l$|! zKV^gZJIWJSHYldSjtp(aEm0WSQINNBn_YsYOr>^WO7l~a+7+wbkRtmi$eEh(OeqSl z7roM6hK>+-_BHo2DjeZ?{nKj$WSUvYc06384_0$O3pj(HvO)arBfM;N7T1`&SBPZa zgx=h_4|7jzyVpwYbH)cSWrSpN)QOk(*1Ll1)_p~)mzSnPHCeUvLfjtc7%$G4Jv z!Lauz6{`w;>S}!Y4@tG5LpwOL$g!kyK%W>GvVgY*hK4}uj?iSE=BE%VA^ya_e1S?; zIUm)IJo*T%%;JIyD=M@xj&^#lK%<3<6hp?pHfX&;KTCi0?E<5*NAz|T#VaTUHN%HE z0ZTrQ3R%l7+z3|2D==6CUbse^;X|ezf&~!#TjCHBCw8N;3scqob*;Jwr-17#Y(T5i zZh5!r8JKGIIn!rp_AH0B184a=?zjUI{UkVcjJp~iWE3i98p5L zx7O?BQenY2*K*_O0XUV|?0D6tN8%s$XGW*u!0dq3eM8hu-$pEG zE=FjP-1c|!1HE3iSFg!GT5qI{?1F7vhCfyAn5StuYidL0wKx z%I=(R5$#TT(FPXSvs+2ysC8{R*bk;2-5Qkwl7^r7>Uen7IX=dk?^Fkl}A|y z7iD8hRG^$Q2DBqb}B3nRq%I5S|ldj zAml-VEB?`gl9Wkw%;%7SS#mMMDeQSf9HZUZY3IM6#)oMlU*;ArlnxO)r_`e0+kfe6 zP^%%Aw3#+DPIH}-ggBf4Ycg=t;DUcSDMH}ZPfH-fPPldNFgV%5;C2u$t)PPh8YyoyCp&2F|XLQyVOc4x|P!1W9xUE_J zG2lYb_{R<&doa^qhv)f=)R)6|y!?!F!Hq%Z7)z^bB9odR2jT)r<%5B>wp@^M?@e0E z(F3RWW5(D72$5()64|*BpbH290$x%5I<6_S@WepO#}1{t|M<^{B*MCXK>f5Cc`$Lt zp8(9TXWzvP1%DySys7fcqAH^&rFdHK0hfY#VM;}`E%(chS|TFe^uWNOi|9qtBw=XH z4JEUpjQ~3(28A!8kvE9Q-m(qg-qS0oPy)=14_G$CSLo)E+uAVrCIQ|zAs@7ZB}|bRkv(V z-4ep6vIlWMxwo*We%aPkE`ceoZ28P78$@SWWKL*XDYGjfpK?9gYMfEP@s5-ay@Do| z*aJCMRXA5fx4-Ymp`%ClJ$PW>L*rHaZkj}#RX^f+TGBg(*mtDuE9Hu*=Q!Hw$!!ME zve`kOr#4~JD6HF203g_u2PNGZNQ8Z%CiE#aaKO2dF+`yr!^T9#n!qGTE@LuX2sYv$ zEC@(y{bUVQ`vOT)yNJmR6>Rl~!s0q5w(1$+vi^wbp) zDvgB?y={H?;L&3T9@!eA%y4Sz64uWVZ$!XHlo8n=D%QVrM_X zhwK}B0`bVJ+*s?ZO2y+18{x{is)VwSyH9D32=u*6&!MiFIExn+!j-8L8RXwUm@;#7 zDm+Tsx@~qt${R-!8t0A|RzLS1T+?_3M9*b$|ML{(Kg_+OiJqG#0;FGyXzBFMe>!OAh|0ttL|r^Rt@ z8bIO}CwL?d87i`MP}`32sKooc*86Z(W{A%Py|KjLi{hdgf%tQQn!@N-M44hzP``<9 z-ZqNs;QDz`RK!p*@c`)|dfy>Ab@;l9ItH&$@CW0MMV;YsG_V$tu=NK$*go9sl3T00 zif^RQ3amlgSNx*}A*n@%dy1OwPxiC!N@v{~%RDLedm$s~9#|vT&sQcFr_QnBrD2-< zVNnVxsX%Z;V5hn<6&{$o;skNb5(^sCAO<=_TVWw(n!#mb8C;UUq^L61Rm^y-5cv|| z4qk^2pBqym_@!-Lo!}wV0Vu?L1D<1DOB@=lQY7&Chonp}pfV!jvO-4%MdAb9-eN8p zSV(Lqv1*691ysdIaF^s^gg&dX05$?L*|cMjy~iJ9*T4{$%so@B0vJZApIlYZLU^2? z7p+1F*U|mE@~VaM1)-J!rW$KTEZeI~mj_==U~ayAorG+G{Kwf9uM4F_dG8=>y@rcE zi8VUXTS%xErPqs)h;b7j$$o+2F{NUgeAMU+Heptq~J<%+X0@Wy!QpcnCX54(MqJD z53KE+q9TPnCcQkzBvDjMaz~Yga1eB@1>~zJ9sPU?9Y)xj+|b%xy)i|NGMW+jqWsv| zPGjCiT2su8A5U$k8?>D&z@;P+&#gy-h&QG#Z)JYNC)=pZd{_HSR(mF8J$<&8-L>4# zYHR(xClzz^f0ljv(W3{BJhHcW;M29OjuW8!s+dvZ0}a$yV9CwkcS7Bi-SvR?8T%+m zN1K<4%cBD45~FFBP6R`Umc9oF$dg zj&&2`uTay9`V<8J9Ek0xd@@SbL!U8-Ka`QsNz&D~+NU>=tS(Firt3mrN_$eXv@8I_ zSYlYdFvucAeSU(|71oiN$<>C86rZA>e{T3QVdzw>hO;6$PN`r?K@o5{d>_^&*ay4~ z5L$k*cL@g=ln7R5P2pOVxuyd&>pl{M$s^LD2B&J{4mrGV?R=OG{TOX(E?j*_4OIUU zUguL+z~o%OA+%Z?J8<;a{)0!Jc;Z-&st>El+Nc4N;V1iMpLpWP;l22z_^r2nBz==N zDJ(iJ|GJP93wsG6k)javKmbw5J@B|UCOr##FjBHbg$FE(aMSdaa(9I&l=SPRXcgjM z3TqW!t{D5fxDsAYEFE1*5)Td?Yx|a2m)y_jhRN0TYrF#?10|1LShC$360d7uj&mBXoG=e;j=8IVPuH8Ft07(+*l-v2)yh50aL66G`0ocH+qo!DN zN|^jESnR-sD`K-L36{jkBAri)kyR{A=({@=Cr!NSjSwz66(<=+4?od2P>lUM!&ioH zIDEH}w3ZtbC++=rV@)N>$R#=!9DtdkxCKf)z-?bg$+Z&Fg3${hlE8hDTkczE4%;4N zKVv&%ko8y54&Jx#P-_8&+83dh_!9nthC_XROOvqt0WfeupuD~XuLAYhh`@N`2*r*b zPNhq$i@LF5IVUwPdhXs}(Hl>|gxg}w<0a%qkuD22HzkEm<;xFIzO-~aI?sgoSmfcQ zN#SrmOc8S;3Df3jbWF>&56Qg2#J?G^mJ|Qq7T;1re=~SXo`%}L*MjjecR0A9x)pDy`eow{1i-Nz81`|c4EF}7Y?n!1D$SbzygIh3&};b z4DBX$oh$j%NKAzdLf!iAiUaG;!*V^{B7KSj-{g_*Q~QzKmXkr_CG%^;{j$=13iZV` z^&NhfbXD$a_ychJvu;NVqDvYWs56*G?LL?5?!N3;zIb}2z1Xs0u?~V3P$LH1=UYoyGc3(T;PegRX?D>x+D{CQ{??(Hb z4<>oSEmY*A<*eQbH-3jMNQUK!w+Hr2aN3PQchKrA^jREksgJ|BcY^gk++LP5^-#lt zmQuJL;pgThV^+FPMpKh5sN5`^MYO6pS)%UNOlHT_ZlR&?=Yy#8*ae?M@rTIwVN?Zr zxUrOm zP&6OdbdQKL2;o0@llGp%MY3TrM3E=ENw zf@0PEsN@dtMaBPZ*&=rxMWWhgR=d4HwyVc(@h?5IO^x5A2-X#=NLmgvbZGr}dlL({hH_@3+snD6D z>aL9L=H_aR%+MY(a-6~9^sPoRLRBNtFXu(1z<_T~rTrhCRc}Irbdg>(@T7(&ioq=K zkl9v92;w2A4X_@K_o*MK@vI8*32shUxz7UM(CYc5;KUex#*x+q5OGeGJPn^vKr~wh* zET@R!_`?2ImVqX$q{1YZI4c%XwmAi`wl4?MmN@f5J3C=|T8ti1$C8Cv&>F*!&Sa+t zgVp}*U3c{dxQi%_)m!d#pK2_2&)fy0f1kW<|E^toc7EobJ$LnTd9-7#wYVei_YmGCJM0}Zshmua&z^6wNF#7!B@d#mHat%H@$*Kj(-*x+-7h6E_wjW>hBFf96x z9K=CFZh^CCDuLwVzV&=(8$4jW_HcXUNs*@9mpJjPzjpFWcWJGY_k~~Ncwv0Fais6| z8tyBz^yqIlC{4T@YrD}AjzUbHcnH(jjd7^6GSfXItzm^#{BWfr7-*cz z2lZMsXJ%1FN-n3g+Mh4S{V{to`>Ji953XS6s0GRg)>hyJ)m>rkJd6j4H=K=k+;`Jt zhiv%76Sc;lblWTSZok2-vF;B{a`CC9`nK(0nYaZD3)>p~)lM5z$2Z&NXLp3iKxA<^ z!Q+0|rAr1woUj|Ryfd>@U>sD&Og5YtI~(-YkrIEfc-lb%j|oqu`7ykOeuo*y0ZFI2 zM(44d<;+Sh_!;$52wM0DC?V>E9d&e?W~amM zyB#C!)q@H<I(0eTXu0l2i2kC36{qq zmQI5^j(VxxOZF0@3Eg(W92hHm;mv(tHW!G1<4}DGcGv?hMr$xgj)$X2PH|g3LICmN zv<^V#QtxLVje&O1PTEr`S2zF~l0pvt3?9{ru&|77pl!{zK9hj-XSXu#?_$0xzy~GJ z$sByvEOPR@l_O;g?bv|LlWBBs=Vy^U$_oLH7-G=S-Hottj0~fp_NwD%h#IXv*HI=? zRpB4p6wSf_Zsb!Gruy>>3*;*n7W_pv?SNYiRu-sHxbsKiw2Ej)96{|0k%_i5AIESt zlkM+9(P`XHg#{7jMo?O`7;=vb3kys6YA?r4&X*R#Ls|g4+Z!w_xRr5ldG17|!F0%- zVoLK74FUP6jqkdsq2UO&du*VCZC&kl`^s#D-z9#>AIuKg+zxY#*KOl%g><^n(NPC0 z$A|UsDDk)b&J1!wm5F#CKp`;-n7d9umxIH08)kK6X2WD4T}q!lfbn)sXGX}k5Sf_Z zn<5iRPeUw1aFU9$asDXCUar6BhEwHC?#ryO_83wCfm_@UE#x93!*x;#%g%z1SXv9r z1i~!|gV35-O`G$yPf?31?D%AB5b^sQ#56`QGt@~1!IU`fWp&E92#!Gr&6ns(f<8oM z*Ruws@Z#hvDaKZrnqbx29W&!Us_~)QF?Z9v{yrEWzG4a^fEN-K-(j`3u%k(#bwc>a zFt}1hY<~;&mQf^)C!|novxi29=x56HM;$igrW!fU?oRY^5dw5Hos`jpN!Dt8?)F4R z66nQRZ660$Fx<*wp7_pv2tJA&5%pKHMlBR1_W^~aAzT4zK$b)U=E`=TbxMtOir6u2 z2{>%%qdJfi0Cg@ib>&A;Fxj4#O#$7H1#^Yb{sVjEV`` z6X2C`H3&>!TJHe-l<&qJhWX66xQ`4shz!9Oai)L-(COwO_wO2OwiJPXLgPWZ8GU`-iM_l_x{O9(J zlHRHQ+%s_W_?#6kYO@i@i+@LHy0uw1mD0Na8MsEenc8%7K;sr;Ix}~6QxJnbFAH2~ zqP7<55w|h0N9d$SotQg^;H!xaD%|$q+fD9yxu?x-c+j6k5|iFg647PkD!_NGLCgoc zE+{~1$tsTx1K6IgJ=k7a%2y8dLk5mG)_f%QlqL;c)qo^N$_PazE<(xO<Pr$0&T0 zL2npgB1>+Be1;5K*%xB+4Uw zPAUDJL28iz5F?HDitUr*%+06eh_kyEb}#H)aDzZUwHu})`zcpjm|UPH2^M7_$sI(; z^*H{%xu!OseYXcW^62`?;zYMjgR8nHQCBNL2qs07ZW5ckt;K#ecUN6+B_f*D-8&xA zwg{BnF@z@sE};z`x%#9G|8ZFdX1?9XxrNx$ttFbnWs|9j?yl5X*qwAZPdctvVa zff_ux)pWb7?r=Kp`S>lbmTlQ3bcmI`UiKyyX17Vk(Djzpp^x4sJE0i43UciiS$!pc zNwoX_>|CpwZ($owu#+h+c0bVu+bf<0z)R))&#o zI^IpJX={szXLY1U_+{wrK;iTVP~1 zWXeEv4%{D6_Y!WQmIH|GN~)Wr>VH>bcjGf=8daJ!y+U?YVh0R)EVUNOiUjNe_yDxT zOO^&5)fqetBnD3)`rn~l#K=Hcx9C%WalRHoiFY6hJG2Z8Cd9AM=`+t#K|MSVuK=3% zp>SfNZMaZ~nVnU~Gz+LvNnJn+2*mlIr6hWw_Gb95qy^M)B18`{tI0We@sq56Z_99h z$JST#`?hEIS_e=5Zf>F&I6nV*doih(3*PR99C)8XlHHY7U;Gql)5HpFkHF~aPudXQ zQCapW-N(YRkL1fRsGY_Z;ZC84T|2o4$DkeP%VuY*u+Mjw1Y1yw0)a~QqXs+L5!>KT zwJ>vf#D_6uGhKl{{s-3m#Hi3a5+RB3wt-<&7l9@$*#+VU{&Y+|-~HIA2{unZ67cvN z966FC!cl`2W|+iADm1ttG4GavL?7{(OyYJFd$@Soo&rGuyDox^9fSXZE0cYv!!DAS z>&{bWlivMk7+|4rV_~UFo|roaR5VVvh+re$KF%@yk?R&}ESzk^AFna@h~^1zqB*la zAwCCJmhz`z%%PM+%9F3G!CH?)s;5^Tge9>L`$H*@T|nb)F5Q8ZC41IT=Fu8Z0)cy> z;2iN$c?axh$pX*zC44T-6zG)OS{$swgMLT01oJ732}^LC0WrokE$s(8h#ggIm-gQo z7{kxNM+Za*sWJEUVBDA_4LPw!@9wYv(nte$}cf=3;2chtX~r);+q@N0UDo&tt} z<+DXo(%WJr5EC3UxC-eC*BiVWN^|q@^$}JAV}n^uI~RX;(iBfYIe+K^r32AocGpgw zHdW#6CUih_qq&cPu5koquj!b$LZ$ZvWz%bzo<`w`Mf21Ta6r;h z!|{_1$ZW7pjn_o)i$FE@1z<043V!vrYyNAyHvq5AljDpALE8`fFY9Y-?WG3)b2qt_ zaJ2CEXhgye$M(!s*p#uk9NJ=?uK+p|5p zdwcf#+p~KD#YnhJBC7&9YCNT*fH2zA4Z5$!MC>X}Wvaj7RA#QsPjc7nQo&yKU`sij z?E?D4L@68dIz9N{Y_mD~%WE(@UMDvj8VKFSkKQ@iJr*TG=yw8=;O7ZGFsRF`?14*n zJiIV+<)-)Z&i&P;yHm)06Hsqzjgt#S2>PY33YYr+@MpLc*{GePnMgD z8QZl}g$5MJk{8eU0wck>0=%U`IMLyrfJ*Sw56*tN35N>{pH=^+hATa50Ka!yi+Oz= z{M}sXI`e5FhFaz$p#}DDuzMJj$}`~*Oi z2V!b38_Q4d?)nT<8=K^@P2!x z{_MI!@DDumoC06mVj-vi{++hTDqx>F4c7%bV-b5r3z9tr4#yfh`-Db!tw@Z>Ir3&b zBS-gaffA(Gt3%%dn|Ea{&s4jB`_0X{QZu#x!N%#P`q`VCe^i>4 z35PVRdHCk$qipgU;eZGGG*9LRnwyW^+*~NPK?|lYG5xe|ZnoLxx5IwIxJlElb93`- zsomjqwP|ov)9&e;n}5%C@kZo*i6v|~ko(!q&HsbVekU9@jv_N1{+~BDKXnUQ{_>-H z_rXj|co7qydHuV$H1Fi=U&3p`6AgNPzjxfyyqj-t=Ua&}GoRgaOY=YHi(ki!qicZ0 zW8Ek7m8i+dTbe6u@~e;KCm%iXu&BoOoo=n1ve%}6OY=|J;8(N(986c>ISvM7vVqG8puuJQL@60rQ z_txe%w)@A4c0fU<)t$FC_psG(C0hN_(L;}zX1{-HbB@h^z0iynP}AhIw>CeQY7*?s z!CRXr3sb_qT}5bdfY6&uw>Eoh^^g2m9y-=;Z9c=7zl4{B9cCl(Z=b!j`4u|{dE57Z zVy5|Lw>JOM&Vfw;Ob@mp8v&QB`;K0{wfP2H{h|{F{ktFD+I)}ie%rk>FfM6bAT^nh z-oLeZsk)u-?_b~A{0FxCRIo4*}TvK>W?en*SG@{)*}KU|(pGBPajQ$D04><9Ppz=6y)9e);3gJ$&~`_pZBY zmi7A|Z$8FXzhqv;6#w|gn=kQg&Ai1%S{ENOrHzFJqoY|^F#Y}P9^Z~7+2cM=!Vp3BzTn}5hgzv3H3JlEXq z%?{uHu77V3tcf!W$?(eU%|B=3ns4kN0esED{bciHe6U7IE{WUz`6r z0vT4?g+gUQ=94yMVY&2aAOc2n9w#PBM@2bZ9!?@NO2YzMCC^5)Khh-4aS5}cJ6-Q>NMH|3AC04uKonOFW!39|B{fMDcVECxCePu~4{h>)BVnfS~}kMgcc z-j$b;xEPCp<@d2TDet2>IeA-N#ge0O@AT&~QesSW5Q?7V*OBZkuPfOKd7I#k+f2K1sd^7z0b0N*J23hFjCLYxmFD*O{X;Q(T@Z!3a)1HO29|4GUR^~c-)>rKBPd6-t$ zpMnCMsh&+LNBp^G_fo#xUdj90QTz>m!QEyJzO6m?z@~NSZ!sUaUhIR#0lc5xYwf_k zlRjIkZTmM(izcDuqsYz!yQ=0cGM5yoPtL3{y)k%x)6BNe<}(k#sB9YF-yUGzeQoDA z;24rix_%#}mTY7TlgG|Z5V_*aloq?I>o72G;0M;o$7n(}9k??Prl2rjbsN5ppTKJN3?AaArc`0iZkvJ$ z?glidp;iJd`T`H7<1>xj zPds5DRDcc+pil4F&AddlXux~!9y4Inde3fiyfm9)hBY&U+mpx57??Kh=W<)pdLX^d zB6rR&^PaoM^>feNGS@^m&u;A4x6E|ZDW-9<)o(BAtm@E1UAnj#q~wIZ!SE;e2F?cbWVGo{HU7pp=l+y_2Y3ztG1d-7 zO;TyA&cCR(gBPY?@!J>z2~ydgr1?aWP5KzZ-Au9D>N=bv;duCFa8vjU9lxi3XUM~e zPcFdUfew)9=0&(AqTUakBE)qqu7!;5&>9_H`ZDH)8L@BgU3uwwKDkKW37H8xXBlG_ z&Zc7~in`KixiD*ZBwzZPI9|Mu9bs0O3)!9Y#h|bAMcF*;MuyG)09z-Xnjc_zNn@%$ zc4%xmevS^)Oi5bmkyFWb?|`qgHpM_pw3C_;27Q-atPFACe1C-f`68AkBie2G8s-W2 zQMip@mU^Pxd)Y(IhHfNWHCB)3Ja9QioY0%-3OkL@*q&hY&SdCw%M5k(v-GLAo;b#{ zUQU}?p|ZNe?^uC62Bw?f2PlEvs(u!qwpsh2h5La-Dv~PCkVy_AT0XqMtoaS_4-{Mo zp<6ji6D6L{+<)M>* z0@YtuU+lE{$QQp13ScQR-gf0J)`j**5l_NANBE8^R<>PYbX)z&d_AM%LHi^!ogf@> z=I~>C(dh8{V{jz{X_p64zPK@6U`zZo8ej#M7BHtJ)F*%wV2kV486E58EENm=+8T0+ zB3MPD?JzI-w}Jf7b*upfCu~l(3C-zfrj9-i_+-@pbxnB)5 zur zAYNc)#PRLOx{~j$)e(wg=V_YSM3Qj7(D=V4a8oWttIp8$q@Npz;yKS|^Y=O+LfAoT z1*sY}%n&<#A{cpl^sP)hdnWi+2Gn6@!^dY?kD=J{vq8sOW}d|c!CloZ3w*#@XAo_T zeO2B(%WHrRkJ!Ix`$)5GhnKm9(#0mWG5mh?R%RRAOZ5D#9+l)7WK0L3iJ4DW>_alF z1b_~%8(S?A6`G5)4sJZ(Mo6MZZhaYk5;^jTp49K}3wkyNVRWtu4GnEq2*B|&$ulcB z5HY!_&~1?;1pOQXcFa#AQK9Pz8QJv-(}8ZJKLs50qrYs&93WV%FiMPBVR>`yxibs= zK>Buz1DAsfv0c#KeWMm2o1#$LUI|bqF7muw62t!DC~81#`O~%8dr{l*1CVgZ%}%DH zNT=!8PVY!@b_X^4Daj-G0cBi%bm^btA;X3*nlm5-)u8MjoYoYCHOv_74vMXU%nB<4 z?&J#rOM$KsOFYBM#LhpL}7BUDn@^h_=8hocrCL4eqne443>*k0iS^Q7Di)V zlrR;ya9Ol4B`*Za8?*kR;W$2GQi9KW?Zwjz19(`C?83DQzT_?7t^$H< zBFEM~|M}Wly9GMXT|qQ2LlFtYyLNy;6Ic=EnG0`#!^bt_mF;VC+I(qy2GJ^G4$2m; zxT9E%)W;YCrv_0xlaZK01lclk0+`r*k*zup{Vi3!%$aH8s}Vn2W`?inIY|Tu;Ewz} zc<*sv@y=-VV9k_|uMpUQ{~`>ic!h8d9Uw9_dN0~1%5nM6} z$|iukEvzhn=&N|c2Vgn{fY28jgGJ@&{?5Ra`J;U81yHWxt@q<_hGUSAM${{Ea2G!{uch6Y8buh&|QIN=ELpn74x~) z6=|=K{2ytx`?*UQEcFgdJki#zTgB5?h*RZ7BNq&q_aq3HM&KXJ?xB)+dFeUnQvL(1 zvWU!(J5C}8_LGPWGU_LJN018iPN*gFl0-WauZuv;RHkxiiP=HPz*$GLV9YLrK#KGd z>qU`P=)k+Kf1`u6N=+5+in=n_dM4X7JU=Uo8lFdAk<3h4lZiYa#v;@a*#GTI&$}-> z`{6QrKfGgu!-5uU{+XJB)og9}O?>h*K|1frFcP0knke(9nt*tyw!IcW{cP=z|KM16 z^9$>W8vDVXV@fpZ_Xz8ehkcelu`_c9vXdVL1h}eT!1`?YmN@ITi*%PK;jl)v`bu+p%g}Oz%VhK5*!H|AI;3;4nUTBC8iChm0 zEkg;U@B-d}xIM!mzr%CQ<`LNG|6pGsu;HQ-UR{xw(#=bQO<`4FzakZsAw^*8R7J%p zL5C617J_|&S;Vq+Hk8w-do7{?#B>QGD=T=Bw~BltSxTj3@mdVVzy*8*9~AjdrYMQW z$D$A&9B^0oN+N+nb&RcSgLleU7Izdc3=)xB&zjhx+!?-q={dQAAkWbiy!0H7@)aT4 z*dgY0{;{yBxbvKiXzR$8Nl%#L&v2U5Ho5XYvAzfs4E9+seG$h2|B(J;OZcrRjRb~* zcnM?w%xJz+D2S#FXf$Bsh`3My9OpwoRVH#fRfrV-fQ%6C2&M-GlSw>}@tDE}wG=$1Kxq?q z0g(EFz@SVC)vv6=+3r8jPzWs~rb}PJ)^QUBECH;lM;0A6|4`8iiL1~JG`4cGKgQ=s zo1ww}U&gUs#EzdsFU)Rrkvdu`hrfgs{yjj5CAd&-OMo(gx#nmBLn+C8mA|A|91Upd zsDMv8H8-zW-#ViHgDx<9n4m05<^G?U_I?fO^<6YT-jRDY8m4x)xLO8-Byy{kCx0*tno| zUnJUi^Vo_%(RnwZOb1h=6XHmXr+R$UTTs=lO)E1qddLm_#WFqGpbt z1j|^RWY^<#HwnlaExh`ZGe|yyX9rD@&1Zm_DyF0G4+hx0$jq zSyz#V@equ)8x8R4p=1oT@?u9wB-bpMckm&7ftkdP-ndpnw7fdnyen{FHO-yWs3OyV{~TUy_0Y&Q%fUqP*GbM9(H zlB1fkhvo@#Pv+5wA~(;FNb8B`dn8c07M_*+VUpM z48Je;o?JF~7a@8;UxBV0YHG`Ug0BFT6lM`v&eI)sL;wxGnixXOw-wkelB!SKw=2eq z{FXn_5`{r6tnqJzzLWW?%mzs=Se52bP=aSv9>B;Xlwff*)P*ux6ZtP{^Z6T3Lj@M< zH4FS>G!3E7me4o~odEmtB4>uLJF7k?AbFVr`vZ7L+54<66Q*!;4zrc4r>agRX?+{h zCo2iI#?G1Cq^uf{MNvp40g?c#;1M~V@&uZJr-ZUUvV2^6J_Z9GhoHR_^B;pTsbsu{ zUD1BAD-TuRI5q@R=IaW$GN8&%E1`-#D5ZRhJSfRK&Re#gG~VRPQeIr7M*>KKqcmbA zyDR=UOh|A*y8ei-6Lv5$f0TIzyI$UQ+xgf|L9LJ`%8KBmbSG2RlON-uM60g<#bm>K>xFcYn{ zTCADkS~Az#xlyA!Vh!tbd?mK%f=wJ6ETdJHxEfei^>W++wk8jutm;dRtY4o#pUizbf4q3 zy1qw2i)&OYQV?zhf4`F3F%i_bnO$wj2?rVtJ+9@o10ioItArun?|c*#`Bv8e zjQn5|!BN!wa(8GV6cmj#8j^g|YX?fpy*7A<&iaBMyb`7oZ7+B0Vhok&7+IW0kh8=G z*8s*6qfP{D>F+Lg>n4J_^pGX+OEkN7pa*Yn7M5I~?Wq#x!bX?7V==Hrd{fx{D1Zyw zT?0r9hnon*3LjkVPE7<`g|SLNRk^{}4z$|+1;hiP%=1!Kr~NW5pOX#sEiZS^V(9Yy z)wkU-SH+I|R@VTSFxc64zm46PU^7h1E4CS?zcHI(T3xZtpi5>Fr6B5xq9Q~!BRtac z1m$S#gLg$vrFQ~MNME8O#qh_JKMUrggrG}y*ov4|fK1Dn!Z=$|j(R0$!?O>m22zma ze0`{o@dZ^y!U(Nm9lBvPV80;FKVtAwTewrZLbjG5r?i&rU3k8GO>?ph)t1zTQv(1G zBl;kC--e`hcILC@hdyDVKZjQmyuSlIEl*S7n1 zX{j1o;OvHSm$%)wGwjlzjqWjn%+zN95J5#vu)owcgm!#br3(gWRYB0eTFCqhz;O=j z^vt%}d#*dVt=s`L5(@xYgk8F#Nyb?3AlxgnjRKpN%xLj`wE}(KiC~=aD6zxyyJoF8 zZH61AGKy^=3AI%;PYdBerkuYd2aIEFKBBLqK!wsZc$fuI~ccGT^yDhg;Lrz3*I*Pqk2xw)MJ*D39sKV7w@x==TXF*6QX4Kx2ox`PM0Yb#4? zYptnk=wfSSE5edt47HB+*-3;$!Q(#ADw=fL>g)q=1&N^H)v9*p9pTHHrEc%F@#9rZ zUCNy(_O*-L6GymO0=R@mq}=TZBLES`v(OC@|E68;=y8FT=itC)(uo^&r<#lydWvoo zzG3!|yD$Hlx*C6UU5zJpGv2iW7DECwz|0XG;LR`)sLHh%P)AF*AT1K~E9Y9Q84rMK z)zi2*zo~1n^T)zbO1G3bxA>l-Y4LDe!g6bi^yX_A6U0y!|O zs0};?JBo-6<6z~u14=o_-vYLQY5?dQG%kukc`0o!h_#b>9FTMpAjaT84#fRS>{s8~JK0H7C-tY$!|MU%X@;y9ZC*MQ6 ze+fV6^Y{i&820nZ@GoVAR~RGlI=X)ukKT}nFX4+JBU*WPxSAyeUfqt z89l5MyTHa&-nlX59YI2ZgR0^yJ({YLdnA$xax^2GOrRZ$Z&H~<%?doJsCn`FAt>~$ zW>=9KRlPuENt6amR>och8707-S2OT2mg6Xs3FzA}t!Ne<(0try%6*j)k2XGw0bkT? zM>~KG6bUd!=cT=9WG>oF)n4H)nm(vJ<5avNxV)pPd=bCpNn#&m;YB{o`zFnZE465< zOsYTmpmVgfoF9Vzs%J9OAt*W6wFUQ@f#s%2fiy}#)HA!bwyTn-(1*nh7Ie8IIKp7< z+f5?EfDvRrMx!1udl54j4CUS8V%@G5`m#AJHStWBN1&;hkcCUKfSpFA3Fg>3eDLrA z*<}J z_UXigA9K3+_?c&)b*n*Pz}GK*QEW_%IWm|^<6j{r(6d`yzvCz$wMilDjm*{;aHT`# z4I`-0C9xQTI(cDvg^2K&U5<Y27trNpElp6SV~yX zOJi^9C8$S^pu!oc5W&;avh}T%{!=(?Nj7k0FL2ZMB9gGxTj2djs_XdzDtk8NH*C(tW!E3&6d#Ug@Wi)3M}AS5-A@_ z2p0Ibz|34EdqNK!NsR}2?nO-=9NAk{3vRNgfYT{W&`L$5f&7ugLXsTs(m615j_csN zAR$rZ`N#a;m@mp_t?*+-w2Iy8kYIB4BZM`{J_oM=OI5MQ-@+HM=Z?e`iJJ<@RiDYtJ@R&JTN4EbWDUGAkJ_W zl9&1m)LKen8=IB}Y_w#1q45(|Ij{>COArSwr);F-xfud1sf~Ul)*9Js0lQf%a1YNL zlf7il3nMpEw*otf`7*&4jj(zrTVBq{jyyo+^<*!AKo|Q*S>YUbco%{=Un3BSy&1U~08*N< z2K&U+Mif{e+*~^6zuivz2e4SgQY?7Drbmp%D zgh?-)37y8fATT-_S@(I)Z13z$ye+QEWl#wqBve1&5Qt zy3{MHfVR9JqF)sJxGEeMd9a1_Aj}8A^C37>6cQyTv6{{M{z1G-zp-9N!wE{p3edd` zOfxhDvWqJ<6%TTDBZV~Z@ZMJBjo*HX4S$h(%IA2G37|j|2Ik(>GbaL9r#|a2<+g%g z=6Ax~^cdCzEAh(Dx!>;en9B9VrL(|8qfZ0|t%${C3XZWr%@dqJsNUc1Gegg{m8+TQ zisXv9D+D{@->GyxwdjexbZXH%gAA?HWT`zWvd1J#EyW zcIppn>u5NI+O*V&Etevy`BDC`DKu5>7&{grl_bxx243}W1&xR@?iXy0ms#55kQza4 zZ8wc)wbsKDBHmbC4{v7yp`^-S zw5HFHiKZ>yF-cMLlK2FUWWCL z8XdCYnq;-xQF1Xg&QPWO`oj#j6liC#jc!pJKqJzY1?euZ2RMF0u%naZA7+fi-du<1 z!FMS9f|C%{|7uje48nxXjF%zKsMFSJz6cM0nI7RKr^)29hwrE(R#;nYE?Kn=4}(#X z7+jVh-ebOkTsmc7p;4pVzvpg*pVkZhdzRkZbGLL&<4a}u*4&=m(kLarjv+}$2fa}w zsaC5=&v2gJ)XlyMB+0q~Gc3DayXWqjr9`zoyAksy)1K0z8tXf~xq@P*h| z?8_C=mtHn4lABsb`MoPgjd$BmKokR+2@*;C9ML15-vktiXEK&1 zF@eINqoHuL2}uat3RxdUx-)>M%t+cA(oCo+QSjm^&hTNdI8<*#c^zizeQ`1xA~EX| zdw_!3IN2Q}*zMw8pooEl-c3w)$F5&vc%*VGOUP-eMq~kC^`t_QV%6Ep`MGeU8%K&imMDGhC#WV~%KTKzSQ zJgz!5y2JDURT%sN!pk(xgh}FQr^a^)9Y(ZRtb#EHi0G1=$z&BsO_BbRC7w&G#WgMp zh=LFh2}1Oc6*h`oBhxmc1Q~{8Bj5@73n3!WDM;oTWCIi-2>1fCWOLpl4LV^@cuBW0 zxwUM_yT#DE@kiL04BgCNb^G)FlY{Omf;(U0Y%wmw7g^WwU74On{9xN2J(%Hzlad$|H+4MyHCrPYI zR}6uSipp(tFz$zq^83*2^wAtTFa?8V6I93Mq0*qc~C_)knX zj*aRBn*l|G0Vt7x+(CspILbZIKt8~c+J$s)3|4(~(C+kY+8#4ZNBg( ze9b(zxpmfhD4UKXFsyKs?%A)BTkH2PIarui3wvTBVv}SRuaU)%Wqu?nWl}SPrD7*c zv&i*hZ?D%{H|(T6?h@6-=MjQbH3de>>W*L7Mwf=ji-lVB`su-7wLg2;U9MfDhipSg zS+&$%>^IuoyYiL0I;{b6Qr)%KUCM)Y%#?5Q>YpB*>5!Iw2Tt4|8;FRvm)N`C;G1pF{wkmzw12m>UYL9?$LkOX5dOXg%Ke^ zCCr2&%D913lJpE1@u$d<083VKO2Z4Yx+Zq8Bl9Q4$qT22%gTfp%BMSO4@DVa%;`a;A zrug+><|Z>68E3MbWO?6#z3?3(8q4ky)}1s{A&*n!CgbuJK3CbJ2y?-pqQ{(Yo3w4Q zvmoex2ja2^oqY0*uj=vIZai52g$_}~LU*OJZrON7Wec7sjUcVSF=%2FqH5eMO*{f% zfM9|RXEGHjaE}whLrOJ@nm`DYi=;U8B7guWfnoH7@i3VSy#<4lG4;1LI495#wQxfm zp|}Dd;MJ_i$u{w1Oy#!ApNv5L+aQD7444)O$C#j~h%RG#KG~>Zl9S*E7NqX*CSjS> zAE%DvCK7UF*&Ze5|Bku6003|SloPG0OD=nGgr~t9BFBjwL;6Cy76M;nQ9h_j*&Xz| zIOugyW14A7(6>vlkwA>tjQ}1n$VET`<{MTOVHUh|J_iod&|La*FvKcyJ<=wbFEFL4aFxP1Irc4>URm#`he)ua zDnZi@V_i0fCvYXNjL~x>tEDNhwH62Mv-#!U1pzQ1cZ?jg!S!-?3T^K!g z-(>v6FMlG-WDuX~_MRLwn?k#*IVHPqgiDAc*nHey+z}8C{O`wjNUf9HP0M&micXs9 zftwuV0t-?m+pzAE?Iq9vsbw|DPGaFDkXx_+5iI9MbPL77Z!94z z4u2Ubz>nxqyTXw<(f244<1C&wnu|xey)&&&`%iO9#J0)!u~Jnt3DhM{7YbwQp9>@@ zKqdfd;%|z6U>~B5QdsesooouQ&awQ=s)}>o|Ai_YsaIJEB-^t4vY`0N%<#PP-*XI% zstlOvo;EU&6|(zZ!;NxDuz1EHL#u+4+*&a5=>NX||s_eR6A$JtRjwDg$%ZV{Vc zVe9{ZzP$i5L$*pi&ke+bnRML>?z^|p^kS5g>O#$AA(!z?(X0Dh!Q?5#Yfy47h zBC9J8dZQOd`yAIRaLjzoNOhQ5?F5pYA=O&LKia?)r88Za>u4kE+$fp|+WV6qxs$;c zS8CLBxZ)LZ>5FOL@>_l0ALJeXA>?gF)j|*8726dKco%?5D1DNm-lNXq%nmr8>*Jx_*rox zM4r^+ode`Bvn#biN)<%cME33N9mJ-JR;iyNyfc*?1z1r!Pz;174N3=m4_tfh((@6p zbDR$@P-a31!Eljc1^Stktfo}A*2m>S+l)nMQr+J&oo&xk#9^a)u#l9fRALty(n^6jV zAe8?n%Kl(sijAm3fFI)mDFPPAgcMm68)Lt7>A*`OL$Hy7NrsgYPJBq&0Kuw)4 zHe|jsVsX*oH)+2r+<}QrStWP|jw={+rxq;IT|n^Ef@K`GrWP#l0>ow1e)Pf~`5@LayTCk=Ttf>V{5Utp&hWO}GnUbECeo?3VvUd-H>zEp8pN)cL2SgS$mxxEpU@CZEnvf!V7;Pxk=0I&a%ZF3 z^@4KrGBoQO)~c5j(1ke!+Vl|+5vkHA&^C`!p^q3Q)~J=HPF>yRr_Wv{SVCg3qOyD= zit@>n@cjG4hQ5pHFTt~46TjPLgUP*STX*Hf~xV=!p^TvutW6CQ8 znl@3hB4u7qfeqRY+`WU7d86382I%_YF1=~xm;8S;$W4eCS-1Yf=yzLzT*10 zGX01xVN}4MR9$0z8C~t*Ca^p(-kz$y_#!4LIpSrZ=+>(D)isng;6xW@>hN)wu$zn{ zgeFtsLev37bHi)#D?_v0e@EunSZ32Dt zSO`#&bKr0amIaS#d#GmcrqKo;ezXDbs*6BuOn?|F)wGqkz+Za+j`sl7ig6gRV2msH ztmyqKLKp#9Q(h4Zq~>H`%cZSLp|h(OEr(lC;kjDEK^5-w!5x&#PlU<~$2&?KtC(to zdnK}$ajHfE-)LC6eR_4uOkd;kk@y8W}EK03VrmhMJTb*S~aMn#-pHgD2ZLYy~v!Z7Iy5Vk|vgd1w|kM z(Yd~5Z2b%}Jc1-jkz9lMjN&r%Bv`@n;cl0;LS2l4sorT{d4GtQH?Fh!4$|xZ!h?ZmIHz-wnWwz7s`*ba;M@l=!Mb z4`=N88O)jw-VztwqIDjWwS+6toTmO@YzyKhrX8eT5A3UeLULuK-@~`v!ogNcMUe9P z{a*V8Mp;w1i}cPgFn|@KNUko;`wH^gdgt-&o#WeZt|5T#TkG|^y~EvpP*#<#3-@mB znP=T(`I?u7nF`>Qse24m022qe8SVppH>`CK94NTMl8 z0Md^iH|`t4IZMV$`Y7?dZ~#0s4Pzi~Q8!vnmOq8{2p*~Kux{_qcHOjiwyQm)ZL24G z^pKnwaxU?~{El7l8U&uDS7yyS8uN4GI*g4Z&Kw8KKt|@+={rj3f)gnNP=(0^guKWr zD0>7>5=ZqM@n8|SFGdTcuvbMCB$7GC%`vFT4pe@PFzEQ>XkcAF97|*&CLIlq6o*Rx zq9C4@as$W?+L7;7|LPd**%ucQ50}m=$F}wdz_IXP`_$*YD*W*nDwPcMqgqzNI)#QrFjU`cTL#|hj3g8(n18)0C)GZwbf3%BCy!%HKD z)995(gmqE&8FHXf>ne}ya|1uuEArD`|x33Jp$LuKQhj{-6{{ANZ`$M#O4Q)Bb ztNiQ@^zdywn5LG;M!bey;SO?JuzT1u?*1Fu;p4|1JoHHRG;@BMt$qV9{v02?!reVT z{0{U6;felT2A|vI_NldAUI*7G=wOnb|Bm@H{||U89Z9;MnrFIdnqI!l@p;B zl|H{@vixMgkQFz{(0a<@GE4F3J-D*m1*<-D5ij=jh#M#}{Wu#)NM+f?a%N-^ ziu0FHw1k#CI6%*e*^bbO{gr(RkG(Zl9($|jv5~fD0R4uIJj}Yw8TZ#T)Lca5v4rOfo!a7*eieuk#r+zU6=zh@4^_=!M|RVJ>4dGWw00I{wOxa1~yR(^MX65 zhx!3Go)XrVaVN})*?+1WKcq08?AW6O4DeD|v_>$(1*1j{SPMdfAbPNv z)H8hz{3^~X`%g0DAcMe&?3U(|MvIjh;n1B%p#Z$hVP!8!qu5h zlI7ShC!Jf+dwGJ@le@f$U6Dyq+pF=yj2Kbfw_ zBGUGxF5x@o4qL&#+*N?$?5_?xmRj4pqSPq*>&{(KYsE8BfK&;?NCdw)z zM&0#!>U0v2WV3EwhBx2WJ#%Jlg}HIMJ)4M9ZrM>JxYNuB^%6tBJu9A>XPsvOv%OEE4Rb*HO+8gtOIKF9Ho+#fvgsm zDF}ocrs~yJ;dJR#4m>?DsDh@pgUm4nIIxOWCct#h7f{*AyC;oPv4)INLf*v*SPq*^ zlNG1mQ=Y1<*ie;0S#F+svRucWEYvyR$f|3L6h(vL`6^$-r+|=>j@(`+TIvLH0id`) zj_A;0P_l{p#a*^qGjnApD+R3xXcjkpfE9%^;(>+>R?heGk$~Vk=ftAOG89vj zNkW)(fH|4YanHn}Pp3Z7;E;IJZNMy7x(8+QC@Yy6!tz{)MKZ_uu6>z_B%L$8o94+b zx%WO1bV1`mg7^SrKaAwuH2493)N)*D^73K@8I%GyA5Tn}3aA>$Uty&9WkZN4-WFU3 zQc59Zk1(2gqLOu@cZJJ-MHvX%E<9q{5y&$t5m8|Va90?A9|r?r2LywTsqnUhag+VV z&IOLnawh`E6>e5pp5{>~$lNQ1uA^fKS8pgDI}LwS^TXLtJ?C@?T!5?;i?M(ePt*7f z$xR@eC!(8pnMMn+V?_W6yv?TG)1cFzD$S*K@PmiZL>hX0OR`0$-z z>2k?bgDExu9HRK%0I4ez9AYsh@%9)i))s~{@JDyw+-04e?abe?q-x7HE2?9z-3@O^T;m+04)Qllhi8isDhUzc*i~{z3`Yz z`7$Y=wZluYef-ULfe% zKZ7MXUL-`q^Ps|RW|(G0kq|V4B>`!AVx%Ufsc!+S?n7~IcpawX?}+G1Fpp1||sycqI@k)aL$U*Y|?@b(+%=vAB`Izlmm;ooLMIsu5Y z1^#^v{d^z)!tvr|j7NWqZ{y*s`0y3$xsl<|^XAnLFoV}IB3%eDrKxWL@*X(ac!QVB zDHb1aD6$~HRH4$zg(^XG#6;vUULXofBSgV#MVyBk9fh1O0jiq%36MarkO#GU0-43I zhop2z4rSpjU!=0-@2-wTfemiHt@lk+G&NAk0cHAq2(=U1<;q ziprO8P_#x$;nw2fXz#`j7EV+wP88UYj&_{-*cwGk(95DdnSb@NI|ub#&3FKDrrT@1 z_TuS!?ZB&WtSL??2?rTeq^A) z&!96m(aykq1uU<5BpGUbseo^l;WpkRqwsoB)-NIXp96_MvE~k_ED-Q0k=4p=RwZwO zWut69YLqKif&mSS9PR=Sz#s^4M3$ULKpK~I1}4c(SfSsPDx~5;?SE9DzzPXD(RetcwZtcT=dBq)eNclHE$IYZ0&|SwcpNea z;5clG6s_(@3ji#LZoP%PN?_`I<&-c@xN)qTi)to`6c?ulit*Ij`WC(LMtt;V|Pu}v0>*hNmW zq#dwEJ7Ll28%H}jWqYlA1~3XK$h&uiu_NL=XRIqY*~sz&zqrUo0$6*U8UwVG91?^t zWd_x?)eOhNelW=571&YXi0Q|TkKRWIWE){^oia*ylh6GQn8&F(WEyIjn`-PIYAxmn z1&y(Xgl#uu6Y&AyBrOR%LFHtH{9ELcK6IN1WBpa)H~GZLpioEHeH%kIYjF=ij2AC66}o^>BYcNf9$hQ8~&O!&gXS1%@+54!4N3~< z)gSc6DC(Vqo+YZ}d1pz(0)>E)okb|(+L){DdCFQ8!ivkb%0|c!KZa~(qgcex9FZzv zs=}{F+ZeARApI`B%IeH39p&uV6nO+$5Dol+*Qclh%1gRB%PCLD`0|Zik_{UZp$(ar zDV8D3N8_cb(FiJuBHl)#N8r(bltd6%<*2Z1XnBKuXZlfaE)_5<4)`93MzKY5V%F3n z0XZQQ*;FhHc?+K-?Ljt^?cTY2SGIF^wtIKhY_D_?WZix`JGq`6Jlk5ynyr4Pdse!a zZj0L&c3pgj#H<_WzF?rb%4(V!rWa@#>5{5}svJ{x>7|%;w{mHr3IXW;1rSIHtj+?5 z?gA)XQ=^rM>|-`4HDXb{%0Z2EVdR`wu((uaL{>D~;dc4491oZ35%;VN*P624To|9x#FxZ()Y`lXWBMV{+ zc8}`{v`T{X#FS?GGnotE4IJbV;f_#+M0}$emyNfMXtQX9!3<}SIcRY3%&I2h%9kXn zel|OH8o`fe^1?5S?=N#-4Zrlqqkm5-4T;el@NOh4P-8niywYcFljP+22e z%sZVhYjI?4C8$_?m_3^M@5MKB`|sgF@jm(UDH`6ga_RJ$;Vam8i5j*3Nt(z7yJ%gL zY$8~>2#|{b9Sgd=K|A+Z#yDZcDPpFhOgJ}JiyPNs#T`E>TxdSBKQqHOB$E`ZU$lmP z2}ZDUIJB^yI5KlN2(zD=9_PV_wctp-!ekyuDWcM6!#^wpee!en>2j})L=>I%1>ZdA zBk^`rXLRrG2cOH|qdo}SwS$QpzwY+ZB%dxK+dT3y`(>N2<@u-%TCNBTUC@08(ep$H z7FLywjt(W(9ol2kK3lss4t6|SRJho>&UAXRjeuugmz z%DO+)#e@l%36(T!o+<*B$tHbg26pHN;gEsrUDEs^T8!SS;#dIXdsgqB{1XHh-GvRdU;CJ*s0SB=*qq+N)IfdxU9cu5q8I_imXtHP7coZ-m>@jG z)koKDbZ*(5Toa)RpC)nTRqo`$PDcu|u@2V`t&sz4bKN&IiY}uV}F-*r^`tj!`q18Rb;RVaWSvPx6PE#;k4ox zzVa5rcH)PzLMn!r=TP8&jq>rRp<_#l4s z_^uJ}Sb(bHyW=CiJD&P3TKC-iGg}dcnm?^sskXbaS(>Cu>#Zb2n-T_K5?7z4SHmr$ z!%^3X$Y$RO?&J}uvLD|y7jX@d1cXovlY*ar z_=GdjRAFu^3F$82IOqma35LL@p=6ypB(gem&Y=5-Nlz*+A50qHrXUyRab(#o?(HrZ z7FkZ=@q5efcAIy{%ijS;^}FNc?~d<|rSRG#suFL*slU+f<7 zgl6C0sA03&k83C<;`;>mDQddT;jibSemjz;+h%?% zl(3VCJ!xP`17h|fSP#;z$5({gbh$8-Qm?sfm+3qJSD2-IDcV2oc=6a5yQ}L7#}-|5 zsuKq&mf~db1{FYqv#Rb4GXnQk$t{N)>x9n{-NjH@8rmKawxM#53P2h`0y{+5rLm3E zrtYAJz!dA}7<^Mqavz}efXqrV{Fo;ZA6Z+n6Sn`-G5qvZt+=%_~q zqzs6%S8<1hT{7L2W>Wsrpz!c&Ps9VTC;JmG?r}x&lk^xf1hzZ=8+U1Fz$9IU+`)(r zC!b@1RY>$%y0(?@S~`!EP9KO+bGgy6GYK4!2jl$-RQrM`Au) z6o>a+9qKHlyV^s3UHo*xQi>6YwTq4960MHdD&2?nknO^7^X`)vXfm={Dt zXRKGCq-1R8i3um#u{xx**E8S?+{XLnbo=D5KV*6nyxE?lUjk){NSfkqh55(ZX2-Pc9IX0%QLz)R{$Z?C>QqHGouaBvn=t zvP#{M(HtROX&cUanys3u-;T2)eYh)GjRQo1_6(-A~9@v)ND#EZgIE9q+DQx(7xFA9B*AgxM9$g`1p zsKb95W73A82oa<*776Wcg3#4tV)^(kNXv=IJ-%z35WYh5;}y-1r<*^%8}fFlcOXLw zIt#3c&RFtUG-&b-=5@E5Kf^m=f`*5n_OXfLyo6gS8m^Z$-b+0 zFWGwJ=EcB3DJyYW$-Us_#$Q+7^T*S`nCL+m(ZmcMkM$MyV9PyJUf_a`WJC{Db2vVB z4x3mOFFRd-`ESuB@Qvwr034;&zD=!jk&^I=0!1wNFrJw(s>1? zjz<cWF|HD7rYMwRC65|!lT)Au)mY~9T?;dCuV4jksrh4CeBQ5Vk*}dj$A_w zPYuynKBUBUm6y*}6}mkc1L z9K0XKFn#7o7joOf-BYLXUZV|pw!U0@pxw#uz>lfGK9g#LwAi_(KAn9AYm6!CHq>is zuh=~>@6DgvY+?7A)uoe-KDaT;=o%)RR_aRPX{C_*k6Q)KNTe6rWjS*j~TE zjN6?~1IYw>dv-UPs2kQgmEYfe`ms9PsuT|PX%t|T&3kXJ*IM6(FoEOUwO*#4Z1BbM zHX|O)RdYlaOzeom<+-AdzL;{keLA>U*()CD4&!4op^N(B>2_zSToBq-xGLB@%b;lj zRbv~L_p70SE1X><3VRDGuB%SV&C_28CwIl(>P9azTK|@C#V|ho&;!wu>Z2QEnp9uY zCy1HGspA~&XwR9MGz-*4F>h;Cxv_Ze9`NkqW`?gq^`!2vw%{@}qR+u_agLhoNI?w! zux19qC#1ieC{5dVnuy+j9yQwa#H{DHE)IGf1l!P$2q_S(P*wg;?S$kntTDK-0p+o< zG|Z6Ywjo>S1ZjwYlNA<+B)Zhcl?Sp@@RKnj9j9Lw(2Y>eiOm^Ie{|5}T|3rYeKF7ci|D_6te* zUSwiFHsvSpmE6yV7a&EsBu|ul=~~QqgRzZy04QX zZC{m2Wb~~_hL^}PMMLsBnHYf;<%QGG?`i@hq0v`s0v~6xzHRiP6x1h`_xQu933l}= zUW{012e@#Yp2n&^aQzeb3{TaYFLkOyvMfF{94L}U%HtW-izI8ye1~LpneEaEL*gqU z&4fXW@V(_0M_^*lJ$6c;!pUH+{1k<*B41C+aq38g`ka@}(Uk-E8i=(JEfhKqIbQam ze0@7bgfoBK>a69$*_Ni!XyZL{{rRbqq|XfhTAZnVOcj^FH_)@e@-ae=C4$Zaoz|%% zQg~u7@-((jt_|{_j264*&&;Twh`;b@0HG5@lp+3WeZ=@D=z$7=JbR{5mq#RTBE*1F zyZOtVkNSo#fy#=y-=b~QgE60Kyc?Wya%Ck${LJu&g;|0!(e;Z0stYS&fBc~`BRHOZ zh2Q6-L(>B`fE4K8eD13ujt` z#na>Gp_!h>xAUro@okss%C35e@r_q|IWAdikS{Qo;`sKG=Qf{kCl+1KvGE<-wnPKt zTQmI`Q%{Zsp)kkR_|{gFP(Z=FYs4=}ho4x>z^44EMiix+89f+1o`4Chg;k_v={TTBBz%sa!k12hBGoi7&2sS_0@Xh#AMmnawrX=Am!s%RXD z$t$*EKNAoD(Fqw!j~MpMLpUgf(0)xgJ4ALABPbYoA|@l51svp1gVN9bB^m3u(jAOs zq>GxMS9I|e{!Zl}Xebk}T!cJjg2LVsHRg}OP3kW}WD7PW)c2(cIF=vp621x(?@aiW zz)$7gh8_C-H3#Qj>NTQ^63uCM(f)ca&HE zV0E5bCp?~y@}XKVGKWx`a7)HOknJr59_qIxYFHChS!PMa!2%qa?>C4TaL=J+z&!_8 z0%r(ws))c<;}yk)Dn^Rce;M$v={-LHVkHKGe#0SPq60IlNx>$05d~Y?L|n#p%grp? zU=+_|IgCje6An8vpOmvfq!5Fi5MpAm;&aB9@L$R%_lB6EwGjaSIUPyj+e{YAkC zFoDVrW)@1|_`{`cnX37gd)+grfPH8+UqM~#hPYB(s~Sc(u9|Pu{hF%!tS+Q<-Ee7* zViMsr?&6B%4;?z*L4l$~W~%C&s`{p?KF42?2jWjk5S^Q<`h3lju?i5M4t^p<+Emro zLgx6T2^CyZRiD#7PgQ-W@a+vPf}=|4EP60i^*y~oiQX#ruD(XdYa=HW??1{~p{c5` z3r9~_8?LB66&-qo7@3_Ags#5+){bb@SXXFqwl}{rb!EM}sy;CkUMr2U1Y~bi`xl<= zM-`HcRriWq674I5qL-=1f_cGuk=-B)(ZJ=9{_Y2!X0>cBGiZ}ZA2_(Mue)+K?}fhB zMia_!iZQGcri$ig$30UOAgQ)XhA$SC$YL-NT^Ajo08FT~s>&_YMsqAKb2l5c;s4*> zw?)T!UFVUyIia04b}Ywj9{dw%Ly(3>xR4T!mg)j=Az@$$2mnRWiaTov41qBR7_6Cr zNXAL)M7ek^v%b)zMN1+jl8I$Uily43CE2o)UY^@w`_R`mD=%HEZ*5oC>QldO?{oVv z0}Mq_64TLz1onR}`|PvNKKtym_daCetVd`v7@xIboU}XPq8F?SL^vYK0Qb9$k@zbb z;pmk`_c47;L!N$%HP+f5Cv2a1uA4qPegQFa7Be4u2OV4z^Ve3(r-ugnv_m4Eq0l#F z;X9}1`h*Lw^nzi~M>g(SmPzyG8@uB?kRXxrSn>uwy-PR=!BXYbfJt+%(k7WFtP74$JdsAg zvF8R@xH2hB+!v|61?c$2u>n55PzoXcN$OK)H_Y|4(?FBtOw`$eQRoWZU* zZws*Sl4Ao*e4!LA{U@ov6&M*QMai`hPC>CWR>8-u#;dGZ5Myf*2a)*dv*NeBxHFmf z*s+=~(-MEv*A`IKNqU4Ao0R9V5jd<|!ChZ|dKb&4kaHz`_Vg`9&?kCp14Aji0gAq{ zEydBMjcWr#6x{$n+t8L`7bKu-13@jl0ggd)TY)B?M=!6GpxSJ(x&yr;DgXSZ_q(#+ zw;v9Volx|HRQ7bEkrSth;%zI`cWd%0L8s>tAf`G)Y3J(}qH8)gms`w3>#oY-!GgS{ zaNm?jG&#UB38g#*@CFaI3=&~1F~czQ^*nfO;Xhok^E`q84HP#Q@IR4;n3R`kA{a&| zk!n!tnc`MoYGISChv)@{pD=FWEth-5#}>E*$kL2qW=pgBd8Qy4=WDrR`{rPv%OFk>&G zZw-sPI9x`miI*S@B$T4N0u4 z#Zs@}KGP~cqh9QZ#B9Hw~g(y|t$plxdJTM|ddi_kP7Kxj@Bsza?RmPK6YdH&JwzSz&aq(EOY%V@~QmpK;AfqQcc)Dw>R;$(+l-Tv|N?q%K8%3^T699L(@s|)M(luj#9x3Us~ zMk#9rS~Kh6CcfB41(vs7IB4_ul-yQ2x-Xx#X&WZ& zO7jxFK2J#0d>Oxd55O0jmzc-&YV#ugy#z3U7f|C;^Ez5V1$=)QzdwgRUq>0+$7NP~ z8HHa!q!5rv4?6%+?$t~Fmoc+{Vv^D98+2N=SS zBlu->bYG|I!Fu%Jw$r2_mug&9<+So~Z^M`rGtK(QQ(+SHLnefUVE3Z{~r zV4Gk-_n@X6A52GGrXQOcVre|IYG^CfbPlOQ)gLddmUh(T>cYZ0QpC_|8#@g|Ju8|> zdN(|T(hB=7QP@qc>0Muj|4omi45!I>qZ;$I;zEgqP$%$?j-OCDtM5ZymK2cGmlt98 zEmYO;TUhm$-{9z6IaVvKt(9uZ7`+SC3X)(S*tJwEl~#B4HkQi^r+LIbFwlFdT&Wy@ z&3teGub9A+T+bbxD;zmGHPy?@XMLxnyvn1?T&W=|Rg-Wf&BzyU+eLMnZv`6Hqqug> zxc}sKq*i96H-R7AEq&JUrkZN*t?Q}osK0qlElE(rVlIU=UVlR_`!K#pJb>Q{-XzT0 z@IO>Fg$|6dTehsdB@632cD-~5^q8g;GBr?fy(EuqN!Hp()8VD8xv0S0;I{Nn%`vLvVM66GM14j8?-K>fj{G zTj5^{HS{7b*|7RVaxtOF4gDe&F5zx>IHGD=5w0A#I@WvhTw!) zTHFO+L?cI{T_=$Ya2HM;FY$6H{ep!l7>vc@g1r4eo|#(P7=V*k7(+NUSWgKV(`qCw z@YAQjl*&OTC`)nibnhnAOle^6M>Gwm5e-nsH!-i_8WU6>H4r zCWd9bn)NQ$d!jvilp*%)i55`jWGO0@Y3^eKn1vEv2tkB!1kc^5ij*~(?C0c04|XuV zp=J5g8|B!Mn_u+herBuA$trRU48*H)k3_BI>Y1ofjrbe&37X0?>YD8{-U7=>za^xF zs@4{9U)?Cx*?YVdG|%1LVNyqjZhTRqu&HgF+kA)NY>2yDj0J+`n5Sp6gQeUA$E28M zAcOFNa|-^zj?ZUdAuHb`kL!L%4;8%#MjowLk8yU&@iCTDH1#DOrKjIgu3jmX)_VGK z`~29tqs8j#u7*+xgIg>YE7c{-l_o8s>#!Ro$gPP^%k_dO873?3_IjCXK)JJy4e_fE z#$sI}0lS8xzO#LOr%v_t^~OI_F3MMaOML|!o2snrtEx*k+wW#DUAeKV9u=e0tJO2m zUPXm-z2LJ#M6;D|b-y0jg!z2H{7`>d0cwV20W?9jbno@Jw)s)M;MtJa;`i^)2D8;2 zE!0ZjW?@cbrRgyX-_IF<1$Ctb9Yxh-u11=>>$wrBJA-Pm?ukN7DV>=s%uP>CjP{}% zqr5U+j%uy%D2B?(+IoGNxs&SU#gZ?hV1oyCq4k9Z4hZ$!)byc)vq$F+2P2cBxys48 z#<>b|C(6QiSlW+=nJCka%c{_a=L(|}!-qy@r|0J4H8vr{K_We|x>zRtd&~nkC(qSN zr+TDA;~hfsbVp0L?x6S>Ej?3SDACr}D4lJ%{uUQ3T1j$`j`VbmPRz|r4WH=hl}xeW zpOGh4ceF+#@&O%HI_i|lRdA;3B{83RF=)=CiwnJxplwF&8{VvzXBl4yOP``KB`}2q zBdrjc1tE*8OO;Zb!H61ZERMD2NB9VtpTw2b{H!jSAsVCbDl+^oqmx&8fpK&O(p~u3 zzuul0s8%)PX^S+m8ZF4;@fj`G*DA$xSQ)|#AXc%_Hdcm-&PoAGTN=D>NOH6^Cn_1ZK2 zKyOU%vc^COp5(1P_XpfM@{r3{R;cD1pIzGT-hzwrxAY(&frjVxIP4tc@#rrJaw@|Ds)bWf>PuEP>?r2Z6fA@}~eDTlvW5{zgD{$UGN_SK~&?PAl zVQig(5(JNq9Q2@iwNiSjR4bo42X$`8rSsRe$v+o=|6R{2~|CD}uO(a*N${{xG6Wfk`w z1T}7L&;NJU_=iCaxm_|dH?eAHmj55y^AFs&K}k%Lq07ha%YTj~f1QM%o=dgVbzi=Z z-$S}(`k0ya2JXv$k>x)-b8I-457u6TnQ~M2<*%?@cV;;NF(noH{oqhys=Rbx{=c$H zNU(xF8YAzY9Xyw>;!R4jkE!uD_vIhHA2ohEBv^Khc^KkNtIp1@1@=P$6#Z-p%z-lem7z)6?x&;NC*=zQ%Qyl~*uR4UNn$@Kj1?$7@>77aPb z(rp;$vuDbUb3x00dw>2@4{_q3&V=SJv-iWh7;!6+Yf5c+svg0R0 z0?Yac(0%oR{HGp7$rx{tV06$Tp7E8OfB3=tahBf`5^dvGe+*8)^I-nRteH#KG{P%0 zQLm}}lLzy^`VeYAjM`}ze^cla59R+k3w4<&5G)arem>*jLQ|voP=4JuYek9|=cdrv zhw?A5P;AY{6&O?U%0u~o!;-%SEK|+=`-k$s`Z0X`6hCHG|HQ}g5lXC6qP8`L|9IcF zZCT4+;O#9-DZ0T*m+!5pE+0cq&z6-^EL`%gSW-r&8U(E})`Apkxmn294JS)Vw88S} zmM9-W0lQ%d5z$g2d+U==A^EZeg%oSO;^p(kLab#ADv9JX=QwK#$j2D1vfPs|enrZK zlN^ejm|T~VZOd~hecM7qYTcHQk{U5GrUbkc2}#jH`;c<&X&q8@LoqESGG&H*X|cn} zx1<;%aQ*y0NF=%jZAVM>(=gOrY+%z*enm3JlhtBv@nX;M?~ZQUCO*KY4b0}q-m{|& z<*^3K87$1uW$DJpbSq37gqsz)pwS>p+-D&rOJp0}acp>EzA!vKKQ>#K8yhK%PfZWc zLv`)T?S(C_c|jE7cW-?Q3c0)HLyI?gMfWqYj`OuED#VC#;^R{I651^Er4wX8|HZ9u zO4cJ>5aJC(xd)Ori*a+5i5M<}l0(3adg_TQYU}Pk(}oE05X=|A7&(DIHK2-w+6k*HLgi2(sb}enNS9YZBks(Z7drP>$}EqVo_509Bk~9S(8gGq7~MeeOS>Z?j3)5E*0&zG;!i3_ zss}DzS>X%Zs-bAP(O9bwJ^E;UwY;{LtF1puga66XkJfRm_sBwZu~gr&V{+_70VeiB z^Ut_!&i0Q*-NPPuS%8CmQTIU)ye7Z_lpOKE3kpQZQ4hSKZ4N};V;=ZzE!iJ+k9*)t z3Pj069{92X2cz!89{59T^YN&A!UL~rNi6y=df*ER+!u9Edf-I`J{EOPdEjdTgb#0b z-UF{I5O^N(z#j>)e}B|H?SaoJ@C#A*j0b*Sfgs3}9{9WhF``)yd{u$tQTLn&UQ!@N zH1C1mRUnW*>VYo`Z~)bx^1vTxNg#jB17FdSqfz&954@r!L8TKO__~%HiMqe!fq$St z4D(-j;P(`W=@|0B?+9=Z!~CZn_+tfPL{E6&p9`>mIO=}d1OGyS2czyUd*ELRZ~&Cw zrCd99CH)137b)v<5I$& zRG4E@!e$lbc$Ba?g*g@_O!nEc{f{{96&N#i;VgPwfj zIst>8aN|n)K~J)ACHkPpe_Y8u=%;hs5ZX`VxFNBh!f``f&m7~1tbTyw{mMam_qrjC z_bb->{A7*y8@}=LG~TaxKOT$(YlF-1@n9(ZiuvQgSo#(9$AiK2EAIP)(O@mJt^L7p z`W5^A!FUD~`~AUy1{C}K!GH!7`~Ca;7zY&l{f`A8#eVaw*c5Yn5sMAaOwY~F zPR|@RwBVi;b-BKt8k?P;7#W@_OidgyB~bnMqTlg^9GlY}$xS0n`6F0ep4&#IvF47?7xH6Aj1=DI`EKs;#CS030l(b!iy!Hr=YWyj&c|WUnWQZPU}+5(tR;$?<)7 z!7?*DaRiJ%GCMY={r3<0QA`|}124;XgDo|_H8{3c(c_U)x#NYCk@T*-N*phiRNVMU zP)X@2Z^WdlZ)BwVT?M2kt4hb=9pW2ttcG{6aZ5E1XB?Q-hU#>6Ew93nqj+w-QY|)y zPVvtJeS{jb{9FSbRKuqlr5Z0_hEC!S%~69QV`uSbtq03Z9Kdps#2T%>kE&~%z+ClNNBx)Lj}&b;^IfEg>gvbQCyDL7NW;x9?stZT4vNZuFB;% z>;SAs0|=hdmd?Va;7jC>Fk=f4B5NZ&2 zaaE?xh%LMmF$f-qc2d*#mT3!816Oz*tTbV+Sqy|0G>$rM_Tl5TcxV+iB}}9se_m`i zGA<=15h_+1pC=k?)$(dX-G-a5fSN*8rb*MR->|%pkmL^;Dv}y|k^xAI4V~Y4S1rAT zz2Y-$U@|$tNv8EZlV^xfG|PlT7z8o?nY3@G8^$mstYRT}9-$ML;Z3RWGYtP`fQmK| zqdn%s8uc)OKLYn*COAOy9~u^P$!XSoTzqQvlQSdIK>|g{yKkF_1cVbajG7VK{QHuy z@+H`xX!$WQ*)KGI44cml1PM2<0s1m#>G|djU~~~BUIy{$=%M2w`S73u;SMI1E#7poK&=tbDGURUGRcTnJZ6S33RBATmE^mX(^oY99j zRs9gi2#6*xA25A`R4YZ*;iYfbAC<9Zu5O8uz;G1{PU^FI@RA zh&0Jay2pt{3W4+zgAjCXL>oQTXghI*Eg+}cM_2PDupWgb<+Df($YR6=V%3OP#*eqY zwlg|hs#L1c%DHF}?g7!6YOS)k6TT4Atcgo;G8qFx>U}5YAsNMugW?j)RQOz)2B*ga z(p`|OiXZdN`YmIKULbMAgFQ0>cTfP)+ng(wVi;@kO)zX|U&fkEnA^EMVJUK-aZ4C2 zeT&4z$X;T5>ByD77=|GpvU#Id*yhEA9mq1yOnd;@+j|6-CYCa_F{$ch7}hlH+49=A z`r4vr=d=%qB| zk}z8$)_@Aaa3(+r%!Eb1&${ka(jISSLgRAI$kJJyGDsjhU|?> z)XVYN&9ovNM6P5g=@88b5=d`OJ$uTl*aCRT?G6i8vFD*EH`trenmI{qtnyRDVU5Za zpNbsnAkb@+jX_e*pR~@ zHy}9zA#HikYg%SX?C51xWhgYzLo^$Vy$-`Y7*q=GaZJXd8DgL%ByZAU>IL;7-h{n+ zk0=KzrKZQ}4ZK~W#mJdbdSjnx&K{=UGX2Y<&qqa}D+5Vfu{&#gBxrnLs~aEo@fWv) zt~C+GNkJ;X)Ya=pZfOUocBG=*rVB)uT$s?Gu0iH=!$uOREm$?&np&64+KwZIS?vUmkcZ5?DXXKNGiuD%n-6ftHhbXJfB=;LCP!ueZ2wSumw1`e|bRu=o zbddDeiwVjg9_4QWOK~RPfs-))VTBX7mq55df52Xtq30ANUHRkZde|B9uX@ii)iZ65EfG_j(BmIfYdv%-_dwgjx zVA9Dt)}R;EGt0&{`xwh;d&ndGjKLDScm+bFr&hvCY4y?~EQIEZ3F=FaFsSWgJ5yr} zNf(h_z0QkpfH4wc@no^<7bM#E3?FAKj_qh9Xpx*X(f~ftY~>26B(` z>0gV~gCG&sy8GG(r$@TlJnspZMx5Lrsy__#gi#WL8I@qDtC#|+dH#Jvp*K&7IHWUo zgd9C|+VtEC0M7B)6=+V0S4p6VQ%G8S5NI}$fT9Zaj3R;LJ*Kh-R6r*>L( zY)iP%;-^w{Vzn^@6S16}sxy?<{=S4kOZs6}rCs7vYk`z`tV&5Jl@OO9Fu>M&gpQeu zc|v*=W*4px9G|f)xFqC4zd$&+P|hDRi=Gfa{B zYV$f2B%J47!r4u&)cB?cxoh|v-itIWzZzHN`rMpK@nTzSeUTZ zWE@Z;$(T$v!5YP4-QJFgakLr=!gerDt@}H}JJ$W}VBXo~x867^$Dn1oD}yalnH%j#pzRLl|fX7s09b z8=al-!#uZu;acp2X`TsXvh0S5`&7FXKvsW{20XFp1s1%`Hm3A~>Kuyh^iZ^kxRmsJ zF)^t*6DarEmW}jZxGT~z)cATJp5#D6h3*a|qqZdOFCEE9*OYtej3DgRk&PYMc$a0P z8e*VXS`AW!WqW#~T$)eRQ<6~(#ymnegRyE^yb7a#0k>z7Za7%Qq!hwzV{V^t+I$1L z;037xJr1W`;v3;7`peMxA>z^qxqlJ~^1Fz9xOFUb}Wmc?`@IVxUkeD&`1m)aC@xNtw`1izq2?yP%c@5vMHm^eh!N!T- zF3^$*dnTSFqNnR+1amWh-1^=E7&^&b7O^LPeB^JCgs)nx!0+L}{DxS~XdP^Eiw|l1 zQCV|NehBHUX%2(SHWhYGWLs~*Izus)FkrQ*RGfx4L8Dq=j)H>ZDCp@z@;hXm>y8Hc z5V_d*ScDkO<_nUL1D7>4elsY`&w{H$wP*R+Qi;E;Z;xXp?+hk`G46&KLDeBRlWx%rG8k5#a7N+m8+%orv<<=p%4g zfzK)YN)fMs1lWz`=$Jld9(lAy7e;a?o4ed@=)5^FexByy!FxqmUt2IRjhIx68Ir|7 zBr$Os*9UH}f%Ah=Y&PFf9Cg~z^{@@Ap9Ok)SHvcbBOAp^xYk|i3PFgigKFnK=7c0h z6;tH~*j$HNA%Sh^P2G)ej|3{$Yc#d__ykLFqe3|p3*_8=aYFz&0C@@?xlXo7@Ty;KSVG`6YSYbu(c4bG4jbcxtv61n@ z(IXQh)1yeGaC}}jz+{n1wO(?Km=5hjRNAk4r@JzKe1?4!EoO}%QDkgot#QsZXgW=l zK{u|%=3|2+JW1W&5M{%?AH>uBZ1Q81pT@p-KYBEP&rEg$@CnzyFZz!scgMc?I-j3> z)NF~`@_*uvsBQAcjJ##8dFCy9IGMLh5{V*dS=SRLY1!Jj;(DXHv|etJwJhsO3@l?( zk-^MM;Q|?NLNVfj7}6UBHMJPVHo`WtaR?O-Uyz!2p0P}N#z`oRAbd_t5E}4CI^p%1=64LOknNXZer<bGcIw-CGZ z6Z{MH>DC{k$(y&n18%;^X1UMMKq2P>GO#Wf#vMw|Jh4h7;>Cy<`bNx^#Lzf)q_qNO z61K)*c1CFH1QA`G87P_f4!b1d5d4iZH5@D(yN0lC#eH9-fyO_Io4!OQlQ6{7btFWP zcx^)+qfG3?DJB_Bj5|{_%78R@1@Y*Eh-I^2K}>@#Cz@;|u4E|8ix{@kvbeZ+zC7}L&eK=ocxCseyB*0wyb+k!()dkE8 za>kxc)aZuve1LrK4n@a%=%sM$YrAo%?OQwB8=W9GgO>r=2SCz{DIy_i{s08gc``gq zgWKE6wHtAdL54fW+tG2X9O)cmqhka^Ol$%Gwd8^1=aIuf=w|IGia}YD+;fdFI&s5r zTM=4Ygz^bl>|E;fc;jN!d=c_~rxfpJ&WeFB-9cR>f7}#iH14*N^iO;iP zIqOO8cP#2DIHGceP{vv6GVg{{mnhxg_Cm+ZxCIeoF<}?Cg1{{2MYM9hg^>b>Q;DFa_Dn%QGTzmQZrR#E z;14*QdqGszvp8{cf9Q=E#7)tQ_u%-Yj$dQajB1FAD11qZ2Ru+FDk?rXhKB!+QB48O z;(#{I%TB)@t*)QM17z)J*=cTROYOZVYScR-q##_J^pOR=xhf%AEY~`P9O@^PAdv$Q zHu%a!6MxEbsu)WcKYZj8S)F^pos3?kgn<`jsFvMh>ZB~@kDMxLIBH{s^36MA3Spy; zehGEo1@_)!`lXX-u=aFxnJw34(z3dp7j2H8@sOY6WiRV z>{8#O<^(a$$RC*pk&Ev4>~BeITi%X!UX7y|BW_hJSR8c^I7~ zD`gpSrmWC51ck$@;u1`VLNIS7bQojg!m-CBnxN%L3?Q)GX`ZWu6-rK(#~(cb3bI^q zXk%WitVwZJL6rC1@IZHOn!-MEx{It!n!m0p6VkMzOehv6IZg9?igh4aO_;RJOiIGX zu49}6h3=|x%8SO1@^BXnA?Y2aqdeS^^030!7)8LORR?>@#~o>K&c6+XLc$e4aCHK= zED1RozkkY>l${M2hA+K5{($eI+V;K?%NeiW@A}1)Fs>KnqUEYtncFa|y`Yo{jfECQ ziy=G}Y1Hm)!*ctI6^QFEnpB-~D7UJ5t@Q!i5&5~hqiq;S`xPad~HxkSv*4c=+ zINhpj#E?68VH>6~e!gl9=`mLo_e++&-X$0lpOo~3Z}HjQNeVf3a^=|z^KT{&_u_oQ z!?*Fo!sjgfJEzYral(jm4{hh5H%+<+2KvM)qkZ#@n_}4vQf3a?aS{#}p}PgT>l|lk z){=W{Ty1{<`)Jm>3Y{Rm4XShT45de2px{+t=i)iCZr>}q`(*8FTXJDc$1(}-m|Lh- zE0w28wMKcNSiyFufYhxv52SA66G3)oj|16!CT-ZSod9fOkAsh8kY3JO{4&f}dhk$7 zFP#7I>mMR`<5@8-(;1NFY5F|=viVanb@TU|Vx@-fW*j4mWE7>rTs&pqWf+M&3B6kQ z@h6b|8D#BjwOg{)COFvawZg9%`|k5*u8l2N=T0Uzm{#M-tHyjZq9;^(=5aE0H{s7Q zPt-OxVy-&=BWLnl0`W)C5f933VrX20H^Na4lwfKwBOFd!-2tU;C;S1_aHzYJ&R}Bf zYtL`Q|0a96T|T%QF^dORB_N@Se>9Mpf_rDC;rYFtYCb^I;bh{Z`E4xR;Einbg_h0R zCtT{{r^cHky$GPA<*JgT{Mzbnn+qBYR|Mzu^T8nhpV;n?^ahEAEe5&vw0ntk@}L^RhthM zkEtF#4uSSQ&V%n;9ctkne|stsFHPaEj@`p~2HQQRqbc!?NIiCcl-&7rHwjq(UelEV z)H~V|^o{s~B|BS&y?p2zlez6_zITUOleli6m5$bwQ1tFGZ_$p{w8a-8%Xdd>(i}2k z3^Fn74^8ewr25ANq@LmCL-*u1LCs7Og=ez3co+3rg2kidGhxG`+K@G zSu2$J_Ae(d;oGk#cP;bvxyipYf$_n-9v_wz^ySI^Bgs%vw_QzgXQKk+Nuwo%RP#+!U+qDD1>7YTkz4bFQ&mMZ$&J3ZK!f z*1Cv3zuOErYs&~u)ny<$JtR^@D(xmxL60p^(3idRLwWU(yK*1GVsbUJN zwaf-`c-pgu)Jf8Kx2vL!=Dvc5##7%+a|W&%Qo{L;v(Jc~`8pV))x>W!d+9kbbHT-7 z=JT0itz1M%nT*0@aLHKZ-O+4G))uScRUFQwEP@oRY%Zym{DKAM7Dg5lwqn2-To-3n z7b&@VmhnSxv{GN{jm}75WN%cFzfE2lPBm5w3PgCdP1D0vS95mRD~VZ%|Hx;ExEz*z zqgFkqLQDG4dDUVOhAgAk0AT`4mF!MN$L8i|r%$x#W~N$iJh@(OfivWH(Of5dvv9mwAOQGK}W@z3NaYLVr-NQi4&dm+TH`%3u)gg{n$z1 z-?(Yd{7?5umT)7USzlQ*gsz)WXK?lb-9o$l7HXuW+d~Bh%(jt+ergRMEsj7d*?2@s zizIr=?$1VkKZ18LbjK>4EjNsW+9CSb16&{giq0&vdFEdBQ-*1*)^lsc#xnFD@NB&&>^=}7><{SY>ZL}Z zfi!w0!$E`x>GubbG{B_kiX&onls$ZmS&%kug95q^%>U*oh4=J`~baSG1{VcRpd)Po)bRF8ui9-v^U^I{sbz bcI^F|!l$hYkxA=mo!jwY~n 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�k&vW9$g2LhTrH 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 z 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 diff --git a/Wiki/RUS_Guide/doctrees/index.doctree b/Wiki/RUS_Guide/doctrees/index.doctree index 8f396b29bec3e8afb122f926d42fb39c03b64ace..be164731e88f8063ca5151c917ae872257e9c661 100644 GIT binary patch literal 74119 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 literal 48383 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 diff --git a/Wiki/RUS_Guide/html/01_HowToInstall.html b/Wiki/RUS_Guide/html/01_HowToInstall.html index 1cd6d2ef..ef9bbd31 100644 --- a/Wiki/RUS_Guide/html/01_HowToInstall.html +++ b/Wiki/RUS_Guide/html/01_HowToInstall.html @@ -41,7 +41,7 @@ - + @@ -91,24 +91,22 @@

МОДУЛЬ РОБОТ

МОДУЛЬ СТУДИЯ

    @@ -117,20 +115,19 @@

МОДУЛЬ ОРКЕСТРАТОР

МОДУЛЬ АГЕНТ

ИНСТРУМЕНТЫ

@@ -200,35 +197,35 @@

1. Первый запуск

-

Are you ready to install the pyOpenRPA solution on your machine?

-

Ok, we start. -Do the following operations:

+

Готовы испытать всю мощь перспективных технологий?

+

Будет очень интересно - начинаем!

+

Для начала необходимо выполнить следующие действия:

-

Installation has been completed :)

-
-

How to check installation

+

ВСЁ - Развертывание pyOpenRPA завершено! :)

+
+

Проверить, что pyOpenRPA развернута корректно?

+

В папке pyOpenRPA запустить интерпретатор Python

    -
  • Run portable python (built in the pyOpenRPA)

    -
      -
    • x32 python (GIT\Resources\WPy32-3720\python-3.7.2\python.exe)

    • -
    • x64 python (GIT\Resources\WPy64-3720\python-3.7.2.amd64\python.exe)

    • -
    -
  • +
  • x32 Python (GIT\Resources\WPy32-3720\python-3.7.2\python.exe)

  • +
  • x64 Python (GIT\Resources\WPy64-3720\python-3.7.2.amd64\python.exe)

-

The pyOpenRPA has been successfully installed if the portable python 3.7.2 was started without any exceptions (see screenshot).

+

Платформа pyOpenRPA успешно развернута корректно. если интерпретаторы python 3.7.2 были запущены без проблем (см. скриншот).

cb5dec8cecafa7d64f6cd14b2672acce.png
-
-

System requirements

+
+

Быстрая навигация

-

.. v1.2.12 replace:: v1.2.12 - .. |author| replace:: Ivan Maslov <ivan.maslov@unicodelabs.ru>

+

.. v1.2.12 replace:: v1.2.12

@@ -239,7 +236,7 @@
diff --git a/Wiki/RUS_Guide/html/03_Copyrights_Contacts.html b/Wiki/RUS_Guide/html/03_Copyrights_Contacts.html index 2ff42668..dc4237a3 100644 --- a/Wiki/RUS_Guide/html/03_Copyrights_Contacts.html +++ b/Wiki/RUS_Guide/html/03_Copyrights_Contacts.html @@ -7,7 +7,7 @@ - 2. Права & Контакты — документация pyOpenRPA v1.2.12 v1.2.12 + 2. Лицензия & Контакты — документация pyOpenRPA v1.2.12 v1.2.12 @@ -91,25 +91,27 @@
  • Выбрать версию
  • 1. Первый запуск
  • -
  • 2. Права & Контакты

    МОДУЛЬ РОБОТ

    МОДУЛЬ СТУДИЯ

      @@ -118,20 +120,19 @@

    МОДУЛЬ ОРКЕСТРАТОР

    МОДУЛЬ АГЕНТ

    ИНСТРУМЕНТЫ

    @@ -180,7 +181,7 @@
  • »
  • -
  • 2. Права & Контакты
  • +
  • 2. Лицензия & Контакты
  • @@ -200,58 +201,85 @@
    -

    2. Права & Контакты

    -

    pyOpenRPA is created by Ivan Maslov (Russia). -Hosted by PYOPENRPA LLC (Russia)

    -

    My purpose is to create #IT4Business models in the companies. -I can help you to create the new #IT4Business in your company. -#IT4Business homepage - https://www.facebook.com/RU.IT4Business -#IT4Busines is the methodology which is created for build compact fast and reliable IT function in company. -If you has many IT specialists, very long deadlines for the IT tasks, many bugs in IT software - #IT4Business is for you :)

    -

    If you need some IT help - feel free to contact me (prefer e-mail or skype). -If you will find some issue in pyOpenRPA - write about it to me via e-mail/skype/gitlab issue.

    -

    Thank you!

    +

    2. Лицензия & Контакты

    -

    Центр поддержки клиентов

    +

    Лицензия

    +

    Лицензия pyOpenRPA разрешает бесплатное использование только для некоммерческих организаций и физических лиц (не ИП и не самозанятый). В остальных случаях требуется получение цифрового сертификата от правообладателя (ООО «ОПЕН РПА»).

    +

    Получить, проверить сертификат, а также ознакомиться с текстом лицензионного соглашения Вы можете по адресу: +https://pyopenrpa.ru/verification

    +

    pyOpenRPA не использует какие-либо инструменты физической блокировки функциональности своего ПО. +По всем вопросам Вы можете обратиться к правообладателю, контакты см. по адресу: +https://pyopenrpa.ru/Index/pyOpenRPA_product_service.pdf +Используя ПО pyOpenRPA Вы осознаете свою ответственность в случаях нарушения лицензионного законодательства и совершения неправомерных действий.

    +

    ВНИМАНИЕ! НЕЗНАНИЕ ЗАКОНА НЕ ОСВОБОЖДАЕТ ОТ ОТВЕТСТВЕННОСТИ.

    +

    pyOpenRPA - роботы Вам помогут!

    +
    +
    +

    Автор

    +

    Маслов Иван Дмитриевич (с 2019г.)

    +
    +
    +

    Правообладатель

    +

    с 2022г. +ООО «ОПЕН РПА», ОГРН 1227700251350, ИНН/КПП 9718191421/771801001 +г. Москва: 125310, улица Муравская +г. Санкт-Петербург: 197022, улица Льва Толстого

    +

    с 2019г. по 2021г. +Маслов Иван Дмитриевич (с 2019г.)

    +
    +
    +

    Центр поддержки клиентов

    У вас остались вопросы? Мы вам поможем!

    -
    -

    Иван Маслов (Основатель & генеральный директор)

    +
    +

    Иван Маслов (генеральный директор ООО «ОПЕН РПА»)

    -
    -

    Используемые сторонние компоненты (лицензионная чистота)

    +
    +

    Используемые сторонние компоненты (лицензионная чистота)

    + +
    +
    +

    Быстрая навигация

    -

    .. v1.2.12 replace:: v1.2.12 - .. |author| replace:: Ivan Maslov <ivan.maslov@unicodelabs.ru>

    +

    .. v1.2.12 replace:: v1.2.12

    diff --git a/Wiki/RUS_Guide/html/Agent/02_Defs.html b/Wiki/RUS_Guide/html/Agent/02_Defs.html index bb8a43a5..4938a632 100644 --- a/Wiki/RUS_Guide/html/Agent/02_Defs.html +++ b/Wiki/RUS_Guide/html/Agent/02_Defs.html @@ -7,7 +7,7 @@ - 2. Defs — документация pyOpenRPA v1.2.12 v1.2.12 + 2. Функции — документация pyOpenRPA v1.2.12 v1.2.12 @@ -41,8 +41,8 @@ - - + + @@ -91,20 +91,18 @@

    МОДУЛЬ РОБОТ

    МОДУЛЬ СТУДИЯ

      @@ -113,24 +111,22 @@

    МОДУЛЬ ОРКЕСТРАТОР

    МОДУЛЬ АГЕНТ

      -
    • 2. Defs

      ИНСТРУМЕНТЫ

      @@ -179,7 +175,7 @@
    • »
    • -
    • 2. Defs
    • +
    • 2. Функции
    • @@ -198,8 +194,8 @@
      -
      -

      2. Defs

      +
      +

      2. Функции

      pyOpenRPA.Agent.__Agent__

      Functions:

      @@ -350,17 +346,7 @@ -
      -
      -

      References

      -

      reStructuredText 1

      -
      -
      1
      -

      http://docutils.sourceforge.net/rst.html

      -
      -
      -

      .. v1.2.12 replace:: v1.2.12 - .. |author| replace:: Ivan Maslov <ivan.maslov@unicodelabs.ru>

      +

      .. v1.2.12 replace:: v1.2.12

      @@ -371,8 +357,8 @@

      diff --git a/Wiki/RUS_Guide/html/Orchestrator/01_Orchestrator.html b/Wiki/RUS_Guide/html/Orchestrator/01_Orchestrator.html index 7a187816..680b0652 100644 --- a/Wiki/RUS_Guide/html/Orchestrator/01_Orchestrator.html +++ b/Wiki/RUS_Guide/html/Orchestrator/01_Orchestrator.html @@ -7,7 +7,7 @@ - 1. Description — документация pyOpenRPA v1.2.12 v1.2.12 + 1. Описание — документация pyOpenRPA v1.2.12 v1.2.12 @@ -41,7 +41,7 @@ - + @@ -91,20 +91,18 @@

      МОДУЛЬ РОБОТ

      МОДУЛЬ СТУДИЯ

        @@ -113,27 +111,25 @@

      МОДУЛЬ ОРКЕСТРАТОР

        -
      • 1. Description

        МОДУЛЬ АГЕНТ

        ИНСТРУМЕНТЫ

        @@ -182,7 +178,7 @@
      • »
      • -
      • 1. Description
      • +
      • 1. Описание
      • @@ -201,77 +197,61 @@
        -
        -

        1. Description

        -

        pyOpenRPA Orchestrator is the executable process.

        -

        The features of the orchestrator is: -- Centralized/decentralized user control interface (applicable and for business users and for technical users). Web based, support desktop, tablet, phone. -- Automatized robots control (customized algorithms, robots scheduling) -- Source code mega flexibility: Light Orchestrator architecture is good for own customization

        -
        -

        Global settings dict concept

        -

        pyOpenRPA project is complex tool which consist of several executable modules such as Robot, Orchestrator, Studio,

        -

        Because of module compexity, we use 1 init arg - inGSettings -inGSettings is a complex dictionary which has all reqired parameters for the module execution.

        -

        The description of the GSettings you can find in executable module details.

        -
        -
        -

        Orchestrator how to configure

        -

        To init pyOpenRPA Orchestrator instance use script:

        -

        from pyOpenRPA import Orchestrator # Import orchestrator main -gSettings = SettingsTemplate.Create(inModeStr=»BASIC») # Create GSettings with basic configuration -Orchestrator.Orchestrator(inGSettings=gSettings) # Call the orchestrator def

        -

        gSettings structure

        +
        +

        1. Описание

        +
        +

        Общее

        +

        Модуль оркестратор - это координирующее звено, которое обеспечивает бесперебойную работа массива роботов. Этот массив может состоять как из одного так и из тысячи роботов RPA.

        +

        Основные возможности

        +
          +
        • Запуск / пауза / безопасная остановка / принудительная остановка робота

        • +
        • Интеллектуальное расписание

        • +
        • Просмотр состояния графических сессий роботов через панель управления

        • +
        • Удаленное администрирование сессий оркестратора и робота

        • +
        • Среда отладки функциональности через панель управления оркестратора

        • +
        • Консолидированное хранилище логов, доступное для просмотра через панель управления

        • +
        • Ролевая модель разграничения доступа

        • +
        • Функциональность очередей для координации роботов

        • +
        -
        -

        Orchestrator architecture

        -

        Orchestrator has several source code components: -- User/robot activity consolidated queue single thread (Processor) -- User/robot activity asynchonus many threads (Processor) -- Scheduler single thread (main) -- RDP keep active many thread -- Autocleaner single thread -- GUI keep active single thread -- HTTP web server single thread (create user socket threads) --

        -

        Below you can find more information about all of the component.

        +
        +

        Концепция единого глобального словаря настроек (GSettings)

        +

        pyOpenRPA - это сложное решение, которое направлено на упрощение жизни пользователей и разработчиков роботов.

        +

        Для того, чтобы предлагать рынку гибкое, адаптивное и надежное решение, одним из архитектурных решений был выбран подхъод хранения !ВСЕЙ! конфигурационной информации в едином словаре, который мы называем GSettings.

        +

        GSettings - это многоуровневая и иерархичная структура, которая позволяет произвести широкую кастомизацию под свои нужды, и в то же время быть открытой к внедрению новых возможностей.

        +

        Ознакомиться со структурой GSettings можно по ссылке: 3. Настройки GSettings (шаблон)

        +

        Мы не рекомендуем вносить изменения напрямую в GSettings, хоть мы и оставляем такую возможность. Для корректировки функциональности Вы можете воспользоваться соответствующей функцией в модуле Оркестратора (см. здесь: 2. Функции)

        +

        Используя специальные функции модуля Оркестратора вы существенно увеличиваете шансы бесшовного перехода на новые версии pyOpenRPA, если вам это потребуется.

        -
        -

        Component Processor

        -

        Sync - Append activity list to consolidated processor queue. Execution goes sequency by the activity list order

        -

        Async - Create New thread to execute the activity list

        +
        +

        Архитектура

        +

        Оркестратор состоит из следующих основных потоков:

          -
        • Activity list

        • +
        • Процессорная очередь активностей (ActivityItem) (Processor)

        • +
        • Функциональность асинхронного исполнения активностей (ActivityItem) (Processor)

        • +
        • Поток интеллектуального расписания (main)

        • +
        • Поток контроля активности RDP сессий

        • +
        • Поток сбора мусорных данных

        • +
        • Поток контроля графической сессии на учетной записи, где работает Оркестратор

        • +
        • Поток веб-сервера Оркестратора

        -

        List of the activity item

        +

        Ознакомиться с возможностями и функциями оркестратора можно по ссылке: 2. Функции

        +

        Дорогие коллеги!

        +

        Мы знаем, что с pyOpenRPA вы сможете существенно улучшить качество вашего бизнеса. Платформа роботизации pyOpenRPA - это разработка, которая дает возможность делать виртуальных сотрудников (программных роботов RPA) выгодными, начиная от эффекта всего в 10 тыс. руб. И управлять ими будете только Вы!

        +

        Если у вас останутся вопросы, то вы всегда можете обратиться в центр поддержки клиентов pyOpenRPA. Контакты: 2. Лицензия & Контакты

        +

        pyOpenRPA - роботы помогут!

        +
        +
        +

        Быстрая навигация

        -

        Activity item is universal mechanism to execute different algorythms from any sources. -The core feature of the Activity is to call python defs with args and kwargs. -If you need to init do some activity you can write some python def, then create Activity item with current def. -ATTENTION: In some cases (such as web transmition), when you can’t transmit python def as object you can use symbolic names for python defs. It is apply you to init all of you want from the web UI.

        -

        ?Why i cant transmit python def from the web -Because the WEB space is not the Python executable space. Interaction between it spaces create by JSON protocol. So, we know than JSON apply int, float, str, bool, None, list, dict - that is all.

        -
        -

        Примечание

        -

        Example -{

        -
        -

        «Def»:»DefAliasTest», # def link or def alias (look gSettings[«Processor»][«AliasDefDict»]) -«ArgList»:[1,2,3], # Args list -«ArgDict»:{«ttt»:1,»222»:2,»dsd»:3}, # Args dictionary -«ArgGSettings»: None # Name of GSettings attribute: str (ArgDict) or index (for ArgList) -«ArgLogger»: None # Name of GSettings attribute: str (ArgDict) or index (for ArgList)

        -
        -

        }# Pay attention! Do not left comma symbol after the end of the dict - it can be interpretated like a turple..

        -
        -
        -
        -

        References

        -

        `Python-sphinx`_

        -

        .. v1.2.12 replace:: v1.2.12 - .. |author| replace:: Ivan Maslov <ivan.maslov@unicodelabs.ru>

        +

        .. v1.2.12 replace:: v1.2.12

        @@ -282,7 +262,7 @@ Because the WEB space is not the Python executable space. Interaction between it
        diff --git a/Wiki/RUS_Guide/html/Orchestrator/02_Defs.html b/Wiki/RUS_Guide/html/Orchestrator/02_Defs.html index 778ad5bf..82fd6eb1 100644 --- a/Wiki/RUS_Guide/html/Orchestrator/02_Defs.html +++ b/Wiki/RUS_Guide/html/Orchestrator/02_Defs.html @@ -7,7 +7,7 @@ - 2. Defs — документация pyOpenRPA v1.2.12 v1.2.12 + 2. Функции — документация pyOpenRPA v1.2.12 v1.2.12 @@ -41,8 +41,8 @@ - - + + @@ -91,20 +91,18 @@

        МОДУЛЬ РОБОТ

        МОДУЛЬ СТУДИЯ

          @@ -113,38 +111,25 @@

        МОДУЛЬ ОРКЕСТРАТОР

          -
        • 1. Description
        • -
        • 2. Defs

          МОДУЛЬ АГЕНТ

          ИНСТРУМЕНТЫ

          @@ -193,7 +178,7 @@
        • »
        • -
        • 2. Defs
        • +
        • 2. Функции
        • @@ -212,62 +197,52 @@
          -
          -

          2. Defs

          -
          -

          pyOpenRPA.Orchestrator.__Orchestrator__

          -
          # EXAMPLE 1
          +  
          +

          2. Функции

          +
          +

          Общее

          +

          Раздел содержит всю необходимую информацию о функциях pyOpenRPA.Orchestrator

          +

          При необходимости вы всегда можете обратиться в центр поддержки клиентов pyOpenRPA. Контакты: 2. Лицензия & Контакты

          +
          +
          +

          Что такое активность (ActivityItem)?

          +

          Архитектура pyOpenRPA позволяет обмениваться сообщениями о выполнении функций через механизм активностей (ActivityItem).

          +

          На стороне Агента и Оркестратора реализована процессорная очередь, которая последовательно выполняет поставленные активности. Результат этих активностей сообщается инициатору (см. функции группы Agent… в Оркестраторе)

          +
          +
          +

          Функции

          +
          # ПРИМЕР 1 (ОСНОВНОЙ)
           from pyOpenRPA import Orchestrator
           Orchestrator.OSCMD(inCMDStr = "git status", inRunAsyncBool=True)
           
          -# EXAMPLE 2
          +# ПРИМЕР 2 (ВСПОМОГАТЕЛЬНЫЙ)
           from pyOpenRPA.Orchestrator import __Orchestrator__
           __Orchestrator__.OSCMD(inCMDStr = "git status", inRunAsyncBool=True)
           
          -
          -

          Group Agent…

          -

          Interaction between Orchestrator and pyOpenRPA.Agent daemon process, which can be deployed in another user session.

          -
          -
          -

          Group GSettings…

          -

          Basic defs to work with singleton gSettings.

          -
          -
          -

          Group Storage…

          -

          Defs to work with special locations in Orchestrator: Robot, User (TODO), User + Robot (TODO)

          -
          -
          -

          Group OS…

          -

          Interaction with shell on the Orchestrator user session.

          -
          -
          -

          Group Process…

          -

          Interaction with some process on the Orchestrator user session.

          -
          -
          -

          Group Processor…

          -

          Work with Processor queue (see …).

          -
          -
          -

          Group Python…

          -

          Work with extra python modules.

          -
          -
          -

          Group RDPSession…

          -

          Interaction with RDP session, where you can manage some robots.

          -
          -
          -

          Group Web…

          -

          Manipulate the Orchestrator WEB side.

          -
          -
          -

          Group UAC…

          -

          Manipulate the User Access Controls (actual for the Orchestrator WEB access for the business users)

          -
          -
          -

          Group Scheduler…

          -

          Work with activity scheduling.

          +

          Группа функций Agent…

          +

          Взаимодействие между Оркестратором и Агентом, который развертнут на других графических сессиях, где будет происходить запуск робота.

          +

          Группа функций GSettings…

          +

          Вспомогательные функции для работы с глобальным словарем настроек Оркестратора

          +

          Группа функций Storage…

          +

          Функции для взаимодействия со специальным хранилищем переменных, предназначенного для хранения информации от роботов.

          +

          !ВНИМАНИЕ! Данное хранилище сохраняется при перезагрузке Оркестратора из панели управления.

          +

          Группа функций OS…

          +

          Функции взаимодействия с командной строкой на сессии, где запущен Оркестратор.

          +

          Группа функций Process…

          +

          Запуск / остановка процессов на сессии Оркестратора.

          +

          Группа функций Processor…

          +

          Функции взаимодействия с процессорной очередью. Если требуется выполнить синхронизацию нескольких разных задач, то можно их отправлять в процессорную очередь.

          +

          Группа функций Python…

          +

          Функции взаимодействия с Python модулями.

          +

          Группа функций RDPSession…

          +

          Запуск, отключение, перезапуск, отправка CMD команд, раскрыть на весь экран на RDP сессию

          +

          Группа функций Web…

          +

          Управление веб-сервером Оркестратора.

          +

          Группа функций UAC…

          +

          Управление ролевой моделью доступа пользователей к панели управления Оркестратора. Актуально для подключения бизнес-пользователей.

          +

          Группа функций Scheduler…

          +

          Установка расписания на различные активности.

          Functions:

          @@ -276,288 +251,276 @@ - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - - - - - - - + + - + - + - + - + - + - + - - - - - - - + - - + + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + - + - + - + - + - + - + - +

          ActivityItemCreate(inDef[, inArgList, …])

          Create activity item.

          Создать Активность (ActivityItem).

          ActivityItemDefAliasCreate(inDef[, …])

          Create alias for def (can be used in ActivityItem in field Def) !WHEN DEF ALIAS IS REQUIRED! - Def alias is required when you try to call Python def from the Orchestrator WEB side (because you can’t transmit Python def object out of the Python environment)

          Создать синоним (текстовый ключ) для инициации выполнения функции в том случае, если запрос на выполнения пришел из вне (передача функций невозможна).

          ActivityItemDefAliasModulesLoad()

          Load all def from sys.modules.

          Загрузить все функции из импортированных модулей sys.modules в ActivityItem синонимы - полезно для отладки со стороны панели управления.

          ActivityItemDefAliasUpdate(inDef, inAliasStr)

          Update alias for def (can be used in ActivityItem in field Def).

          Обновить синоним (текстовый ключ) для инициации выполнения функции в том случае, если запрос на выполнения пришел из вне (передача функций невозможна).

          ActivityItemHelperDefAutofill(inDef)

          Detect def by the name and prepare the activity item dict with values.

          Анализ аргументов функции по синониму (текстовому ключу).

          ActivityItemHelperDefList([inDefQueryStr])

          Create list of the available Def names in activity item. You can use query def filter via arg inDefQueryStr

          Получить список синонимов (текстовых ключей), доступных для использования в Активностях (ActivityItem).

          AgentActivityItemAdd(inHostNameStr, …[, …])

          Add activity in AgentDict.

          Добавить активность в словарь активностей выбранного Агента

          AgentActivityItemExists(inHostNameStr, …)

          Check by GUID if ActivityItem has exists in request list.

          Выполнить проверку, что активность (ActivityItem) была отправлена на сторону Агента.

          AgentActivityItemReturnExists(inGUIDStr[, …])

          Check by GUID if ActivityItem has been executed and result has come to the Orchestrator

          Выполнить проверку, что активность (ActivityItem) была выполнена на стороне Агента и результат был получен на стороне Оркестратора.

          AgentActivityItemReturnGet(inGUIDStr[, …])

          Work synchroniously! Wait while result will be recieved.

          Ожидает появления результата по активности (ActivityItem).

          AgentOSCMD(inHostNameStr, inUserStr, inCMDStr)

          Send CMD to OS thought the pyOpenRPA.Agent daemon.

          Отправка команды командной строки на сессию, где работает pyOpenRPA.Agent.

          AgentOSFileBinaryDataBase64StrAppend(…[, …])

          Append binary file by the base64 string by the pyOpenRPA.Agent daemon process (safe for JSON transmission)

          Добавить бинарную информацию в существующий бинарный файл, который будет расположен по адресу inFilePathStr на стороне Агента с содержимым, декодированным с формата base64: inFileDataBase64Str

          AgentOSFileBinaryDataBase64StrCreate(…[, …])

          Create binary file by the base64 string by the pyOpenRPA.Agent daemon process (safe for JSON transmission)

          Создать бинарный файл, который будет расположен по адресу inFilePathStr на стороне Агента с содержимым, декодированным с формата base64: inFileDataBase64Str

          AgentOSFileBinaryDataBase64StrReceive(…[, …])

          Read binary file and encode in base64 to transmit (safe for JSON transmition)

          Выполнить чтение бинарного файла и получить содержимое в формате base64 (строка)

          AgentOSFileBinaryDataBytesCreate(…[, …])

          Create binary file by the base64 string by the pyOpenRPA.Agent daemon process (safe for JSON transmition)

          Создать бинарный файл, который будет расположен по адресу inFilePathStr на стороне Агента с содержимым inFileDataBytes

          AgentOSFileBinaryDataReceive(inHostNameStr, …)

          Read binary file from agent (synchronious)

          Чтение бинарного файла на стороне Агента по адресу inFilePathStr.

          AgentOSFileSend(inHostNameStr, inUserStr, …)

          Send the file from the Orchestrator to Agent (synchroniously) pyOpenRPA.Agent daemon process (safe for JSON transmition).

          Отправить файл по адресу inOrchestratorFilePathStr со стороны Оркестратора и сохранить по адресу inAgentFilePathStr на стороне Агента.

          AgentOSFileTextDataStrCreate(inHostNameStr, …)

          Create text file by the string by the pyOpenRPA.Agent daemon process

          Создать текстовый файл, который будет расположен по адресу inFilePathStr на стороне Агента с содержимым inFileDataStr в кодировке inEncodingStr

          AgentOSFileTextDataStrReceive(inHostNameStr, …)

          Read text file in the agent GUI session

          Чтение текстового файла на стороне Агента по адресу inFilePathStr.

          AgentOSLogoff(inHostNameStr, inUserStr)

          Logoff the agent user session

          Выполнить операцию logoff на стороне пользователя.

          AgentProcessWOExeUpperUserListGet(…[, …])

          Return the process list only for the current user (where Agent is running) without .EXE in upper case.

          Получить список процессов, которые выполняется на сессии Агента.

          GSettingsAutocleaner([inGSettings])

          HIDDEN Interval gSettings auto cleaner def to clear some garbage.

          GSettingsGet([inGSettings])

          Вернуть глобальный словарь настроек Оркестратора.

          GSettingsGet([inGSettings])

          Get the GSettings from the singleton module.

          GSettingsKeyListValueAppend(inValue[, …])

          Применить операцию .append к обьекту, расположенному по адресу списка ключей inKeyList в глобальном словаре настроек Оркестратора GSettings.

          GSettingsKeyListValueAppend(inValue[, …])

          Append value in GSettings by the key list

          GSettingsKeyListValueGet([inKeyList, …])

          Получить значение из глобального словаря настроек Оркестратора GSettings по списку ключей.

          GSettingsKeyListValueGet([inKeyList, …])

          Get the value from the GSettings by the key list

          GSettingsKeyListValueOperatorPlus(inValue[, …])

          Применить оператор сложения (+) к обьекту, расположенному по адресу списка ключей inKeyList в глобальном словаре настроек Оркестратора GSettings.

          GSettingsKeyListValueOperatorPlus(inValue[, …])

          Execute plus operation between 2 lists (1:inValue and 2:gSettings by the inKeyList)

          GSettingsKeyListValueSet(inValue[, …])

          Установить значение из глобального словаря настроек Оркестратора GSettings по списку ключей.

          GSettingsKeyListValueSet(inValue[, …])

          Set value in GSettings by the key list

          OSCMD(inCMDStr[, inRunAsyncBool, inLogger])

          Отправить команду на выполнение на сессию, где выполняется Оркестратор.

          OSCMD(inCMDStr[, inRunAsyncBool, inLogger])

          OS send command in shell locally

          OSCredentialsVerify(inUserStr, inPasswordStr)

          Выполнить верификацию доменного (локального) пользователя по паре логин/пароль

          OSCredentialsVerify(inUserStr, inPasswordStr)

          Verify user credentials in windows.

          OSLogoff()

          Выполнить отключение сессии, на которой выполняется Оркестратор.

          OSLogoff()

          Logoff the current orchestrator session :return:

          OSRemotePCRestart(inHostStr[, inForceBool, …])

          Отправить сигнал на удаленную перезагрузку операционной системы.

          OSRemotePCRestart(inHostStr[, inForceBool, …])

          Send signal via power shell to restart remote PC ATTENTION: Orchestrator user need to have restart right on the Remote machine to restart PC.

          Orchestrator([inGSettings, …])

          Инициализация ядра Оркестратора (всех потоков)

          Orchestrator([inGSettings, …])

          Main def to start orchestrator

          OrchestratorInitWait()

          Ожидать инициализацию ядра Оркестратора

          OrchestratorInitWait()

          Wait thread while orc will process initial action.

          OrchestratorIsAdmin()

          Проверить, запущен ли Оркестратор с правами администратора.

          OrchestratorIsAdmin()

          Check if Orchestrator process is running as administrator

          OrchestratorIsInited()

          Проверить, было ли проинициализировано ядро Оркестратора

          OrchestratorIsInited()

          Check if Orchestrator initial actions were processed

          OrchestratorLoggerGet()

          Получить логгер Оркестратора

          OrchestratorLoggerGet()

          Get the logger from the Orchestrator

          OrchestratorPySearchInit(inGlobPatternStr[, …])

          Выполнить поиск и инициализацию пользовательских .py файлов в Оркестраторе (например панелей управления роботов)

          OrchestratorPySearchInit(inGlobPatternStr[, …])

          Search the py files by the glob and do the safe init (in try except).

          OrchestratorRerunAsAdmin()

          Перезапустить Оркестратор с правами локального администратора.

          OrchestratorRerunAsAdmin()

          Check if not admin - then rerun orchestrator as administrator

          OrchestratorRestart([inGSettings])

          Перезапуск Оркестратора с сохранением информации о запущенных RDP сессиях.

          OrchestratorRestart([inGSettings])

          Orchestrator restart

          OrchestratorScheduleGet()

          Базовый объект расписания, который можно использовать для запуска / остановки роботов.

          OrchestratorScheduleGet()

          Get the schedule (schedule.readthedocs.io) from the Orchestrator

          OrchestratorSessionRestore([inGSettings])

          Восстановить состояние Оркестратора, если ранее состояние Оркестратора было сохранено с помощью функции OrchestratorSessionSave:

          OrchestratorSessionRestore([inGSettings])

          Check _SessioLast… files in working directory. if exist - load into gsettings (from version 1.2.7) _SessionLast_GSettings.pickle (binary).

          OrchestratorSessionSave([inGSettings])

          Сохранить состояние Оркестратора (для дальнейшего восстановления в случае перезапуска):

          OrchestratorSessionSave([inGSettings])

          Orchestrator session save in file (from version 1.2.7) _SessionLast_GSettings.pickle (binary)

          OrchestratorThreadStart(inDef, *inArgList, …)

          Запустить функцию в отдельном потоке.

          OrchestratorThreadStart(inDef, *inArgList, …)

          Execute def in new thread and pass some args with list and dict types

          ProcessDefIntervalCall(inDef, inIntervalSecFloat)

          Периодический вызов функции Python.

          ProcessDefIntervalCall(inDef, inIntervalSecFloat)

          Use this procedure if you need to run periodically some def.

          ProcessIsStarted(inProcessNameWOExeStr)

          Проверить, запущен ли процесс, который в наименовании содержит inProcessNameWOExeStr.

          ProcessIsStarted(inProcessNameWOExeStr)

          Check if there is any running process that contains the given name processName.

          ProcessListGet([inProcessNameWOExeList])

          Вернуть список процессов, запущенных на ОС, где работает Оркестратор.

          ProcessListGet([inProcessNameWOExeList])

          Return process list on the orchestrator machine sorted by Memory Usage.

          ProcessStart(inPathStr, inArgList[, …])

          Запуск процесса на сессии Оркестратора, если на ОС не запущен процесс inStopProcessNameWOExeStr.

          ProcessStart(inPathStr, inArgList[, …])

          Start process locally.

          ProcessStop(inProcessNameWOExeStr, …[, …])

          Остановить процесс на ОС, где работает Оркестратор, под учетной записью inUserNameStr.

          ProcessStop(inProcessNameWOExeStr, …[, …])

          Stop process on the orchestrator machine.

          ProcessorActivityItemAppend([inGSettings, …])

          Добавить активность (ActivityItem) в процессорную очередь.

          ProcessorActivityItemAppend([inGSettings, …])

          Create and add activity item in processor queue.

          ProcessorActivityItemCreate(inDef[, …])

          Создать Активность (ActivityItem).

          ProcessorActivityItemCreate(inDef[, …])

          Create activity item.

          ProcessorAliasDefCreate(inDef[, inAliasStr, …])

          Создать синоним (текстовый ключ) для инициации выполнения функции в том случае, если запрос на выполнения пришел из вне (передача функций невозможна).

          ProcessorAliasDefCreate(inDef[, inAliasStr, …])

          Create alias for def (can be used in ActivityItem in field Def) !WHEN DEF ALIAS IS REQUIRED! - Def alias is required when you try to call Python def from the Orchestrator WEB side (because you can’t transmit Python def object out of the Python environment) Deprecated.

          ProcessorAliasDefUpdate(inDef, inAliasStr[, …])

          Обновить синоним (текстовый ключ) для инициации выполнения функции в том случае, если запрос на выполнения пришел из вне (передача функций невозможна).

          ProcessorAliasDefUpdate(inDef, inAliasStr[, …])

          Update alias for def (can be used in ActivityItem in field Def).

          PythonStart(inModulePathStr, inDefNameStr[, …])

          Импорт модуля и выполнение функции в процессе Оркестратора.

          PythonStart(inModulePathStr, inDefNameStr[, …])

          Import module and run def in the Orchestrator process.

          RDPSessionCMDRun(inRDPSessionKeyStr, inCMDStr)

          Отправить CMD команду на удаленную сесиию через RDP окно (без Агента).

          RDPSessionCMDRun(inRDPSessionKeyStr, inCMDStr)

          Send CMD command to the RDP session «RUN» window

          RDPSessionConnect(inRDPSessionKeyStr[, …])

          Выполнить подключение к RDP и следить за стабильностью соединения со стороны Оркестратора.

          RDPSessionConnect(inRDPSessionKeyStr[, …])

          Create new RDPSession in RobotRDPActive. Attention - activity will be ignored if RDP key is already exists

          RDPSessionDisconnect(inRDPSessionKeyStr[, …])

          Disconnect the RDP session and stop monitoring it.

          RDPSessionDublicatesResolve(inGSettings)

          DEVELOPING Search duplicates in GSettings RDPlist !def is developing!

          RDPSessionDisconnect(inRDPSessionKeyStr[, …])

          Выполнить отключение RDP сессии и прекратить мониторить его активность.

          RDPSessionFileStoredRecieve(…[, inGSettings])

          Recieve file from RDP session to the Orchestrator session using shared drive in RDP (see RDP Configuration Dict, Shared drive)

          Получение файла со стороны RDP сессии на сторону Оркестратора через UI инструменты RDP окна (без Агента).

          RDPSessionFileStoredSend(inRDPSessionKeyStr, …)

          Send file from Orchestrator session to the RDP session using shared drive in RDP (see RDP Configuration Dict, Shared drive)

          Отправка файла со стороны Оркестратора на сторону RDP сессии через UI инструменты RDP окна (без Агента).

          RDPSessionLogoff(inRDPSessionKeyStr[, …])

          Logoff the RDP session from the Orchestrator process (close all apps in session when logoff)

          Выполнить отключение (logoff) на RDP сессии и прекратить мониторить активность со стороны Оркестратора.

          RDPSessionMonitorStop(inRDPSessionKeyStr[, …])

          Stop monitoring the RDP session by the Orchestrator process.

          Прекратить мониторить активность RDP соединения со стороны Оркестратора.

          RDPSessionProcessStartIfNotRunning(…[, …])

          Start process in RDP if it is not running (check by the arg inProcessNameWEXEStr)

          Выполнить запуск процесса на RDP сессии через графические UI инструменты (без Агента).

          RDPSessionProcessStop(inRDPSessionKeyStr, …)

          Send CMD command to the RDP session «RUN» window.

          Отправка CMD команды в RDP окне на остановку процесса (без Агента).

          RDPSessionReconnect(inRDPSessionKeyStr[, …])

          Reconnect the RDP session

          RDPSessionResponsibilityCheck(inRDPSessionKeyStr)

          DEVELOPING, MAYBE NOT USEFUL Check RDP Session responsibility TODO NEED DEV + TEST

          RDPTemplateCreate(inLoginStr, inPasswordStr)

          Create RDP connect dict item/ Use it connect/reconnect (Orchestrator.RDPSessionConnect)

          Выполнить переподключение RDP сессии и продолжить мониторить его активность.

          SchedulerActivityTimeAddWeekly([…])

          Add activity item list in scheduler.

          RDPTemplateCreate(inLoginStr, inPasswordStr)

          Создать шаблон подключения RDP (dict).

          Start([inDumpRestoreBool, …])

          Start the orchestrator threads execution

          SchedulerActivityTimeAddWeekly([…])

          Добавить активность по расписанию.

          StorageRobotExists(inRobotNameStr)

          Check if robot storage exists

          Проверить, существует ли ключ inRobotNameStr в хранилище пользовательской информации StorageDict (GSettings > StarageDict)

          StorageRobotGet(inRobotNameStr)

          Get the robot storage by the robot name.

          Получить содержимое по ключу робота inRobotNameStr в хранилище пользовательской информации StorageDict (GSettings > StarageDict)

          UACKeyListCheck(inRequest, inRoleKeyList)

          Check is client is has access for the key list

          Проверить права доступа для пользователя запроса по списку ключей до права.

          UACSuperTokenUpdate(inSuperTokenStr[, …])

          Add supertoken for the all access (it is need for the robot communication without human)

          Добавить супертокен (полный доступ).

          UACUpdate(inADLoginStr[, inADStr, …])

          Update user access (UAC)

          Дообогащение словаря доступа UAC пользователя inADStrinADLoginStr.

          UACUserDictGet(inRequest)

          Return user UAC hierarchy dict of the inRequest object.

          Вернуть UAC (User Access Control) словарб доступов для пользователя, который отправил запрос.

          WebAuditMessageCreate([inRequest, …])

          Create message string with request user details (IP, Login etc…).

          Создание сообщения ИТ аудита с такими сведениями как (Домен, IP, логин и тд.).

          WebCPUpdate(inCPKeyStr[, inHTMLRenderDef, …])

          Add control panel HTML, JSON generator or JS when page init

          Добавить панель управления робота в Оркестратор.

          WebListenCreate([inServerKeyStr, …])

          Create listen interface for the web server

          Настроить веб-сервер Оркестратора.

          WebRequestGet()

          Return the web request instance if current thread was created by web request from client.

          Вернуть экземпляр HTTP запроса, если функция вызвана в потоке, который был порожден для отработки HTTP запроса пользователя.

          WebRequestParseBodyBytes([inRequest])

          Extract the body in bytes from the request

          Извлечь данные в байт виде из тела (body) HTTP запроса.

          WebRequestParseBodyJSON([inRequest])

          Extract the body in dict/list from the request

          Извлечь из тела (body) запроса HTTP JSON данные и преобразовать в Dict / List структуры языка Python.

          WebRequestParseBodyStr([inRequest])

          Extract the body in str from the request

          Извлечь данные в виде строки из тела (body) HTTP запроса.

          WebRequestParseFile([inRequest])

          Parse the request - extract the file (name, body in bytes)

          Извлечь файл (наименование + содержимое в виде строки байт b““) из HTTP запроса пользователя.

          WebRequestParsePath([inRequest])

          Parse the request - extract the url.

          Извлечь декодированный URL путь из HTTP запроса пользователя в формате строки.

          WebRequestResponseSend(inResponeStr[, inRequest])

          Send response for the request

          WebRequestResponseSend(inResponeStr[, …])

          Установить ответ на HTTP запрос пользователя.

          WebURLConnectDef(inMethodStr, inURLStr, …)

          Connect URL to DEF

          Подключить функцию Python к URL.

          WebURLConnectFile(inMethodStr, inURLStr, …)

          Connect URL to File

          Подключить файл к URL.

          WebURLConnectFolder(inMethodStr, inURLStr, …)

          Connect URL to Folder

          Подключить папку к URL.

          WebURLIndexChange([inURLIndexStr])

          Change the index page of the orchestrator if you dont want the „/“ (main) path

          Изменить адрес главной страницы Оркестратора.

          WebUserInfoGet([inRequest])

          Return User info about request

          Информация о пользователе, который отправил HTTP запрос.

          WebUserIsSuperToken([inRequest, inGSettings])

          Return bool if request is authentificated with supetoken (token which is never expires)

          Проверить, авторизован ли HTTP запрос с помощью супер токена (токен, который не истекает).

          WebUserUACHierarchyGet([inRequest])

          Return User UAC Hierarchy DICT Return {…}

          Вернуть словарь доступа UAC в отношении пользователя, который выполнил HTTP запрос inRequest

          pyOpenRPA.Orchestrator.__Orchestrator__.ActivityItemCreate(inDef, inArgList=None, inArgDict=None, inArgGSettingsStr=None, inArgLoggerStr=None, inGUIDStr=None, inThreadBool=False)[исходный код]
          -

          Create activity item. Activity item can be used as list item in ProcessorActivityItemAppend or in Processor.ActivityListExecute.

          -
          # USAGE
          +

          Создать Активность (ActivityItem). Активность можно использовать в ProcessorActivityItemAppend или в Processor.ActivityListExecute или в функциях работы с Агентами.

          +
          # ПРИМЕР
           from pyOpenRPA import Orchestrator
           
          -# EXAMPLE 1
          +# ВАРИАНТ 1
           def TestDef(inArg1Str, inGSettings, inLogger):
               pass
           lActivityItem = Orchestrator.ActivityItemCreate(
          @@ -575,7 +538,7 @@
           #       "ArgLogger": "inLogger"
           #   }
           
          -# EXAMPLE 2
          +# ВАРИАНТ 2
           def TestDef(inArg1Str):
               pass
           Orchestrator.ActivityItemDefAliasUpdate(
          @@ -601,17 +564,28 @@
           
          Параметры
            -
          • inDef – def link or def alias (look gSettings[«Processor»][«AliasDefDict»])

          • -
          • inArgList – Args list for the Def

          • -
          • inArgDict – Args dict for the def

          • -
          • inArgGSettingsStr – Name of def argument of the GSettings dict

          • -
          • inArgLoggerStr – Name of def argument of the logging object

          • -
          • inGUIDStr – GUID which you can specify. If None the GUID will be generated

          • -
          • inThreadBool – True - execute ActivityItem in new thread; False - in processor thread

          • +
          • inDef – Функция Python или синоним (текстовый ключ)

          • +
          • inArgList – Список (list) неименованных аргументов к функции

          • +
          • inArgDict – Словарь (dict) именованных аргументов к функции

          • +
          • inArgGSettingsStr – Текстовое наименование аргумента GSettings (если требуется передавать)

          • +
          • inArgLoggerStr – Текстовое наименование аргумента logger (если требуется передавать)

          • +
          • inGUIDStr – ГУИД идентификатор активности (ActivityItem). Если ГУИД не указан, то он будет сгенерирован автоматически

          • +
          • inThreadBool – True - выполнить ActivityItem в новом потоке; False - выполнить последовательно в общем потоке процессорной очереди

          Результат
          -

          {}

          +

          +
          lActivityItemDict= {

          «Def»:inDef, # def link or def alias (look gSettings[«Processor»][«AliasDefDict»]) +«ArgList»:inArgList, # Args list +«ArgDict»:inArgDict, # Args dictionary +«ArgGSettings»: inArgGSettingsStr, # Name of GSettings attribute: str (ArgDict) or index (for ArgList) +«ArgLogger»: inArgLoggerStr, # Name of GSettings attribute: str (ArgDict) or index (for ArgList) +«GUIDStr»: inGUIDStr, +«ThreadBool»: inThreadBool

          +
          +
          +

          }

          +

          @@ -619,9 +593,8 @@
          pyOpenRPA.Orchestrator.__Orchestrator__.ActivityItemDefAliasCreate(inDef, inAliasStr=None, inGSettings=None)[исходный код]
          -

          Create alias for def (can be used in ActivityItem in field Def) -!WHEN DEF ALIAS IS REQUIRED! - Def alias is required when you try to call Python def from the Orchestrator WEB side (because you can’t transmit Python def object out of the Python environment)

          -
          # USAGE
          +

          Создать синоним (текстовый ключ) для инициации выполнения функции в том случае, если запрос на выполнения пришел из вне (передача функций невозможна).

          +
          # ПРИМЕР
           from pyOpenRPA import Orchestrator
           
           def TestDef():
          @@ -636,13 +609,13 @@
           
          Параметры
            -
          • inGSettings – Global settings dict (singleton)

          • -
          • inDef – Def

          • -
          • inAliasStr – String alias for associated def

          • +
          • inDef – функция Python

          • +
          • inAliasStr – Строковый ключ (синоним), который можно будет использовать в Активности (ActivityItem)

          • +
          • inGSettings – Глобальный словарь настроек Оркестратора (синглтон)

          Результат
          -

          str Alias string (Alias can be regenerated if previous alias was occupied)

          +

          Строковый ключ, который был назначен. Ключ может быть изменен, если входящий текстовый ключ был уже занят.

          @@ -650,19 +623,13 @@
          pyOpenRPA.Orchestrator.__Orchestrator__.ActivityItemDefAliasModulesLoad()[исходный код]
          -

          Load all def from sys.modules… in ActivityItem def alias dict

          -
          -
          Результат
          -

          None

          -
          -
          +

          Загрузить все функции из импортированных модулей sys.modules в ActivityItem синонимы - полезно для отладки со стороны панели управления.

          pyOpenRPA.Orchestrator.__Orchestrator__.ActivityItemDefAliasUpdate(inDef, inAliasStr, inGSettings=None)[исходный код]
          -

          Update alias for def (can be used in ActivityItem in field Def). -!WHEN DEF ALIAS IS REQUIRED! - Def alias is required when you try to call Python def from the Orchestrator WEB side (because you can’t transmit Python def object out of the Python environment)

          +

          Обновить синоним (текстовый ключ) для инициации выполнения функции в том случае, если запрос на выполнения пришел из вне (передача функций невозможна).

          # USAGE
           from pyOpenRPA import Orchestrator
           
          @@ -678,13 +645,13 @@
           
          Параметры
            -
          • inGSettings – Global settings dict (singleton)

          • -
          • inDef – Def

          • -
          • inAliasStr – String alias for associated def

          • +
          • inDef – функция Python

          • +
          • inAliasStr – Строковый ключ (синоним), который можно будет использовать в Активности (ActivityItem)

          • +
          • inGSettings – Глобальный словарь настроек Оркестратора (синглтон)

          Результат
          -

          str Alias string

          +

          Строковый ключ, который был назначен. Ключ будет тем же, если входящий текстовый ключ был уже занят.

          @@ -692,13 +659,23 @@
          pyOpenRPA.Orchestrator.__Orchestrator__.ActivityItemHelperDefAutofill(inDef)[исходный код]
          -

          Detect def by the name and prepare the activity item dict with values.

          +

          Анализ аргументов функции по синониму (текстовому ключу).

          Параметры
          -

          inDef

          +

          inDef – Часть текстового ключ (начало / середина / конец)

          Результат
          -

          +

          Преднастроенная структура активности (ActivityItem) +{

          +
          +

          »Def»: None, +«ArgList»: [], +«ArgDict»: {}, +«ArgGSettingsStr»: None, +«ArgLoggerStr»: None

          +
          +

          }

          +

          @@ -706,15 +683,13 @@
          pyOpenRPA.Orchestrator.__Orchestrator__.ActivityItemHelperDefList(inDefQueryStr=None)[исходный код]
          -
          -

          Create list of the available Def names in activity item. You can use query def filter via arg inDefQueryStr

          -
          +

          Получить список синонимов (текстовых ключей), доступных для использования в Активностях (ActivityItem).

          Параметры
          -

          inDefStr

          +

          inDefStr – Часть текстового ключ (начало / середина / конец)

          Результат
          -

          [«ActivityItemDefAliasUpdate», «ActivityItemDefAliasCreate», etc…]

          +

          Список доступных ключей в формате: [«ActivityItemDefAliasUpdate», «ActivityItemDefAliasCreate», etc…]

          @@ -722,18 +697,18 @@
          pyOpenRPA.Orchestrator.__Orchestrator__.AgentActivityItemAdd(inHostNameStr, inUserStr, inActivityItemDict, inGSettings=None)[исходный код]
          -

          Add activity in AgentDict. Check if item is created

          +

          Добавить активность в словарь активностей выбранного Агента

          Параметры
            -
          • inGSettings – Global settings dict (singleton)

          • -
          • inHostNameStr – Agent host name

          • -
          • inUserStr – User login, where agent is based

          • -
          • inActivityItemDict – ActivityItem

          • +
          • inGSettings – Глобальный словарь настроек Оркестратора (синглтон)

          • +
          • inHostNameStr – Наименование хоста, на котором запущен Агент. Наименования подключенных агентов доступно для просмотра в панели управления

          • +
          • inUserStr – Наименование пользователя, на графической сессии которого запущен Агент. Наименования подключенных агентов доступно для просмотра в панели управления

          • +
          • inActivityItemDict – Активность (ActivityItem). См. функцию ProcessorActivityitemCreate

          Результат
          -

          GUID String of the ActivityItem - you can wait (sync or async) result by this guid!

          +

          ГУИД (GUID) строка Активности (ActivityItem). Далее можно ожидать результат этой функции по ГУИД с помощью функции AgentActivityItemReturnGet

          @@ -741,16 +716,16 @@
          pyOpenRPA.Orchestrator.__Orchestrator__.AgentActivityItemExists(inHostNameStr, inUserStr, inGUIDStr, inGSettings=None)[исходный код]
          -

          Check by GUID if ActivityItem has exists in request list. If exist - the result response has not been recieved from the agent

          +

          Выполнить проверку, что активность (ActivityItem) была отправлена на сторону Агента.

          Параметры
            -
          • inGSettings – Global settings dict (singleton)

          • -
          • inGUIDStr – GUID String of the ActivityItem

          • +
          • inGSettings – Глобальный словарь настроек Оркестратора (синглтон)

          • +
          • inGUIDStr – ГУИД (GUID) активности (ActivityItem)

          Результат
          -

          True - ActivityItem is exist in AgentDict ; False - else case

          +

          True - Активность присутствует ; False - Активность еще не была отправлена на сторону Агента

          @@ -758,16 +733,16 @@
          pyOpenRPA.Orchestrator.__Orchestrator__.AgentActivityItemReturnExists(inGUIDStr, inGSettings=None)[исходный код]
          -

          Check by GUID if ActivityItem has been executed and result has come to the Orchestrator

          +

          Выполнить проверку, что активность (ActivityItem) была выполнена на стороне Агента и результат был получен на стороне Оркестратора.

          Параметры
            -
          • inGSettings – Global settings dict (singleton)

          • -
          • inGUIDStr – GUID String of the ActivityItem - you can wait (sync or async) result by this guid!

          • +
          • inGSettings – Глобальный словарь настроек Оркестратора (синглтон)

          • +
          • inGUIDStr – ГУИД (GUID) активности (ActivityItem)

          Результат
          -

          True - result has been received from the Agent to orc; False - else case

          +

          True - Активность присутствует; False - Активность еще не была выполнена на стороне Агента

          @@ -775,18 +750,19 @@
          pyOpenRPA.Orchestrator.__Orchestrator__.AgentActivityItemReturnGet(inGUIDStr, inCheckIntervalSecFloat=0.5, inGSettings=None)[исходный код]
          -

          Work synchroniously! Wait while result will be recieved. Get the result of the ActivityItem execution on the Agent side. Before this please check by the def AgentActivityItemReturnExists that result has come to the Orchestrator

          -

          !ATTENTION! Use only after Orchestrator initialization! Before orchestrator init exception will be raised.

          +

          Ожидает появления результата по активности (ActivityItem). Возвращает результат выполнения активности.

          +

          !ВНИМАНИЕ! Замораживает поток, пока не будет получен результат. +!ВНИМАНИЕ! Запускать следует после того как будет инициализировано ядро Оркестратора (см. функцию OrchestratorInitWait), иначе будет инициирована ошибка.

          Параметры
            -
          • inGSettings – Global settings dict (singleton)

          • -
          • inGUIDStr – GUID String of the ActivityItem - you can wait (sync or async) result by this guid!

          • -
          • inCheckIntervalSecFloat – Interval in sec of the check Activity Item result

          • +
          • inGSettings – Глобальный словарь настроек Оркестратора (синглтон)

          • +
          • inGUIDStr – ГУИД (GUID) активности (ActivityItem)

          • +
          • inCheckIntervalSecFloat – Интервал в секундах, с какой частотой выполнять проверку результата. По умолчанию 0.5

          Результат
          -

          Result of the ActivityItem executed on the Agent side anr transmitted to the Orchestrator. IMPORTANT! ONLY JSON ENABLED Types CAN BE TRANSMITTED TO ORCHESTRATOR!

          +

          Результат выполнения активности. !ВНИМАНИЕ! Возвращаются только то результаты, которые могут быть интерпретированы в JSON формате.

          @@ -794,22 +770,22 @@
          pyOpenRPA.Orchestrator.__Orchestrator__.AgentOSCMD(inHostNameStr, inUserStr, inCMDStr, inRunAsyncBool=True, inSendOutputToOrchestratorLogsBool=True, inCMDEncodingStr='cp1251', inGSettings=None, inCaptureBool=True)[исходный код]
          -

          Send CMD to OS thought the pyOpenRPA.Agent daemon. Result return to log + Orchestrator by the A2O connection

          +

          Отправка команды командной строки на сессию, где работает pyOpenRPA.Agent. Результат выполнения команды можно выводить в лог оркестратора.

          Параметры
            -
          • inGSettings – Global settings dict (singleton)

          • -
          • inHostNameStr – Agent host name in upper case (example «RPA01», «RPA_99» and so on). Active agent session you can see on the orchestrator dashboard as Orchestrator admin

          • -
          • inUserStr – Agent user name in upper case (example «UserRPA»). Active agent session you can see on the orchestrator dashboard as Orchestrator admin

          • -
          • inCMDStr – command to execute on the Agent session

          • -
          • inRunAsyncBool – True - Agent processor don’t wait execution; False - Agent processor wait cmd execution

          • -
          • inSendOutputToOrchestratorLogsBool – True - catch cmd execution output and send it to the Orchestrator logs; Flase - else case; Default True

          • -
          • inCMDEncodingStr – Set the encoding of the DOS window on the Agent server session. Windows is beautiful :) . Default is «cp1251» early was «cp866» - need test

          • -
          • inCaptureBool – !ATTENTION! If you need to start absolutely encapsulated app - set this flag as False. If you set True - the app output will come to Agent

          • +
          • inGSettings – Глобальный словарь настроек Оркестратора (синглтон)

          • +
          • inHostNameStr – Наименование хоста, на котором запущен Агент. Наименования подключенных агентов доступно для просмотра в панели управления

          • +
          • inUserStr – Наименование пользователя, на графической сессии которого запущен Агент. Наименования подключенных агентов доступно для просмотра в панели управления

          • +
          • inCMDStr – Команда для исполнения на стороне сессии Агента

          • +
          • inRunAsyncBool – True - Агент не ожидает окончания выполнения команды. !ВНИМАНИЕ! Логирование в такой ситуации будет невозможно; False - Агент ожидает окончания выполнения операции.

          • +
          • inSendOutputToOrchestratorLogsBool – True - отправлять весь вывод от команды в логи Оркестратора; Flase - Не отправлять; Default True

          • +
          • inCMDEncodingStr – Кодировка DOS среды, в которой исполняется команда. Если некорректно установить кодировку - русские символы будут испорчены. По умолчанию установлена «cp1251»

          • +
          • inCaptureBool – True - не запускать приложение как отдельное. Результат выполнения команды будет выводиться в окне Агента (если окно Агента присутствует на экране). False - команда будет запущена в отдельном DOS окне.

          Результат
          -

          GUID String of the ActivityItem - you can wait (sync or async) result by this guid!

          +

          ГУИД (GUID) строка Активности (ActivityItem). Далее можно ожидать результат этой функции по ГУИД с помощью функции AgentActivityItemReturnGet

          @@ -817,19 +793,19 @@
          pyOpenRPA.Orchestrator.__Orchestrator__.AgentOSFileBinaryDataBase64StrAppend(inHostNameStr, inUserStr, inFilePathStr, inFileDataBase64Str, inGSettings=None)[исходный код]
          -

          Append binary file by the base64 string by the pyOpenRPA.Agent daemon process (safe for JSON transmission)

          +

          Добавить бинарную информацию в существующий бинарный файл, который будет расположен по адресу inFilePathStr на стороне Агента с содержимым, декодированным с формата base64: inFileDataBase64Str

          Параметры
            -
          • inGSettings – Global settings dict (singleton)

          • -
          • inHostNameStr

          • -
          • inUserStr

          • -
          • inFilePathStr

          • -
          • inFileDataBase64Str

          • +
          • inHostNameStr – Наименование хоста, на котором запущен Агент. Наименования подключенных агентов доступно для просмотра в панели управления

          • +
          • inUserStr – Наименование пользователя, на графической сессии которого запущен Агент. Наименования подключенных агентов доступно для просмотра в панели управления

          • +
          • inFilePathStr – Полный путь к сохраняемому файлу на стороне Агента.

          • +
          • inFileDataBase64Str – Строка в формате base64 для отправки в создаваемый файл на стороне Агента.

          • +
          • inGSettings – Глобальный словарь настроек Оркестратора (синглтон)

          Результат
          -

          GUID String of the ActivityItem - you can wait (sync or async) result by this guid!

          +

          ГУИД (GUID) строка Активности (ActivityItem). Далее можно ожидать результат этой функции по ГУИД с помощью функции AgentActivityItemReturnGet

          @@ -837,19 +813,19 @@
          pyOpenRPA.Orchestrator.__Orchestrator__.AgentOSFileBinaryDataBase64StrCreate(inHostNameStr, inUserStr, inFilePathStr, inFileDataBase64Str, inGSettings=None)[исходный код]
          -

          Create binary file by the base64 string by the pyOpenRPA.Agent daemon process (safe for JSON transmission)

          +

          Создать бинарный файл, который будет расположен по адресу inFilePathStr на стороне Агента с содержимым, декодированным с формата base64: inFileDataBase64Str

          Параметры
            -
          • inGSettings – Global settings dict (singleton)

          • -
          • inHostNameStr

          • -
          • inUserStr

          • -
          • inFilePathStr

          • -
          • inFileDataBase64Str

          • +
          • inHostNameStr – Наименование хоста, на котором запущен Агент. Наименования подключенных агентов доступно для просмотра в панели управления

          • +
          • inUserStr – Наименование пользователя, на графической сессии которого запущен Агент. Наименования подключенных агентов доступно для просмотра в панели управления

          • +
          • inFilePathStr – Полный путь к сохраняемому файлу на стороне Агента.

          • +
          • inFileDataBase64Str – Строка в формате base64 для отправки в создаваемый файл на стороне Агента.

          • +
          • inGSettings – Глобальный словарь настроек Оркестратора (синглтон)

          Результат
          -

          GUID String of the ActivityItem - you can wait (sync or async) result by this guid!

          +

          ГУИД (GUID) строка Активности (ActivityItem). Далее можно ожидать результат этой функции по ГУИД с помощью функции AgentActivityItemReturnGet

          @@ -857,18 +833,18 @@
          pyOpenRPA.Orchestrator.__Orchestrator__.AgentOSFileBinaryDataBase64StrReceive(inHostNameStr, inUserStr, inFilePathStr, inGSettings=None)[исходный код]
          -

          Read binary file and encode in base64 to transmit (safe for JSON transmition)

          +

          Выполнить чтение бинарного файла и получить содержимое в формате base64 (строка)

          Параметры
            -
          • inGSettings – Global settings dict (singleton)

          • -
          • inHostNameStr

          • -
          • inUserStr

          • -
          • inFilePathStr – File path to read

          • +
          • inHostNameStr – Наименование хоста, на котором запущен Агент. Наименования подключенных агентов доступно для просмотра в панели управления

          • +
          • inUserStr – Наименование пользователя, на графической сессии которого запущен Агент. Наименования подключенных агентов доступно для просмотра в панели управления

          • +
          • inFilePathStr – Путь к бинарному файлу на чтение на стороне Агента

          • +
          • inGSettings – Глобальный словарь настроек Оркестратора (синглтон)

          Результат
          -

          GUID String of the ActivityItem - you can wait (sync or async) result by this guid!

          +

          ГУИД (GUID) строка Активности (ActivityItem). Далее можно ожидать результат этой функции по ГУИД с помощью функции AgentActivityItemReturnGet

          @@ -876,19 +852,19 @@
          pyOpenRPA.Orchestrator.__Orchestrator__.AgentOSFileBinaryDataBytesCreate(inHostNameStr, inUserStr, inFilePathStr, inFileDataBytes, inGSettings=None)[исходный код]
          -

          Create binary file by the base64 string by the pyOpenRPA.Agent daemon process (safe for JSON transmition)

          +

          Создать бинарный файл, который будет расположен по адресу inFilePathStr на стороне Агента с содержимым inFileDataBytes

          Параметры
            -
          • inGSettings – Global settings dict (singleton)

          • -
          • inHostNameStr

          • -
          • inUserStr

          • -
          • inFilePathStr

          • -
          • inFileDataBytes

          • +
          • inHostNameStr – Наименование хоста, на котором запущен Агент. Наименования подключенных агентов доступно для просмотра в панели управления

          • +
          • inUserStr – Наименование пользователя, на графической сессии которого запущен Агент. Наименования подключенных агентов доступно для просмотра в панели управления

          • +
          • inFilePathStr – Полный путь к сохраняемому файлу на стороне Агента.

          • +
          • inFileDataBytes – Строка байт (b““) для отправки в создаваемый файл на стороне Агента.

          • +
          • inGSettings – Глобальный словарь настроек Оркестратора (синглтон)

          Результат
          -

          GUID String of the ActivityItem - you can wait (sync or async) result by this guid!

          +

          ГУИД (GUID) строка Активности (ActivityItem). Далее можно ожидать результат этой функции по ГУИД с помощью функции AgentActivityItemReturnGet

          @@ -896,18 +872,18 @@
          pyOpenRPA.Orchestrator.__Orchestrator__.AgentOSFileBinaryDataReceive(inHostNameStr, inUserStr, inFilePathStr)[исходный код]
          -

          Read binary file from agent (synchronious)

          +

          Чтение бинарного файла на стороне Агента по адресу inFilePathStr.

          +

          !ВНИМАНИЕ - СИНХРОННАЯ! Функция не завершится, пока не будет получен результат чтения на стороне Агента.

          Параметры
            -
          • inGSettings – Global settings dict (singleton)

          • -
          • inHostNameStr

          • -
          • inUserStr

          • -
          • inFilePathStr – File path to read

          • +
          • inHostNameStr – Наименование хоста, на котором запущен Агент. Наименования подключенных агентов доступно для просмотра в панели управления

          • +
          • inUserStr – Наименование пользователя, на графической сессии которого запущен Агент. Наименования подключенных агентов доступно для просмотра в панели управления

          • +
          • inFilePathStr – Путь к бинарному файлу, который требуется прочитать на стороне Агента

          Результат
          -

          file data bytes

          +

          Строка байт (b““) - содержимое бинарного файла

          @@ -915,46 +891,42 @@
          pyOpenRPA.Orchestrator.__Orchestrator__.AgentOSFileSend(inHostNameStr, inUserStr, inOrchestratorFilePathStr, inAgentFilePathStr, inGSettings=None)[исходный код]
          -

          Send the file from the Orchestrator to Agent (synchroniously) pyOpenRPA.Agent daemon process (safe for JSON transmition). -Work safety with big files -Thread safe - you can call def even if you dont init the orchestrator - def will be executed later

          -
          -
          -
          param inGSettings
          -

          Global settings dict (singleton)

          -
          -
          param inHostNameStr
          -

          -
          param inUserStr
          -

          -
          param inFilePathStr
          -

          -
          param inFileDataBytes
          -

          -
          return
          -

          GUID String of the ActivityItem - you can wait (sync or async) result by this guid!

          +

          Отправить файл по адресу inOrchestratorFilePathStr со стороны Оркестратора и сохранить по адресу inAgentFilePathStr на стороне Агента. +Поддерживает передачу крупных файлов (более 2-х Гб.). Функция является синхронной - не закончит свое выполнение, пока файл не будет передан полностью.

          +

          !ВНИМАНИЕ - ПОТОКОБЕЗОПАСНАЯ! Вы можете вызвать эту функцию до инициализации ядра Оркестратора. Оркестратор добавит эту функцию в процессорную очередь на исполение. Если вам нужен результат функции, то необходимо сначала убедиться в том, что ядро Оркестратора было инициализированно (см. функцию OrchestratorInitWait).

          +
          +
          Параметры
          +
            +
          • inHostNameStr – Наименование хоста, на котором запущен Агент. Наименования подключенных агентов доступно для просмотра в панели управления

          • +
          • inUserStr – Наименование пользователя, на графической сессии которого запущен Агент. Наименования подключенных агентов доступно для просмотра в панели управления

          • +
          • inOrchestratorFilePathStr – Полный путь к передаваемому файлу на стороне Оркестратора.

          • +
          • inAgentFilePathStr – Полный путь к локации, в которую требуется сохранить передаваемый файл.

          • +
          • inGSettings – Глобальный словарь настроек Оркестратора (синглтон)

          • +
          +
          +
          Результат
          +

          ГУИД (GUID) строка Активности (ActivityItem). Далее можно ожидать результат этой функции по ГУИД с помощью функции AgentActivityItemReturnGet

          -
          pyOpenRPA.Orchestrator.__Orchestrator__.AgentOSFileTextDataStrCreate(inHostNameStr, inUserStr, inFilePathStr, inFileDataStr, inEncodingStr='utf-8', inGSettings=None)[исходный код]
          -

          Create text file by the string by the pyOpenRPA.Agent daemon process

          +

          Создать текстовый файл, который будет расположен по адресу inFilePathStr на стороне Агента с содержимым inFileDataStr в кодировке inEncodingStr

          Параметры
            -
          • inGSettings – Global settings dict (singleton)

          • -
          • inHostNameStr

          • -
          • inUserStr

          • -
          • inFilePathStr

          • -
          • inFileDataStr

          • -
          • inEncodingStr

          • +
          • inHostNameStr – Наименование хоста, на котором запущен Агент. Наименования подключенных агентов доступно для просмотра в панели управления

          • +
          • inUserStr – Наименование пользователя, на графической сессии которого запущен Агент. Наименования подключенных агентов доступно для просмотра в панели управления

          • +
          • inFilePathStr – Полный путь к сохраняемому файлу на стороне Агента.

          • +
          • inFileDataStr – Строка для отправки в создаваемый файл на стороне Агента.

          • +
          • inEncodingStr – Кодировка текстового файла. По умолчанию utf-8

          • +
          • inGSettings – Глобальный словарь настроек Оркестратора (синглтон)

          Результат
          -

          GUID String of the ActivityItem - you can wait (sync or async) result by this guid!

          +

          ГУИД (GUID) строка Активности (ActivityItem). Далее можно ожидать результат этой функции по ГУИД с помощью функции AgentActivityItemReturnGet

          @@ -962,19 +934,20 @@ Thread safe - you can call def even if you dont init the orchestrator - def will
          pyOpenRPA.Orchestrator.__Orchestrator__.AgentOSFileTextDataStrReceive(inHostNameStr, inUserStr, inFilePathStr, inEncodingStr='utf-8', inGSettings=None)[исходный код]
          -

          Read text file in the agent GUI session

          +

          Чтение текстового файла на стороне Агента по адресу inFilePathStr. По ГИУД с помощью функции AgentActivityItemReturnGet можно будет получить текстовую строку данных, которые были расположены в файле.

          +

          !ВНИМАНИЕ - АСИНХРОННАЯ! Функция завершится сразу, не дожидаясь окончания выполнения операции на стороне Агента.

          Параметры
            -
          • inGSettings – Global settings dict (singleton)

          • -
          • inHostNameStr

          • -
          • inUserStr

          • -
          • inFilePathStr – File path to read

          • -
          • inEncodingStr – Text file encoding. Default „utf-8“

          • +
          • inHostNameStr – Наименование хоста, на котором запущен Агент. Наименования подключенных агентов доступно для просмотра в панели управления

          • +
          • inUserStr – Наименование пользователя, на графической сессии которого запущен Агент. Наименования подключенных агентов доступно для просмотра в панели управления

          • +
          • inFilePathStr – Путь к бинарному файлу, который требуется прочитать на стороне Агента

          • +
          • inEncodingStr – Кодировка текстового файла. По умолчанию utf-8

          • +
          • inGSettings – Глобальный словарь настроек Оркестратора (синглтон)

          Результат
          -

          GUID String of the ActivityItem - you can wait (sync or async) result by this guid!

          +

          ГУИД (GUID) строка Активности (ActivityItem). Далее можно ожидать результат этой функции по ГУИД с помощью функции AgentActivityItemReturnGet

          @@ -982,42 +955,35 @@ Thread safe - you can call def even if you dont init the orchestrator - def will
          pyOpenRPA.Orchestrator.__Orchestrator__.AgentOSLogoff(inHostNameStr, inUserStr)[исходный код]
          -

          Logoff the agent user session

          -
          -
          Результат
          -

          GUID String of the ActivityItem - you can wait (sync or async) result by this guid!

          -
          -
          -
          - -
          -
          -pyOpenRPA.Orchestrator.__Orchestrator__.AgentProcessWOExeUpperUserListGet(inHostNameStr, inUserStr, inGSettings=None)[исходный код]
          -

          Return the process list only for the current user (where Agent is running) without .EXE in upper case. Can use in ActivityItem from Orchestrator to Agent

          +

          Выполнить операцию logoff на стороне пользователя.

          Параметры
            -
          • inGSettings – Global settings dict (singleton)

          • -
          • inHostNameStr

          • -
          • inUserStr

          • +
          • inHostNameStr – Наименование хоста, на котором запущен Агент. Наименования подключенных агентов доступно для просмотра в панели управления

          • +
          • inUserStr – Наименование пользователя, на графической сессии которого запущен Агент. Наименования подключенных агентов доступно для просмотра в панели управления

          Результат
          -

          GUID String of the ActivityItem - you can wait (sync or async) result by this guid!

          +

          ГУИД (GUID) строка Активности (ActivityItem). Далее можно ожидать результат этой функции по ГУИД с помощью функции AgentActivityItemReturnGet

          -
          -pyOpenRPA.Orchestrator.__Orchestrator__.GSettingsAutocleaner(inGSettings=None)[исходный код]
          -

          HIDDEN Interval gSettings auto cleaner def to clear some garbage.

          +
          +pyOpenRPA.Orchestrator.__Orchestrator__.AgentProcessWOExeUpperUserListGet(inHostNameStr, inUserStr, inGSettings=None)[исходный код]
          +

          Получить список процессов, которые выполняется на сессии Агента. Все процессы фиксируются без постфикса .exe, а также в верхнем регистре.

          +

          ПРИМЕР РЕЗУЛЬТАТА, КОТОРЫЙ МОЖНО ПОЛУЧИТЬ ПО ГУИД ЧЕРЕЗ ФУНКЦИЮ AgentActivityItemReturnGet: [«ORCHESTRATOR», «AGENT», «CHROME», «EXPLORER», …]

          Параметры
          -

          inGSettings – Global settings dict (singleton)

          +
            +
          • inGSettings – Глобальный словарь настроек Оркестратора (синглтон)

          • +
          • inHostNameStr – Наименование хоста, на котором запущен Агент. Наименования подключенных агентов доступно для просмотра в панели управления

          • +
          • inUserStr – Наименование пользователя, на графической сессии которого запущен Агент. Наименования подключенных агентов доступно для просмотра в панели управления

          • +
          Результат
          -

          None

          +

          ГУИД (GUID) строка Активности (ActivityItem). Далее можно ожидать результат этой функции по ГУИД с помощью функции AgentActivityItemReturnGet

          @@ -1025,13 +991,13 @@ Thread safe - you can call def even if you dont init the orchestrator - def will
          pyOpenRPA.Orchestrator.__Orchestrator__.GSettingsGet(inGSettings=None)[исходный код]
          -

          Get the GSettings from the singleton module.

          +

          Вернуть глобальный словарь настроек Оркестратора. Во время выполнения программы глобальный словарь настроек существует в единственном экземпляре (синглтон)

          Параметры
          -

          inGSettings – You can pass some GSettings to check if it equal to base gsettings. If not equal - def will merge it

          +

          inGSettings – Дополнительный словарь настроек, который необходимо добавить в основной глобальный словарь настроек Оркестратора (синглтон)

          Результат
          -

          GSettings

          +

          Глобальный словарь настроек GSettings

          @@ -1039,8 +1005,8 @@ Thread safe - you can call def even if you dont init the orchestrator - def will
          pyOpenRPA.Orchestrator.__Orchestrator__.GSettingsKeyListValueAppend(inValue, inKeyList=None, inGSettings=None)[исходный код]
          -

          Append value in GSettings by the key list

          -
          # USAGE
          +

          Применить операцию .append к обьекту, расположенному по адресу списка ключей inKeyList в глобальном словаре настроек Оркестратора GSettings. Пример: Добавить значение в конец списка (list).

          +
          # ПРИМЕР
           from pyOpenRPA import Orchestrator
           
           Orchestrator.GSettingsKeyListValueAppend(
          @@ -1060,30 +1026,27 @@ Thread safe - you can call def even if you dont init the orchestrator - def will
           
          Параметры
            -
          • inGSettings – Global settings dict (singleton)

          • -
          • inValue – Any value to be appended in gSettings Dict by the key list

          • -
          • inKeyList – List of the nested keys (see example)

          • +
          • inGSettings – Глобальный словарь настроек Оркестратора (синглтон)

          • +
          • inValue – Значение для установки в глобальный словарь настроек Оркестратора GSettings

          • +
          • inKeyList – Список ключей, по адресу которого выполнить добавление в конец списка (list)

          -
          Результат
          -

          True every time

          -
          pyOpenRPA.Orchestrator.__Orchestrator__.GSettingsKeyListValueGet(inKeyList=None, inGSettings=None)[исходный код]
          -

          Get the value from the GSettings by the key list

          +

          Получить значение из глобального словаря настроек Оркестратора GSettings по списку ключей.

          Параметры
            -
          • inGSettings – Global settings dict (singleton)

          • -
          • inKeyList

          • +
          • inGSettings – Глобальный словарь настроек Оркестратора (синглтон)

          • +
          • inKeyList – Список ключей, по адресу которого получить значение из GSettings

          Результат
          -

          value any type

          +

          Значение (тип данных определяется форматом хранения в GSettings)

          @@ -1091,8 +1054,8 @@ Thread safe - you can call def even if you dont init the orchestrator - def will
          pyOpenRPA.Orchestrator.__Orchestrator__.GSettingsKeyListValueOperatorPlus(inValue, inKeyList=None, inGSettings=None)[исходный код]
          -

          Execute plus operation between 2 lists (1:inValue and 2:gSettings by the inKeyList)

          -
          # USAGE
          +

          Применить оператор сложения (+) к обьекту, расположенному по адресу списка ключей inKeyList в глобальном словаре настроек Оркестратора GSettings. Пример: соединить 2 списка (list).

          +
          # ПРИМЕР
           from pyOpenRPA import Orchestrator
           
           Orchestrator.GSettingsKeyListValueOperatorPlus(
          @@ -1115,49 +1078,44 @@ Thread safe - you can call def even if you dont init the orchestrator - def will
           
          Параметры
            -
          • inGSettings – Global settings dict (singleton)

          • -
          • inValue – List with values to be merged with list in gSettings

          • -
          • inKeyList – List of the nested keys (see example)

          • +
          • inGSettings – Глобальный словарь настроек Оркестратора (синглтон)

          • +
          • inValue – Значение для установки в глобальный словарь настроек Оркестратора GSettings

          • +
          • inKeyList – Список ключей, по адресу которого выполнить добавление в конец списка (list)

          -
          Результат
          -

          True every time

          -
          pyOpenRPA.Orchestrator.__Orchestrator__.GSettingsKeyListValueSet(inValue, inKeyList=None, inGSettings=None)[исходный код]
          -

          Set value in GSettings by the key list

          +

          Установить значение из глобального словаря настроек Оркестратора GSettings по списку ключей.

          +

          Пример: Для того, чтобы установить значение для ключа car в словаре {«complex»:{«car»:»green»}, «simple»:»HELLO»}, необходимо передать список ключей: [«complex», «car»]

          Параметры
            -
          • inGSettings – Global settings dict (singleton)

          • -
          • inValue

          • -
          • inKeyList

          • +
          • inGSettings – Глобальный словарь настроек Оркестратора (синглтон)

          • +
          • inValue – Значение для установки в глобальный словарь настроек Оркестратора GSettings

          • +
          • inKeyList – Список ключей, по адресу которого установить значение в GSettings

          -
          Результат
          -

          bool

          -
          pyOpenRPA.Orchestrator.__Orchestrator__.OSCMD(inCMDStr, inRunAsyncBool=True, inLogger=None)[исходный код]
          -

          OS send command in shell locally

          +

          Отправить команду на выполнение на сессию, где выполняется Оркестратор.

          Параметры
            -
          • inCMDStr

          • -
          • inRunAsyncBool

          • -
          • inLogger

          • +
          • inCMDStr – Команда на отправку

          • +
          • inRunAsyncBool – True - выполнить команду в асинхронном режиме (не дожидаться окончания выполнения программы и не захватывать результат выполнения); False - Ждать окончания выполнения и захватывать результат

          • +
          • inLogger – Логгер, в который отправлять информацию о результате выполнения команды

          Результат
          -

          CMD result string

          +

          Строка результата выполнения команды. Если inRunAsyncBool = False

          @@ -1165,17 +1123,17 @@ Thread safe - you can call def even if you dont init the orchestrator - def will
          pyOpenRPA.Orchestrator.__Orchestrator__.OSCredentialsVerify(inUserStr, inPasswordStr, inDomainStr='')[исходный код]
          -

          Verify user credentials in windows. Return bool

          +

          Выполнить верификацию доменного (локального) пользователя по паре логин/пароль

          Параметры
            -
          • inUserStr

          • -
          • inPasswordStr

          • -
          • inDomainStr

          • +
          • inUserStr – Наименование пользователя

          • +
          • inPasswordStr – Пароль

          • +
          • inDomainStr – Домен. Если домена нет - не указывать или «»

          Результат
          -

          True - Credentials are actual; False - Credentials are not actual

          +

          True - Учетные данные верны; False - Учетные данные представлены некорректно

          @@ -1183,21 +1141,25 @@ Thread safe - you can call def even if you dont init the orchestrator - def will
          pyOpenRPA.Orchestrator.__Orchestrator__.OSLogoff()[исходный код]
          -

          Logoff the current orchestrator session -:return:

          +

          Выполнить отключение сессии, на которой выполняется Оркестратор.

          +
          +
          Результат
          +

          +
          +
          pyOpenRPA.Orchestrator.__Orchestrator__.OSRemotePCRestart(inHostStr, inForceBool=True, inLogger=None)[исходный код]
          -

          Send signal via power shell to restart remote PC -ATTENTION: Orchestrator user need to have restart right on the Remote machine to restart PC.

          +

          Отправить сигнал на удаленную перезагрузку операционной системы.

          +

          !ВНИМАНИЕ! Перезапуск будет принят, если учетная запись имеет полномочия на перезапуск на соответсвующей машине.

          Параметры
            -
          • inLogger – logger to log powershell result in logs

          • -
          • inHostStr – PC hostname which you need to restart.

          • -
          • inForceBool – True - send signal to force retart PC; False - else case

          • +
          • inHostStr – Имя хоста, который требуется перезагрузить

          • +
          • inForceBool – True - принудительная перезагрузка; False - мягкая перезагрузка (дождаться окончания выполнения всех операций). По умолчанию True

          • +
          • inLogger – Логгер, в который отправлять информацию о результате выполнения команды

          Результат
          @@ -1209,35 +1171,32 @@ ATTENTION: Orchestrator user need to have restart right on the Remote machine to
          pyOpenRPA.Orchestrator.__Orchestrator__.Orchestrator(inGSettings=None, inDumpRestoreBool=True, inRunAsAdministratorBool=True)[исходный код]
          -

          Main def to start orchestrator

          +

          Инициализация ядра Оркестратора (всех потоков)

          Параметры
            -
          • inGSettings

          • -
          • inDumpRestoreBool

          • -
          • inRunAsAdministratorBool

          • +
          • inGSettings – Глобальный словарь настроек Оркестратора (синглтон)

          • +
          • inDumpRestoreBool – True - Восстановить информацию о RDP сессиях и StorageDict; False - не восстанавливать

          • +
          • inRunAsAdministratorBool – True - Проверить права администратратора и обеспечить их; False - Не обеспечивать права администратора

          -
          Результат
          -

          -
          pyOpenRPA.Orchestrator.__Orchestrator__.OrchestratorInitWait() → None[исходный код]
          -

          Wait thread while orc will process initial action. -ATTENTION: DO NOT CALL THIS DEF IN THREAD WHERE ORCHESTRATOR MUST BE INITIALIZED - INFINITE LOOP

          +

          Ожидать инициализацию ядра Оркестратора

          +

          !ВНИМАНИЕ!: НИ В КОЕМ СЛУЧАЕ НЕ ЗАПУСКАТЬ ЭТУ ФУНКЦИЮ В ОСНОВНОМ ПОТОКЕ, ГДЕ ПРОИСХОДИТ ИНИЦИАЛИЗАЦИЯ ЯДРА ОРКЕСТРАТОРА - ВОЗНИКНЕТ ВЕЧНЫЙ ЦИКЛ

          pyOpenRPA.Orchestrator.__Orchestrator__.OrchestratorIsAdmin()[исходный код]
          -

          Check if Orchestrator process is running as administrator

          +

          Проверить, запущен ли Оркестратор с правами администратора. Права администратора нужны Оркестратору только для контроля графической сессии, на которой он запущен. Если эти права выделить индивидуально, то права администратора будут необязательны.

          Результат
          -

          True - run as administrator; False - not as administrator

          +

          True - Запущен с правами администратора; False - Не запущен с правами администратора

          @@ -1245,10 +1204,10 @@ ATTENTION: DO NOT CALL THIS DEF IN THREAD WHERE ORCHESTRATOR MUST BE INITIALIZED
          pyOpenRPA.Orchestrator.__Orchestrator__.OrchestratorIsInited() → bool[исходный код]
          -

          Check if Orchestrator initial actions were processed

          +

          Проверить, было ли проинициализировано ядро Оркестратора

          Результат
          -

          True - orc is already inited; False - else

          +

          True - Ядро Оркестратора было проинициализировано; False - Требуется время на инициализацию

          Тип результата

          bool

          @@ -1259,10 +1218,10 @@ ATTENTION: DO NOT CALL THIS DEF IN THREAD WHERE ORCHESTRATOR MUST BE INITIALIZED
          pyOpenRPA.Orchestrator.__Orchestrator__.OrchestratorLoggerGet() → logging.Logger[исходный код]
          -

          Get the logger from the Orchestrator

          +

          Получить логгер Оркестратора

          Результат
          -

          +

          Логгер

          @@ -1270,40 +1229,37 @@ ATTENTION: DO NOT CALL THIS DEF IN THREAD WHERE ORCHESTRATOR MUST BE INITIALIZED
          pyOpenRPA.Orchestrator.__Orchestrator__.OrchestratorPySearchInit(inGlobPatternStr, inDefStr=None, inDefArgNameGSettingsStr=None, inAsyncInitBool=False)[исходный код]
          -

          Search the py files by the glob and do the safe init (in try except). Also add inited module in sys.modules as imported (module name = file name without extension). -You can init CP in async way! -.. code-block:: python

          -
          -

          # USAGE VAR 1 (without the def auto call) -# Autoinit control panels starts with CP_ -Orchestrator.OrchestratorPySearchInit(inGlobPatternStr=»ControlPanelCP_*.py»)

          -

          # USAGE VAR 2 (with the def auto call) - for the backward compatibility CP for the Orchestrator ver. < 1.2.7 -# Autoinit control panels starts with CP_ -Orchestrator.OrchestratorPySearchInit(inGlobPatternStr=»ControlPanelCP_*.py», inDefStr=»SettingsUpdate», inDefArgNameGSettingsStr=»inGSettings»)

          -

          # INFO: The code above will replace the code below -## !!! For Relative import !!! CP Version Check -try:

          -
          -

          sys.path.insert(0,os.path.abspath(os.path.join(r»»))) -from ControlPanel import CP_VersionCheck -CP_VersionCheck.SettingsUpdate(inGSettings=gSettings)

          -
          -
          -
          except Exception as e:

          gSettings[«Logger»].exception(f»Exception when init CP. See below.»)

          -
          -
          -
          +

          Выполнить поиск и инициализацию пользовательских .py файлов в Оркестраторе (например панелей управления роботов)

          +

          Добавляет инициализированный модуль в пространство sys.modules как imported (имя модуля = имя файла без расширения).

          +
          # ВАРИАНТ ИСПОЛЬЗОВАНИЯ 1 (инициализация модуля py без вызова каких-либо функций внутри)
          +# автоинициализация всех .py файлов, с префиксом CP_, которые расположены в папке ControlPanel
          +Orchestrator.OrchestratorPySearchInit(inGlobPatternStr="ControlPanel\CP_*.py")
          +
          +# ВАРИАНТ ИСПОЛЬЗОВАНИЯ 2 (инициализация модуля py с вызовом функции внутри) - преимущественно для обратной совместимости старых версий панелей управления < 1.2.7
          +# автоинициализация всех .py файлов, с префиксом CP_, которые расположены в папке ControlPanel
          +Orchestrator.OrchestratorPySearchInit(inGlobPatternStr="ControlPanel\CP_*.py", inDefStr="SettingsUpdate", inDefArgNameGSettingsStr="inGSettings")
          +
          +# ДЛЯ СПРАВКИ & ИСТОРИИ: Код выше позволил отказаться от блока кода ниже для каждого .py файла
          +## !!! For Relative import !!! CP Version Check
          +try:
          +    sys.path.insert(0,os.path.abspath(os.path.join(r"")))
          +    from ControlPanel import CP_VersionCheck
          +    CP_VersionCheck.SettingsUpdate(inGSettings=gSettings)
          +except Exception as e:
          +    gSettings["Logger"].exception(f"Exception when init CP. See below.")
          +
          +
          Параметры
            -
          • inGlobPatternStr – example»..***X64*.cmd»

          • -
          • inDefStr – OPTIONAL The string name of the def. For backward compatibility if you need to auto call some def from initialized module

          • -
          • inDefArgNameGSettingsStr – OPTIONAL The name of the GSettings argument in def (if exists)

          • -
          • inAsyncInitBool – OPTIONAL True - init py modules in many threads - parallel execution. False (default) - sequence execution

          • +
          • inGlobPatternStr – Пример «..***_CP*.py»

          • +
          • inDefStr – ОПЦИОНАЛЬНО Строковое наименование функции. Преимущественно для обратной совместимости

          • +
          • inDefArgNameGSettingsStr – ОПЦИОНАЛЬНО Наименование аргумента, в который требуется передать GSettings (если необходимо)

          • +
          • inAsyncInitBool – ОПЦИОНАЛЬНО True - Инициализация py модулей в отдельных параллельных потоках - псевдопараллельное выполнение. False - последовательная инициализация

          Результат
          -

          { «ModuleNameStr»:{«PyPathStr»: «», «Module»: …}, …}

          +

          Сведения об инициализированных модулях в структуре: { «ModuleNameStr»:{«PyPathStr»: «», «Module»: …}, …}

          @@ -1311,10 +1267,10 @@ CP_VersionCheck.SettingsUpdate(inGSettings=gSettings)

          pyOpenRPA.Orchestrator.__Orchestrator__.OrchestratorRerunAsAdmin()[исходный код]
          -

          Check if not admin - then rerun orchestrator as administrator

          +

          Перезапустить Оркестратор с правами локального администратора. Права администратора нужны Оркестратору только для контроля графической сессии, на которой он запущен. Если эти права выделить индивидуально, то права администратора будут необязательны.

          Результат
          -

          True - run as administrator; False - not as administrator

          +

          True - Запущен с правами администратора; False - Не запущен с правами администратора

          @@ -1322,10 +1278,10 @@ CP_VersionCheck.SettingsUpdate(inGSettings=gSettings)

          pyOpenRPA.Orchestrator.__Orchestrator__.OrchestratorRestart(inGSettings=None)[исходный код]
          -

          Orchestrator restart

          +

          Перезапуск Оркестратора с сохранением информации о запущенных RDP сессиях.

          Параметры
          -

          inGSettings – Global settings dict (singleton)

          +

          inGSettings – Глобальный словарь настроек Оркестратора (синглтон)

          @@ -1333,11 +1289,18 @@ CP_VersionCheck.SettingsUpdate(inGSettings=gSettings)

          pyOpenRPA.Orchestrator.__Orchestrator__.OrchestratorScheduleGet() → <module „schedule“ from „c:\abs\archive\scopesrcul\pyopenrpa\resources\wpy64-3720\python-3.7.2.amd64\lib\site-packages\schedule\__init__.py“>[исходный код]
          -

          Get the schedule (schedule.readthedocs.io) from the Orchestrator

          -

          Fro example you can use:

          +

          Базовый объект расписания, который можно использовать для запуска / остановки роботов. +Подробнее про объект schedule и его примеры использования см. по адресу: schedule.readthedocs.io

          +
          # Однопоточный schedule
          +Orchestrator.OrchestratorScheduleGet().every(5).seconds.do(lProcess.StatusCheckStart)
          +
          +#Многопоточный schedule. cм. описание Orchestrator.OrchestratorThreadStart
          +Orchestrator.OrchestratorScheduleGet().every(5).seconds.do(Orchestrator.OrchestratorThreadStart,lProcess.StatusCheckStart)
          +
          +
          Результат
          -

          schedule module. Example see here https://schedule.readthedocs.io/en/stable/examples.html

          +

          schedule объект

          @@ -1345,22 +1308,21 @@ CP_VersionCheck.SettingsUpdate(inGSettings=gSettings)

          pyOpenRPA.Orchestrator.__Orchestrator__.OrchestratorSessionRestore(inGSettings=None)[исходный код]
          -

          Check _SessioLast… files in working directory. if exist - load into gsettings -(from version 1.2.7)

          -
          -

          _SessionLast_GSettings.pickle (binary)

          -
          +

          Восстановить состояние Оркестратора, если ранее состояние Оркестратора было сохранено с помощью функции OrchestratorSessionSave:

          +
            +
          • RDP сессий, которые контролирует Оркестратор

          • +
          • Хранилища DataStorage в глобальном словаре настроек GSettings. DataStorage поддерживает хранение объектов Python

          • +
          -
          (above the version 1.2.7)

          _SessionLast_RDPList.json (encoding = «utf-8») +

          (до версии 1.2.7)

          _SessionLast_GSettings.pickle (binary)

          +
          +
          (начиная с версии 1.2.7)

          _SessionLast_RDPList.json (encoding = «utf-8») _SessionLast_StorageDict.pickle (binary)

          Параметры
          -

          inGSettings – Global settings dict (singleton)

          -
          -
          Результат
          -

          +

          inGSettings – Глобальный словарь настроек Оркестратора (синглтон)

          @@ -1368,22 +1330,21 @@ _SessionLast_StorageDict.pickle (binary)

          pyOpenRPA.Orchestrator.__Orchestrator__.OrchestratorSessionSave(inGSettings=None)[исходный код]
          -

          Orchestrator session save in file -(from version 1.2.7)

          -
          -

          _SessionLast_GSettings.pickle (binary)

          -
          +

          Сохранить состояние Оркестратора (для дальнейшего восстановления в случае перезапуска):

          +
            +
          • RDP сессий, которые контролирует Оркестратор

          • +
          • Хранилища DataStorage в глобальном словаре настроек GSettings. DataStorage поддерживает хранение объектов Python

          • +
          -
          (above the version 1.2.7)

          _SessionLast_RDPList.json (encoding = «utf-8») +

          (до версии 1.2.7)

          _SessionLast_GSettings.pickle (binary)

          +
          +
          (начиная с версии 1.2.7)

          _SessionLast_RDPList.json (encoding = «utf-8») _SessionLast_StorageDict.pickle (binary)

          Параметры
          -

          inGSettings – Global settings dict (singleton)

          -
          -
          Результат
          -

          True every time

          +

          inGSettings – Глобальный словарь настроек Оркестратора (синглтон)

          @@ -1391,17 +1352,17 @@ _SessionLast_StorageDict.pickle (binary)

          pyOpenRPA.Orchestrator.__Orchestrator__.OrchestratorThreadStart(inDef, *inArgList, **inArgDict)[исходный код]
          -

          Execute def in new thread and pass some args with list and dict types

          +

          Запустить функцию в отдельном потоке. В таком случае получить результат выполнения функции можно только через общие переменные. (Например через GSettings)

          Параметры
            -
          • inDef – Python Def

          • -
          • inArgList – args as list

          • -
          • inArgDict – args as dict

          • +
          • inDef – Python функция

          • +
          • inArgList – Список неименованных аргументов функции inDef

          • +
          • inArgDict – Словарь именованных аргументов функции inDef

          Результат
          -

          threading.Thread object

          +

          threading.Thread экземпляр

          @@ -1409,33 +1370,31 @@ _SessionLast_StorageDict.pickle (binary)

          pyOpenRPA.Orchestrator.__Orchestrator__.ProcessDefIntervalCall(inDef, inIntervalSecFloat, inIntervalAsyncBool=False, inDefArgList=None, inDefArgDict=None, inDefArgGSettingsNameStr=None, inDefArgLoggerNameStr=None, inExecuteInNewThreadBool=True, inLogger=None, inGSettings=None)[исходный код]
          -

          Use this procedure if you need to run periodically some def. Set def, args, interval and enjoy :)

          +

          Периодический вызов функции Python.

          Параметры
            -
          • inGSettings – global settings

          • -
          • inDef – def link, which will be called with interval inIntervalSecFloat

          • -
          • inIntervalSecFloat – Interval in seconds between call

          • -
          • inIntervalAsyncBool – False - wait interval before next call after the previous iteration result; True - wait interval after previous iteration call

          • -
          • inDefArgList – List of the args in def. Default None (empty list)

          • -
          • inDefArgDict – Dict of the args in def. Default None (empty dict)

          • -
          • inDefArgGSettingsNameStr – Name of the GSettings arg name for def (optional)

          • -
          • inDefArgLoggerNameStr – Name of the Logger arg name for def (optional). If Use - please check fill of the inLogger arg.

          • -
          • inExecuteInNewThreadBool – True - create new thread for the periodic execution; False - execute in current thread. Default: True

          • -
          • inLogger – logging def if some case is appear

          • +
          • inDef – Функция Python, которую потребуется периодически вызывать

          • +
          • inIntervalSecFloat – Интервал между вызовами функции в сек.

          • +
          • inIntervalAsyncBool – False - ожидать интервал inIntervalSecFloat только после окончания выполнения предыдущей итерации; True - Ожидать интервал сразу после запуска итерации

          • +
          • inDefArgList – Список (list) неименованных аргументов для передачи в функцию. По умолчанию None

          • +
          • inDefArgDict – Словарь (dict) именованных аргументов для передачи в функцию. По умолчанию None

          • +
          • inDefArgGSettingsNameStr – Наименование аргумента глобального словаря настроек Оркестратора GSettings (опционально)

          • +
          • inDefArgLoggerNameStr – Наименование аргумента логгера Оркестратора (опционально)

          • +
          • inExecuteInNewThreadBool – True - периодический вызов выполнять в отдельном потоке (не останавливать выполнение текущего потока); False - Выполнение периодического вызова в текущем потоке, в котором была вызвана функция ProcessDefIntervalCall. По умолчанию: True

          • +
          • inLogger – Логгер для фиксации сообщений выполнения функции (опционально)

          • +
          • inGSettings – Глобальный словарь настроек Оркестратора (синглтон)

          -
          Результат
          -

          -
          pyOpenRPA.Orchestrator.__Orchestrator__.ProcessIsStarted(inProcessNameWOExeStr)[исходный код]
          -

          Check if there is any running process that contains the given name processName.

          -
          # USAGE
          +

          Проверить, запущен ли процесс, который в наименовании содержит inProcessNameWOExeStr.

          +

          !ВНИМАНИЕ! ПРОВЕРЯЕТ ВСЕ ПРОЦЕССЫ ОПЕРАЦИОННОЙ СИСТЕМЫ. И ДРУГИХ ПОЛЬЗОВАТЕЛЬСКИХ СЕССИЙ, ЕСЛИ ОНИ ЗАПУЩЕНЫ НА ЭТОЙ МАШИНЕ.

          +
          # ПРИМЕР
           from pyOpenRPA import Orchestrator
           
           lProcessIsStartedBool = Orchestrator.ProcessIsStarted(inProcessNameWOExeStr = "notepad")
          @@ -1444,10 +1403,10 @@ _SessionLast_StorageDict.pickle (binary)

          Параметры
          -

          inProcessNameWOExeStr – Process name WithOut (WO) „.exe“ postfix. Example: «notepad» (not «notepad.exe»)

          +

          inProcessNameWOExeStr – Наименование процесса без расширения .exe (WO = WithOut = Без) Пример: Для проверки процесса блокнота нужно указывать «notepad», не «notepad.exe»

          Результат
          -

          True - process is running on the orchestrator machine; False - process is not running on the orchestrator machine

          +

          True - Процесс запущен на ОС ; False - Процесс не запущен на ОС, где работает Оркестратор

          @@ -1455,8 +1414,9 @@ _SessionLast_StorageDict.pickle (binary)

          pyOpenRPA.Orchestrator.__Orchestrator__.ProcessListGet(inProcessNameWOExeList=None)[исходный код]
          -

          Return process list on the orchestrator machine sorted by Memory Usage. You can determine the list of the processes you are interested - def will return the list about it.

          -
          # USAGE
          +

          Вернуть список процессов, запущенных на ОС, где работает Оркестратор. В списке отсортировать процессы по количеству используемой оперативной памяти. Также можно указать перечень процессов, которые интересуют - функция будет показывать активные из них.

          +

          !ВНИМАНИЕ! ДЛЯ ПОЛУЧЕНИЯ СПИСКА ВСЕХ ПРОЦЕССОВ ОС НЕОБХОДИМО ЗАПУСКАТЬ ОРКЕСТРАТОР С ПРАВАМИ АДМИНИСТРАТОРА.

          +
          # ПРИМЕР
           from pyOpenRPA import Orchestrator
           
           lProcessList = Orchestrator.ProcessListGet()
          @@ -1466,35 +1426,36 @@ _SessionLast_StorageDict.pickle (binary)

          Параметры
          -

          inProcessNameWOExeList

          +

          inProcessNameWOExeList – Список процессов, среди которых искать активные. Если параметр не указывать - вернет перечень всех доступных процессов

          Результат
          -

          {

          -

          -
          -
          -

          «ProcessWOExeList»: [«notepad»,»…»], +

          Сведения о запущенных процессах в следующем формате { +«ProcessWOExeList»: [«notepad»,»…»], «ProcessWOExeUpperList»: [«NOTEPAD»,»…»], «ProcessDetailList»: [

          -
          {

          „pid“: 412, +

          {

          „pid“: 412, # Идентификатор процесса „username“: «DESKTOPUSER», „name“: „notepad.exe“, -„vms“: 13.77767775, +„vms“: 13.77767775, # В Мб „NameWOExeUpperStr“: „NOTEPAD“, „NameWOExeStr“: «„notepad“»},

          {…}]

          +

          +
          +
          pyOpenRPA.Orchestrator.__Orchestrator__.ProcessStart(inPathStr, inArgList, inStopProcessNameWOExeStr=None)[исходный код]
          -

          Start process locally. Extra feature: Use inStopProcessNameWOExeStr to stop the execution if current process is running.

          -
          # USAGE
          +

          Запуск процесса на сессии Оркестратора, если на ОС не запущен процесс inStopProcessNameWOExeStr.

          +

          !ВНИМАНИЕ! ПРИ ПРОВЕРКЕ РАНЕЕ ЗАПУЩЕННЫХ ПРОЦЕССОВ ПРОВЕРЯЕТ ВСЕ ПРОЦЕССЫ ОПЕРАЦИОННОЙ СИСТЕМЫ. И ДРУГИХ ПОЛЬЗОВАТЕЛЬСКИХ СЕССИЙ, ЕСЛИ ОНИ ЗАПУЩЕНЫ НА ЭТОЙ МАШИНЕ.

          +
          # ПРИМЕР
           from pyOpenRPA import Orchestrator
           
           Orchestrator.ProcessStart(
          @@ -1507,22 +1468,19 @@ _SessionLast_StorageDict.pickle (binary)

          Параметры
            -
          • inPathStr – Command to send in CMD

          • -
          • inArgList – List of the arguments for the CMD command. Example: [«test.txt»]

          • -
          • inStopProcessNameWOExeStr – Trigger: stop execution if process is running. Process name WithOut (WO) „.exe“ postfix. Example: «notepad» (not «notepad.exe»)

          • +
          • inPathStr – Путь к файлу запускаемого процесса

          • +
          • inArgList – Список аргументов, передаваемых в запускаемый процесс. Пример: [«test.txt»]

          • +
          • inStopProcessNameWOExeStr – Доп. контроль: Не запускать процесс, если обнаружен запущенный процесс под наименованием inStopProcessNameWOExeStr без расширения .exe (WO = WithOut = Без)

          -
          Результат
          -

          None - nothing is returned. If process will not start -exception will be raised

          -
          pyOpenRPA.Orchestrator.__Orchestrator__.ProcessStop(inProcessNameWOExeStr, inCloseForceBool, inUserNameStr='%username%')[исходный код]
          -

          Stop process on the orchestrator machine. You can set user session on the machine and set flag about to force close process.

          -
          # USAGE
          +

          Остановить процесс на ОС, где работает Оркестратор, под учетной записью inUserNameStr.

          +
          # ПРИМЕР
           from pyOpenRPA import Orchestrator
           
           Orchestrator.ProcessStop(
          @@ -1535,21 +1493,18 @@ _SessionLast_StorageDict.pickle (binary)

          Параметры
            -
          • inProcessNameWOExeStr – Process name WithOut (WO) „.exe“ postfix. Example: «notepad» (not «notepad.exe»)

          • -
          • inCloseForceBool – True - do force close. False - send signal to safe close (!ATTENTION! - Safe close works only in orchestrator session. Win OS doens’t allow to send safe close signal between GUI sessions)

          • -
          • inUserNameStr – User name which is has current process to close. Default value is close process on the Orchestrator session

          • +
          • inProcessNameWOExeStr – Наименование процесса без расширения .exe (WO = WithOut = Без). Пример: Для проверки процесса блокнота нужно указывать «notepad», не «notepad.exe»

          • +
          • inCloseForceBool – True - принудительно завершить процесс. False - отправить сигнал на безопасное отключение (!ВНИМАНИЕ! - ОС не позволяет отправлять сигнал на безопасное отключение на другую сесиию - только на той, где работает Оркестратор)

          • +
          • inUserNameStr – Наименование пользователя, под именем которого искать процесс для остановки. По умолчанию «%username%» - искать процесс на текущей сессии

          -
          Результат
          -

          None

          -
          pyOpenRPA.Orchestrator.__Orchestrator__.ProcessorActivityItemAppend(inGSettings=None, inDef=None, inArgList=None, inArgDict=None, inArgGSettingsStr=None, inArgLoggerStr=None, inActivityItemDict=None)[исходный код]
          -

          Create and add activity item in processor queue.

          +

          Добавить активность (ActivityItem) в процессорную очередь.

          # USAGE
           from pyOpenRPA import Orchestrator
           
          @@ -1587,89 +1542,95 @@ _SessionLast_StorageDict.pickle (binary)

          Параметры
            -
          • inGSettings – Global settings dict (singleton)

          • -
          • inDef – def link or def alias (look gSettings[«Processor»][«AliasDefDict»])

          • -
          • inArgList – Args list for the Def

          • -
          • inArgDict – Args dict for the Def

          • -
          • inArgGSettingsStr – Name of def argument of the GSettings dict

          • -
          • inArgLoggerStr – Name of def argument of the logging object

          • -
          • inActivityItemDict – Fill if you already have ActivityItemDict (don’t fill inDef, inArgList, inArgDict, inArgGSettingsStr, inArgLoggerStr)

          • +
          • inGSettings – Глобальный словарь настроек Оркестратора (синглтон)

          • +
          • inDef – Функция Python или синоним (текстовый ключ)

          • +
          • inArgList – Список (list) неименованных аргументов к функции

          • +
          • inArgDict – Словарь (dict) именованных аргументов к функции

          • +
          • inArgGSettingsStr – Текстовое наименование аргумента GSettings (если требуется передавать)

          • +
          • inArgLoggerStr – Текстовое наименование аргумента logger (если требуется передавать)

          • +
          • inGUIDStr – ГУИД идентификатор активности (ActivityItem). Если ГУИД не указан, то он будет сгенерирован автоматически

          • +
          • inThreadBool – True - выполнить ActivityItem в новом потоке; False - выполнить последовательно в общем потоке процессорной очереди

          • +
          • inActivityItemDict – Альтернативный вариант заполнения, если уже имеется Активность (ActivityItem). В таком случае не требуется заполнять аргументы inDef, inArgList, inArgDict, inArgGSettingsStr, inArgLoggerStr

          -

          :return ActivityItem GUIDStr

          +

          :return ГУИД активности (ActivityItem)

          pyOpenRPA.Orchestrator.__Orchestrator__.ProcessorActivityItemCreate(inDef, inArgList=None, inArgDict=None, inArgGSettingsStr=None, inArgLoggerStr=None, inGUIDStr=None, inThreadBool=False)[исходный код]
          -

          Create activity item. Activity item can be used as list item in ProcessorActivityItemAppend or in Processor.ActivityListExecute. -Deprecated. See ActivityItemCreate -.. code-block:: python

          -
          -

          # USAGE -from pyOpenRPA import Orchestrator

          -

          # EXAMPLE 1 -def TestDef(inArg1Str, inGSettings, inLogger):

          -
          -

          pass

          -
          -
          -
          lActivityItem = Orchestrator.ProcessorActivityItemCreate(

          inDef = TestDef, -inArgList=[], -inArgDict={«inArg1Str»: «ArgValueStr»}, -inArgGSettingsStr = «inGSettings», -inArgLoggerStr = «inLogger»)

          -
          -
          -

          # lActivityItem: -# { -# «Def»:TestDef, -# «ArgList»:inArgList, -# «ArgDict»:inArgDict, -# «ArgGSettings»: «inArgGSettings», -# «ArgLogger»: «inLogger» -# }

          -

          # EXAMPLE 2 -def TestDef(inArg1Str):

          -
          -

          pass

          -
          -
          -
          Orchestrator.ProcessorAliasDefUpdate(

          inGSettings = gSettings, -inDef = TestDef, -inAliasStr=»TestDefAlias»)

          -
          -
          lActivityItem = Orchestrator.ProcessorActivityItemCreate(

          inDef = «TestDefAlias», -inArgList=[], -inArgDict={«inArg1Str»: «ArgValueStr»}, -inArgGSettingsStr = None, -inArgLoggerStr = None)

          -
          -
          -

          # lActivityItem: -# { -# «Def»:»TestDefAlias», -# «ArgList»:inArgList, -# «ArgDict»:inArgDict, -# «ArgGSettings»: None, -# «ArgLogger»: None -# }

          -
          +

          Создать Активность (ActivityItem). Активность можно использовать в ProcessorActivityItemAppend или в Processor.ActivityListExecute или в функциях работы с Агентами.

          +

          Старая версия. Новую версию см. в ActivityItemCreate

          +
          # ПРИМЕР
          +from pyOpenRPA import Orchestrator
          +
          +# ВАРИАНТ 1
          +def TestDef(inArg1Str, inGSettings, inLogger):
          +    pass
          +lActivityItem = Orchestrator.ProcessorActivityItemCreate(
          +    inDef = TestDef,
          +    inArgList=[],
          +    inArgDict={"inArg1Str": "ArgValueStr"},
          +    inArgGSettingsStr = "inGSettings",
          +    inArgLoggerStr = "inLogger")
          +# lActivityItem:
          +#   {
          +#       "Def":TestDef,
          +#       "ArgList":inArgList,
          +#       "ArgDict":inArgDict,
          +#       "ArgGSettings": "inArgGSettings",
          +#       "ArgLogger": "inLogger"
          +#   }
          +
          +# ВАРИАНТ 2
          +def TestDef(inArg1Str):
          +    pass
          +Orchestrator.ProcessorAliasDefUpdate(
          +    inGSettings = gSettings,
          +    inDef = TestDef,
          +    inAliasStr="TestDefAlias")
          +lActivityItem = Orchestrator.ProcessorActivityItemCreate(
          +    inDef = "TestDefAlias",
          +    inArgList=[],
          +    inArgDict={"inArg1Str": "ArgValueStr"},
          +    inArgGSettingsStr = None,
          +    inArgLoggerStr = None)
          +# lActivityItem:
          +#   {
          +#       "Def":"TestDefAlias",
          +#       "ArgList":inArgList,
          +#       "ArgDict":inArgDict,
          +#       "ArgGSettings": None,
          +#       "ArgLogger": None
          +#   }
          +
          +
          Параметры
            -
          • inDef – def link or def alias (look gSettings[«Processor»][«AliasDefDict»])

          • -
          • inArgList – Args list for the Def

          • -
          • inArgDict – Args dict for the def

          • -
          • inArgGSettingsStr – Name of def argument of the GSettings dict

          • -
          • inArgLoggerStr – Name of def argument of the logging object

          • -
          • inGUIDStr – GUID which you can specify. If None the GUID will be generated

          • -
          • inThreadBool – True - execute ActivityItem in new thread; False - in processor thread

          • +
          • inDef – Функция Python или синоним (текстовый ключ)

          • +
          • inArgList – Список (list) неименованных аргументов к функции

          • +
          • inArgDict – Словарь (dict) именованных аргументов к функции

          • +
          • inArgGSettingsStr – Текстовое наименование аргумента GSettings (если требуется передавать)

          • +
          • inArgLoggerStr – Текстовое наименование аргумента logger (если требуется передавать)

          • +
          • inGUIDStr – ГУИД идентификатор активности (ActivityItem). Если ГУИД не указан, то он будет сгенерирован автоматически

          • +
          • inThreadBool – True - выполнить ActivityItem в новом потоке; False - выполнить последовательно в общем потоке процессорной очереди

          Результат
          -

          {}

          +

          +
          lActivityItemDict= {

          «Def»:inDef, # def link or def alias (look gSettings[«Processor»][«AliasDefDict»]) +«ArgList»:inArgList, # Args list +«ArgDict»:inArgDict, # Args dictionary +«ArgGSettings»: inArgGSettingsStr, # Name of GSettings attribute: str (ArgDict) or index (for ArgList) +«ArgLogger»: inArgLoggerStr, # Name of GSettings attribute: str (ArgDict) or index (for ArgList) +«GUIDStr»: inGUIDStr, +«ThreadBool»: inThreadBool

          +
          +
          +

          }

          +

          @@ -1677,9 +1638,8 @@ inArgLoggerStr = None)

          pyOpenRPA.Orchestrator.__Orchestrator__.ProcessorAliasDefCreate(inDef, inAliasStr=None, inGSettings=None)[исходный код]
          -

          Create alias for def (can be used in ActivityItem in field Def) -!WHEN DEF ALIAS IS REQUIRED! - Def alias is required when you try to call Python def from the Orchestrator WEB side (because you can’t transmit Python def object out of the Python environment) -Deprecated. See ActivityItemDefAliasCreate

          +

          Создать синоним (текстовый ключ) для инициации выполнения функции в том случае, если запрос на выполнения пришел из вне (передача функций невозможна).

          +

          Старая версия. Новую версию см. ActivityItemDefAliasCreate

          # USAGE
           from pyOpenRPA import Orchestrator
           
          @@ -1695,13 +1655,13 @@ Deprecated. See ActivityItemDefAliasCreate

          Параметры
            -
          • inGSettings – Global settings dict (singleton)

          • -
          • inDef – Def

          • -
          • inAliasStr – String alias for associated def

          • +
          • inDef – функция Python

          • +
          • inAliasStr – Строковый ключ (синоним), который можно будет использовать в Активности (ActivityItem)

          • +
          • inGSettings – Глобальный словарь настроек Оркестратора (синглтон)

          Результат
          -

          str Alias string (Alias can be regenerated if previous alias was occupied)

          +

          Строковый ключ, который был назначен. Ключ может быть изменен, если входящий текстовый ключ был уже занят.

          @@ -1709,9 +1669,8 @@ Deprecated. See ActivityItemDefAliasCreate

          pyOpenRPA.Orchestrator.__Orchestrator__.ProcessorAliasDefUpdate(inDef, inAliasStr, inGSettings=None)[исходный код]
          -

          Update alias for def (can be used in ActivityItem in field Def). -!WHEN DEF ALIAS IS REQUIRED! - Def alias is required when you try to call Python def from the Orchestrator WEB side (because you can’t transmit Python def object out of the Python environment) -Deprecated. See ActivityItemDefAliasUpdate

          +

          Обновить синоним (текстовый ключ) для инициации выполнения функции в том случае, если запрос на выполнения пришел из вне (передача функций невозможна).

          +

          Старая версия. Новую версию см. ActivityItemDefAliasUpdate

          # USAGE
           from pyOpenRPA import Orchestrator
           
          @@ -1727,13 +1686,13 @@ Deprecated. See ActivityItemDefAliasUpdate

          Параметры
            -
          • inGSettings – Global settings dict (singleton)

          • -
          • inDef – Def

          • -
          • inAliasStr – String alias for associated def

          • +
          • inGSettings – Глобальный словарь настроек Оркестратора (синглтон)

          • +
          • inDef – функция Python

          • +
          • inAliasStr – Строковый ключ (синоним), который можно будет использовать в Активности (ActivityItem)

          Результат
          -

          str Alias string

          +

          Строковый ключ, который был назначен. Ключ будет тем же, если входящий текстовый ключ был уже занят.

          @@ -1741,12 +1700,12 @@ Deprecated. See ActivityItemDefAliasUpdate

          pyOpenRPA.Orchestrator.__Orchestrator__.PythonStart(inModulePathStr, inDefNameStr, inArgList=None, inArgDict=None, inLogger=None)[исходный код]
          -

          Import module and run def in the Orchestrator process.

          +

          Импорт модуля и выполнение функции в процессе Оркестратора.

          Примечание

          -

          Import module will be each time when PythonStart def will be called.

          +

          Импорт модуля inModulePathStr будет происходить каждый раз в вызовом функции PythonStart.

          -
          # USAGE
          +
          # ПРИМЕР
           from pyOpenRPA import Orchestrator
           
           Orchestrator.PythonStart(
          @@ -1758,24 +1717,22 @@ Deprecated. See ActivityItemDefAliasUpdate

          Параметры
            -
          • inModulePathStr – Absolute or relative (working directory of the orchestrator process) path to the importing module .py

          • -
          • inDefNameStr – Def name in module

          • -
          • inArgList – List of the arguments for callable def

          • -
          • inArgDict – Dict of the named arguments for callable def

          • -
          • inLogger – Logger instance to log some information when PythonStart def is running

          • +
          • inModulePathStr – Абсолютный или относительный путь (относительно рабочей директории процесса Оркестратора), по которому расположен импортируемый .py файл

          • +
          • inDefNameStr – Наименование функции в модуле .py

          • +
          • inArgList – Список (list) неименованных аргументов для передачи в функцию. По умолчанию None

          • +
          • inArgDict – Словарь (dict) именованных аргументов для передачи в функцию. По умолчанию None

          • +
          • inLogger – Логгер для фиксации сообщений выполнения функции (опционально)

          -
          Результат
          -

          None

          -
          pyOpenRPA.Orchestrator.__Orchestrator__.RDPSessionCMDRun(inRDPSessionKeyStr, inCMDStr, inModeStr='CROSSCHECK', inGSettings=None)[исходный код]
          -

          Send CMD command to the RDP session «RUN» window

          -
          # USAGE
          +

          Отправить CMD команду на удаленную сесиию через RDP окно (без Агента).

          +

          !ВНИМАНИЕ! Данная функция может работать нестабильно из-за использования графических элементов UI при работе с RDP. Мы рекомендуем использовать конструкцию взаимодействия Оркестратора с Агентом.

          +
          # ПРИМЕР
           from pyOpenRPA import Orchestrator
           
           lResultDict = Orchestrator.RDPSessionCMDRun(
          @@ -1788,20 +1745,20 @@ Deprecated. See ActivityItemDefAliasUpdate

          Параметры
            -
          • inGSettings – Global settings dict (singleton)

          • -
          • inRDPSessionKeyStr – RDP Session string key - need for the further identification

          • -
          • inCMDStr – Any CMD string

          • -
          • inModeStr – Variants: -«LISTEN» - Get result of the cmd command in result; -«CROSSCHECK» - Check if the command was successfully sent -«RUN» - Run without crosscheck and get clipboard

          • +
          • inRDPSessionKeyStr – Ключ RDP сессии - необходим для дальнейшей идентификации

          • +
          • inCMDStr – Команда CMD, которую отправить на удаленную сессию

          • +
          • inModeStr – По умолчанию «CROSSCHECK». Варианты: +«LISTEN» - Получить результат выполнения операции. Внимание! необходим общий буфер обмена с сессией Оркестратора! +«CROSSCHECK» - Выполнить проверку, что операция была выполнена (без получения результата отработки CMD команды). Внимание! необходим общий буфер обмена с сессией Оркестратора! +«RUN» - Не получать результат и не выполнять проверку

          • +
          • inGSettings – Глобальный словарь настроек Оркестратора (синглтон)

          Результат

          -
          # OLD > True - CMD was executed successfully
          -
          {

          «OutStr»: <> # Result string -«IsResponsibleBool»: True|False # Flag is RDP is responsible - works only when inModeStr = CROSSCHECK

          +
          Результат выполнения операции в соответсвии с параметрами инициализации функции. Выходная структура:
          +
          {

          «OutStr»: <> # Результат выполнения CMD (если inModeStr = «LISTEN») +«IsResponsibleBool»: True|False # True - RDP приняло команду; False - обратная связь не была получена (если inModeStr = «CROSSCHECK»)

          @@ -1815,13 +1772,12 @@ Deprecated. See ActivityItemDefAliasUpdate

          pyOpenRPA.Orchestrator.__Orchestrator__.RDPSessionConnect(inRDPSessionKeyStr, inRDPTemplateDict=None, inHostStr=None, inPortStr=None, inLoginStr=None, inPasswordStr=None, inGSettings=None, inRedirectClipboardBool=True)[исходный код]
          -
          -
          Create new RDPSession in RobotRDPActive. Attention - activity will be ignored if RDP key is already exists

          2 way of the use

          -
          -
          -

          Var 1 (Main stream): inGSettings, inRDPSessionKeyStr, inRDPTemplateDict -Var 2 (Backward compatibility): inGSettings, inRDPSessionKeyStr, inHostStr, inPortStr, inLoginStr, inPasswordStr

          -
          # USAGE
          +

          Выполнить подключение к RDP и следить за стабильностью соединения со стороны Оркестратора. +!ВНИМАНИЕ! - Подключение будет проигнорировано, если соединение по таком RDP ключу уже было инициализировано ранее.

          +

          2 способа использования функции: +ВАРИАНТ 1 (ОСНОВНОЙ): inGSettings, inRDPSessionKeyStr, inRDPTemplateDict. Для получения inRDPTemplateDict см. функцию Orchestrator.RDPTemplateCreate +ВАРИАНТ 2 (ОБРАТНАЯ СОВМЕСТИМОСТЬ ДО ВЕРСИИ 1.1.20): inGSettings, inRDPSessionKeyStr, inHostStr, inPortStr, inLoginStr, inPasswordStr

          +
          # ПРИМЕР (ВАРИАНТ 1)
           from pyOpenRPA import Orchestrator
           
           lRDPItemDict = Orchestrator.RDPTemplateCreate(
          @@ -1838,26 +1794,24 @@ Var 2 (Backward compatibility): inGSettings, inRDPSessionKeyStr, inHostStr, inPo
           
          Параметры
            -
          • inGSettings – Global settings dict (singleton)

          • -
          • inRDPSessionKeyStr – RDP Session string key - need for the further identification

          • -
          • inRDPTemplateDict – RDP configuration dict with settings (see def Orchestrator.RDPTemplateCreate)

          • -
          • inHostStr – Backward compatibility from Orchestrator v 1.1.20. Use inRDPTemplateDict

          • -
          • inPortStr – Backward compatibility from Orchestrator v 1.1.20. Use inRDPTemplateDict

          • -
          • inLoginStr – Backward compatibility from Orchestrator v 1.1.20. Use inRDPTemplateDict

          • -
          • inPasswordStr – Backward compatibility from Orchestrator v 1.1.20. Use inRDPTemplateDict

          • +
          • inRDPSessionKeyStr – Ключ RDP сессии - необходим для дальнейшей идентификации

          • +
          • inRDPTemplateDict – Конфигурационный словарь (dict) RDP подключения (см. функцию Orchestrator.RDPTemplateCreate)

          • +
          • inLoginStr – Логин учетной записи, на которую будет происходить вход по RDP. Обратная совместимость до версии v 1.1.20. Мы рекомендуем использовать inRDPTemplateDict (см. функцию Orchestrator.RDPTemplateCreate)

          • +
          • inPasswordStr – Пароль учетной записи, на которую будет происходить вход по RDP. !ВНИМАНИЕ! Пароль нигде не сохраняется - конфиденциальность обеспечена. Обратная совместимость до версии v 1.1.20. Мы рекомендуем использовать inRDPTemplateDict (см. функцию Orchestrator.RDPTemplateCreate)

          • +
          • inHostStr – Имя хоста, к которому планируется подключение по RDP. Пример «77.77.22.22». Обратная совместимость до версии v 1.1.20. Мы рекомендуем использовать inRDPTemplateDict (см. функцию Orchestrator.RDPTemplateCreate)

          • +
          • inPortInt – RDP порт, по которому будет происходить подключение. По умолчанию 3389 (стандартный порт RDP). Обратная совместимость до версии v 1.1.20. Мы рекомендуем использовать inRDPTemplateDict (см. функцию Orchestrator.RDPTemplateCreate)

          • +
          • inGSettings – Глобальный словарь настроек Оркестратора (синглтон)

          • +
          • inRedirectClipboardBool – True - Синхронизировать буфер обмена между сессией Оркестратора и удаленной RDP сессией; False - Не синхронизировать буфер обмена. По умолчанию True (в целях обратной совместимости). !ВНИМАНИЕ! Для учетных записей роботов мы рекомендуем не синхронизировать буфер обмена, так как это может привести к ошибкам роботов, которые работают с клавиатурой и буфером обмена

          -
          Результат
          -

          True every time :)

          -
          pyOpenRPA.Orchestrator.__Orchestrator__.RDPSessionDisconnect(inRDPSessionKeyStr, inBreakTriggerProcessWOExeList=None, inGSettings=None)[исходный код]
          -

          Disconnect the RDP session and stop monitoring it.

          -
          # USAGE
          +

          Выполнить отключение RDP сессии и прекратить мониторить его активность.

          +
          # ПРИМЕР
           from pyOpenRPA import Orchestrator
           
           Orchestrator.RDPSessionDisconnect(
          @@ -1869,39 +1823,21 @@ Var 2 (Backward compatibility): inGSettings, inRDPSessionKeyStr, inHostStr, inPo
           
          Параметры
            -
          • inGSettings – Global settings dict (singleton)

          • -
          • inRDPSessionKeyStr – RDP Session string key - need for the further identification

          • -
          • inBreakTriggerProcessWOExeList

            List of the processes, which will stop the execution. Example [«notepad»]

            -

            Orchestrator look processes on the current machine

            -

          • +
          • inRDPSessionKeyStr – Ключ RDP сессии - необходим для дальнейшей идентификации

          • +
          • inBreakTriggerProcessWOExeList – Список процессов, наличие которых в диспетчере задач приведет к прерыванию задачи по остановке RDP соединения. Пример [«notepad»]

          • +
          • inGSettings – Глобальный словарь настроек Оркестратора (синглтон)

          -
          Результат
          -

          True every time

          -
          -
          -
          - -
          -
          -pyOpenRPA.Orchestrator.__Orchestrator__.RDPSessionDublicatesResolve(inGSettings)[исходный код]
          -

          DEVELOPING Search duplicates in GSettings RDPlist -!def is developing!

          -
          -
          Параметры
          -

          inGSettings – Global settings dict (singleton)

          -
          -
          Результат
          -

          -
          pyOpenRPA.Orchestrator.__Orchestrator__.RDPSessionFileStoredRecieve(inRDPSessionKeyStr, inRDPFilePathStr, inHostFilePathStr, inGSettings=None)[исходный код]
          -

          Recieve file from RDP session to the Orchestrator session using shared drive in RDP (see RDP Configuration Dict, Shared drive)

          -
          # USAGE
          +

          Получение файла со стороны RDP сессии на сторону Оркестратора через UI инструменты RDP окна (без Агента).

          +

          !ВНИМАНИЕ! Данная функция может работать нестабильно из-за использования графических элементов UI при работе с RDP. Мы рекомендуем использовать конструкцию взаимодействия Оркестратора с Агентом.

          +

          !ВНИМАНИЕ! Для работы функции требуется открыть доступ по RDP к тем дискам, с которых будет производится копирование файла.

          +
          # ПРИМЕР
           from pyOpenRPA import Orchestrator
           
           lResultDict = Orchestrator.RDPSessionFileStoredRecieve(
          @@ -1915,23 +1851,22 @@ Var 2 (Backward compatibility): inGSettings, inRDPSessionKeyStr, inHostStr, inPo
           
          Параметры
            -
          • inGSettings – Global settings dict (singleton)

          • -
          • inRDPSessionKeyStr – RDP Session string key - need for the further identification

          • -
          • inRDPFilePathStr – !Absolute! path to the destination file location on the RDP side. Example: «C:RPATESTDIRTest.py»

          • -
          • inHostFilePathStr – Relative or absolute path to the file location on the Orchestrator side. Example: «TESTDIRTest.py»

          • +
          • inRDPSessionKeyStr – Ключ RDP сессии - необходим для дальнейшей идентификации

          • +
          • inRDPFilePathStr – Откуда скопировать файл. !Абсолютный! путь на стороне RDP сессии. Пример: «C:RPATESTDIRTest.py»

          • +
          • inHostFilePathStr – Куда скопировать файл. Относительный или абсолютный путь к файлу на стороне Оркестратора. Пример: «TESTDIRTest.py»

          • +
          • inGSettings – Глобальный словарь настроек Оркестратора (синглтон)

          -
          Результат
          -

          True every time

          -
          pyOpenRPA.Orchestrator.__Orchestrator__.RDPSessionFileStoredSend(inRDPSessionKeyStr, inHostFilePathStr, inRDPFilePathStr, inGSettings=None)[исходный код]
          -

          Send file from Orchestrator session to the RDP session using shared drive in RDP (see RDP Configuration Dict, Shared drive)

          -
          # USAGE
          +

          Отправка файла со стороны Оркестратора на сторону RDP сессии через UI инструменты RDP окна (без Агента).

          +

          !ВНИМАНИЕ! Данная функция может работать нестабильно из-за использования графических элементов UI при работе с RDP. Мы рекомендуем использовать конструкцию взаимодействия Оркестратора с Агентом.

          +

          !ВНИМАНИЕ! Для работы функции требуется открыть доступ по RDP к тем дискам, с которых будет производится копирование файла.

          +
          # ПРИМЕР
           from pyOpenRPA import Orchestrator
           
           lResultDict = Orchestrator.RDPSessionFileStoredSend(
          @@ -1945,23 +1880,20 @@ Var 2 (Backward compatibility): inGSettings, inRDPSessionKeyStr, inHostStr, inPo
           
          Параметры
            -
          • inGSettings – Global settings dict (singleton)

          • -
          • inRDPSessionKeyStr – RDP Session string key - need for the further identification

          • -
          • inHostFilePathStr – Relative or absolute path to the file location on the Orchestrator side. Example: «TESTDIRTest.py»

          • -
          • inRDPFilePathStr – !Absolute! path to the destination file location on the RDP side. Example: «C:RPATESTDIRTest.py»

          • +
          • inRDPSessionKeyStr – Ключ RDP сессии - необходим для дальнейшей идентификации

          • +
          • inHostFilePathStr – Откуда взять файл. Относительный или абсолютный путь к файлу на стороне Оркестратора. Пример: «TESTDIRTest.py»

          • +
          • inRDPFilePathStr – Куда скопировать файл. !Абсолютный! путь на стороне RDP сессии. Пример: «C:RPATESTDIRTest.py»

          • +
          • inGSettings – Глобальный словарь настроек Оркестратора (синглтон)

          -
          Результат
          -

          True every time

          -
          pyOpenRPA.Orchestrator.__Orchestrator__.RDPSessionLogoff(inRDPSessionKeyStr, inBreakTriggerProcessWOExeList=None, inGSettings=None)[исходный код]
          -

          Logoff the RDP session from the Orchestrator process (close all apps in session when logoff)

          -
          # USAGE
          +

          Выполнить отключение (logoff) на RDP сессии и прекратить мониторить активность со стороны Оркестратора.

          +
          # ПРИМЕР
           from pyOpenRPA import Orchestrator
           
           Orchestrator.RDPSessionLogoff(
          @@ -1974,13 +1906,13 @@ Var 2 (Backward compatibility): inGSettings, inRDPSessionKeyStr, inHostStr, inPo
           
          Параметры
            -
          • inGSettings – Global settings dict (singleton)

          • -
          • inRDPSessionKeyStr – RDP Session string key - need for the further identification

          • -
          • inBreakTriggerProcessWOExeList – List of the processes, which will stop the execution. Example [«notepad»]

          • +
          • inRDPSessionKeyStr – Ключ RDP сессии - необходим для дальнейшей идентификации

          • +
          • inBreakTriggerProcessWOExeList – Список процессов, наличие которых в диспетчере задач приведет к прерыванию задачи по остановке RDP соединения. Пример [«notepad»]

          • +
          • inGSettings – Глобальный словарь настроек Оркестратора (синглтон)

          Результат
          -

          True - logoff is successful

          +

          True - Отключение прошло успешно; False - были зафиксированы ошибки при отключении.

          @@ -1988,8 +1920,8 @@ Var 2 (Backward compatibility): inGSettings, inRDPSessionKeyStr, inHostStr, inPo
          pyOpenRPA.Orchestrator.__Orchestrator__.RDPSessionMonitorStop(inRDPSessionKeyStr, inGSettings=None)[исходный код]
          -

          Stop monitoring the RDP session by the Orchestrator process. Current def don’t kill RDP session - only stop to track it (it can give )

          -
          # USAGE
          +

          Прекратить мониторить активность RDP соединения со стороны Оркестратора. Данная функция не уничтожает активное RDP соединение.

          +
          # ПРИМЕР
           from pyOpenRPA import Orchestrator
           
           Orchestrator.RDPSessionMonitorStop(
          @@ -2001,21 +1933,19 @@ Var 2 (Backward compatibility): inGSettings, inRDPSessionKeyStr, inHostStr, inPo
           
          Параметры
            -
          • inGSettings – Global settings dict (singleton)

          • -
          • inRDPSessionKeyStr – RDP Session string key - need for the further identification

          • +
          • inRDPSessionKeyStr – Ключ RDP сессии - необходим для дальнейшей идентификации

          • +
          • inGSettings – Глобальный словарь настроек Оркестратора (синглтон)

          -
          Результат
          -

          True every time :>

          -
          pyOpenRPA.Orchestrator.__Orchestrator__.RDPSessionProcessStartIfNotRunning(inRDPSessionKeyStr, inProcessNameWEXEStr, inFilePathStr, inFlagGetAbsPathBool=True, inGSettings=None)[исходный код]
          -

          Start process in RDP if it is not running (check by the arg inProcessNameWEXEStr)

          -
          # USAGE
          +

          Выполнить запуск процесса на RDP сессии через графические UI инструменты (без Агента).

          +

          !ВНИМАНИЕ! Данная функция может работать нестабильно из-за использования графических элементов UI при работе с RDP. Мы рекомендуем использовать конструкцию взаимодействия Оркестратора с Агентом.

          +
          # ПРИМЕР
           from pyOpenRPA import Orchestrator
           
           Orchestrator.RDPSessionProcessStartIfNotRunning(
          @@ -2030,24 +1960,22 @@ Var 2 (Backward compatibility): inGSettings, inRDPSessionKeyStr, inHostStr, inPo
           
          Параметры
            -
          • inGSettings – Global settings dict (singleton)

          • -
          • inRDPSessionKeyStr – RDP Session string key - need for the further identification

          • -
          • inProcessNameWEXEStr – Process name with extension (.exe). This arg allow to check the process is running. Example: «Notepad.exe»

          • -
          • inFilePathStr – Path to run process if it is not running.

          • -
          • inFlagGetAbsPathBool – True - get abs path from the relative path in inFilePathStr. False - else case

          • +
          • inRDPSessionKeyStr – Ключ RDP сессии - необходим для дальнейшей идентификации

          • +
          • inProcessNameWEXEStr – Наименование процесса с расширением .exe (WEXE - WITH EXE - С EXE). Параметр позволяет не допустить повторного запуска процесса, если он уже был запущен. Example: «Notepad.exe»

          • +
          • inFilePathStr – Путь к файлу запуска процесса на стороне RDP сессии

          • +
          • inFlagGetAbsPathBool – True - Преобразовать относительный путь inFilePathStr в абсолютный с учетом рабочей директории Оркестратора; False - Не выполнять преобразований

          • +
          • inGSettings – Глобальный словарь настроек Оркестратора (синглтон)

          -
          Результат
          -

          True every time :)

          -
          pyOpenRPA.Orchestrator.__Orchestrator__.RDPSessionProcessStop(inRDPSessionKeyStr, inProcessNameWEXEStr, inFlagForceCloseBool, inGSettings=None)[исходный код]
          -

          Send CMD command to the RDP session «RUN» window.

          -
          # USAGE
          +

          Отправка CMD команды в RDP окне на остановку процесса (без Агента).

          +

          !ВНИМАНИЕ! Данная функция может работать нестабильно из-за использования графических элементов UI при работе с RDP. Мы рекомендуем использовать конструкцию взаимодействия Оркестратора с Агентом.

          +
          # ПРИМЕР
           from pyOpenRPA import Orchestrator
           
           lResultDict = Orchestrator.RDPSessionProcessStop(
          @@ -2061,23 +1989,20 @@ Var 2 (Backward compatibility): inGSettings, inRDPSessionKeyStr, inHostStr, inPo
           
          Параметры
            -
          • inGSettings – Global settings dict (singleton)

          • -
          • inRDPSessionKeyStr – RDP Session string key - need for the further identification

          • -
          • inProcessNameWEXEStr – Process name to kill. Example: „notepad.exe“

          • -
          • inFlagForceCloseBool – True - force close the process. False - safe close the process

          • +
          • inRDPSessionKeyStr – Ключ RDP сессии - необходим для дальнейшей идентификации

          • +
          • inProcessNameWEXEStr – Наименование процесса, который требуется выключить с расширением .exe (WEXE - WITH EXE - С EXE). Пример: «Notepad.exe»

          • +
          • inFlagForceCloseBool – True - Принудительное отключение. False - Отправка сигнала на безопасное отключение (если процесс поддерживает)

          • +
          • inGSettings – Глобальный словарь настроек Оркестратора (синглтон)

          -
          Результат
          -

          True every time

          -
          pyOpenRPA.Orchestrator.__Orchestrator__.RDPSessionReconnect(inRDPSessionKeyStr, inRDPTemplateDict=None, inGSettings=None)[исходный код]
          -

          Reconnect the RDP session

          -
          # USAGE
          +

          Выполнить переподключение RDP сессии и продолжить мониторить его активность.

          +
          # ПРИМЕР
           from pyOpenRPA import Orchestrator
           
           lRDPItemDict = Orchestrator.RDPTemplateCreate(
          @@ -2094,39 +2019,19 @@ Var 2 (Backward compatibility): inGSettings, inRDPSessionKeyStr, inHostStr, inPo
           
          Параметры
            -
          • inGSettings – Global settings dict (singleton)

          • -
          • inRDPSessionKeyStr – RDP Session string key - need for the further identification

          • -
          • inRDPTemplateDict – RDP configuration dict with settings (see def Orchestrator.RDPTemplateCreate)

          • +
          • inRDPSessionKeyStr – Ключ RDP сессии - необходим для дальнейшей идентификации

          • +
          • inRDPTemplateDict – Конфигурационный словарь (dict) RDP подключения (см. функцию Orchestrator.RDPTemplateCreate)

          • +
          • inGSettings – Глобальный словарь настроек Оркестратора (синглтон)

          -
          Результат
          -

          -
          -
          -
          - -
          -
          -pyOpenRPA.Orchestrator.__Orchestrator__.RDPSessionResponsibilityCheck(inRDPSessionKeyStr, inGSettings=None)[исходный код]
          -

          DEVELOPING, MAYBE NOT USEFUL Check RDP Session responsibility TODO NEED DEV + TEST

          -
          -
          Параметры
          -
            -
          • inGSettings – Global settings dict (singleton)

          • -
          • inRDPSessionKeyStr – RDP Session string key - need for the further identification

          • -
          -
          -
          Результат
          -

          True every time

          -
          pyOpenRPA.Orchestrator.__Orchestrator__.RDPTemplateCreate(inLoginStr, inPasswordStr, inHostStr='127.0.0.1', inPortInt=3389, inWidthPXInt=1680, inHeightPXInt=1050, inUseBothMonitorBool=False, inDepthBitInt=32, inSharedDriveList=None, inRedirectClipboardBool=True)[исходный код]
          -

          Create RDP connect dict item/ Use it connect/reconnect (Orchestrator.RDPSessionConnect)

          -
          # USAGE
          +

          Создать шаблон подключения RDP (dict). Данный шаблон далее можно использовать в Orchestrator.RDPSessionConnect

          +
          # ПРИМЕР
           from pyOpenRPA import Orchestrator
           
           lRDPItemDict = Orchestrator.RDPTemplateCreate(
          @@ -2138,57 +2043,46 @@ Var 2 (Backward compatibility): inGSettings, inRDPSessionKeyStr, inHostStr, inPo
               inHeightPXInt = 1050,
               inUseBothMonitorBool = False,
               inDepthBitInt = 32,
          -    inSharedDriveList=None)
          -#     lRDPTemplateDict= {  # Init the configuration item
          -#         "Host": "127.0.0.1", "Port": "3389", "Login": "USER_99", "Password": "USER_PASS_HERE",
          -#         "Screen": { "Width": 1680, "Height": 1050, "FlagUseAllMonitors": False, "DepthBit": "32" },
          -#         "SharedDriveList": ["c"],
          -#         "RedirectClipboardBool": True, # True - share clipboard to RDP; False - else
          -#         ###### Will updated in program ############
          -#         "SessionHex": "77777sdfsdf77777dsfdfsf77777777",  # Hex is created when robot runs, example ""
          -#         "SessionIsWindowExistBool": False, "SessionIsWindowResponsibleBool": False, "SessionIsIgnoredBool": False
          -#     }
          +    inSharedDriveList=None,
          +    inRedirectClipboardBool=False)
           
          Параметры
            -
          • inLoginStr – User/Robot Login, example «USER_99»

          • -
          • inPasswordStr – Password, example «USER_PASS_HERE»

          • -
          • inHostStr – Host address, example «77.77.22.22»

          • -
          • inPortInt – RDP Port, example «3389» (default)

          • -
          • inWidthPXInt – Width of the remote desktop in pixels, example 1680

          • -
          • inHeightPXInt – Height of the remote desktop in pixels, example 1050

          • -
          • inUseBothMonitorBool – True - connect to the RDP with both monitors. False - else case

          • -
          • inDepthBitInt – Remote desktop bitness. Available: 32 or 24 or 16 or 15, example 32

          • -
          • inSharedDriveList – Host local disc to connect to the RDP session. Example: [«c», «d»]

          • -
          • inRedirectClipboardBool – # True - share clipboard to RDP; False - else

          • +
          • inLoginStr – Логин учетной записи, на которую будет происходить вход по RDP

          • +
          • inPasswordStr – Пароль учетной записи, на которую будет происходить вход по RDP. !ВНИМАНИЕ! Пароль нигде не сохраняется - конфиденциальность обеспечена

          • +
          • inHostStr – Имя хоста, к которому планируется подключение по RDP. Пример «77.77.22.22»

          • +
          • inPortInt – RDP порт, по которому будет происходить подключение. По умолчанию 3389 (стандартный порт RDP)

          • +
          • inWidthPXInt – Разрешение ширины RDP графической сессии в пикселях. По умолчанию 1680

          • +
          • inHeightPXInt – Разрешение высоты RDP графической сессии в пикселях. По умолчанию 1050

          • +
          • inUseBothMonitorBool – True - Использовать все подключенные мониторы на RDP сессии; False - Использовать только один монитор на подключенной RDP сессии

          • +
          • inDepthBitInt – Глубина цвета на удаленной RDP графической сессии. Допустимые варианты: 32 || 24 || 16 || 15. По умолчанию 32

          • +
          • inSharedDriveList – Перечень общих дисков, доступ к которым предоставить на сторону удаленной RDP сессии. Пример: [«c», «d»]

          • +
          • inRedirectClipboardBool – True - Синхронизировать буфер обмена между сессией Оркестратора и удаленной RDP сессией; False - Не синхронизировать буфер обмена. По умолчанию True (в целях обратной совместимости). !ВНИМАНИЕ! Для учетных записей роботов мы рекомендуем не синхронизировать буфер обмена, так как это может привести к ошибкам роботов, которые работают с клавиатурой и буфером обмена

          Результат

          -
          {

          «Host»: inHostStr, # Host address, example «77.77.22.22» -«Port»: str(inPortInt), # RDP Port, example «3389» -«Login»: inLoginStr, # Login, example «test» -«Password»: inPasswordStr, # Password, example «test» +

          {

          «Host»: inHostStr, # Адрес хоста, пример «77.77.22.22» +«Port»: str(inPortInt), # RDP порт, пример «3389» +«Login»: inLoginStr, # Логин УЗ, пример «test» +«Password»: inPasswordStr, # Пароль УЗ, пример «test» «Screen»: {

          -

          »Width»: inWidthPXInt, # Width of the remote desktop in pixels, example 1680 -«Height»: inHeightPXInt, # Height of the remote desktop in pixels, example 1050 -# «640x480» or «1680x1050» or «FullScreen». If Resolution not exists set full screen, example -«FlagUseAllMonitors»: inUseBothMonitorBool, # True or False, example False -«DepthBit»: str(inDepthBitInt) # «32» or «24» or «16» or «15», example «32»

          +

          »Width»: inWidthPXInt, # Разрешение ширины RDP графической сессии в пикселях. По умолчанию 1680 +«Height»: inHeightPXInt, Разрешение высоты RDP графической сессии в пикселях. По умолчанию 1050 +«FlagUseAllMonitors»: inUseBothMonitorBool, +«DepthBit»: str(inDepthBitInt)

          }, -«SharedDriveList»: inSharedDriveList, # List of the Root sesion hard drives, example [«c»] -«RedirectClipboardBool»: True, # True - share clipboard to RDP; False - else -###### Will updated in program ############ -«SessionHex»: «77777sdfsdf77777dsfdfsf77777777», # Hex is created when robot runs, example «» +«SharedDriveList»: inSharedDriveList, +«RedirectClipboardBool»: True, +###### PROGRAM VARIABLE ############ +«SessionHex»: «77777sdfsdf77777dsfdfsf77777777», «SessionIsWindowExistBool»: False, -# Flag if the RDP window is exist, old name «FlagSessionIsActive». Check every n seconds , example False «SessionIsWindowResponsibleBool»: False, -# Flag if RDP window is responsible (recieve commands). Check every nn seconds. If window is Responsible - window is Exist too , example False -«SessionIsIgnoredBool»: False # Flag to ignore RDP window False - dont ignore, True - ignore, example False

          +«SessionIsIgnoredBool»: False

          }

          @@ -2200,11 +2094,11 @@ Var 2 (Backward compatibility): inGSettings, inRDPSessionKeyStr, inHostStr, inPo
          pyOpenRPA.Orchestrator.__Orchestrator__.SchedulerActivityTimeAddWeekly(inTimeHHMMStr='23:55:', inWeekdayList=None, inActivityList=None, inGSettings=None)[исходный код]
          -

          Add activity item list in scheduler. You can set weekday list and set time when launch. Activity list will be executed at planned time/day.

          -
          # USAGE
          +

          Добавить активность по расписанию. Допускается указание времени и дней недели, в которые производить запуск.

          +
          # ПРИМЕР
           from pyOpenRPA import Orchestrator
           
          -# EXAMPLE 1
          +# ВАРИАНТ 1
           def TestDef(inArg1Str):
               pass
           lActivityItem = Orchestrator.ProcessorActivityItemCreate(
          @@ -2224,45 +2118,25 @@ Var 2 (Backward compatibility): inGSettings, inRDPSessionKeyStr, inHostStr, inPo
           
          Параметры
            -
          • inGSettings – Global settings dict (singleton)

          • -
          • inTimeHHMMStr – Activation time from «00:00» to «23:59». Example: «05:29»

          • -
          • inWeekdayList – Week day list to initiate activity list. Use int from 0 (monday) to 6 (sunday) as list items. Example: [0,1,2,3,4]. Default value is everyday ([0,1,2,3,4,5,6])

          • -
          • inActivityList – Activity list structure

          • +
          • inGSettings – Глобальный словарь настроек Оркестратора (синглтон)

          • +
          • inTimeHHMMStr – Время запуска активности. Допускаются значения от «00:00» до «23:59». Example: «05:29»

          • +
          • inWeekdayList – Список (list) дней недели, в которые выполнять запуск список активностей (ActivityItem list). 0 (понедельник) - 6 (воскресенье). Пример: [0,1,2,3,4]. По умолчанию устанавливается каждый день [0,1,2,3,4,5,6]

          • +
          • inActivityList – Список активностей (ActivityItem list) на исполнение

          -
          Результат
          -

          None

          -
          -
          -
          - -
          -
          -pyOpenRPA.Orchestrator.__Orchestrator__.Start(inDumpRestoreBool=True, inRunAsAdministratorBool=True)[исходный код]
          -

          Start the orchestrator threads execution

          -
          -
          Параметры
          -
            -
          • inDumpRestoreBool – True - restore data from the dumo

          • -
          • inRunAsAdministratorBool – True - rerun as admin if not

          • -
          -
          -
          Результат
          -

          -
          pyOpenRPA.Orchestrator.__Orchestrator__.StorageRobotExists(inRobotNameStr)[исходный код]
          -

          Check if robot storage exists

          +

          Проверить, существует ли ключ inRobotNameStr в хранилище пользовательской информации StorageDict (GSettings > StarageDict)

          Параметры
          -

          inRobotNameStr – Robot name (case sensitive)

          +

          inRobotNameStr – Наименование (ключ) робота. !ВНИМАНИЕ! Наименование чувствительно к регистру

          Результат
          -

          True - robot storage exist; False - does not exist

          +

          True - ключ робота присутствует в хранилище; False - отсутствует

          @@ -2270,13 +2144,13 @@ Var 2 (Backward compatibility): inGSettings, inRDPSessionKeyStr, inHostStr, inPo
          pyOpenRPA.Orchestrator.__Orchestrator__.StorageRobotGet(inRobotNameStr)[исходный код]
          -

          Get the robot storage by the robot name. If Robot storage is not exist - function will create it

          +

          Получить содержимое по ключу робота inRobotNameStr в хранилище пользовательской информации StorageDict (GSettings > StarageDict)

          Параметры
          -

          inRobotNameStr – Robot name (case sensitive)

          +

          inRobotNameStr – Наименование (ключ) робота. !ВНИМАНИЕ! Наименование чувствительно к регистру

          Результат
          -

          Dict

          +

          Значение или структура, которая расположена по адресу (GSettings > StarageDict > inRobotNameStr)

          @@ -2284,16 +2158,21 @@ Var 2 (Backward compatibility): inGSettings, inRDPSessionKeyStr, inHostStr, inPo
          pyOpenRPA.Orchestrator.__Orchestrator__.UACKeyListCheck(inRequest, inRoleKeyList) → bool[исходный код]
          -

          Check is client is has access for the key list

          +

          Проверить права доступа для пользователя запроса по списку ключей до права.

          +
          # ВАРИАНТ ИСПОЛЬЗОВАНИЯ 1 (инициализация модуля py без вызова каких-либо функций внутри)
          +# автоинициализация всех .py файлов, с префиксом CP_, которые расположены в папке ControlPanel
          +Orchestrator.UACKeyListCheck(inRequest=lRequest, inRoleKeyList=["ROBOT1","DISPLAY_DASHBOARD"])
          +
          +
          Параметры
            -
          • inRequest – request handler (from http.server import BaseHTTPRequestHandler)

          • -
          • inRoleKeyList

          • +
          • inRequest – Экземпляр request (from http.server import BaseHTTPRequestHandler)

          • +
          • inRoleKeyList – Список ключей, права доступа к которому требуется проверить

          Результат
          -

          bool

          +

          True - Пользователь обладает соответствующим правом; False - Пользователь не обладает соответствующим правом

          @@ -2301,12 +2180,12 @@ Var 2 (Backward compatibility): inGSettings, inRDPSessionKeyStr, inHostStr, inPo
          pyOpenRPA.Orchestrator.__Orchestrator__.UACSuperTokenUpdate(inSuperTokenStr, inGSettings=None)[исходный код]
          -

          Add supertoken for the all access (it is need for the robot communication without human)

          +

          Добавить супертокен (полный доступ). Супертокены используются для подключения к Оркестратору по API

          Параметры
            -
          • inGSettings – Global settings dict (singleton)

          • -
          • inSuperTokenStr

          • +
          • inGSettings – Глобальный словарь настроек Оркестратора (синглтон)

          • +
          • inSuperTokenStr – Кодовая строковая комбинация, которая будет предоставлять доступ роботу / агенту для взаимодействия с Оркестратором по API

          @@ -2315,16 +2194,27 @@ Var 2 (Backward compatibility): inGSettings, inRDPSessionKeyStr, inHostStr, inPo
          pyOpenRPA.Orchestrator.__Orchestrator__.UACUpdate(inADLoginStr, inADStr='', inADIsDefaultBool=True, inURLList=None, inRoleHierarchyAllowedDict=None, inGSettings=None)[исходный код]
          -

          Update user access (UAC)

          +

          Дообогащение словаря доступа UAC пользователя inADStrinADLoginStr. Если ранее словарь не устанавливался, то по умолчанию он {}. Далее идет дообогащение теми ключами, которые присутствуют в inRoleHierarchyAllowedDict

          Параметры
            -
          • inGSettings – Global settings dict (singleton)

          • -
          • inADLoginStr

          • -
          • inADStr

          • -
          • inADIsDefaultBool

          • -
          • inURLList

          • -
          • inRoleHierarchyAllowedDict

          • +
          • inGSettings – Глобальный словарь настроек Оркестратора (синглтон)

          • +
          • inADLoginStr – Логин пользователя

          • +
          • inADStr – Домен пользователя. Если пусто - локальный компьютер или домен по-умолчанию, который настроен в ОС

          • +
          • inADIsDefaultBool – True - домен настроен по умолчанию; False - домен требуется обязательно указывать

          • +
          • inURLList

            Список разрешенных URL для пользователя. Для добавления URL рекомендуем использовать функции WebURLConnectDef, WebURLConnectFile, WebURLConnectFolder +Формат: {

            +
            +

            »Method»: «GET» || «POST», +«URL»: «/GetScreenshot», +«MatchType»: «BeginWith» || «Equal» || «EqualCase» || «Contains» || «EqualNoParam», +«ResponseDefRequestGlobal»: Функция python || «ResponseFilePath»: Путь к файлу || «ResponseFolderPath»: Путь к папке, в которой искать файлы, +«ResponseContentType»: пример MIME «image/png», +«UACBool»:False - не выполнять проверку прав доступа по запросу, +«UseCacheBool»: True - кэшировать ответ},

            +
            +

          • +
          • inRoleHierarchyAllowedDict – Словарь доступа пользователя UAC. Пустой словарь - полный доступ

          @@ -2333,13 +2223,13 @@ Var 2 (Backward compatibility): inGSettings, inRDPSessionKeyStr, inHostStr, inPo
          pyOpenRPA.Orchestrator.__Orchestrator__.UACUserDictGet(inRequest) → dict[исходный код]
          -

          Return user UAC hierarchy dict of the inRequest object. Empty dict - superuser access

          +

          Вернуть UAC (User Access Control) словарб доступов для пользователя, который отправил запрос. Пустой словарь - супердоступ (доступ ко всему)

          Параметры
          -

          inRequest – request handler (from http.server import BaseHTTPRequestHandler)

          +

          inRequest – Экземпляр request (from http.server import BaseHTTPRequestHandler)

          Результат
          -

          user UAC hierarchy dict

          +

          Словарь доступов пользователя. Пустой словарь - супердоступ (доступ ко всему)

          @@ -2347,8 +2237,8 @@ Var 2 (Backward compatibility): inGSettings, inRDPSessionKeyStr, inHostStr, inPo
          pyOpenRPA.Orchestrator.__Orchestrator__.WebAuditMessageCreate(inRequest=None, inOperationCodeStr='-', inMessageStr='-')[исходный код]
          -

          Create message string with request user details (IP, Login etc…). Very actual for IT security in big company.

          -
          # USAGE
          +

          Создание сообщения ИТ аудита с такими сведениями как (Домен, IP, логин и тд.). Данная функция особенно актуальна в том случае, если требуется реализовать дополнительные меры контроля ИТ системы.

          +
          # ПРИМЕР
           from pyOpenRPA import Orchestrator
           
           lWebAuditMessageStr = Orchestrator.WebAuditMessageCreate(
          @@ -2356,20 +2246,20 @@ Var 2 (Backward compatibility): inGSettings, inRDPSessionKeyStr, inHostStr, inPo
               inOperationCodeStr = "OP_CODE_1",
               inMessageStr="Success"):
           
          -# Log the WebAudit message
          +# Логгирование сообщения
           lLogger.info(lWebAuditMessageStr)
           
          Параметры
            -
          • inRequest – HTTP request handler. Optional if call def from request thread

          • -
          • inOperationCodeStr – operation code in string format (actual for IT audit in control panels)

          • -
          • inMessageStr – additional message after

          • +
          • inRequest – Экземпляр HTTP request. Опционален, если сообщение фиксируется из под потока, который был инициирован запросом пользователя

          • +
          • inOperationCodeStr – Код операции, который принят в компании в соответствии с регламентными процедурами

          • +
          • inMessageStr – Дополнительное сообщение, которое необходимо отправить в сообщение об ИТ аудите

          Результат
          -

          format «WebAudit :: DOMAINUSER@101.121.123.12 :: operation code :: message»

          +

          Формат сообщения: «WebAudit :: DOMAINUSER@101.121.123.12 :: operation code :: message»

          @@ -2377,15 +2267,15 @@ Var 2 (Backward compatibility): inGSettings, inRDPSessionKeyStr, inHostStr, inPo
          pyOpenRPA.Orchestrator.__Orchestrator__.WebCPUpdate(inCPKeyStr, inHTMLRenderDef=None, inJSONGeneratorDef=None, inJSInitGeneratorDef=None, inGSettings=None)[исходный код]
          -

          Add control panel HTML, JSON generator or JS when page init

          +

          Добавить панель управления робота в Оркестратор. Для панели управления открыт доступ для использования функции-генератора HTML, генератора JSON данных, генератора JS кода.

          Параметры
            -
          • inGSettings – Global settings dict (singleton)

          • -
          • inCPKeyStr

          • -
          • inHTMLRenderDef

          • -
          • inJSONGeneratorDef

          • -
          • inJSInitGeneratorDef

          • +
          • inGSettings – Глобальный словарь настроек Оркестратора (синглтон)

          • +
          • inCPKeyStr – Текстовый ключ панели управления. Ключ для каждой панели управления должен быть уникальным!

          • +
          • inHTMLRenderDef – Функция Python для генерации HTML кода. Для использования Jinja2 шаблонов HTML см. pyOpenRPA.Orchestrator.Managers.ControlPanel

          • +
          • inJSONGeneratorDef – Функция Python для генерации JSON контейнера для отправки на клиентскую часть Оркестратора

          • +
          • inJSInitGeneratorDef – Функция Python для генерации JS кода для отправки на клиентскую часть Оркестратора

          @@ -2394,15 +2284,15 @@ Var 2 (Backward compatibility): inGSettings, inRDPSessionKeyStr, inHostStr, inPo
          pyOpenRPA.Orchestrator.__Orchestrator__.WebListenCreate(inServerKeyStr='Default', inAddressStr='', inPortInt=80, inCertFilePEMPathStr=None, inKeyFilePathStr=None, inGSettings=None)[исходный код]
          -

          Create listen interface for the web server

          +

          Настроить веб-сервер Оркестратора.

          Параметры
            -
          • inGSettings – Global settings dict (singleton)

          • -
          • inAddressStr – IP interface to listen

          • -
          • inPortInt – Port int to listen for HTTP default is 80; for HTTPS default is 443

          • -
          • inCertFilePEMPathStr – Path to .pem (base 64) certificate. Required for SSL connection. ATTENTION - do not use certificate with password

          • -
          • inKeyFilePathStr – Path to the private key file

          • +
          • inAddressStr – IP адрес для прослушивания. Если «», то прослушивать запросы со всех сетевых карт. Если «127.0.0.1», то слушать запросы только с той ОС, на которой работает Оркестратор

          • +
          • inPortInt – Номер порта для прослушивания. Если HTTP - 80; Если HTTPS - 443. По умолчанию 80. Допускается установка других портов

          • +
          • inCertFilePEMPathStr – Путь файлу сертификата, сгенерированного в .pem (base64) формате. Обязателен при использовании защищенного HTTPS/SSL соединения.

          • +
          • inKeyFilePathStr – Путь к файлу закрытого ключа в base64 формате

          • +
          • inGSettings – Глобальный словарь настроек Оркестратора (синглтон)

          Результат
          @@ -2414,19 +2304,19 @@ Var 2 (Backward compatibility): inGSettings, inRDPSessionKeyStr, inHostStr, inPo
          pyOpenRPA.Orchestrator.__Orchestrator__.WebRequestGet()[исходный код]
          -

          Return the web request instance if current thread was created by web request from client. else return None

          +

          Вернуть экземпляр HTTP запроса, если функция вызвана в потоке, который был порожден для отработки HTTP запроса пользователя.

          pyOpenRPA.Orchestrator.__Orchestrator__.WebRequestParseBodyBytes(inRequest=None)[исходный код]
          -

          Extract the body in bytes from the request

          +

          Извлечь данные в байт виде из тела (body) HTTP запроса.

          Параметры
          -

          inRequest – inRequest from the server. Optional if call def from request thread

          +

          inRequest – Экземпляр HTTP request. Опционален, если сообщение фиксируется из под потока, который был инициирован запросом пользователя

          Результат
          -

          Bytes or None

          +

          Строка байт b““ или None (если тело запроса было пустым)

          @@ -2434,13 +2324,13 @@ Var 2 (Backward compatibility): inGSettings, inRDPSessionKeyStr, inHostStr, inPo
          pyOpenRPA.Orchestrator.__Orchestrator__.WebRequestParseBodyJSON(inRequest=None)[исходный код]
          -

          Extract the body in dict/list from the request

          +

          Извлечь из тела (body) запроса HTTP JSON данные и преобразовать в Dict / List структуры языка Python.

          Параметры
          -

          inRequest – inRequest from the server. Optional if call def from request thread

          +

          inRequest – Экземпляр HTTP request. Опционален, если сообщение фиксируется из под потока, который был инициирован запросом пользователя

          Результат
          -

          dict or list

          +

          Словарь (dict), список (list) или None (если тело запроса было пустым)

          @@ -2448,13 +2338,13 @@ Var 2 (Backward compatibility): inGSettings, inRDPSessionKeyStr, inHostStr, inPo
          pyOpenRPA.Orchestrator.__Orchestrator__.WebRequestParseBodyStr(inRequest=None)[исходный код]
          -

          Extract the body in str from the request

          +

          Извлечь данные в виде строки из тела (body) HTTP запроса.

          Параметры
          -

          inRequest – inRequest from the server. Optional if call def from request thread

          +

          inRequest – Экземпляр HTTP request. Опционален, если сообщение фиксируется из под потока, который был инициирован запросом пользователя

          Результат
          -

          str or None

          +

          Текстовая строка „“ или None (если тело запроса было пустым)

          @@ -2462,13 +2352,13 @@ Var 2 (Backward compatibility): inGSettings, inRDPSessionKeyStr, inHostStr, inPo
          pyOpenRPA.Orchestrator.__Orchestrator__.WebRequestParseFile(inRequest=None)[исходный код]
          -

          Parse the request - extract the file (name, body in bytes)

          +

          Извлечь файл (наименование + содержимое в виде строки байт b““) из HTTP запроса пользователя.

          Параметры
          -

          inRequest – inRequest from the server. Optional if call def from request thread

          +

          inRequest – Экземпляр HTTP request. Опционален, если сообщение фиксируется из под потока, который был инициирован запросом пользователя

          Результат
          -

          (FileNameStr, FileBodyBytes) or (None, None)

          +

          Кортеж формата (FileNameStr, FileBodyBytes) or (None, None), если файл не был обнаружен

          @@ -2476,27 +2366,29 @@ Var 2 (Backward compatibility): inGSettings, inRDPSessionKeyStr, inHostStr, inPo
          pyOpenRPA.Orchestrator.__Orchestrator__.WebRequestParsePath(inRequest=None)[исходный код]
          -

          Parse the request - extract the url. Example: /pyOpenRPA/Debugging/DefHelper/…

          +

          Извлечь декодированный URL путь из HTTP запроса пользователя в формате строки.

          Параметры
          -

          inRequest – inRequest from the server. Optional if call def from request thread

          +

          inRequest – Экземпляр HTTP request. Опционален, если сообщение фиксируется из под потока, который был инициирован запросом пользователя

          Результат
          -

          Str, Example: /pyOpenRPA/Debugging/DefHelper/…

          +

          str, пример: /pyOpenRPA/Debugging/DefHelper

          -pyOpenRPA.Orchestrator.__Orchestrator__.WebRequestResponseSend(inResponeStr, inRequest=None)[исходный код]
          -

          Send response for the request

          +pyOpenRPA.Orchestrator.__Orchestrator__.WebRequestResponseSend(inResponeStr, inRequest=None, inContentTypeStr: Optional[str] = None, inHeadersDict: Optional[dict] = None)[исходный код]
+

Установить ответ на HTTP запрос пользователя.

Параметры
-

inRequest – inRequest from the server. Optional if call def from request thread

-
-
Результат
-

+
    +
  • inResponeStr – Тело ответа (строка)

  • +
  • inRequest – Экземпляр HTTP request. Опционален, если сообщение фиксируется из под потока, который был инициирован запросом пользователя

  • +
  • inContentTypeStr – МИМЕ тип. Пример: «html/text»

  • +
  • inHeadersDict – Словарь (dict) ключей, которые добавить в headers HTTP ответа на запрос пользователя

  • +
@@ -2505,25 +2397,18 @@ Var 2 (Backward compatibility): inGSettings, inRDPSessionKeyStr, inHostStr, inPo
pyOpenRPA.Orchestrator.__Orchestrator__.WebURLConnectDef(inMethodStr, inURLStr, inMatchTypeStr, inDef, inContentTypeStr='application/octet-stream', inGSettings=None, inUACBool=None)[исходный код]
-
-
Connect URL to DEF

«inMethodStr»:»GET|POST», -«inURLStr»: «/index», #URL of the request -«inMatchTypeStr»: «», #»BeginWith|Contains|Equal|EqualCase», -«inContentTypeStr»: «», #HTTP Content-type -«inDef»: None #Function with str result

-
-
+

Подключить функцию Python к URL.

Параметры
    -
  • inGSettings – Global settings dict (singleton)

  • -
  • inMethodStr – «GET|POST»,

  • -
  • inURLStr – example «/index», #URL of the request

  • -
  • inMatchTypeStr – #»BeginWith|Contains|Equal|EqualCase»,

  • -
  • inDef – def arg allowed list: 2:[inRequest, inGSettings], 1: [inRequest], 0: []

  • -
  • inContentTypeStr – default: «application/octet-stream»

  • -
  • inUACBool – default: None; True - check user access before do this URL item. None - get Server flag if ask user

  • +
  • inMethodStr – Метод доступа по URL «GET» || «POST»

  • +
  • inURLStr – URL адрес. Пример «/index»

  • +
  • inMatchTypeStr – Тип соответсвия строки URL с inURLStr: «BeginWith» || «Contains» || «Equal» || «EqualCase» || «EqualNoParam»

  • +
  • inDef – Функция Python. Допускаются функции, которые принимают следующие наборы параметров: 2:[inRequest, inGSettings], 1: [inRequest], 0: []

  • +
  • inContentTypeStr – МИМЕ тип. По умолчанию: «application/octet-stream»

  • +
  • inUACBool – True - Выполнять проверку прав доступа пользователя перед отправкой ответа; False - не выполнять проверку прав доступа пользователя

  • +
  • inGSettings – Глобальный словарь настроек Оркестратора (синглтон)

@@ -2532,24 +2417,18 @@ Var 2 (Backward compatibility): inGSettings, inRDPSessionKeyStr, inHostStr, inPo
pyOpenRPA.Orchestrator.__Orchestrator__.WebURLConnectFile(inMethodStr, inURLStr, inMatchTypeStr, inFilePathStr, inContentTypeStr=None, inGSettings=None, inUACBool=None, inUseCacheBool=False)[исходный код]
-
-
Connect URL to File

«inMethodStr»:»GET|POST», -«inURLStr»: «/index», #URL of the request -«inMatchTypeStr»: «», #»BeginWith|Contains|Equal|EqualCase», -«inFolderPathStr»: «», #Absolute or relative path

-
-
+

Подключить файл к URL.

Параметры
    -
  • inGSettings – Global settings dict (singleton)

  • -
  • inMethodStr

  • -
  • inURLStr

  • -
  • inMatchTypeStr

  • -
  • inFilePathStr

  • -
  • inContentTypeStr – If none - autodetect

  • -
  • inUACBool – default: None; True - check user access before do this URL item. None - get Server flag if ask user

  • -
  • inUseCacheBool – True - cache this page - dont open ever

  • +
  • inMethodStr – Метод доступа по URL «GET» || «POST»

  • +
  • inURLStr – URL адрес. Пример «/index»

  • +
  • inMatchTypeStr – Тип соответсвия строки URL с inURLStr: «BeginWith» || «Contains» || «Equal» || «EqualCase» || «EqualNoParam»

  • +
  • inFilePathStr – Путь к файлу на диске, который возвращать пользователю по HTTP

  • +
  • inContentTypeStr – МИМЕ тип. Если None - выполнить автоматическое определение

  • +
  • inUACBool – True - Выполнять проверку прав доступа пользователя перед отправкой ответа; False - не выполнять проверку прав доступа пользователя

  • +
  • inUseCacheBool – True - выполнить кэширование страницы, чтобы в следющих запросах открыть быстрее; False - не кэшировать

  • +
  • inGSettings – Глобальный словарь настроек Оркестратора (синглтон)

@@ -2558,24 +2437,17 @@ Var 2 (Backward compatibility): inGSettings, inRDPSessionKeyStr, inHostStr, inPo
pyOpenRPA.Orchestrator.__Orchestrator__.WebURLConnectFolder(inMethodStr, inURLStr, inMatchTypeStr, inFolderPathStr, inGSettings=None, inUACBool=None, inUseCacheBool=False)[исходный код]
-
-
Connect URL to Folder

«inMethodStr»:»GET|POST», -«inURLStr»: «/Folder/», #URL of the request -«inMatchTypeStr»: «», #»BeginWith|Contains|Equal|EqualCase», -«inFolderPathStr»: «», #Absolute or relative path -«inUACBool»

-
-
+

Подключить папку к URL.

Параметры
    -
  • inGSettings – Global settings dict (singleton)

  • -
  • inMethodStr

  • -
  • inURLStr

  • -
  • inMatchTypeStr

  • -
  • inFolderPathStr

  • -
  • inUACBool – default: None; True - check user access before do this URL item. None - get Server flag if ask user

  • -
  • inUseCacheBool – True - cache this page - dont open ever

  • +
  • inMethodStr – Метод доступа по URL «GET» || «POST»

  • +
  • inURLStr – URL адрес. Пример «/index»

  • +
  • inMatchTypeStr – Тип соответсвия строки URL с inURLStr: «BeginWith» || «Contains» || «Equal» || «EqualCase» || «EqualNoParam»

  • +
  • inFolderPathStr – Путь к папке на диске, в которой искать файл и возвращать пользователю по HTTP

  • +
  • inUACBool – True - Выполнять проверку прав доступа пользователя перед отправкой ответа; False - не выполнять проверку прав доступа пользователя

  • +
  • inUseCacheBool – True - выполнить кэширование страницы, чтобы в следющих запросах открыть быстрее; False - не кэшировать

  • +
  • inGSettings – Глобальный словарь настроек Оркестратора (синглтон)

@@ -2584,10 +2456,10 @@ Var 2 (Backward compatibility): inGSettings, inRDPSessionKeyStr, inHostStr, inPo
pyOpenRPA.Orchestrator.__Orchestrator__.WebURLIndexChange(inURLIndexStr: str = '/')[исходный код]
-

Change the index page of the orchestrator if you dont want the „/“ (main) path

+

Изменить адрес главной страницы Оркестратора. По умолчанию „/“

Параметры
-

inURLIndexStr (str, optional) – New url for the index page of the orchestrator, defaults to «/»

+

inURLIndexStr (str, опционально) – Новый адрес главной страницы Оркестратора.

@@ -2595,13 +2467,13 @@ Var 2 (Backward compatibility): inGSettings, inRDPSessionKeyStr, inHostStr, inPo
pyOpenRPA.Orchestrator.__Orchestrator__.WebUserInfoGet(inRequest=None)[исходный код]
-

Return User info about request

+

Информация о пользователе, который отправил HTTP запрос.

Параметры
-

inRequest – inRequest from the server. Optional if call def from request thread

+

inRequest – Экземпляр HTTP request. Опционален, если сообщение фиксируется из под потока, который был инициирован запросом пользователя

Результат
-

{«DomainUpperStr»: «», «UserNameUpperStr»: «»}

+

Сведения в формате {«DomainUpperStr»: «PYOPENRPA», «UserNameUpperStr»: «IVAN.MASLOV»}

@@ -2609,16 +2481,16 @@ Var 2 (Backward compatibility): inGSettings, inRDPSessionKeyStr, inHostStr, inPo
pyOpenRPA.Orchestrator.__Orchestrator__.WebUserIsSuperToken(inRequest=None, inGSettings=None)[исходный код]
-

Return bool if request is authentificated with supetoken (token which is never expires)

+

Проверить, авторизован ли HTTP запрос с помощью супер токена (токен, который не истекает).

Параметры
    -
  • inRequest – inRequest from the server. Optional if call def from request thread

  • -
  • inGSettings – Global settings dict (singleton)

  • +
  • inRequest – Экземпляр HTTP request. Опционален, если сообщение фиксируется из под потока, который был инициирован запросом пользователя

  • +
  • inGSettings – Глобальный словарь настроек Оркестратора (синглтон)

Результат
-

bool True - is supertoken; False - is not supertoken

+

True - является супертокеном; False - не является супертокеном

@@ -2626,87 +2498,29 @@ Var 2 (Backward compatibility): inGSettings, inRDPSessionKeyStr, inHostStr, inPo
pyOpenRPA.Orchestrator.__Orchestrator__.WebUserUACHierarchyGet(inRequest=None)[исходный код]
-

Return User UAC Hierarchy DICT Return {…}

-
-
Параметры
-

inRequest – inRequest from the server. Optional if call def from request thread

-
-
Результат
-

UAC Dict {}

-
-
-
- - - -
-

pyOpenRPA.Orchestrator.Web.Basic

-

Functions:

- ---- - - - - - - - - -

JSActivityListExecute(inActivityList[, …])

Create JS for execute activity list/ activity permanent

JSProcessorActivityListAdd(inActivityList[, …])

# Create JS for send activity list/ activity to the processor

-
-
-pyOpenRPA.Orchestrator.Web.Basic.JSActivityListExecute(inActivityList, inGUIDRemoveBool=True)[исходный код]
-
-

Create JS for execute activity list/ activity permanent -USAGE: Orchestrator.Web.Basic.JSActivityListExecute(inActivityList, inGUIDRemoveBool = True)

-
+

Вернуть словарь доступа UAC в отношении пользователя, который выполнил HTTP запрос inRequest

Параметры
-
    -
  • inActivityList – List of the activities (See __Orchestrator__.ProcessorActivityItemCreate)

  • -
  • inGUIDRemoveBool – True - remove GUID before generate JS (if GUID is not important)

  • -
+

inRequest – Экземпляр HTTP request. Опционален, если сообщение фиксируется из под потока, который был инициирован запросом пользователя

Результат
-

JavaScript string for the front end

-
-
-
- -
-
-pyOpenRPA.Orchestrator.Web.Basic.JSProcessorActivityListAdd(inActivityList, inGUIDRemoveBool=True)[исходный код]
-
-

# Create JS for send activity list/ activity to the processor -# USAGE: Orchestrator.Web.Basic.JSProcessorActivityListAdd(inActivityList)

-
-
-
Параметры
-
    -
  • inActivityList – List of the activities (See __Orchestrator__.ProcessorActivityItemCreate)

  • -
  • inGUIDRemoveBool – True - remove GUID before generate JS (if GUID is not important)

  • -
-
-
Результат
-

JavaScript string for the front end

+

UAC словарь доступа или {}, что означает полный доступ

- @@ -2717,8 +2531,8 @@ USAGE: Orchestrator.Web.Basic.JSActivityListExecute(inActivityList, inGUIDRemove

diff --git a/Wiki/RUS_Guide/html/Orchestrator/03_gSettingsTemplate.html b/Wiki/RUS_Guide/html/Orchestrator/03_gSettingsTemplate.html index ecf4f018..9beb3ca8 100644 --- a/Wiki/RUS_Guide/html/Orchestrator/03_gSettingsTemplate.html +++ b/Wiki/RUS_Guide/html/Orchestrator/03_gSettingsTemplate.html @@ -7,7 +7,7 @@ - 3. gSettings Template — документация pyOpenRPA v1.2.12 v1.2.12 + 3. Настройки GSettings (шаблон) — документация pyOpenRPA v1.2.12 v1.2.12 @@ -41,8 +41,8 @@ - - + + @@ -91,20 +91,18 @@

МОДУЛЬ РОБОТ

МОДУЛЬ СТУДИЯ

    @@ -113,20 +111,24 @@

МОДУЛЬ ОРКЕСТРАТОР

МОДУЛЬ АГЕНТ

ИНСТРУМЕНТЫ

@@ -175,7 +177,7 @@
  • »
  • -
  • 3. gSettings Template
  • +
  • 3. Настройки GSettings (шаблон)
  • @@ -194,9 +196,14 @@
    -
    -

    3. gSettings Template

    -

    gSettings structure

    +
    +

    3. Настройки GSettings (шаблон)

    +
    +

    Общее

    +

    Ниже представлена структура единого глобального словаря настроек GSettings

    +
    +
    +

    Структура

    import os, logging, datetime, sys
     import schedule # https://schedule.readthedocs.io/en/stable/examples.html
     
    @@ -562,9 +569,20 @@
         return lResult # return the result dict
     
    -

    .. v1.2.12 replace:: v1.2.12 - .. |author| replace:: Ivan Maslov <ivan.maslov@unicodelabs.ru>

    +
    +
    @@ -573,8 +591,8 @@

    diff --git a/Wiki/RUS_Guide/html/Orchestrator/04_HowToUse.html b/Wiki/RUS_Guide/html/Orchestrator/04_HowToUse.html index 920b4f20..751eee50 100644 --- a/Wiki/RUS_Guide/html/Orchestrator/04_HowToUse.html +++ b/Wiki/RUS_Guide/html/Orchestrator/04_HowToUse.html @@ -7,7 +7,7 @@ - 4. How to use — документация pyOpenRPA v1.2.12 v1.2.12 + 4. Как использовать? — документация pyOpenRPA v1.2.12 v1.2.12 @@ -41,8 +41,8 @@ - - + + @@ -91,20 +91,18 @@

    МОДУЛЬ РОБОТ

    МОДУЛЬ СТУДИЯ

      @@ -113,20 +111,24 @@

    МОДУЛЬ ОРКЕСТРАТОР

    МОДУЛЬ АГЕНТ

    ИНСТРУМЕНТЫ

    @@ -175,7 +177,7 @@
  • »
  • -
  • 4. How to use
  • +
  • 4. Как использовать?
  • @@ -194,9 +196,16 @@
    -
    -

    4. How to use

    -

    You need to run orchestrator process?

    +
    +

    4. Как использовать?

    +
    +

    Как запустить?

    +

    Хотите выполнить запуск Оркестратора?

    +

    Для этого достаточно (выбрать одно):

    +
      +
    • запустить .cmd файл, расположенный в папке pyOpenRPA по адресу: OrchestratorpyOpenRPA.Orchestrator_x64.cmd

    • +
    • в свой .py скрипт добавить следующий код (см. ниже)

    • +
    if __name__ == "__main__": # New init way - allow run as module -m PyOpenRPA.Orchestrator
         from pyOpenRPA import Orchestrator  # Import orchestrator main
         gSettings = SettingsTemplate.Create(inModeStr="BASIC") # Create GSettings with basic configuration - no more config is available from the box - you can create own
    @@ -204,7 +213,10 @@
         Orchestrator.Orchestrator(inGSettings=gSettings)
     
    -

    If you need more configurations - so you can see here:

    +
    +
    +

    Параметры настройки

    +

    Также вы можете выполнить более тонкую настройку параметров Оркестратора. Ниже пример такой настройки:

    import psutil, datetime, logging, os, sys
     
     
    @@ -245,9 +257,20 @@
     
     
    -

    .. v1.2.12 replace:: v1.2.12 - .. |author| replace:: Ivan Maslov <ivan.maslov@unicodelabs.ru>

    +
    +
    @@ -256,8 +279,8 @@

    diff --git a/Wiki/RUS_Guide/html/Orchestrator/05_UAC.html b/Wiki/RUS_Guide/html/Orchestrator/05_UAC.html index 80def0ec..fbae8ee2 100644 --- a/Wiki/RUS_Guide/html/Orchestrator/05_UAC.html +++ b/Wiki/RUS_Guide/html/Orchestrator/05_UAC.html @@ -7,7 +7,7 @@ - 5. UAC - User Access Control — документация pyOpenRPA v1.2.12 v1.2.12 + 5. Права доступа пользователей UAC — документация pyOpenRPA v1.2.12 v1.2.12 @@ -41,8 +41,8 @@ - - + + @@ -91,20 +91,18 @@

    МОДУЛЬ РОБОТ

    МОДУЛЬ СТУДИЯ

      @@ -113,24 +111,24 @@

    МОДУЛЬ ОРКЕСТРАТОР

      -
    • 1. Description
    • -
    • 2. Defs
    • -
    • 3. gSettings Template
    • -
    • 4. How to use
    • -
    • 5. UAC - User Access Control

      МОДУЛЬ АГЕНТ

      ИНСТРУМЕНТЫ

      @@ -179,7 +177,7 @@
    • »
    • -
    • 5. UAC - User Access Control
    • +
    • 5. Права доступа пользователей UAC
    • @@ -198,16 +196,17 @@
      -
      -

      5. UAC - User Access Control

      -
      -

      About

      -

      Orchestrator has mega feature - user access control (UAC). This feature allow you to manipulate access of the web UI for the all users!

      -

      If you need to give admin rights - you don’t customize UAC dict.

      -

      If you need to give some little rights for user only for one robot in orchestrator web panel - you can set the following properties in UAC dict.

      -

      To work with UAC you can use defs Orchestrator.UAC group.

      -

      !!!ATTENTION!!!

      -

      Need practice example to work with UAC! - too hard to understand

      +
      +

      5. Права доступа пользователей UAC

      +
      +

      Описание

      +

      Оркестратор обладает уникальным и гибким механизмом контроля и распределения прав доступа пользователей (UAC - User Access Control). Концепция pyOpenRPA заключается в том, что настройка доступа должна быть максимально функциональной, но при этом удобной в использовании.

      +

      Если требуется дать все права доступа - не нужно ничего редактировать - они будут по умолчанию.

      +

      Если нужно внести корректировки - вы можете указать лишь те ключи доступа, которые потребуются пользователю.

      +

      Также UAC механизм распределения прав доступа отлично интегрируется со сторонними системами безопасности, которые уже используются в компаниях, например Active Directory и другие.

      +

      Функции по работе с UAC представлены в группе Orchestrator.UAC в разделе описания функций: 2. Функции.

      +

      Если у вас останутся вопросы, то вы всегда можете обратиться в центр поддержки клиентов pyOpenRPA. Контакты: 2. Лицензия & Контакты

      +

      pyOpenRPA - роботы помогут!

      UAC Dict for Orchestrator WEB UI rights

      @@ -245,8 +244,18 @@ }
      -

      .. v1.2.12 replace:: v1.2.12 - .. |author| replace:: Ivan Maslov <ivan.maslov@unicodelabs.ru>

      +
      +
      @@ -257,8 +266,8 @@

      diff --git a/Wiki/RUS_Guide/html/Orchestrator/06_Defs Managers.html b/Wiki/RUS_Guide/html/Orchestrator/06_Defs Managers.html deleted file mode 100644 index 2142566c..00000000 --- a/Wiki/RUS_Guide/html/Orchestrator/06_Defs Managers.html +++ /dev/null @@ -1,2220 +0,0 @@ - - - - - - - - - - 6. Defs Managers — документация pyOpenRPA v1.2.12 v1.2.12 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
      - - - -
      - - - - - -
      - -
      - - - - - - - - - - - - - - - - - - - -
      - - - - -
      -
      -
      -
      - -
      -

      6. Defs Managers

      -
      -

      Process (General)

      -
      # EXAMPLE
      -from pyOpenRPA.Orchestrator import Orchestrator
      -lProcess = Orchestrator.Managers.Process(inAgentHostNameStr="PC-DESKTOP",inAgentUserNameStr="ND", inProcessNameWOExeStr="notepad",inStartCMDStr="notepad")
      -
      -
      -

      Classes:

      - ---- - - - - - -

      Process(inAgentHostNameStr, …[, …])

      Manager process, which is need to be started / stopped / restarted

      -

      Functions:

      - ---- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

      ProcessExists(inAgentHostNameStr, …)

      Check if the Process instance is exists in GSettings by the (inAgentHostNameStr: str, inAgentUserNameStr: str, inProcessNameWOExeStr: str)

      ProcessGet(inAgentHostNameStr, …)

      Return the process instance by the inProcessNameWOExeStr

      ProcessInitSafe(inAgentHostNameStr, …[, …])

      Exception safe function.

      ProcessManual2Auto(inAgentHostNameStr, …)

      Remove Manual flag from process (if exists) - it will allow the schedule operations via def StatusCheckStart(self): def StatusCheckStorForce(self): def StatusCheckStopSafe(self):

      ProcessManualStopListClear(…)

      Clear the last start tries list.

      ProcessManualStopTriggerSet(…)

      Remove Manual flag from process (if exists) - it will allow the schedule operations via def StatusCheckStart(self): def StatusCheckStorForce(self): def StatusCheckStopSafe(self):

      ProcessScheduleStatusCheckEverySeconds(…)

      Run status check every interval in second you specify.

      ProcessStart(inAgentHostNameStr, …[, …])

      Manual/Auto start.

      ProcessStatusCheck(inAgentHostNameStr, …)

      Check if process is alive.

      ProcessStatusRestore(inAgentHostNameStr, …)

      Execute the StatusCheck, after that restore status to the saved state (see StatusSave).

      ProcessStatusSave(inAgentHostNameStr, …)

      Save current status of the process.

      ProcessStatusStrGet(inAgentHostNameStr, …)

      Get the status of the Process instance.

      ProcessStopForce(inAgentHostNameStr, …[, …])

      Manual/Auto stop force.

      ProcessStopSafe(inAgentHostNameStr, …[, …])

      Manual/Auto stop safe.

      -
      -
      -class pyOpenRPA.Orchestrator.Managers.Process.Process(inAgentHostNameStr, inAgentUserNameStr, inProcessNameWOExeStr, inStartPathStr=None, inStartCMDStr=None, inStopSafeTimeoutSecFloat=300, inStartArgDict=None, inStatusCheckIntervalSecFloat=30)[исходный код]
      -

      Manager process, which is need to be started / stopped / restarted

      -

      With Process instance you can automate your process activity. Use schedule package to set interval when process should be active and when not.

      -

      All defs in class are pickle safe! After orchestrator restart (if not the force stop of the orchestrator process) your instance with properties will be restored. But it not coverage the scheduler which is in __Orchestrator__ . -After orc restart you need to reinit all schedule rules: Orchestrator.OrchestratorScheduleGet

      -
      -
      Process instance has the following statuses:
        -
      • 0_STOPPED

      • -
      • 1_STOPPED_MANUAL

      • -
      • 2_STOP_SAFE

      • -
      • 3_STOP_SAFE_MANUAL

      • -
      • 4_STARTED

      • -
      • 5_STARTED_MANUAL

      • -
      -
      -
      -

      How to use StopSafe on the robot side

      -

      Methods:

      - ---- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

      KeyTurpleGet()

      Get the key turple of the current process

      Manual2Auto()

      Remove Manual flag from process (if exists) - it will allow the schedule operations via def StatusCheckStart(self): def StatusCheckStorForce(self): def StatusCheckStopSafe(self):

      ManualStopListClear()

      Clear the last start tries list.

      ManualStopTriggerNewStart()

      Log new start event.

      ManualStopTriggerSet(inMSTdTSecFloat, inMSTdNInt)

      Set ManualStopTrigger (MST) to switch to STOPPED MANUAL if specified count of start fails will be catched in specified time period

      MuteWait()

      Internal def.

      RestartForce([inIsManualBool])

      Manual/Auto restart force.

      RestartSafe([inIsManualBool])

      Manual/Auto restart safe.

      Start([inIsManualBool, inStartArgDict])

      Manual/Auto start.

      StartCheck()

      Start program if auto stopped (0_STOPPED).

      StatusChangeLog()

      Lof information about status change

      StatusCheck()

      Check if process is alive.

      StatusCheckIntervalRestore()

      Call from orchestrator when init

      StatusCheckStart()

      Check process status and run it if auto stopped self.mStatusStr is «0_STOPPED»

      StatusCheckStopForce()

      Check process status and auto stop force it if self.mStatusStr is 4_STARTED

      StatusCheckStopSafe()

      Check process status and auto stop safe it if self.mStatusStr is 4_STARTED

      StatusRestore()

      Execute the StatusCheck, after that restore status to the saved state (see StatusSave).

      StatusSave()

      Save current status of the process.

      StopForce([inIsManualBool, inMuteIgnoreBool])

      Manual/Auto stop force.

      StopForceCheck()

      Stop force program if auto started (4_STARTED).

      StopSafe([inIsManualBool, …])

      Manual/Auto stop safe.

      StopSafeCheck([inStopSafeTimeoutSecFloat])

      Stop safe program if auto started (4_STARTED).

      -
      -
      -KeyTurpleGet()[исходный код]
      -

      Get the key turple of the current process

      -
      - -
      -
      -Manual2Auto() → str[исходный код]
      -

      Remove Manual flag from process (if exists) - it will allow the schedule operations via def StatusCheckStart(self): def StatusCheckStorForce(self): def StatusCheckStopSafe(self):

      -
      -
      Результат
      -

      Process status. See self.mStatusStr. 0_STOPPED 1_STOPPED_MANUAL 2_STOP_SAFE 3_STOP_SAFE_MANUAL 4_STARTED 5_STARTED_MANUAL

      -
      -
      -
      - -
      -
      -ManualStopListClear() → None[исходный код]
      -

      Clear the last start tries list.

      -
      -
      Результат
      -

      None

      -
      -
      -
      - -
      -
      -ManualStopTriggerNewStart()[исходный код]
      -

      Log new start event. Check if it is applicable. Change status if ManualStop trigger criteria is applied

      -
      -
      Результат
      -

      # 0_STOPPED 1_STOPPED_MANUAL 2_STOP_SAFE 3_STOP_SAFE_MANUAL 4_STARTED 5_STARTED_MANUAL

      -
      -
      -
      - -
      -
      -ManualStopTriggerSet(inMSTdTSecFloat: float, inMSTdNInt: int) → None[исходный код]
      -

      Set ManualStopTrigger (MST) to switch to STOPPED MANUAL if specified count of start fails will be catched in specified time period

      -
      -
      Параметры
      -
        -
      • inMSTdTSecFloat – Time perios in seconds

      • -
      • inMSTdNInt – Counts of the start tries

      • -
      -
      -
      Результат
      -

      None

      -
      -
      -
      - -
      -
      -MuteWait()[исходный код]
      -

      Internal def. Wait when class is apply to send new activities to the agent

      -
      -
      Результат
      -

      -
      -
      -
      - -
      -
      -RestartForce(inIsManualBool=True)[исходный код]
      -

      Manual/Auto restart force. Force restart dont wait process termination - it just terminate process now ant then start it. -Manual restart will block scheduling execution. To return schedule execution use def Manual2Auto

      -
      -
      Параметры
      -

      inIsManualBool – Default is True - Mark this operation as manual - StatusCheckStart/Stop will be blocked - only StatusCheck will be working. False - Auto operation

      -
      -
      Результат
      -

      Process status. See self.mStatusStr. 0_STOPPED 1_STOPPED_MANUAL 2_STOP_SAFE 3_STOP_SAFE_MANUAL 4_STARTED 5_STARTED_MANUAL

      -
      -
      -
      - -
      -
      -RestartSafe(inIsManualBool=True)[исходный код]
      -

      Manual/Auto restart safe. Restart safe is the operation which send signal to process to terminate own work (send term signal to process). Then it run process. Managers.Process wait for the mStopSafeTimeoutSecFloat seconds. After that, if process is not terminated - self will StopForce it. -Manual stop safe will block scheduling execution. To return schedule execution use def Manual2Auto

      -
      -
      Параметры
      -

      inIsManualBool – Default is True - Mark this operation as manual - StatusCheckStart/Stop will be blocked - only StatusCheck will be working. False - Auto operation

      -
      -
      Результат
      -

      Process status. See self.mStatusStr. 0_STOPPED 1_STOPPED_MANUAL 2_STOP_SAFE 3_STOP_SAFE_MANUAL 4_STARTED 5_STARTED_MANUAL

      -
      -
      -
      - -
      -
      -Start(inIsManualBool=True, inStartArgDict=None) → str[исходный код]
      -

      Manual/Auto start. Manual start will block scheduling execution. To return schedule execution use def Manual2Auto. -Will not start if STOP SAFE is now and don’t start auto is stopped manual now

      -
      -
      Параметры
      -

      inIsManualBool – Default is True - Mark this operation as manual - StatusCheckStart/Stop will be blocked - only StatusCheck will be working. False - Auto operation

      -
      -
      Результат
      -

      Process status. See self.mStatusStr. 0_STOPPED 1_STOPPED_MANUAL 2_STOP_SAFE 3_STOP_SAFE_MANUAL 4_STARTED 5_STARTED_MANUAL

      -
      -
      -
      - -
      -
      -StartCheck() → str[исходный код]
      -

      Start program if auto stopped (0_STOPPED).

      -
      -
      Результат
      -

      Process status. See self.mStatusStr. 0_STOPPED 1_STOPPED_MANUAL 2_STOP_SAFE 3_STOP_SAFE_MANUAL 4_STARTED 5_STARTED_MANUAL

      -
      -
      -
      - -
      -
      -StatusChangeLog()[исходный код]
      -

      Lof information about status change

      -
      -
      Результат
      -

      -
      -
      -
      - -
      -
      -StatusCheck()[исходный код]
      -

      Check if process is alive. The def will save the manual flag is exists. Don’t wait mute but set mute if it is not set.

      -
      -
      Результат
      -

      Process status. See self.mStatusStr. 0_STOPPED 1_STOPPED_MANUAL 2_STOP_SAFE 3_STOP_SAFE_MANUAL 4_STARTED 5_STARTED_MANUAL

      -
      -
      -
      - -
      -
      -StatusCheckIntervalRestore()[исходный код]
      -

      Call from orchestrator when init

      -
      - -
      -
      -StatusCheckStart()[исходный код]
      -

      Check process status and run it if auto stopped self.mStatusStr is «0_STOPPED»

      -
      -
      Результат
      -

      Process status. See self.mStatusStr. 0_STOPPED 1_STOPPED_MANUAL 2_STOP_SAFE 3_STOP_SAFE_MANUAL 4_STARTED 5_STARTED_MANUAL

      -
      -
      -
      - -
      -
      -StatusCheckStopForce()[исходный код]
      -

      Check process status and auto stop force it if self.mStatusStr is 4_STARTED

      -
      -
      Результат
      -

      Process status. See self.mStatusStr. 0_STOPPED 1_STOPPED_MANUAL 2_STOP_SAFE 3_STOP_SAFE_MANUAL 4_STARTED 5_STARTED_MANUAL

      -
      -
      -
      - -
      -
      -StatusCheckStopSafe()[исходный код]
      -

      Check process status and auto stop safe it if self.mStatusStr is 4_STARTED

      -
      -
      Результат
      -

      -
      -
      -
      - -
      -
      -StatusRestore()[исходный код]
      -

      Execute the StatusCheck, after that restore status to the saved state (see StatusSave). Work when orchestrator is restarted.

      -
      -
      Результат
      -

      Process status. See self.mStatusStr. 0_STOPPED 1_STOPPED_MANUAL 2_STOP_SAFE 3_STOP_SAFE_MANUAL 4_STARTED 5_STARTED_MANUAL

      -
      -
      -
      - -
      -
      -StatusSave()[исходный код]
      -

      Save current status of the process. After that you can restore process activity. Work when orchestrator is restarted. Don’t save «STOP_SAFE» status > «STOPPED»

      -
      -
      Результат
      -

      Process status. See self.mStatusStr. 0_STOPPED 1_STOPPED_MANUAL 2_STOP_SAFE 3_STOP_SAFE_MANUAL 4_STARTED 5_STARTED_MANUAL

      -
      -
      -
      - -
      -
      -StopForce(inIsManualBool=True, inMuteIgnoreBool=False) → str[исходный код]
      -

      Manual/Auto stop force. Force stop don’t wait process termination - it just terminate process now. -Manual stop safe will block scheduling execution. To return schedule execution use def Manual2Auto

      -
      -
      Параметры
      -

      inIsManualBool – Default is True - Mark this operation as manual - StatusCheckStart/Stop will be blocked - only StatusCheck will be working. False - Auto operation

      -
      -
      Результат
      -

      Process status. See self.mStatusStr. 0_STOPPED 1_STOPPED_MANUAL 2_STOP_SAFE 3_STOP_SAFE_MANUAL 4_STARTED 5_STARTED_MANUAL

      -
      -
      -
      - -
      -
      -StopForceCheck() → str[исходный код]
      -

      Stop force program if auto started (4_STARTED).

      -
      -
      Результат
      -

      Process status. See self.mStatusStr. 0_STOPPED 1_STOPPED_MANUAL 2_STOP_SAFE 3_STOP_SAFE_MANUAL 4_STARTED 5_STARTED_MANUAL

      -
      -
      -
      - -
      -
      -StopSafe(inIsManualBool=True, inStopSafeTimeoutSecFloat=None) → str[исходный код]
      -

      Manual/Auto stop safe. Stop safe is the operation which send signal to process to terminate own work (send term signal to process). Managers.Process wait for the mStopSafeTimeoutSecFloat seconds. After that, if process is not terminated - self will StopForce it. -Manual stop safe will block scheduling execution. To return schedule execution use def Manual2Auto

      -
      -
      Параметры
      -
        -
      • inIsManualBool – Default is True - Mark this operation as manual - StatusCheckStart/Stop will be blocked - only StatusCheck will be working. False - Auto operation

      • -
      • inStopSafeTimeoutSecFloat – Default value goes from the instance. You can specify time is second to wait while safe stop. After that program will stop force

      • -
      -
      -
      Результат
      -

      Process status. See self.mStatusStr. 0_STOPPED 1_STOPPED_MANUAL 2_STOP_SAFE 3_STOP_SAFE_MANUAL 4_STARTED 5_STARTED_MANUAL

      -
      -
      -
      - -
      -
      -StopSafeCheck(inStopSafeTimeoutSecFloat=None) → str[исходный код]
      -

      Stop safe program if auto started (4_STARTED).

      -
      -
      Параметры
      -

      inStopSafeTimeoutSecFloat – Default value goes from the instance. You can specify time is second to wait while safe stop. After that program will stop force

      -
      -
      Результат
      -

      Process status. See self.mStatusStr. 0_STOPPED 1_STOPPED_MANUAL 2_STOP_SAFE 3_STOP_SAFE_MANUAL 4_STARTED 5_STARTED_MANUAL

      -
      -
      -
      - -
      - -
      -
      -pyOpenRPA.Orchestrator.Managers.Process.ProcessExists(inAgentHostNameStr: str, inAgentUserNameStr: str, inProcessNameWOExeStr: str) → bool[исходный код]
      -

      Check if the Process instance is exists in GSettings by the (inAgentHostNameStr: str, inAgentUserNameStr: str, inProcessNameWOExeStr: str)

      -
      -
      Параметры
      -
        -
      • inAgentHostNameStr – Agent hostname in any case. Required to identify Process

      • -
      • inAgentUserNameStr – Agent user name in any case. Required to identify Process

      • -
      • inProcessNameWOExeStr – The process name without extension .exe (the key of the Process instance). Any case - will be processed to the upper case

      • -
      -
      -
      Результат
      -

      True - process exists in gsettings; False - else

      -
      -
      -
      - -
      -
      -pyOpenRPA.Orchestrator.Managers.Process.ProcessGet(inAgentHostNameStr: str, inAgentUserNameStr: str, inProcessNameWOExeStr: str)pyOpenRPA.Orchestrator.Managers.Process.Process[исходный код]
      -

      Return the process instance by the inProcessNameWOExeStr

      -
      -
      Параметры
      -
        -
      • inAgentHostNameStr – Agent hostname in any case. Required to identify Process

      • -
      • inAgentUserNameStr – Agent user name in any case. Required to identify Process

      • -
      • inProcessNameWOExeStr – The process name without extension .exe (the key of the Process instance). Any case - will be processed to the upper case

      • -
      -
      -
      Результат
      -

      Process instance (if exists) Else None

      -
      -
      -
      - -
      -
      -pyOpenRPA.Orchestrator.Managers.Process.ProcessInitSafe(inAgentHostNameStr, inAgentUserNameStr, inProcessNameWOExeStr, inStartPathStr=None, inStartCMDStr=None, inStopSafeTimeoutSecFloat=300)pyOpenRPA.Orchestrator.Managers.Process.Process[исходный код]
      -

      Exception safe function. Check if process instance is not exists in GSettings (it can be after restart because Orchestrator restore objects from dump of the previous Orchestrator session) -Return existing instance (if exists) or create new instance and return it.

      -
      -
      Параметры
      -
        -
      • inAgentHostNameStr – Agent hostname in any case. Required to identify Process

      • -
      • inAgentUserNameStr – Agent user name in any case. Required to identify Process

      • -
      • inProcessNameWOExeStr – The process name without extension .exe (the key of the Process instance). Any case - will be processed to the upper case

      • -
      • inStartPathStr – Path to start process (.cmd/ .exe or something else). Path can be relative (from orc working directory) or absolute

      • -
      • inStartCMDStr – CMD script to start program (if no start file is exists)

      • -
      • inStopSafeTimeoutSecFloat – Time to wait for stop safe. After that do the stop force (if process is not stopped)

      • -
      -
      -
      Результат
      -

      Process instance

      -
      -
      -
      - -
      -
      -pyOpenRPA.Orchestrator.Managers.Process.ProcessManual2Auto(inAgentHostNameStr: str, inAgentUserNameStr: str, inProcessNameWOExeStr: str) → str[исходный код]
      -

      Remove Manual flag from process (if exists) - it will allow the schedule operations via def StatusCheckStart(self): def StatusCheckStorForce(self): def StatusCheckStopSafe(self):

      -
      -
      Параметры
      -
        -
      • inAgentHostNameStr – Agent hostname in any case. Required to identify Process

      • -
      • inAgentUserNameStr – Agent user name in any case. Required to identify Process

      • -
      • inProcessNameWOExeStr – The process name without extension .exe (the key of the Process instance). Any case - will be processed to the upper case

      • -
      -
      -
      Результат
      -

      Process status. See self.mStatusStr. -Process instance has the following statuses: -- 0_STOPPED -- 1_STOPPED_MANUAL -- 2_STOP_SAFE -- 3_STOP_SAFE_MANUAL -- 4_STARTED -- 5_STARTED_MANUAL -- None (if Process instance not exists)

      -
      -
      -
      - -
      -
      -pyOpenRPA.Orchestrator.Managers.Process.ProcessManualStopListClear(inAgentHostNameStr: str, inAgentUserNameStr: str, inProcessNameWOExeStr: str) → None[исходный код]
      -

      Clear the last start tries list.

      -
      -
      Параметры
      -
        -
      • inAgentHostNameStr – Agent hostname in any case. Required to identify Process

      • -
      • inAgentUserNameStr – Agent user name in any case. Required to identify Process

      • -
      • inProcessNameWOExeStr – The process name without extension .exe (the key of the Process instance). Any case - will be processed to the upper case

      • -
      -
      -
      Результат
      -

      None

      -
      -
      -
      - -
      -
      -pyOpenRPA.Orchestrator.Managers.Process.ProcessManualStopTriggerSet(inAgentHostNameStr: str, inAgentUserNameStr: str, inProcessNameWOExeStr: str, inMSTdTSecFloat: float, inMSTdNInt: int) → None[исходный код]
      -

      Remove Manual flag from process (if exists) - it will allow the schedule operations via def StatusCheckStart(self): def StatusCheckStorForce(self): def StatusCheckStopSafe(self):

      -
      -
      Параметры
      -
        -
      • inAgentHostNameStr – Agent hostname in any case. Required to identify Process

      • -
      • inAgentUserNameStr – Agent user name in any case. Required to identify Process

      • -
      • inProcessNameWOExeStr – The process name without extension .exe (the key of the Process instance). Any case - will be processed to the upper case

      • -
      • inMSTdTSecFloat – Time periods in seconds

      • -
      • inMSTdNInt – Counts of the start tries

      • -
      -
      -
      Результат
      -

      None

      -
      -
      -
      - -
      -
      -pyOpenRPA.Orchestrator.Managers.Process.ProcessScheduleStatusCheckEverySeconds(inAgentHostNameStr: str, inAgentUserNameStr: str, inProcessNameWOExeStr: str, inIntervalSecondsInt: int = 120)[исходный код]
      -

      Run status check every interval in second you specify.

      -
      -
      Параметры
      -
        -
      • inAgentHostNameStr – Agent hostname in any case. Required to identify Process

      • -
      • inAgentUserNameStr – Agent user name in any case. Required to identify Process

      • -
      • inProcessNameWOExeStr – The process name without extension .exe (the key of the Process instance). Any case - will be processed to the upper case

      • -
      • inIntervalSecondsInt – Interval in seconds. Default is 120

      • -
      -
      -
      Результат
      -

      None

      -
      -
      -
      - -
      -
      -pyOpenRPA.Orchestrator.Managers.Process.ProcessStart(inAgentHostNameStr: str, inAgentUserNameStr: str, inProcessNameWOExeStr: str, inIsManualBool: bool = True) → str[исходный код]
      -

      Manual/Auto start. Manual start will block scheduling execution. To return schedule execution use def Manual2Auto

      -
      -
      Параметры
      -
        -
      • inAgentHostNameStr – Agent hostname in any case. Required to identify Process

      • -
      • inAgentUserNameStr – Agent user name in any case. Required to identify Process

      • -
      • inProcessNameWOExeStr – The process name without extension .exe (the key of the Process instance). Any case - will be processed to the upper case

      • -
      • inIsManualBool – Default is True - Mark this operation as manual - StatusCheckStart/Stop will be blocked - only StatusCheck will be working. False - Auto operation

      • -
      -
      -
      Результат
      -

      Process status. See self.mStatusStr. -Process instance has the following statuses: -- 0_STOPPED -- 1_STOPPED_MANUAL -- 2_STOP_SAFE -- 3_STOP_SAFE_MANUAL -- 4_STARTED -- 5_STARTED_MANUAL -- None (if Process instance not exists)

      -
      -
      -
      - -
      -
      -pyOpenRPA.Orchestrator.Managers.Process.ProcessStatusCheck(inAgentHostNameStr: str, inAgentUserNameStr: str, inProcessNameWOExeStr: str) → str[исходный код]
      -

      Check if process is alive. The def will save the manual flag is exists.

      -
      -
      Параметры
      -
        -
      • inAgentHostNameStr – Agent hostname in any case. Required to identify Process

      • -
      • inAgentUserNameStr – Agent user name in any case. Required to identify Process

      • -
      • inProcessNameWOExeStr – The process name without extension .exe (the key of the Process instance). Any case - will be processed to the upper case

      • -
      -
      -
      Результат
      -

      Process status. See self.mStatusStr. -Process instance has the following statuses: -- 0_STOPPED -- 1_STOPPED_MANUAL -- 2_STOP_SAFE -- 3_STOP_SAFE_MANUAL -- 4_STARTED -- 5_STARTED_MANUAL -- None (if Process instance not exists)

      -
      -
      -
      - -
      -
      -pyOpenRPA.Orchestrator.Managers.Process.ProcessStatusRestore(inAgentHostNameStr: str, inAgentUserNameStr: str, inProcessNameWOExeStr: str)[исходный код]
      -

      Execute the StatusCheck, after that restore status to the saved state (see StatusSave). Work when orchestrator is restarted.

      -
      -
      Результат
      -

      Process status. See self.mStatusStr. 0_STOPPED 1_STOPPED_MANUAL 2_STOP_SAFE 3_STOP_SAFE_MANUAL 4_STARTED 5_STARTED_MANUAL

      -
      -
      -
      - -
      -
      -pyOpenRPA.Orchestrator.Managers.Process.ProcessStatusSave(inAgentHostNameStr: str, inAgentUserNameStr: str, inProcessNameWOExeStr: str)[исходный код]
      -

      Save current status of the process. After that you can restore process activity. Work when orchestrator is restarted. Don’t save «STOP_SAFE» status > «STOPPED»

      -
      -
      Результат
      -

      Process status. See self.mStatusStr. 0_STOPPED 1_STOPPED_MANUAL 2_STOP_SAFE 3_STOP_SAFE_MANUAL 4_STARTED 5_STARTED_MANUAL

      -
      -
      -
      - -
      -
      -pyOpenRPA.Orchestrator.Managers.Process.ProcessStatusStrGet(inAgentHostNameStr: str, inAgentUserNameStr: str, inProcessNameWOExeStr: str) → str[исходный код]
      -

      Get the status of the Process instance.

      -
      -
      Параметры
      -
        -
      • inAgentHostNameStr – Agent hostname in any case. Required to identify Process

      • -
      • inAgentUserNameStr – Agent user name in any case. Required to identify Process

      • -
      • inProcessNameWOExeStr – The process name without extension .exe (the key of the Process instance). Any case - will be processed to the upper case

      • -
      -
      -
      Результат
      -

      Process status. See self.mStatusStr. -Process instance has the following statuses: -- 0_STOPPED -- 1_STOPPED_MANUAL -- 2_STOP_SAFE -- 3_STOP_SAFE_MANUAL -- 4_STARTED -- 5_STARTED_MANUAL -- None (if Process instance not exists)

      -
      -
      -
      - -
      -
      -pyOpenRPA.Orchestrator.Managers.Process.ProcessStopForce(inAgentHostNameStr: str, inAgentUserNameStr: str, inProcessNameWOExeStr: str, inIsManualBool: bool = True) → str[исходный код]
      -

      Manual/Auto stop force. Force stop dont wait process termination - it just terminate process now. -Manual stop safe will block scheduling execution. To return schedule execution use def Manual2Auto

      -
      -
      Параметры
      -
        -
      • inAgentHostNameStr – Agent hostname in any case. Required to identify Process

      • -
      • inAgentUserNameStr – Agent user name in any case. Required to identify Process

      • -
      • inProcessNameWOExeStr – The process name without extension .exe (the key of the Process instance). Any case - will be processed to the upper case

      • -
      • inIsManualBool – Default is True - Mark this operation as manual - StatusCheckStart/Stop will be blocked - only StatusCheck will be working. False - Auto operation

      • -
      -
      -
      Результат
      -

      Process status. See self.mStatusStr. -Process instance has the following statuses: -- 0_STOPPED -- 1_STOPPED_MANUAL -- 2_STOP_SAFE -- 3_STOP_SAFE_MANUAL -- 4_STARTED -- 5_STARTED_MANUAL -- None (if Process instance not exists)

      -
      -
      -
      - -
      -
      -pyOpenRPA.Orchestrator.Managers.Process.ProcessStopSafe(inAgentHostNameStr: str, inAgentUserNameStr: str, inProcessNameWOExeStr: str, inIsManualBool: bool = True, inStopSafeTimeoutSecFloat=None) → str[исходный код]
      -

      Manual/Auto stop safe. Stop safe is the operation which send signal to process to terminate own work (send term signal to process). Managers.Process wait for the mStopSafeTimeoutSecFloat seconds. After that, if process is not terminated - self will StopForce it. -Manual stop safe will block scheduling execution. To return schedule execution use def Manual2Auto

      -
      -
      Параметры
      -
        -
      • inAgentHostNameStr – Agent hostname in any case. Required to identify Process

      • -
      • inAgentUserNameStr – Agent user name in any case. Required to identify Process

      • -
      • inProcessNameWOExeStr – The process name without extension .exe (the key of the Process instance). Any case - will be processed to the upper case

      • -
      • inIsManualBool – Default is True - Mark this operation as manual - StatusCheckStart/Stop will be blocked - only StatusCheck will be working. False - Auto operation

      • -
      • inStopSafeTimeoutSecFloat – Default value goes from the instance. You can specify time is second to wait while safe stop. After that program will stop force

      • -
      -
      -
      Результат
      -

      Process status. See self.mStatusStr. -Process instance has the following statuses: -- 0_STOPPED -- 1_STOPPED_MANUAL -- 2_STOP_SAFE -- 3_STOP_SAFE_MANUAL -- 4_STARTED -- 5_STARTED_MANUAL -- None (if Process instance not exists)

      -
      -
      -
      - -
      -
      -

      Process (Details)

      -

      Classes:

      - ---- - - - - - -

      Process(inAgentHostNameStr, …[, …])

      Manager process, which is need to be started / stopped / restarted

      -

      Functions:

      - ---- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

      ProcessExists(inAgentHostNameStr, …)

      Check if the Process instance is exists in GSettings by the (inAgentHostNameStr: str, inAgentUserNameStr: str, inProcessNameWOExeStr: str)

      ProcessGet(inAgentHostNameStr, …)

      Return the process instance by the inProcessNameWOExeStr

      ProcessInitSafe(inAgentHostNameStr, …[, …])

      Exception safe function.

      ProcessManual2Auto(inAgentHostNameStr, …)

      Remove Manual flag from process (if exists) - it will allow the schedule operations via def StatusCheckStart(self): def StatusCheckStorForce(self): def StatusCheckStopSafe(self):

      ProcessManualStopListClear(…)

      Clear the last start tries list.

      ProcessManualStopTriggerSet(…)

      Remove Manual flag from process (if exists) - it will allow the schedule operations via def StatusCheckStart(self): def StatusCheckStorForce(self): def StatusCheckStopSafe(self):

      ProcessScheduleStatusCheckEverySeconds(…)

      Run status check every interval in second you specify.

      ProcessStart(inAgentHostNameStr, …[, …])

      Manual/Auto start.

      ProcessStatusCheck(inAgentHostNameStr, …)

      Check if process is alive.

      ProcessStatusRestore(inAgentHostNameStr, …)

      Execute the StatusCheck, after that restore status to the saved state (see StatusSave).

      ProcessStatusSave(inAgentHostNameStr, …)

      Save current status of the process.

      ProcessStatusStrGet(inAgentHostNameStr, …)

      Get the status of the Process instance.

      ProcessStopForce(inAgentHostNameStr, …[, …])

      Manual/Auto stop force.

      ProcessStopSafe(inAgentHostNameStr, …[, …])

      Manual/Auto stop safe.

      -
      -
      -class pyOpenRPA.Orchestrator.Managers.Process.Process(inAgentHostNameStr, inAgentUserNameStr, inProcessNameWOExeStr, inStartPathStr=None, inStartCMDStr=None, inStopSafeTimeoutSecFloat=300, inStartArgDict=None, inStatusCheckIntervalSecFloat=30)[исходный код]
      -

      Manager process, which is need to be started / stopped / restarted

      -

      With Process instance you can automate your process activity. Use schedule package to set interval when process should be active and when not.

      -

      All defs in class are pickle safe! After orchestrator restart (if not the force stop of the orchestrator process) your instance with properties will be restored. But it not coverage the scheduler which is in __Orchestrator__ . -After orc restart you need to reinit all schedule rules: Orchestrator.OrchestratorScheduleGet

      -
      -
      Process instance has the following statuses:
        -
      • 0_STOPPED

      • -
      • 1_STOPPED_MANUAL

      • -
      • 2_STOP_SAFE

      • -
      • 3_STOP_SAFE_MANUAL

      • -
      • 4_STARTED

      • -
      • 5_STARTED_MANUAL

      • -
      -
      -
      -

      How to use StopSafe on the robot side

      -

      Methods:

      - ---- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

      KeyTurpleGet()

      Get the key turple of the current process

      Manual2Auto()

      Remove Manual flag from process (if exists) - it will allow the schedule operations via def StatusCheckStart(self): def StatusCheckStorForce(self): def StatusCheckStopSafe(self):

      ManualStopListClear()

      Clear the last start tries list.

      ManualStopTriggerNewStart()

      Log new start event.

      ManualStopTriggerSet(inMSTdTSecFloat, inMSTdNInt)

      Set ManualStopTrigger (MST) to switch to STOPPED MANUAL if specified count of start fails will be catched in specified time period

      MuteWait()

      Internal def.

      RestartForce([inIsManualBool])

      Manual/Auto restart force.

      RestartSafe([inIsManualBool])

      Manual/Auto restart safe.

      Start([inIsManualBool, inStartArgDict])

      Manual/Auto start.

      StartCheck()

      Start program if auto stopped (0_STOPPED).

      StatusChangeLog()

      Lof information about status change

      StatusCheck()

      Check if process is alive.

      StatusCheckIntervalRestore()

      Call from orchestrator when init

      StatusCheckStart()

      Check process status and run it if auto stopped self.mStatusStr is «0_STOPPED»

      StatusCheckStopForce()

      Check process status and auto stop force it if self.mStatusStr is 4_STARTED

      StatusCheckStopSafe()

      Check process status and auto stop safe it if self.mStatusStr is 4_STARTED

      StatusRestore()

      Execute the StatusCheck, after that restore status to the saved state (see StatusSave).

      StatusSave()

      Save current status of the process.

      StopForce([inIsManualBool, inMuteIgnoreBool])

      Manual/Auto stop force.

      StopForceCheck()

      Stop force program if auto started (4_STARTED).

      StopSafe([inIsManualBool, …])

      Manual/Auto stop safe.

      StopSafeCheck([inStopSafeTimeoutSecFloat])

      Stop safe program if auto started (4_STARTED).

      -
      -
      -KeyTurpleGet()[исходный код]
      -

      Get the key turple of the current process

      -
      - -
      -
      -Manual2Auto() → str[исходный код]
      -

      Remove Manual flag from process (if exists) - it will allow the schedule operations via def StatusCheckStart(self): def StatusCheckStorForce(self): def StatusCheckStopSafe(self):

      -
      -
      Результат
      -

      Process status. See self.mStatusStr. 0_STOPPED 1_STOPPED_MANUAL 2_STOP_SAFE 3_STOP_SAFE_MANUAL 4_STARTED 5_STARTED_MANUAL

      -
      -
      -
      - -
      -
      -ManualStopListClear() → None[исходный код]
      -

      Clear the last start tries list.

      -
      -
      Результат
      -

      None

      -
      -
      -
      - -
      -
      -ManualStopTriggerNewStart()[исходный код]
      -

      Log new start event. Check if it is applicable. Change status if ManualStop trigger criteria is applied

      -
      -
      Результат
      -

      # 0_STOPPED 1_STOPPED_MANUAL 2_STOP_SAFE 3_STOP_SAFE_MANUAL 4_STARTED 5_STARTED_MANUAL

      -
      -
      -
      - -
      -
      -ManualStopTriggerSet(inMSTdTSecFloat: float, inMSTdNInt: int) → None[исходный код]
      -

      Set ManualStopTrigger (MST) to switch to STOPPED MANUAL if specified count of start fails will be catched in specified time period

      -
      -
      Параметры
      -
        -
      • inMSTdTSecFloat – Time perios in seconds

      • -
      • inMSTdNInt – Counts of the start tries

      • -
      -
      -
      Результат
      -

      None

      -
      -
      -
      - -
      -
      -MuteWait()[исходный код]
      -

      Internal def. Wait when class is apply to send new activities to the agent

      -
      -
      Результат
      -

      -
      -
      -
      - -
      -
      -RestartForce(inIsManualBool=True)[исходный код]
      -

      Manual/Auto restart force. Force restart dont wait process termination - it just terminate process now ant then start it. -Manual restart will block scheduling execution. To return schedule execution use def Manual2Auto

      -
      -
      Параметры
      -

      inIsManualBool – Default is True - Mark this operation as manual - StatusCheckStart/Stop will be blocked - only StatusCheck will be working. False - Auto operation

      -
      -
      Результат
      -

      Process status. See self.mStatusStr. 0_STOPPED 1_STOPPED_MANUAL 2_STOP_SAFE 3_STOP_SAFE_MANUAL 4_STARTED 5_STARTED_MANUAL

      -
      -
      -
      - -
      -
      -RestartSafe(inIsManualBool=True)[исходный код]
      -

      Manual/Auto restart safe. Restart safe is the operation which send signal to process to terminate own work (send term signal to process). Then it run process. Managers.Process wait for the mStopSafeTimeoutSecFloat seconds. After that, if process is not terminated - self will StopForce it. -Manual stop safe will block scheduling execution. To return schedule execution use def Manual2Auto

      -
      -
      Параметры
      -

      inIsManualBool – Default is True - Mark this operation as manual - StatusCheckStart/Stop will be blocked - only StatusCheck will be working. False - Auto operation

      -
      -
      Результат
      -

      Process status. See self.mStatusStr. 0_STOPPED 1_STOPPED_MANUAL 2_STOP_SAFE 3_STOP_SAFE_MANUAL 4_STARTED 5_STARTED_MANUAL

      -
      -
      -
      - -
      -
      -Start(inIsManualBool=True, inStartArgDict=None) → str[исходный код]
      -

      Manual/Auto start. Manual start will block scheduling execution. To return schedule execution use def Manual2Auto. -Will not start if STOP SAFE is now and don’t start auto is stopped manual now

      -
      -
      Параметры
      -

      inIsManualBool – Default is True - Mark this operation as manual - StatusCheckStart/Stop will be blocked - only StatusCheck will be working. False - Auto operation

      -
      -
      Результат
      -

      Process status. See self.mStatusStr. 0_STOPPED 1_STOPPED_MANUAL 2_STOP_SAFE 3_STOP_SAFE_MANUAL 4_STARTED 5_STARTED_MANUAL

      -
      -
      -
      - -
      -
      -StartCheck() → str[исходный код]
      -

      Start program if auto stopped (0_STOPPED).

      -
      -
      Результат
      -

      Process status. See self.mStatusStr. 0_STOPPED 1_STOPPED_MANUAL 2_STOP_SAFE 3_STOP_SAFE_MANUAL 4_STARTED 5_STARTED_MANUAL

      -
      -
      -
      - -
      -
      -StatusChangeLog()[исходный код]
      -

      Lof information about status change

      -
      -
      Результат
      -

      -
      -
      -
      - -
      -
      -StatusCheck()[исходный код]
      -

      Check if process is alive. The def will save the manual flag is exists. Don’t wait mute but set mute if it is not set.

      -
      -
      Результат
      -

      Process status. See self.mStatusStr. 0_STOPPED 1_STOPPED_MANUAL 2_STOP_SAFE 3_STOP_SAFE_MANUAL 4_STARTED 5_STARTED_MANUAL

      -
      -
      -
      - -
      -
      -StatusCheckIntervalRestore()[исходный код]
      -

      Call from orchestrator when init

      -
      - -
      -
      -StatusCheckStart()[исходный код]
      -

      Check process status and run it if auto stopped self.mStatusStr is «0_STOPPED»

      -
      -
      Результат
      -

      Process status. See self.mStatusStr. 0_STOPPED 1_STOPPED_MANUAL 2_STOP_SAFE 3_STOP_SAFE_MANUAL 4_STARTED 5_STARTED_MANUAL

      -
      -
      -
      - -
      -
      -StatusCheckStopForce()[исходный код]
      -

      Check process status and auto stop force it if self.mStatusStr is 4_STARTED

      -
      -
      Результат
      -

      Process status. See self.mStatusStr. 0_STOPPED 1_STOPPED_MANUAL 2_STOP_SAFE 3_STOP_SAFE_MANUAL 4_STARTED 5_STARTED_MANUAL

      -
      -
      -
      - -
      -
      -StatusCheckStopSafe()[исходный код]
      -

      Check process status and auto stop safe it if self.mStatusStr is 4_STARTED

      -
      -
      Результат
      -

      -
      -
      -
      - -
      -
      -StatusRestore()[исходный код]
      -

      Execute the StatusCheck, after that restore status to the saved state (see StatusSave). Work when orchestrator is restarted.

      -
      -
      Результат
      -

      Process status. See self.mStatusStr. 0_STOPPED 1_STOPPED_MANUAL 2_STOP_SAFE 3_STOP_SAFE_MANUAL 4_STARTED 5_STARTED_MANUAL

      -
      -
      -
      - -
      -
      -StatusSave()[исходный код]
      -

      Save current status of the process. After that you can restore process activity. Work when orchestrator is restarted. Don’t save «STOP_SAFE» status > «STOPPED»

      -
      -
      Результат
      -

      Process status. See self.mStatusStr. 0_STOPPED 1_STOPPED_MANUAL 2_STOP_SAFE 3_STOP_SAFE_MANUAL 4_STARTED 5_STARTED_MANUAL

      -
      -
      -
      - -
      -
      -StopForce(inIsManualBool=True, inMuteIgnoreBool=False) → str[исходный код]
      -

      Manual/Auto stop force. Force stop don’t wait process termination - it just terminate process now. -Manual stop safe will block scheduling execution. To return schedule execution use def Manual2Auto

      -
      -
      Параметры
      -

      inIsManualBool – Default is True - Mark this operation as manual - StatusCheckStart/Stop will be blocked - only StatusCheck will be working. False - Auto operation

      -
      -
      Результат
      -

      Process status. See self.mStatusStr. 0_STOPPED 1_STOPPED_MANUAL 2_STOP_SAFE 3_STOP_SAFE_MANUAL 4_STARTED 5_STARTED_MANUAL

      -
      -
      -
      - -
      -
      -StopForceCheck() → str[исходный код]
      -

      Stop force program if auto started (4_STARTED).

      -
      -
      Результат
      -

      Process status. See self.mStatusStr. 0_STOPPED 1_STOPPED_MANUAL 2_STOP_SAFE 3_STOP_SAFE_MANUAL 4_STARTED 5_STARTED_MANUAL

      -
      -
      -
      - -
      -
      -StopSafe(inIsManualBool=True, inStopSafeTimeoutSecFloat=None) → str[исходный код]
      -

      Manual/Auto stop safe. Stop safe is the operation which send signal to process to terminate own work (send term signal to process). Managers.Process wait for the mStopSafeTimeoutSecFloat seconds. After that, if process is not terminated - self will StopForce it. -Manual stop safe will block scheduling execution. To return schedule execution use def Manual2Auto

      -
      -
      Параметры
      -
        -
      • inIsManualBool – Default is True - Mark this operation as manual - StatusCheckStart/Stop will be blocked - only StatusCheck will be working. False - Auto operation

      • -
      • inStopSafeTimeoutSecFloat – Default value goes from the instance. You can specify time is second to wait while safe stop. After that program will stop force

      • -
      -
      -
      Результат
      -

      Process status. See self.mStatusStr. 0_STOPPED 1_STOPPED_MANUAL 2_STOP_SAFE 3_STOP_SAFE_MANUAL 4_STARTED 5_STARTED_MANUAL

      -
      -
      -
      - -
      -
      -StopSafeCheck(inStopSafeTimeoutSecFloat=None) → str[исходный код]
      -

      Stop safe program if auto started (4_STARTED).

      -
      -
      Параметры
      -

      inStopSafeTimeoutSecFloat – Default value goes from the instance. You can specify time is second to wait while safe stop. After that program will stop force

      -
      -
      Результат
      -

      Process status. See self.mStatusStr. 0_STOPPED 1_STOPPED_MANUAL 2_STOP_SAFE 3_STOP_SAFE_MANUAL 4_STARTED 5_STARTED_MANUAL

      -
      -
      -
      - -
      - -
      -
      -pyOpenRPA.Orchestrator.Managers.Process.ProcessExists(inAgentHostNameStr: str, inAgentUserNameStr: str, inProcessNameWOExeStr: str) → bool[исходный код]
      -

      Check if the Process instance is exists in GSettings by the (inAgentHostNameStr: str, inAgentUserNameStr: str, inProcessNameWOExeStr: str)

      -
      -
      Параметры
      -
        -
      • inAgentHostNameStr – Agent hostname in any case. Required to identify Process

      • -
      • inAgentUserNameStr – Agent user name in any case. Required to identify Process

      • -
      • inProcessNameWOExeStr – The process name without extension .exe (the key of the Process instance). Any case - will be processed to the upper case

      • -
      -
      -
      Результат
      -

      True - process exists in gsettings; False - else

      -
      -
      -
      - -
      -
      -pyOpenRPA.Orchestrator.Managers.Process.ProcessGet(inAgentHostNameStr: str, inAgentUserNameStr: str, inProcessNameWOExeStr: str)pyOpenRPA.Orchestrator.Managers.Process.Process[исходный код]
      -

      Return the process instance by the inProcessNameWOExeStr

      -
      -
      Параметры
      -
        -
      • inAgentHostNameStr – Agent hostname in any case. Required to identify Process

      • -
      • inAgentUserNameStr – Agent user name in any case. Required to identify Process

      • -
      • inProcessNameWOExeStr – The process name without extension .exe (the key of the Process instance). Any case - will be processed to the upper case

      • -
      -
      -
      Результат
      -

      Process instance (if exists) Else None

      -
      -
      -
      - -
      -
      -pyOpenRPA.Orchestrator.Managers.Process.ProcessInitSafe(inAgentHostNameStr, inAgentUserNameStr, inProcessNameWOExeStr, inStartPathStr=None, inStartCMDStr=None, inStopSafeTimeoutSecFloat=300)pyOpenRPA.Orchestrator.Managers.Process.Process[исходный код]
      -

      Exception safe function. Check if process instance is not exists in GSettings (it can be after restart because Orchestrator restore objects from dump of the previous Orchestrator session) -Return existing instance (if exists) or create new instance and return it.

      -
      -
      Параметры
      -
        -
      • inAgentHostNameStr – Agent hostname in any case. Required to identify Process

      • -
      • inAgentUserNameStr – Agent user name in any case. Required to identify Process

      • -
      • inProcessNameWOExeStr – The process name without extension .exe (the key of the Process instance). Any case - will be processed to the upper case

      • -
      • inStartPathStr – Path to start process (.cmd/ .exe or something else). Path can be relative (from orc working directory) or absolute

      • -
      • inStartCMDStr – CMD script to start program (if no start file is exists)

      • -
      • inStopSafeTimeoutSecFloat – Time to wait for stop safe. After that do the stop force (if process is not stopped)

      • -
      -
      -
      Результат
      -

      Process instance

      -
      -
      -
      - -
      -
      -pyOpenRPA.Orchestrator.Managers.Process.ProcessManual2Auto(inAgentHostNameStr: str, inAgentUserNameStr: str, inProcessNameWOExeStr: str) → str[исходный код]
      -

      Remove Manual flag from process (if exists) - it will allow the schedule operations via def StatusCheckStart(self): def StatusCheckStorForce(self): def StatusCheckStopSafe(self):

      -
      -
      Параметры
      -
        -
      • inAgentHostNameStr – Agent hostname in any case. Required to identify Process

      • -
      • inAgentUserNameStr – Agent user name in any case. Required to identify Process

      • -
      • inProcessNameWOExeStr – The process name without extension .exe (the key of the Process instance). Any case - will be processed to the upper case

      • -
      -
      -
      Результат
      -

      Process status. See self.mStatusStr. -Process instance has the following statuses: -- 0_STOPPED -- 1_STOPPED_MANUAL -- 2_STOP_SAFE -- 3_STOP_SAFE_MANUAL -- 4_STARTED -- 5_STARTED_MANUAL -- None (if Process instance not exists)

      -
      -
      -
      - -
      -
      -pyOpenRPA.Orchestrator.Managers.Process.ProcessManualStopListClear(inAgentHostNameStr: str, inAgentUserNameStr: str, inProcessNameWOExeStr: str) → None[исходный код]
      -

      Clear the last start tries list.

      -
      -
      Параметры
      -
        -
      • inAgentHostNameStr – Agent hostname in any case. Required to identify Process

      • -
      • inAgentUserNameStr – Agent user name in any case. Required to identify Process

      • -
      • inProcessNameWOExeStr – The process name without extension .exe (the key of the Process instance). Any case - will be processed to the upper case

      • -
      -
      -
      Результат
      -

      None

      -
      -
      -
      - -
      -
      -pyOpenRPA.Orchestrator.Managers.Process.ProcessManualStopTriggerSet(inAgentHostNameStr: str, inAgentUserNameStr: str, inProcessNameWOExeStr: str, inMSTdTSecFloat: float, inMSTdNInt: int) → None[исходный код]
      -

      Remove Manual flag from process (if exists) - it will allow the schedule operations via def StatusCheckStart(self): def StatusCheckStorForce(self): def StatusCheckStopSafe(self):

      -
      -
      Параметры
      -
        -
      • inAgentHostNameStr – Agent hostname in any case. Required to identify Process

      • -
      • inAgentUserNameStr – Agent user name in any case. Required to identify Process

      • -
      • inProcessNameWOExeStr – The process name without extension .exe (the key of the Process instance). Any case - will be processed to the upper case

      • -
      • inMSTdTSecFloat – Time periods in seconds

      • -
      • inMSTdNInt – Counts of the start tries

      • -
      -
      -
      Результат
      -

      None

      -
      -
      -
      - -
      -
      -pyOpenRPA.Orchestrator.Managers.Process.ProcessScheduleStatusCheckEverySeconds(inAgentHostNameStr: str, inAgentUserNameStr: str, inProcessNameWOExeStr: str, inIntervalSecondsInt: int = 120)[исходный код]
      -

      Run status check every interval in second you specify.

      -
      -
      Параметры
      -
        -
      • inAgentHostNameStr – Agent hostname in any case. Required to identify Process

      • -
      • inAgentUserNameStr – Agent user name in any case. Required to identify Process

      • -
      • inProcessNameWOExeStr – The process name without extension .exe (the key of the Process instance). Any case - will be processed to the upper case

      • -
      • inIntervalSecondsInt – Interval in seconds. Default is 120

      • -
      -
      -
      Результат
      -

      None

      -
      -
      -
      - -
      -
      -pyOpenRPA.Orchestrator.Managers.Process.ProcessStart(inAgentHostNameStr: str, inAgentUserNameStr: str, inProcessNameWOExeStr: str, inIsManualBool: bool = True) → str[исходный код]
      -

      Manual/Auto start. Manual start will block scheduling execution. To return schedule execution use def Manual2Auto

      -
      -
      Параметры
      -
        -
      • inAgentHostNameStr – Agent hostname in any case. Required to identify Process

      • -
      • inAgentUserNameStr – Agent user name in any case. Required to identify Process

      • -
      • inProcessNameWOExeStr – The process name without extension .exe (the key of the Process instance). Any case - will be processed to the upper case

      • -
      • inIsManualBool – Default is True - Mark this operation as manual - StatusCheckStart/Stop will be blocked - only StatusCheck will be working. False - Auto operation

      • -
      -
      -
      Результат
      -

      Process status. See self.mStatusStr. -Process instance has the following statuses: -- 0_STOPPED -- 1_STOPPED_MANUAL -- 2_STOP_SAFE -- 3_STOP_SAFE_MANUAL -- 4_STARTED -- 5_STARTED_MANUAL -- None (if Process instance not exists)

      -
      -
      -
      - -
      -
      -pyOpenRPA.Orchestrator.Managers.Process.ProcessStatusCheck(inAgentHostNameStr: str, inAgentUserNameStr: str, inProcessNameWOExeStr: str) → str[исходный код]
      -

      Check if process is alive. The def will save the manual flag is exists.

      -
      -
      Параметры
      -
        -
      • inAgentHostNameStr – Agent hostname in any case. Required to identify Process

      • -
      • inAgentUserNameStr – Agent user name in any case. Required to identify Process

      • -
      • inProcessNameWOExeStr – The process name without extension .exe (the key of the Process instance). Any case - will be processed to the upper case

      • -
      -
      -
      Результат
      -

      Process status. See self.mStatusStr. -Process instance has the following statuses: -- 0_STOPPED -- 1_STOPPED_MANUAL -- 2_STOP_SAFE -- 3_STOP_SAFE_MANUAL -- 4_STARTED -- 5_STARTED_MANUAL -- None (if Process instance not exists)

      -
      -
      -
      - -
      -
      -pyOpenRPA.Orchestrator.Managers.Process.ProcessStatusRestore(inAgentHostNameStr: str, inAgentUserNameStr: str, inProcessNameWOExeStr: str)[исходный код]
      -

      Execute the StatusCheck, after that restore status to the saved state (see StatusSave). Work when orchestrator is restarted.

      -
      -
      Результат
      -

      Process status. See self.mStatusStr. 0_STOPPED 1_STOPPED_MANUAL 2_STOP_SAFE 3_STOP_SAFE_MANUAL 4_STARTED 5_STARTED_MANUAL

      -
      -
      -
      - -
      -
      -pyOpenRPA.Orchestrator.Managers.Process.ProcessStatusSave(inAgentHostNameStr: str, inAgentUserNameStr: str, inProcessNameWOExeStr: str)[исходный код]
      -

      Save current status of the process. After that you can restore process activity. Work when orchestrator is restarted. Don’t save «STOP_SAFE» status > «STOPPED»

      -
      -
      Результат
      -

      Process status. See self.mStatusStr. 0_STOPPED 1_STOPPED_MANUAL 2_STOP_SAFE 3_STOP_SAFE_MANUAL 4_STARTED 5_STARTED_MANUAL

      -
      -
      -
      - -
      -
      -pyOpenRPA.Orchestrator.Managers.Process.ProcessStatusStrGet(inAgentHostNameStr: str, inAgentUserNameStr: str, inProcessNameWOExeStr: str) → str[исходный код]
      -

      Get the status of the Process instance.

      -
      -
      Параметры
      -
        -
      • inAgentHostNameStr – Agent hostname in any case. Required to identify Process

      • -
      • inAgentUserNameStr – Agent user name in any case. Required to identify Process

      • -
      • inProcessNameWOExeStr – The process name without extension .exe (the key of the Process instance). Any case - will be processed to the upper case

      • -
      -
      -
      Результат
      -

      Process status. See self.mStatusStr. -Process instance has the following statuses: -- 0_STOPPED -- 1_STOPPED_MANUAL -- 2_STOP_SAFE -- 3_STOP_SAFE_MANUAL -- 4_STARTED -- 5_STARTED_MANUAL -- None (if Process instance not exists)

      -
      -
      -
      - -
      -
      -pyOpenRPA.Orchestrator.Managers.Process.ProcessStopForce(inAgentHostNameStr: str, inAgentUserNameStr: str, inProcessNameWOExeStr: str, inIsManualBool: bool = True) → str[исходный код]
      -

      Manual/Auto stop force. Force stop dont wait process termination - it just terminate process now. -Manual stop safe will block scheduling execution. To return schedule execution use def Manual2Auto

      -
      -
      Параметры
      -
        -
      • inAgentHostNameStr – Agent hostname in any case. Required to identify Process

      • -
      • inAgentUserNameStr – Agent user name in any case. Required to identify Process

      • -
      • inProcessNameWOExeStr – The process name without extension .exe (the key of the Process instance). Any case - will be processed to the upper case

      • -
      • inIsManualBool – Default is True - Mark this operation as manual - StatusCheckStart/Stop will be blocked - only StatusCheck will be working. False - Auto operation

      • -
      -
      -
      Результат
      -

      Process status. See self.mStatusStr. -Process instance has the following statuses: -- 0_STOPPED -- 1_STOPPED_MANUAL -- 2_STOP_SAFE -- 3_STOP_SAFE_MANUAL -- 4_STARTED -- 5_STARTED_MANUAL -- None (if Process instance not exists)

      -
      -
      -
      - -
      -
      -pyOpenRPA.Orchestrator.Managers.Process.ProcessStopSafe(inAgentHostNameStr: str, inAgentUserNameStr: str, inProcessNameWOExeStr: str, inIsManualBool: bool = True, inStopSafeTimeoutSecFloat=None) → str[исходный код]
      -

      Manual/Auto stop safe. Stop safe is the operation which send signal to process to terminate own work (send term signal to process). Managers.Process wait for the mStopSafeTimeoutSecFloat seconds. After that, if process is not terminated - self will StopForce it. -Manual stop safe will block scheduling execution. To return schedule execution use def Manual2Auto

      -
      -
      Параметры
      -
        -
      • inAgentHostNameStr – Agent hostname in any case. Required to identify Process

      • -
      • inAgentUserNameStr – Agent user name in any case. Required to identify Process

      • -
      • inProcessNameWOExeStr – The process name without extension .exe (the key of the Process instance). Any case - will be processed to the upper case

      • -
      • inIsManualBool – Default is True - Mark this operation as manual - StatusCheckStart/Stop will be blocked - only StatusCheck will be working. False - Auto operation

      • -
      • inStopSafeTimeoutSecFloat – Default value goes from the instance. You can specify time is second to wait while safe stop. After that program will stop force

      • -
      -
      -
      Результат
      -

      Process status. See self.mStatusStr. -Process instance has the following statuses: -- 0_STOPPED -- 1_STOPPED_MANUAL -- 2_STOP_SAFE -- 3_STOP_SAFE_MANUAL -- 4_STARTED -- 5_STARTED_MANUAL -- None (if Process instance not exists)

      -
      -
      -
      - -
      -
      -

      ControlPanel (General)

      -
      # EXAMPLE
      -from pyOpenRPA.Orchestrator import Orchestrator
      -    lCP = Orchestrator.Managers.ControlPanel(inControlPanelNameStr="TestTTT",inRefreshHTMLJinja2TemplatePathStr="ControlPanel\\test.html", inJinja2TemplateRefreshBool = True)
      -
      -
      -

      Classes:

      - ---- - - - - - -

      ControlPanel(inControlPanelNameStr[, …])

      Manage your control panel on the orchestrator

      -
      -
      -class pyOpenRPA.Orchestrator.Managers.ControlPanel.ControlPanel(inControlPanelNameStr, inRefreshHTMLJinja2TemplatePathStr=None, inJinja2TemplateRefreshBool=False, inRobotNameStr=None)[исходный код]
      -

      Manage your control panel on the orchestrator

      -

      Control panel has 3 events types: -- onRefreshHTML - run every n (see settings) second to detect changes in HTML control panel. -- onRefreshJSON - run every n (see settings) second to detect changes in JSON data container to client side. -- onInitJS - run when client reload the Orchestrator web page

      -
      # Usage example:
      -lCPManager = Orchestrator.Managers.ControlPanel(inControlPanelNameStr="TestControlPanel",
      -    inRefreshHTMLJinja2TemplatePathStr="ControlPanel\test.html", inJinja2TemplateRefreshBool = True)
      -
      -
      -

      If you use Jinja2 you can use next data context: -StorageRobotDict: Orchestrator.StorageRobotGet(inRobotNameStr=self.mRobotNameStr), -ControlPanelInstance: self, -OrchestratorModule:Orchestrator, -RequestInstance: inRequest, -UserInfoDict: Orchestrator.WebUserInfoGet(inRequest=inRequest), -UserUACDict: Orchestrator.UACUserDictGet(inRequest=inRequest), -UserUACCheckDef: inRequest.UACClientCheck, -EnumerateDef: enumerate, -OperatorModule: operator, -MathModule: math

      -

      You can modify jinja context by use the function: -Jinja2DataUpdateDictSet

      -

      Methods:

      - ---- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

      DataDictGenerate(inRequest)

      -
      param inRequest
      -

      request handler (from http.server import BaseHTTPRequestHandler)

      -
      -
      -

      InitJSJinja2StrGenerate(inDataDict)

      Generate the HTML str from the Jinja2.

      InitJSJinja2TemplatePathSet(…)

      Create Jinja2 env and load the template html

      Jinja2DataUpdateDictSet(inJinja2DataUpdateDict)

      Set the data dict from the Jinja2 context (you can add some new params)

      OnInitJSDataDict(inRequest)

      Event to prepare data context for the futher Jinja2 JS init generation.

      OnInitJSStr(inRequest)

      Event when orchestrator web page is init on the client side - you can transmit some java script code is str type to execute it once.

      OnRefreshHTMLDataDict(inRequest)

      Event to prepare data context for the futher Jinja2 HTML generation.

      OnRefreshHTMLHashStr(inRequest)

      Generate the hash the result output HTML.

      OnRefreshHTMLStr(inRequest)

      Event to generate HTML code of the control panel when refresh time is over.

      OnRefreshJSONDict(inRequest)

      Event to transmit some data from server side to the client side in JSON format.

      RefreshHTMLJinja2StrGenerate(inDataDict)

      Generate the HTML str from the Jinja2.

      RefreshHTMLJinja2TemplatePathSet(…)

      Create Jinja2 env and load the template html

      -
      -
      -DataDictGenerate(inRequest)[исходный код]
      -
      -
      Параметры
      -

      inRequest – request handler (from http.server import BaseHTTPRequestHandler)

      -
      -
      Результат
      -

      -
      -
      -
      - -
      -
      -InitJSJinja2StrGenerate(inDataDict)[исходный код]
      -

      Generate the HTML str from the Jinja2. Pass the context inDataDict -:param inDataDict: -:return:

      -
      - -
      -
      -InitJSJinja2TemplatePathSet(inJinja2TemplatePathStr)[исходный код]
      -

      Create Jinja2 env and load the template html

      -
      -
      Параметры
      -

      inJinja2TemplatePathStr

      -
      -
      Результат
      -

      -
      -
      -
      - -
      -
      -Jinja2DataUpdateDictSet(inJinja2DataUpdateDict)[исходный код]
      -

      Set the data dict from the Jinja2 context (you can add some new params)

      -
      -
      Параметры
      -

      inJinja2DataUpdateDict – dict, which will be appended to main data context

      -
      -
      Результат
      -

      None

      -
      -
      -
      - -
      -
      -OnInitJSDataDict(inRequest)[исходный код]
      -

      Event to prepare data context for the futher Jinja2 JS init generation. You can override this def if you want some thing more data

      -
      -
      Параметры
      -

      inRequest – request handler (from http.server import BaseHTTPRequestHandler)

      -
      -
      Результат
      -

      dict

      -
      -
      -
      - -
      -
      -OnInitJSStr(inRequest)[исходный код]
      -

      Event when orchestrator web page is init on the client side - you can transmit some java script code is str type to execute it once.

      -
      -
      Параметры
      -

      inRequest – request handler (from http.server import BaseHTTPRequestHandler)

      -
      -
      Результат
      -

      »»

      -

      -
      -
      -
      - -
      -
      -OnRefreshHTMLDataDict(inRequest)[исходный код]
      -

      Event to prepare data context for the futher Jinja2 HTML generation. You can override this def if you want some thing more data

      -
      -
      Параметры
      -

      inRequest – request handler (from http.server import BaseHTTPRequestHandler)

      -
      -
      Результат
      -

      dict

      -
      -
      -
      - -
      -
      -OnRefreshHTMLHashStr(inRequest)[исходный код]
      -

      Generate the hash the result output HTML. You can override this function if you know how to optimize HTML rendering. -TODO NEED TO MODIFY ServerSettings to work with Hash because of all defs are need do use Hash

      -
      -
      Параметры
      -

      inRequest – request handler (from http.server import BaseHTTPRequestHandler)

      -
      -
      Результат
      -

      None - default, hash function is not determined. Str - hash function is working on!

      -
      -
      -
      - -
      -
      -OnRefreshHTMLStr(inRequest)[исходный код]
      -

      Event to generate HTML code of the control panel when refresh time is over. -Support backward compatibility for previous versions.

      -
      -
      Параметры
      -

      inRequest – request handler (from http.server import BaseHTTPRequestHandler)

      -
      -
      Результат
      -

      -
      -
      -
      - -
      -
      -OnRefreshJSONDict(inRequest)[исходный код]
      -

      Event to transmit some data from server side to the client side in JSON format. Call when page refresh is initialized

      -
      -
      Параметры
      -

      inRequest – request handler (from http.server import BaseHTTPRequestHandler)

      -
      -
      Результат
      -

      Dict type

      -
      -
      -
      - -
      -
      -RefreshHTMLJinja2StrGenerate(inDataDict)[исходный код]
      -

      Generate the HTML str from the Jinja2. Pass the context inDataDict -:param inDataDict: -:return:

      -
      - -
      -
      -RefreshHTMLJinja2TemplatePathSet(inJinja2TemplatePathStr)[исходный код]
      -

      Create Jinja2 env and load the template html

      -
      -
      Параметры
      -

      inJinja2TemplatePathStr

      -
      -
      Результат
      -

      -
      -
      -
      - -
      - -
      -
      -

      ControlPanel (Details)

      -

      Classes:

      - ---- - - - - - -

      ControlPanel(inControlPanelNameStr[, …])

      Manage your control panel on the orchestrator

      -
      -
      -class pyOpenRPA.Orchestrator.Managers.ControlPanel.ControlPanel(inControlPanelNameStr, inRefreshHTMLJinja2TemplatePathStr=None, inJinja2TemplateRefreshBool=False, inRobotNameStr=None)[исходный код]
      -

      Manage your control panel on the orchestrator

      -

      Control panel has 3 events types: -- onRefreshHTML - run every n (see settings) second to detect changes in HTML control panel. -- onRefreshJSON - run every n (see settings) second to detect changes in JSON data container to client side. -- onInitJS - run when client reload the Orchestrator web page

      -
      # Usage example:
      -lCPManager = Orchestrator.Managers.ControlPanel(inControlPanelNameStr="TestControlPanel",
      -    inRefreshHTMLJinja2TemplatePathStr="ControlPanel\test.html", inJinja2TemplateRefreshBool = True)
      -
      -
      -

      If you use Jinja2 you can use next data context: -StorageRobotDict: Orchestrator.StorageRobotGet(inRobotNameStr=self.mRobotNameStr), -ControlPanelInstance: self, -OrchestratorModule:Orchestrator, -RequestInstance: inRequest, -UserInfoDict: Orchestrator.WebUserInfoGet(inRequest=inRequest), -UserUACDict: Orchestrator.UACUserDictGet(inRequest=inRequest), -UserUACCheckDef: inRequest.UACClientCheck, -EnumerateDef: enumerate, -OperatorModule: operator, -MathModule: math

      -

      You can modify jinja context by use the function: -Jinja2DataUpdateDictSet

      -

      Methods:

      - ---- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

      DataDictGenerate(inRequest)

      -
      param inRequest
      -

      request handler (from http.server import BaseHTTPRequestHandler)

      -
      -
      -

      InitJSJinja2StrGenerate(inDataDict)

      Generate the HTML str from the Jinja2.

      InitJSJinja2TemplatePathSet(…)

      Create Jinja2 env and load the template html

      Jinja2DataUpdateDictSet(inJinja2DataUpdateDict)

      Set the data dict from the Jinja2 context (you can add some new params)

      OnInitJSDataDict(inRequest)

      Event to prepare data context for the futher Jinja2 JS init generation.

      OnInitJSStr(inRequest)

      Event when orchestrator web page is init on the client side - you can transmit some java script code is str type to execute it once.

      OnRefreshHTMLDataDict(inRequest)

      Event to prepare data context for the futher Jinja2 HTML generation.

      OnRefreshHTMLHashStr(inRequest)

      Generate the hash the result output HTML.

      OnRefreshHTMLStr(inRequest)

      Event to generate HTML code of the control panel when refresh time is over.

      OnRefreshJSONDict(inRequest)

      Event to transmit some data from server side to the client side in JSON format.

      RefreshHTMLJinja2StrGenerate(inDataDict)

      Generate the HTML str from the Jinja2.

      RefreshHTMLJinja2TemplatePathSet(…)

      Create Jinja2 env and load the template html

      -
      -
      -DataDictGenerate(inRequest)[исходный код]
      -
      -
      Параметры
      -

      inRequest – request handler (from http.server import BaseHTTPRequestHandler)

      -
      -
      Результат
      -

      -
      -
      -
      - -
      -
      -InitJSJinja2StrGenerate(inDataDict)[исходный код]
      -

      Generate the HTML str from the Jinja2. Pass the context inDataDict -:param inDataDict: -:return:

      -
      - -
      -
      -InitJSJinja2TemplatePathSet(inJinja2TemplatePathStr)[исходный код]
      -

      Create Jinja2 env and load the template html

      -
      -
      Параметры
      -

      inJinja2TemplatePathStr

      -
      -
      Результат
      -

      -
      -
      -
      - -
      -
      -Jinja2DataUpdateDictSet(inJinja2DataUpdateDict)[исходный код]
      -

      Set the data dict from the Jinja2 context (you can add some new params)

      -
      -
      Параметры
      -

      inJinja2DataUpdateDict – dict, which will be appended to main data context

      -
      -
      Результат
      -

      None

      -
      -
      -
      - -
      -
      -OnInitJSDataDict(inRequest)[исходный код]
      -

      Event to prepare data context for the futher Jinja2 JS init generation. You can override this def if you want some thing more data

      -
      -
      Параметры
      -

      inRequest – request handler (from http.server import BaseHTTPRequestHandler)

      -
      -
      Результат
      -

      dict

      -
      -
      -
      - -
      -
      -OnInitJSStr(inRequest)[исходный код]
      -

      Event when orchestrator web page is init on the client side - you can transmit some java script code is str type to execute it once.

      -
      -
      Параметры
      -

      inRequest – request handler (from http.server import BaseHTTPRequestHandler)

      -
      -
      Результат
      -

      »»

      -

      -
      -
      -
      - -
      -
      -OnRefreshHTMLDataDict(inRequest)[исходный код]
      -

      Event to prepare data context for the futher Jinja2 HTML generation. You can override this def if you want some thing more data

      -
      -
      Параметры
      -

      inRequest – request handler (from http.server import BaseHTTPRequestHandler)

      -
      -
      Результат
      -

      dict

      -
      -
      -
      - -
      -
      -OnRefreshHTMLHashStr(inRequest)[исходный код]
      -

      Generate the hash the result output HTML. You can override this function if you know how to optimize HTML rendering. -TODO NEED TO MODIFY ServerSettings to work with Hash because of all defs are need do use Hash

      -
      -
      Параметры
      -

      inRequest – request handler (from http.server import BaseHTTPRequestHandler)

      -
      -
      Результат
      -

      None - default, hash function is not determined. Str - hash function is working on!

      -
      -
      -
      - -
      -
      -OnRefreshHTMLStr(inRequest)[исходный код]
      -

      Event to generate HTML code of the control panel when refresh time is over. -Support backward compatibility for previous versions.

      -
      -
      Параметры
      -

      inRequest – request handler (from http.server import BaseHTTPRequestHandler)

      -
      -
      Результат
      -

      -
      -
      -
      - -
      -
      -OnRefreshJSONDict(inRequest)[исходный код]
      -

      Event to transmit some data from server side to the client side in JSON format. Call when page refresh is initialized

      -
      -
      Параметры
      -

      inRequest – request handler (from http.server import BaseHTTPRequestHandler)

      -
      -
      Результат
      -

      Dict type

      -
      -
      -
      - -
      -
      -RefreshHTMLJinja2StrGenerate(inDataDict)[исходный код]
      -

      Generate the HTML str from the Jinja2. Pass the context inDataDict -:param inDataDict: -:return:

      -
      - -
      -
      -RefreshHTMLJinja2TemplatePathSet(inJinja2TemplatePathStr)[исходный код]
      -

      Create Jinja2 env and load the template html

      -
      -
      Параметры
      -

      inJinja2TemplatePathStr

      -
      -
      Результат
      -

      -
      -
      -
      - -
      - -

      .. v1.2.12 replace:: v1.2.12 - .. |author| replace:: Ivan Maslov <ivan.maslov@unicodelabs.ru>

      -

      -
      -
      - - -
      - -
      - -
      -
      - -
      - -
      - - - - - - - - - - - \ No newline at end of file diff --git a/Wiki/RUS_Guide/html/Robot/01_Robot.html b/Wiki/RUS_Guide/html/Robot/01_Robot.html index 950f00c5..1067be8c 100644 --- a/Wiki/RUS_Guide/html/Robot/01_Robot.html +++ b/Wiki/RUS_Guide/html/Robot/01_Robot.html @@ -41,8 +41,8 @@ - - + + @@ -91,20 +91,23 @@

      МОДУЛЬ РОБОТ

      МОДУЛЬ СТУДИЯ

        @@ -113,20 +116,19 @@

      МОДУЛЬ ОРКЕСТРАТОР

      МОДУЛЬ АГЕНТ

      ИНСТРУМЕНТЫ

      @@ -196,29 +198,38 @@

      1. Описание

      +
      +

      Общее

      Модуль обеспечивает всю необходимую функциональность для создания любого программного робота RPA. Модуль робота поставляется в качестве библиотеки Python, что позволяет с легкостью интегрировать его в другие проекты перспективных технологий.

      Содержит

        -
      • Уровень доступа к элементам локального приложения (win32, UI automation), и веб приложения

        +
      • Уровень доступа к элементам локального приложения (win32, UI automation), и веб приложения

          -
        • UIDesktop: инструменты взаимодействия с элементами локального приложения (взаимодействие с ОС через протоколы win32, UI automation). Перейти к описанию функций: 2. UIDesktop

        • -
        • UIWeb: инструменты взаимодействия с элементами веб приложения. Перейти к описанию функций: 3. UIWeb

        • +
        • UIDesktop: инструменты взаимодействия с элементами локального приложения (взаимодействие с ОС через протоколы win32, UI automation). Перейти к описанию функций: 2. Функции UIDesktop

        • +
        • UIWeb: инструменты взаимодействия с элементами веб приложения. Перейти к описанию функций: 3. Функции UIWeb

      • -
      • Уровень доступа к текстовым каналам передачи данных (клавиатура, буфер обмена)

        +
      • Уровень доступа к текстовым каналам передачи данных (клавиатура, буфер обмена)

          -
        • Keyboard: инструменты взаимодействия с клавиатурой. Перейти к описанию функций: 4. Keyboard

        • -
        • Clipboard: инструменты взаимодействия с буфером обмена. Перейти к описанию функций: 5. Clipboard

        • +
        • Keyboard: инструменты взаимодействия с клавиатурой. Перейти к описанию функций: 4. Функции Keyboard

        • +
        • Clipboard: инструменты взаимодействия с буфером обмена. Перейти к описанию функций: 5. Функции Clipboard

      • -
      • Уровень доступа к графическим каналам передачи данных (мышь, экран)

        +
      • Уровень доступа к графическим каналам передачи данных (мышь, экран)

          -
        • Mouse: инструменты взаимодействия с мышью. Перейти к описанию функций: 6. Mouse

        • -
        • Image: инструменты взаимодействия с эраном рабочего стола. Перейти к описанию функций: 7. Image

        • +
        • Mouse: инструменты взаимодействия с мышью. Перейти к описанию функций: 6. Функции Mouse

        • +
        • Image: инструменты взаимодействия с эраном рабочего стола. Перейти к описанию функций: 7. Функции Image

      -

      Ниже преставлен пример использования инструментов робота.

      +

      Дорогие коллеги!

      +

      Мы знаем, что с pyOpenRPA вы сможете существенно улучшить качество вашего бизнеса. Платформа роботизации pyOpenRPA - это разработка, которая дает возможность делать виртуальных сотрудников (программных роботов RPA) выгодными, начиная от эффекта всего в 10 тыс. руб. И управлять ими будете только Вы!

      +

      Если у вас останутся вопросы, то вы всегда можете обратиться в центр поддержки клиентов pyOpenRPA. Контакты: 2. Лицензия & Контакты

      +

      pyOpenRPA - роботы помогут!

      +
      +
      +

      Примеры

      +

      Ниже преставлен пример использования инструментов робота.

      import time
       from pyOpenRPA.Robot import UIDesktop
       
      @@ -304,9 +315,20 @@
       Mouse.mouseUp()
       
      -

      .. v1.2.12 replace:: v1.2.12 - .. |author| replace:: Ivan Maslov <ivan.maslov@unicodelabs.ru>

      +
      +
      @@ -315,8 +337,8 @@

      diff --git a/Wiki/RUS_Guide/html/Robot/02_Defs.html b/Wiki/RUS_Guide/html/Robot/02_Defs.html deleted file mode 100644 index 3eb75ba3..00000000 --- a/Wiki/RUS_Guide/html/Robot/02_Defs.html +++ /dev/null @@ -1,710 +0,0 @@ - - - - - - - - - - 2. Функции — документация pyOpenRPA v1.2.12 v1.2.12 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
      - - - -
      - - - - - -
      - -
      - - - - - - - - - - - - - - - - - - - -
      - - - - -
      -
      -
      -
      - -
      -

      2. Функции

      -

      Here you can find the functions description for interaction with desktop GUI applications

      -

      How to use both x32 and x64 python processes (it can be helpfully, if another app GUI is on another bitness than your app)

      -
      from pyOpenRPA.Robot import UIDesktop
      -#Section for robot init
      -lPyOpenRPA_SettingsDict = {
      -        "Python32FullPath": "..\\Resources\\WPy32-3720\\python-3.7.2\\python.exe", #Set from user: "..\\Resources\\WPy32-3720\\python-3.7.2\\OpenRPARobotGUIx32.exe"
      -        "Python64FullPath": "..\\Resources\\WPy64-3720\\python-3.7.2.amd64\\python.exe", #Set from user
      -        "Python32ProcessName": "pyOpenRPA_UIDesktopX32.exe", #Config set once
      -        "Python64ProcessName": "pyOpenRPA_UIDesktopX64.exe" #Config set once
      -}
      -# Init the pyOpenRPA configuration
      -UIDesktop.Utils.ProcessBitness.SettingsInit(lPyOpenRPA_SettingsDict)
      -# Now you can use pyOpenRPA with both bitness.
      -
      -
      -

      Functions:

      - ---- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

      Get_OSBitnessInt()

      Detect OS bitness.

      PWASpecification_Get_PWAApplication(…)

      #Backend selection - attribute «backend» («win32» || «uia») in 1-st list element

      PWASpecification_Get_UIO(…)

      #Backend def selection - attribute «backend» («win32» || «uia») in 1-st list element #old name - GetControl

      UIOSelectorSecs_WaitAppear_Bool(…)

      Wait for UI object will appear in GUI for inWaitSecs seconds.

      UIOSelectorSecs_WaitDisappear_Bool(…)

      Wait for UI object will disappear in GUI for inWaitSecs seconds.

      UIOSelectorUIOActivity_Run_Dict(…[, …])

      Run the activity in UIO (UI Object)

      UIOSelector_Exist_Bool(inUIOSelector)

      Check if object is exist by the UIO selector.

      UIOSelector_FocusHighlight(inUIOSelector)

      Set focus and highlight (draw outline) the element (in app) by the UIO selector.

      UIOSelector_GetChildList_UIOList([…])

      Get list of child UIO’s by the parent UIOSelector

      UIOSelector_Get_BitnessInt(inSpecificationList)

      Detect process bitness by the UI Object UIO Selector.

      UIOSelector_Get_BitnessStr(inSpecificationList)

      Detect process bitness by the UI Object UIO Selector.

      UIOSelector_Get_UIO(inSpecificationList[, …])

      Get the pywinauto object by the UIO selector.

      UIOSelector_Get_UIOActivityList(inUIOSelector)

      Get the list of the UI object activities

      UIOSelector_Get_UIOInfo(inUIOSelector)

      Get the UIO dict of the attributes

      UIOSelector_Get_UIOList(inSpecificationList)

      Get the UIO list by the selector

      UIOSelector_Highlight(inUIOSelector)

      Highlight (draw outline) the element (in app) by the UIO selector.

      UIOSelector_SafeOtherGet_Process(inUIOSelector)

      Safe get other process or None if destination app is the other/same bitness

      UIOSelector_SearchChildByMouse_UIO(…)

      UIOSelector (see description on the top of the document) #old name - AutomationSearchMouseElement

      UIOSelector_SearchChildByMouse_UIOTree(…)

      !!!!Safe call is included (you can set activity and UIDesktop will choose the bitness and return the result)!!!!!

      UIOSelector_TryRestore_Dict(inSpecificationList)

      Try to restore (maximize) window, if it’s minimized.

      UIOSelectorsSecs_WaitAppear_List(…[, …])

      Wait for many UI object will appear in GUI for inWaitSecs seconds.

      UIOSelectorsSecs_WaitDisappear_List(…[, …])

      Wait for many UI object will disappear in GUI for inWaitSecs seconds.

      -
      -
      -pyOpenRPA.Robot.UIDesktop.Get_OSBitnessInt()[исходный код]
      -

      Detect OS bitness.

      -
      -
      Результат
      -

      int 32 or int 64

      -
      -
      -
      - -
      -
      -pyOpenRPA.Robot.UIDesktop.PWASpecification_Get_PWAApplication(inControlSpecificationArray)[исходный код]
      -

      #Backend selection - attribute «backend» («win32» || «uia») in 1-st list element

      -
      -
      Параметры
      -

      inControlSpecificationArray – List of dict, dict in pywinauto.find_windows notation

      -
      -
      Результат
      -

      process application object

      -
      -
      -
      - -
      -
      -pyOpenRPA.Robot.UIDesktop.PWASpecification_Get_UIO(inControlSpecificationArray)[исходный код]
      -

      #Backend def selection - attribute «backend» («win32» || «uia») in 1-st list element -#old name - GetControl

      -
      -
      Параметры
      -

      inControlSpecificationArray – List of dict, dict in pywinauto.find_windows notation

      -
      -
      Результат
      -

      list of UIO object

      -
      -
      -
      - -
      -
      -pyOpenRPA.Robot.UIDesktop.UIOSelectorSecs_WaitAppear_Bool(inSpecificationList, inWaitSecs)[исходный код]
      -

      Wait for UI object will appear in GUI for inWaitSecs seconds.

      -
      -
      Параметры
      -
        -
      • inSpecificationList – UIOSelector. Example: [{«title»:»notepad»},{«title»:»OK»}]

      • -
      • inWaitSecs – Float value (seconds) for wait UI element appear in GUI

      • -
      -
      -
      Результат
      -

      True - UI object will appear. False - else case

      -
      -
      -
      - -
      -
      -pyOpenRPA.Robot.UIDesktop.UIOSelectorSecs_WaitDisappear_Bool(inSpecificationList, inWaitSecs)[исходный код]
      -

      Wait for UI object will disappear in GUI for inWaitSecs seconds.

      -
      -
      Параметры
      -
        -
      • inSpecificationList – UIOSelector. -Example: [{«title»:»notepad»},{«title»:»OK»}]

      • -
      • inWaitSecs – Float value (seconds) for wait UI element disappear in GUI

      • -
      -
      -
      Результат
      -

      True - UI object will disappear. False - else case

      -
      -
      -
      - -
      -
      -pyOpenRPA.Robot.UIDesktop.UIOSelectorUIOActivity_Run_Dict(inUIOSelector, inActionName, inArgumentList=None, inkwArgumentObject=None)[исходный код]
      -

      Run the activity in UIO (UI Object)

      -
      -
      Параметры
      -
        -
      • inUIOSelector – UIOSelector - List of items, which contains condition attributes

      • -
      • inActionName – UIOActivity (name) activity name string from Pywinauto

      • -
      • inArgumentList

      • -
      • inkwArgumentObject

      • -
      -
      -
      Результат
      -

      -
      -
      -
      - -
      -
      -pyOpenRPA.Robot.UIDesktop.UIOSelector_Exist_Bool(inUIOSelector)[исходный код]
      -

      Check if object is exist by the UIO selector.

      -
      -
      Параметры
      -

      inUIOSelector

      -
      -
      Результат
      -

      True - Object is exist. False - else case

      -
      -
      -
      - -
      -
      -pyOpenRPA.Robot.UIDesktop.UIOSelector_FocusHighlight(inUIOSelector)[исходный код]
      -

      Set focus and highlight (draw outline) the element (in app) by the UIO selector.

      -
      -
      Параметры
      -

      inUIOSelector – UIOSelector - List of items, which contains condition attributes

      -
      -
      Результат
      -

      -
      -
      -
      - -
      -
      -pyOpenRPA.Robot.UIDesktop.UIOSelector_GetChildList_UIOList(inUIOSelector=None, inBackend='win32')[исходный код]
      -

      Get list of child UIO’s by the parent UIOSelector

      -
      -
      Параметры
      -
        -
      • inUIOSelector – UIOSelector - List of items, which contains condition attributes

      • -
      • inBackend – «win32» or «uia»

      • -
      -
      -
      Результат
      -

      -
      -
      -
      - -
      -
      -pyOpenRPA.Robot.UIDesktop.UIOSelector_Get_BitnessInt(inSpecificationList)[исходный код]
      -

      Detect process bitness by the UI Object UIO Selector.

      -
      -
      Параметры
      -

      inSpecificationList – UIOSelector. Example: [{«title»:»notepad»},{«title»:»OK»}]

      -
      -
      Результат
      -

      int 32 or int 64

      -
      -
      -
      - -
      -
      -pyOpenRPA.Robot.UIDesktop.UIOSelector_Get_BitnessStr(inSpecificationList)[исходный код]
      -

      Detect process bitness by the UI Object UIO Selector.

      -
      -
      Параметры
      -

      inSpecificationList – UIOSelector. Example: [{«title»:»notepad»},{«title»:»OK»}]

      -
      -
      Результат
      -

      str «32» or str «64»

      -
      -
      -
      - -
      -
      -pyOpenRPA.Robot.UIDesktop.UIOSelector_Get_UIO(inSpecificationList, inElement=None, inFlagRaiseException=True)[исходный код]
      -

      Get the pywinauto object by the UIO selector.

      -
      -
      Параметры
      -
        -
      • inSpecificationList

      • -
      • inElement

      • -
      • inFlagRaiseException

      • -
      -
      -
      Результат
      -

      -
      -
      -
      - -
      -
      -pyOpenRPA.Robot.UIDesktop.UIOSelector_Get_UIOActivityList(inUIOSelector)[исходный код]
      -

      Get the list of the UI object activities

      -
      -
      Параметры
      -

      inUIOSelector – UIOSelector - List of items, which contains condition attributes

      -
      -
      Результат
      -

      -
      -
      -
      - -
      -
      -pyOpenRPA.Robot.UIDesktop.UIOSelector_Get_UIOInfo(inUIOSelector)[исходный код]
      -

      Get the UIO dict of the attributes

      -
      -
      Параметры
      -

      inUIOSelector – UIOSelector - List of items, which contains condition attributes

      -
      -
      Результат
      -

      -
      -
      -
      - -
      -
      -pyOpenRPA.Robot.UIDesktop.UIOSelector_Get_UIOList(inSpecificationList, inElement=None, inFlagRaiseException=True)[исходный код]
      -

      Get the UIO list by the selector

      -
      -
      Параметры
      -
        -
      • inSpecificationList – UIO Selector

      • -
      • inElement – Входной элемент - показатель, что не требуется выполнять коннект к процессу

      • -
      • inFlagRaiseException – Флаг True - выкинуть ошибку в случае обнаружении пустого списка

      • -
      -
      -
      Результат
      -

      -
      -
      -
      - -
      -
      -pyOpenRPA.Robot.UIDesktop.UIOSelector_Highlight(inUIOSelector)[исходный код]
      -

      Highlight (draw outline) the element (in app) by the UIO selector.

      -
      -
      Параметры
      -

      inUIOSelector – UIOSelector - List of items, which contains condition attributes

      -
      -
      Результат
      -

      -
      -
      -
      - -
      -
      -pyOpenRPA.Robot.UIDesktop.UIOSelector_SafeOtherGet_Process(inUIOSelector)[исходный код]
      -

      Safe get other process or None if destination app is the other/same bitness

      -
      -
      Параметры
      -

      inUIOSelector – UIO Selector of the UI object

      -
      -
      Результат
      -

      None or process (of the other bitness)

      -
      -
      -
      - -
      -
      -pyOpenRPA.Robot.UIDesktop.UIOSelector_SearchChildByMouse_UIO(inElementSpecification)[исходный код]
      -

      UIOSelector (see description on the top of the document) -#old name - AutomationSearchMouseElement

      -
      -
      Параметры
      -

      inElementSpecification – UIOSelector of the UI Object

      -
      -
      Результат
      -

      pywinauto element wrapper instance or None

      -
      -
      -
      - -
      -
      -pyOpenRPA.Robot.UIDesktop.UIOSelector_SearchChildByMouse_UIOTree(inUIOSelector)[исходный код]
      -

      !!!!Safe call is included (you can set activity and UIDesktop will choose the bitness and return the result)!!!!!

      -
      -
      Параметры
      -

      inUIOSelector – UIOSelector of the UI Object

      -
      -
      Результат
      -

      ?

      -

      -
      -
      -
      - -
      -
      -pyOpenRPA.Robot.UIDesktop.UIOSelector_TryRestore_Dict(inSpecificationList)[исходный код]
      -

      Try to restore (maximize) window, if it’s minimized. (!IMPORTANT! When use UIA framework minimized windows doesn’t appear by the UIOSelector. You need to try restore windows and after that try to get UIO)

      -
      -
      Параметры
      -

      inSpecificationList – UIOSelector - List of items, which contains condition attributes

      -
      -
      Результат
      -

      -
      -
      -
      - -
      -
      -pyOpenRPA.Robot.UIDesktop.UIOSelectorsSecs_WaitAppear_List(inSpecificationListList, inWaitSecs, inFlagWaitAllInMoment=False)[исходный код]
      -

      Wait for many UI object will appear in GUI for inWaitSecs seconds.

      -
      -
      Параметры
      -
        -
      • inSpecificationListList

        UIOSelector list. -Example: [

        -
        -

        [{«title»:»notepad»},{«title»:»OK»}], -[{«title»:»notepad»},{«title»:»Cancel»}]

        -
        -

        ]

        -

      • -
      • inWaitSecs – Float value (seconds) for wait UI element appear in GUI

      • -
      • inFlagWaitAllInMoment – True - Wait all UI objects from the UIOSelector list to be appeared

      • -
      -
      -
      Результат
      -

      List of index, which UI object UIO will be appeared. Example: [1] # Appear only UI object with UIO selector: [{«title»:»notepad»},{«title»:»Cancel»}]

      -
      -
      -
      - -
      -
      -pyOpenRPA.Robot.UIDesktop.UIOSelectorsSecs_WaitDisappear_List(inSpecificationListList, inWaitSecs, inFlagWaitAllInMoment=False)[исходный код]
      -

      Wait for many UI object will disappear in GUI for inWaitSecs seconds.

      -
      -
      Параметры
      -
        -
      • inSpecificationListList

        UIOSelector list. -Example: [

        -
        -

        [{«title»:»notepad»},{«title»:»OK»}], -[{«title»:»notepad»},{«title»:»Cancel»}]

        -
        -

        ]

        -

      • -
      • inWaitSecs – Float value (seconds) for wait UI element disappear in GUI

      • -
      • inFlagWaitAllInMoment – True - Wait all UI objects from the UIOSelector list to be disappeared.

      • -
      -
      -
      Результат
      -

      List of index, which UI object UIO will be disappeared. Example: [1] # Disappear only UI object with UIO selector: [{«title»:»notepad»},{«title»:»Cancel»}]

      -
      -
      Результат
      -

      -
      -
      -
      - -
      -

      References

      -

      reStructuredText 1

      -
      -
      1
      -

      http://docutils.sourceforge.net/rst.html

      -
      -
      -

      .. v1.2.12 replace:: v1.2.12 - .. |author| replace:: Ivan Maslov <ivan.maslov@unicodelabs.ru>

      -

      -
      -
      - - -
      - -
      - -
      -
      - -
      - -
      - - - - - - - - - - - \ No newline at end of file diff --git a/Wiki/RUS_Guide/html/Robot/02_uidesktop.html b/Wiki/RUS_Guide/html/Robot/02_uidesktop.html index 85f7697e..3555d9c3 100644 --- a/Wiki/RUS_Guide/html/Robot/02_uidesktop.html +++ b/Wiki/RUS_Guide/html/Robot/02_uidesktop.html @@ -7,7 +7,7 @@ - 2. UIDesktop — документация pyOpenRPA v1.2.12 v1.2.12 + 2. Функции UIDesktop — документация pyOpenRPA v1.2.12 v1.2.12 @@ -41,8 +41,8 @@ - - + + @@ -91,23 +91,24 @@

      МОДУЛЬ РОБОТ

      • 1. Описание
      • -
      • 2. Функции
      • -
      • 2. UIDesktop

        МОДУЛЬ СТУДИЯ

          @@ -116,20 +117,19 @@

        МОДУЛЬ ОРКЕСТРАТОР

        МОДУЛЬ АГЕНТ

        ИНСТРУМЕНТЫ

        @@ -178,7 +178,7 @@
      • »
      • -
      • 2. UIDesktop
      • +
      • 2. Функции UIDesktop
      • @@ -198,104 +198,152 @@
        -

        2. UIDesktop

        -

        Here you can find the functions description for interaction with desktop GUI applications

        -

        How to use both x32 and x64 python processes (it can be helpfully, if another app GUI is on another bitness than your app)

        -
        from pyOpenRPA.Robot import UIDesktop
        -#Section for robot init
        -lPyOpenRPA_SettingsDict = {
        -        "Python32FullPath": "..\\Resources\\WPy32-3720\\python-3.7.2\\python.exe", #Set from user: "..\\Resources\\WPy32-3720\\python-3.7.2\\OpenRPARobotGUIx32.exe"
        -        "Python64FullPath": "..\\Resources\\WPy64-3720\\python-3.7.2.amd64\\python.exe", #Set from user
        -        "Python32ProcessName": "pyOpenRPA_UIDesktopX32.exe", #Config set once
        -        "Python64ProcessName": "pyOpenRPA_UIDesktopX64.exe" #Config set once
        -}
        -# Init the pyOpenRPA configuration
        -UIDesktop.Utils.ProcessBitness.SettingsInit(lPyOpenRPA_SettingsDict)
        -# Now you can use pyOpenRPA with both bitness.
        -
        +

        2. Функции UIDesktop

        +
        +

        Общее

        +

        Здесь представлено описание всех функций, которые используются для взаимодействия с UI интерфейсами локальных приложений.

        +

        Функции в модуле UIDesktop именуются по следующему принципу: +<Входящий аргумент>_<действие>_<исходящий аргумент - если присутствует>

        +

        Термины и определения:

        +
          +
        • UIO: Объект пользовательского интерфейса

        • +
        • UIOSelector: Селектор (адрес) одного и/или более UIO объектов. Селектор представлен в формате списка (list) словарей (dict) атрибутивных критериев.

        • +
        -

        Functions:

        +
        +

        Описание функций

        +

        Functions:

        - - + + + + + + + + + + + + + + + + + + + + + + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + + + + + + +

        Get_OSBitnessInt()

        Detect OS bitness.

        BackendStr_GetTopLevelList_UIOInfo([inBackend])

        Получить список UIOInfo словарей - процессы, которые запущены в рабочей сессии и готовы для взаимодействия с роботом через backend inBackend

        Get_OSBitnessInt()

        Определить разрядность робота, в котором запускается данная функция

        PWASpecification_Get_PWAApplication(…)

        Получить значение атрибута backend по PWA (pywinauto) селектору.

        PWASpecification_Get_UIO(…)

        Получить UIO объект по PWA (pywinauto) селектору.

        UIOEI_Convert_UIOInfo(inElementInfo)

        Техническая функция: Дообогащение словаря с параметрами UIO объекта по заданному UIO.element_info

        UIOSelectorSecs_WaitAppear_Bool(…)

        Ожидать появление 1-го UIO объекта по заданному UIO селектору

        UIOSelectorSecs_WaitDisappear_Bool(…)

        Ожидать исчезновение 1-го UIO объекта по заданному UIO селектору

        UIOSelectorUIOActivity_Run_Dict(…[, …])

        Выполнить активность inActionName над UIO объектом, полученным с помощью UIO селектора inUIOSelector.

        PWASpecification_Get_PWAApplication(…)

        #Backend selection - attribute «backend» («win32» || «uia») in 1-st list element

        UIOSelector_Exist_Bool(inUIOSelector)

        Проверить существование хотя бы 1-го UIO объекта по заданному UIO селектору

        PWASpecification_Get_UIO(…)

        #Backend def selection - attribute «backend» («win32» || «uia») in 1-st list element #old name - GetControl

        UIOSelector_FocusHighlight(inUIOSelector)

        Установить фокус и подсветить на несколько секунд на экране зеленой рамкой UIO объект, который соответствует входящему UIO селектору inUIOSelector

        UIOSelectorSecs_WaitAppear_Bool(…)

        Wait for UI object will appear in GUI for inWaitSecs seconds.

        UIOSelector_GetChildList_UIOList([…])

        Получить список дочерних UIO объектов по входящему UIO селектору inUIOSelector.

        UIOSelectorSecs_WaitDisappear_Bool(…)

        Wait for UI object will disappear in GUI for inWaitSecs seconds.

        UIOSelector_Get_BitnessInt(inSpecificationList)

        Определить разрядность приложения по UIO селектору.

        UIOSelectorUIOActivity_Run_Dict(…[, …])

        Run the activity in UIO (UI Object)

        UIOSelector_Get_BitnessStr(inSpecificationList)

        Определить разрядность приложения по UIO селектору.

        UIOSelector_Exist_Bool(inUIOSelector)

        Check if object is exist by the UIO selector.

        UIOSelector_Get_UIO(inSpecificationList[, …])

        Получить список UIO объект по UIO селектору.

        UIOSelector_FocusHighlight(inUIOSelector)

        Set focus and highlight (draw outline) the element (in app) by the UIO selector.

        UIOSelector_Get_UIOActivityList(inUIOSelector)

        Получить список доступных действий/функций по UIO селектору inUIOSelector.

        UIOSelector_GetChildList_UIOList([…])

        Get list of child UIO’s by the parent UIOSelector

        UIOSelector_Get_UIOInfo(inUIOSelector)

        Получить свойства UIO объекта (element_info), по заданному UIO селектору.

        UIOSelector_Get_BitnessInt(inSpecificationList)

        Detect process bitness by the UI Object UIO Selector.

        UIOSelector_Get_UIOInfoList(inUIOSelector[, …])

        Техническая функция: Получить список параметров последних уровней UIO селектора по UIO объектам, которые удовлетворяют входящим inUIOSelector, поиск по которым будет производится от уровня inElement.

        UIOSelector_Get_BitnessStr(inSpecificationList)

        Detect process bitness by the UI Object UIO Selector.

        UIOSelector_Get_UIOList(inSpecificationList)

        Получить список UIO объектов по UIO селектору

        UIOSelector_Get_UIO(inSpecificationList[, …])

        Get the pywinauto object by the UIO selector.

        UIOSelector_Highlight(inUIOSelector)

        Подсветить на несколько секунд на экране зеленой рамкой UIO объект, который соответствует входящему UIO селектору inUIOSelector

        UIOSelector_Get_UIOActivityList(inUIOSelector)

        Get the list of the UI object activities

        UIOSelector_SafeOtherGet_Process(inUIOSelector)

        Получить процесс робота другой разрядности (если приложение UIO объекта выполняется в другой разрядности).

        UIOSelector_Get_UIOInfo(inUIOSelector)

        Get the UIO dict of the attributes

        UIOSelector_SearchChildByMouse_UIO(…)

        Инициировать визуальный поиск UIO объекта с помощью указателя мыши.

        UIOSelector_Get_UIOList(inSpecificationList)

        Get the UIO list by the selector

        UIOSelector_SearchChildByMouse_UIOTree(…)

        Получить список уровней UIO объекта с указнием всех имеющихся атрибутов по входящему UIO селектору.

        UIOSelector_Highlight(inUIOSelector)

        Highlight (draw outline) the element (in app) by the UIO selector.

        UIOSelector_SearchProcessNormalize_UIOSelector(…)

        Нормализовать UIO селектор для дальнейшего использования в функциях поиска процесса, в котором находится искомый UIO объект.

        UIOSelector_SafeOtherGet_Process(inUIOSelector)

        Safe get other process or None if destination app is the other/same bitness

        UIOSelector_SearchUIONormalize_UIOSelector(…)

        Нормализовать UIO селектор для дальнейшего использования в функциях поиск UIO объекта.

        UIOSelector_SearchChildByMouse_UIO(…)

        UIOSelector (see description on the top of the document) #old name - AutomationSearchMouseElement

        UIOSelector_TryRestore_Dict(inSpecificationList)

        Восстановить окно приложения на экране по UIO селектору inSpecificationList, если оно было свернуто.

        UIOSelector_SearchChildByMouse_UIOTree(…)

        !!!!Safe call is included (you can set activity and UIDesktop will choose the bitness and return the result)!!!!!

        UIOSelectorsSecs_WaitAppear_List(…[, …])

        Ожидать появление хотя бы 1-го / всех UIO объектов по заданным UIO селекторам

        UIOSelector_TryRestore_Dict(inSpecificationList)

        Try to restore (maximize) window, if it’s minimized.

        UIOSelectorsSecs_WaitDisappear_List(…[, …])

        Ожидать исчезновение хотя бы 1-го / всех UIO объектов по заданным UIO селекторам

        UIOSelectorsSecs_WaitAppear_List(…[, …])

        Wait for many UI object will appear in GUI for inWaitSecs seconds.

        UIOXY_SearchChild_ListDict(inRootElement, …)

        Техническая функция: Получить иерархию вложенности UIO объекта по заданным корневому UIO объекту, координатам X и Y.

        UIOSelectorsSecs_WaitDisappear_List(…[, …])

        Wait for many UI object will disappear in GUI for inWaitSecs seconds.

        UIO_FocusHighlight(lWrapperObject[, colour, …])

        Установить фокус и выполнить подсветку UIO объекта на экране

        UIO_GetCtrlIndex_Int(inElement)

        Получить индекс UIO объекта inElement в списке родительского UIO объекта.

        UIO_Highlight(lWrapperObject[, colour, …])

        Выполнить подсветку UIO объекта на экране

        +
        +
        +pyOpenRPA.Robot.UIDesktop.BackendStr_GetTopLevelList_UIOInfo(inBackend='win32')[исходный код]
        +

        Получить список UIOInfo словарей - процессы, которые запущены в рабочей сессии и готовы для взаимодействия с роботом через backend inBackend

        +
        # UIDesktop: Взаимодействие с UI объектами приложений
        +from pyOpenRPA.Robot import UIDesktop
        +lAppList = UIDesktop.BackendStr_GetTopLevelList_UIOInfo() # Очистить UIO селектор от недопустимых ключей для дальнейшего использования
        +
        +
        +
        +
        Параметры
        +

        inBackend (list, обязательный) – вид backend, который планируется использовать для взаимодействия с UIO объектами

        +
        +
        Результат
        +

        список UIOInfo словарей

        +
        +
        +
        +
        pyOpenRPA.Robot.UIDesktop.Get_OSBitnessInt()[исходный код]
        -

        Detect OS bitness.

        +

        Определить разрядность робота, в котором запускается данная функция

        +
        from pyOpenRPA.Robot import UIDesktop
        +lRobotBitInt = UIDesktop.Get_OSBitnessInt() # Определить разрядность робота, в котором была вызвана это функция
        +
        +
        Результат
        -

        int 32 or int 64

        +

        64 (int) - разрядность приложения равна 64 битам; 32 (int) - разрядность приложения равна 32 битам

        @@ -303,13 +351,43 @@
        pyOpenRPA.Robot.UIDesktop.PWASpecification_Get_PWAApplication(inControlSpecificationArray)[исходный код]
        -

        #Backend selection - attribute «backend» («win32» || «uia») in 1-st list element

        +

        Получить значение атрибута backend по PWA (pywinauto) селектору. Мы рекомендуем использовать метод UIOSelector_UIO_Get, так как UIO селектор обладает большей функциональностью.

        +
        # UIDesktop: Взаимодействие с UI объектами приложений
        +from pyOpenRPA.Robot import UIDesktop
        +# 1С: UIO Селектор выбора базы
        +lDemoBaseUIOSelector = [{"title":"Запуск 1С:Предприятия","class_name":"V8TopLevelFrameTaxiStarter","backend":"uia"}]            
        +lBackendStr = UIDesktop.PWASpecification_Get_PWAApplication(lDemoBaseUIOSelector) # Получить backend по PWA селектору
        +
        +
        Параметры
        -

        inControlSpecificationArray – List of dict, dict in pywinauto.find_windows notation

        +

        inControlSpecificationArray (list, обязательный) –

        PWA селектор, который определяет критерии поиска UIO объекта +Допустимые ключи PWA селектора:

        +
          +
        • class_name содержимое атрибута class UIO объекта

        • +
        • class_name_re содержимое атрибута class UIO объекта, которое удовлетворяет установленному рег. выражению

        • +
        • process идентификатор процесса, в котором находится UIO объект

        • +
        • title содержимое атрибута title UIO объекта

        • +
        • title_re содержимое атрибута title UIO объекта, которое удовлетворяет установленному рег. выражению

        • +
        • top_level_only признак поиска только на верхнем уровне приложения. По умолчанию True

        • +
        • visible_only признак поиска только среди видимых UIO объектов. По умолчанию True

        • +
        • enabled_only признак поиска только среди разблокированных UIO объектов. По умолчанию False

        • +
        • best_match содержимое атрибута title UIO объекта максимально приближено к заданному

        • +
        • handle идентификатор handle искомого UIO объекта

        • +
        • ctrl_index индекс UIO объекта среди всех дочерних объектов в списке родительского

        • +
        • found_index индекс UIO объекта среди всех обнаруженных

        • +
        • predicate_func пользовательская функция проверки соответсвия UIO элемента

        • +
        • active_only признак поиска только среди активных UIO объектов. По умолчанию False

        • +
        • control_id идентификатор control_id искомого UIO объекта

        • +
        • control_type тип элемента (применимо, если backend == «uia»)

        • +
        • auto_id идентификатор auto_id искомого UIO объекта (применимо, если backend == «uia»)

        • +
        • framework_id идентификатор framework_id искомого UIO объекта (применимо, если backend == «uia»)

        • +
        • backend вид технологии подключения к поиску UIO объекта («uia» или «win32»)

        • +
        +

        Результат
        -

        process application object

        +

        «win32» или «uia»

        @@ -317,14 +395,65 @@
        pyOpenRPA.Robot.UIDesktop.PWASpecification_Get_UIO(inControlSpecificationArray)[исходный код]
        -

        #Backend def selection - attribute «backend» («win32» || «uia») in 1-st list element -#old name - GetControl

        +

        Получить UIO объект по PWA (pywinauto) селектору. (https://pywinauto.readthedocs.io/en/latest/code/pywinauto.findwindows.html). Мы рекомендуем использовать метод UIOSelector_UIO_Get, так как UIO селектор обладает большей функциональностью.

        +
        # UIDesktop: Взаимодействие с UI объектами приложений
        +from pyOpenRPA.Robot import UIDesktop
        +# 1С: UIO Селектор выбора базы
        +lDemoBaseUIOSelector = [{"title":"Запуск 1С:Предприятия","class_name":"V8TopLevelFrameTaxiStarter","backend":"uia"}]            
        +lUIOObject = UIDesktop.PWASpecification_Get_UIO(lDemoBaseUIOSelector) # Получить UIO объект по PWA селектору
        +
        +
        +
        +
        Параметры
        +

        inControlSpecificationArray (list, обязательный) –

        PWA селектор, который определяет критерии поиска UIO объекта +Допустимые ключи PWA селектора:

        +
          +
        • class_name содержимое атрибута class UIO объекта

        • +
        • class_name_re содержимое атрибута class UIO объекта, которое удовлетворяет установленному рег. выражению

        • +
        • process идентификатор процесса, в котором находится UIO объект

        • +
        • title содержимое атрибута title UIO объекта

        • +
        • title_re содержимое атрибута title UIO объекта, которое удовлетворяет установленному рег. выражению

        • +
        • top_level_only признак поиска только на верхнем уровне приложения. По умолчанию True

        • +
        • visible_only признак поиска только среди видимых UIO объектов. По умолчанию True

        • +
        • enabled_only признак поиска только среди разблокированных UIO объектов. По умолчанию False

        • +
        • best_match содержимое атрибута title UIO объекта максимально приближено к заданному

        • +
        • handle идентификатор handle искомого UIO объекта

        • +
        • ctrl_index индекс UIO объекта среди всех дочерних объектов в списке родительского

        • +
        • found_index индекс UIO объекта среди всех обнаруженных

        • +
        • predicate_func пользовательская функция проверки соответсвия UIO элемента

        • +
        • active_only признак поиска только среди активных UIO объектов. По умолчанию False

        • +
        • control_id идентификатор control_id искомого UIO объекта

        • +
        • control_type тип элемента (применимо, если backend == «uia»)

        • +
        • auto_id идентификатор auto_id искомого UIO объекта (применимо, если backend == «uia»)

        • +
        • framework_id идентификатор framework_id искомого UIO объекта (применимо, если backend == «uia»)

        • +
        • backend вид технологии подключения к поиску UIO объекта («uia» или «win32»)

        • +
        +

        +
        +
        Результат
        +

        UIO объект

        +
        +
        +
        + +
        +
        +pyOpenRPA.Robot.UIDesktop.UIOEI_Convert_UIOInfo(inElementInfo)[исходный код]
        +

        Техническая функция: Дообогащение словаря с параметрами UIO объекта по заданному UIO.element_info

        +
        # UIDesktop: Взаимодействие с UI объектами приложений
        +from pyOpenRPA.Robot import UIDesktop
        +# 1С: UIO Селектор выбора базы
        +lDemoBaseUIOSelector = [{"title":"Запуск 1С:Предприятия","class_name":"V8TopLevelFrameTaxiStarter","backend":"uia"}]            
        +lUIO = UIDesktop.UIOSelector_Get_UIO(lDemoBaseUIOSelector) # Получить UIO объект по UIO селектору.
        +lUIOProcessInfoDict = UIDesktop.UIOEI_Convert_UIOInfo(lUIO.element_info)
        +
        +
        Параметры
        -

        inControlSpecificationArray – List of dict, dict in pywinauto.find_windows notation

        +

        inElementInfo (object, обязательный) – экземпляр класса UIO.element_info, для которого требуется дообогатить словарь с параметрами (в дальнейшем можно использовать как элемент UIO селектора).

        Результат
        -

        list of UIO object

        +

        dict, пример: {«title»:None,»rich_text»:None,»process_id»:None,»process»:None,»handle»:None,»class_name»:None,»control_type»:None,»control_id»:None,»rectangle»:{«left»:None,»top»:None,»right»:None,»bottom»:None}, „runtime_id“:None}

        @@ -332,16 +461,24 @@
        pyOpenRPA.Robot.UIDesktop.UIOSelectorSecs_WaitAppear_Bool(inSpecificationList, inWaitSecs)[исходный код]
        -

        Wait for UI object will appear in GUI for inWaitSecs seconds.

        +

        Ожидать появление 1-го UIO объекта по заданному UIO селектору

        +

        !ВНИМАНИЕ! ДАННАЯ ФУНКЦИОНАЛЬНОСТЬ В АВТОМАТИЧЕСКОМ РЕЖИМЕ ПОДДЕРЖИВАЕТ ВСЕ РАЗРЯДНОСТИ ПРИЛОЖЕНИЙ (32|64), КОТОРЫЕ ЗАПУЩЕНЫ В СЕСИИ. PYTHON x64 ИМЕЕТ ВОЗМОЖНОСТЬ ВЗЗАИМОДЕЙСТВИЯ С x32 UIO ОБЪЕКТАМИ, НО МЫ РЕКОМЕНДУЕМ ДОПОЛНИТЕЛЬНО ИСПОЛЬЗОВАТЬ ИНТЕРПРЕТАТОР PYTHON x32 (ПОДРОБНЕЕ СМ. ФУНКЦИЮ Configure())

        +
        # UIDesktop: Взаимодействие с UI объектами приложений
        +from pyOpenRPA.Robot import UIDesktop
        +# 1С: UIO Селектор выбора базы
        +lDemoBaseUIOSelector = [{"title":"Запуск 1С:Предприятия","class_name":"V8TopLevelFrameTaxiStarter","backend":"uia"},{"title":"DEMO", "depth_start": 5, "depth_end": 5}]         
        +lDemoBaseUIOExistBool = UIDesktop.UIOSelectorSecs_WaitAppear_Bool(lDemoBaseUIOSelector) # Ожидать появление UIO объекта
        +
        +
        Параметры
          -
        • inSpecificationList – UIOSelector. Example: [{«title»:»notepad»},{«title»:»OK»}]

        • -
        • inWaitSecs – Float value (seconds) for wait UI element appear in GUI

        • +
        • inSpecificationList (list, обязательный) – UIO селектор, который определяет критерии поиска UIO объекта

        • +
        • inWaitSecs (float, необязательный) – Количество секунд, которые отвести на ожидание UIO объекта. По умолчанию 24 часа (86400 секунд)

        Результат
        -

        True - UI object will appear. False - else case

        +

        True - UIO объект был обнаружен. False - обратная ситуациая

        @@ -349,17 +486,24 @@
        pyOpenRPA.Robot.UIDesktop.UIOSelectorSecs_WaitDisappear_Bool(inSpecificationList, inWaitSecs)[исходный код]
        -

        Wait for UI object will disappear in GUI for inWaitSecs seconds.

        +

        Ожидать исчезновение 1-го UIO объекта по заданному UIO селектору

        +

        !ВНИМАНИЕ! ДАННАЯ ФУНКЦИОНАЛЬНОСТЬ В АВТОМАТИЧЕСКОМ РЕЖИМЕ ПОДДЕРЖИВАЕТ ВСЕ РАЗРЯДНОСТИ ПРИЛОЖЕНИЙ (32|64), КОТОРЫЕ ЗАПУЩЕНЫ В СЕСИИ. PYTHON x64 ИМЕЕТ ВОЗМОЖНОСТЬ ВЗЗАИМОДЕЙСТВИЯ С x32 UIO ОБЪЕКТАМИ, НО МЫ РЕКОМЕНДУЕМ ДОПОЛНИТЕЛЬНО ИСПОЛЬЗОВАТЬ ИНТЕРПРЕТАТОР PYTHON x32 (ПОДРОБНЕЕ СМ. ФУНКЦИЮ Configure())

        +
        # UIDesktop: Взаимодействие с UI объектами приложений
        +from pyOpenRPA.Robot import UIDesktop
        +# 1С: UIO Селектор выбора базы
        +lDemoBaseUIOSelector = [{"title":"Запуск 1С:Предприятия","class_name":"V8TopLevelFrameTaxiStarter","backend":"uia"},{"title":"DEMO", "depth_start": 5, "depth_end": 5}]         
        +lDemoBaseUIOExistBool = UIDesktop.UIOSelectorSecs_WaitDisappear_Bool(lDemoBaseUIOSelector) # Ожидать исчезновение UIO объекта
        +
        +
        Параметры
          -
        • inSpecificationList – UIOSelector. -Example: [{«title»:»notepad»},{«title»:»OK»}]

        • -
        • inWaitSecs – Float value (seconds) for wait UI element disappear in GUI

        • +
        • inSpecificationList (list, обязательный) – UIO селектор, который определяет критерии поиска UIO объекта

        • +
        • inWaitSecs (float, необязательный) – Количество секунд, которые отвести на исчезновение UIO объекта. По умолчанию 24 часа (86400 секунд)

        Результат
        -

        True - UI object will disappear. False - else case

        +

        True - UIO объект был обнаружен. False - обратная ситуациая

        @@ -367,18 +511,26 @@ Example: [{«title»:»notepad»},{«title»:»OK»}]

      • pyOpenRPA.Robot.UIDesktop.UIOSelectorUIOActivity_Run_Dict(inUIOSelector, inActionName, inArgumentList=None, inkwArgumentObject=None)[исходный код]
        -

        Run the activity in UIO (UI Object)

        +

        Выполнить активность inActionName над UIO объектом, полученным с помощью UIO селектора inUIOSelector. Описание возможных активностей см. ниже.

        +

        !ВНИМАНИЕ! ДАННАЯ ФУНКЦИОНАЛЬНОСТЬ В АВТОМАТИЧЕСКОМ РЕЖИМЕ ПОДДЕРЖИВАЕТ ВСЕ РАЗРЯДНОСТИ ПРИЛОЖЕНИЙ (32|64), КОТОРЫЕ ЗАПУЩЕНЫ В СЕСИИ. PYTHON x64 ИМЕЕТ ВОЗМОЖНОСТЬ ВЗЗАИМОДЕЙСТВИЯ С x32 UIO ОБЪЕКТАМИ, НО МЫ РЕКОМЕНДУЕМ ДОПОЛНИТЕЛЬНО ИСПОЛЬЗОВАТЬ ИНТЕРПРЕТАТОР PYTHON x32 (ПОДРОБНЕЕ СМ. ФУНКЦИЮ Configure())

        +
        # UIDesktop: Взаимодействие с UI объектами приложений
        +from pyOpenRPA.Robot import UIDesktop
        +# 1С: UIO Селектор выбора базы
        +lDemoBaseUIOSelector = [{"title":"Запуск 1С:Предприятия","class_name":"V8TopLevelFrameTaxiStarter","backend":"uia"}]            
        +lActivityResult = UIDesktop.UIOSelectorUIOActivity_Run_Dict(lDemoBaseUIOSelector, "click") # выполнить действие над UIO объектом с помощью UIO селектора.
        +
        +
        Параметры
          -
        • inUIOSelector – UIOSelector - List of items, which contains condition attributes

        • -
        • inActionName – UIOActivity (name) activity name string from Pywinauto

        • -
        • inArgumentList

        • -
        • inkwArgumentObject

        • +
        • inUIOSelector (list, обязательный) – UIO селектор, который определяет UIO объект, для которого будет представлен перечень доступных активностей.

        • +
        • inActionName (str, обязательный) – наименование активности, которую требуется выполнить над UIO объектом

        • +
        • inArgumentList (list, необязательный) – список передаваемых неименованных аргументов в функцию inActionName

        • +
        • inkwArgumentObject (dict, необязательный) – словарь передаваемых именованных аргументов в функцию inActionName

        Результат
        -

        +

        возвращает результат запускаемой функции с наименованием inActionName над UIO объектом

        @@ -386,13 +538,21 @@ Example: [{«title»:»notepad»},{«title»:»OK»}]

        pyOpenRPA.Robot.UIDesktop.UIOSelector_Exist_Bool(inUIOSelector)[исходный код]
        -

        Check if object is exist by the UIO selector.

        +

        Проверить существование хотя бы 1-го UIO объекта по заданному UIO селектору

        +

        !ВНИМАНИЕ! ДАННАЯ ФУНКЦИОНАЛЬНОСТЬ В АВТОМАТИЧЕСКОМ РЕЖИМЕ ПОДДЕРЖИВАЕТ ВСЕ РАЗРЯДНОСТИ ПРИЛОЖЕНИЙ (32|64), КОТОРЫЕ ЗАПУЩЕНЫ В СЕСИИ. PYTHON x64 ИМЕЕТ ВОЗМОЖНОСТЬ ВЗЗАИМОДЕЙСТВИЯ С x32 UIO ОБЪЕКТАМИ, НО МЫ РЕКОМЕНДУЕМ ДОПОЛНИТЕЛЬНО ИСПОЛЬЗОВАТЬ ИНТЕРПРЕТАТОР PYTHON x32 (ПОДРОБНЕЕ СМ. ФУНКЦИЮ Configure())

        +
        # UIDesktop: Взаимодействие с UI объектами приложений
        +from pyOpenRPA.Robot import UIDesktop
        +# 1С: UIO Селектор выбора базы
        +lDemoBaseUIOSelector = [{"title":"Запуск 1С:Предприятия","class_name":"V8TopLevelFrameTaxiStarter","backend":"uia"},{"title":"DEMO", "depth_start": 5, "depth_end": 5}]         
        +lDemoBaseUIOExistBool = UIDesktop.UIOSelector_Exist_Bool(lDemoBaseUIOSelector) # Получить булевый результат проверки существования UIO объекта
        +
        +
        Параметры
        -

        inUIOSelector

        +

        inUIOSelector (list, обязательный) – UIO Селектор, который определяет критерии поиска UIO объектов

        Результат
        -

        True - Object is exist. False - else case

        +

        True - существует хотя бы 1 UIO объект. False - не существует ни одного UIO объекта по заданному UIO селектору

        @@ -400,13 +560,18 @@ Example: [{«title»:»notepad»},{«title»:»OK»}]

        pyOpenRPA.Robot.UIDesktop.UIOSelector_FocusHighlight(inUIOSelector)[исходный код]
        -

        Set focus and highlight (draw outline) the element (in app) by the UIO selector.

        +

        Установить фокус и подсветить на несколько секунд на экране зеленой рамкой UIO объект, который соответствует входящему UIO селектору inUIOSelector

        +

        !ВНИМАНИЕ! ДАННАЯ ФУНКЦИОНАЛЬНОСТЬ В АВТОМАТИЧЕСКОМ РЕЖИМЕ ПОДДЕРЖИВАЕТ ВСЕ РАЗРЯДНОСТИ ПРИЛОЖЕНИЙ (32|64), КОТОРЫЕ ЗАПУЩЕНЫ В СЕСИИ. PYTHON x64 ИМЕЕТ ВОЗМОЖНОСТЬ ВЗЗАИМОДЕЙСТВИЯ С x32 UIO ОБЪЕКТАМИ, НО МЫ РЕКОМЕНДУЕМ ДОПОЛНИТЕЛЬНО ИСПОЛЬЗОВАТЬ ИНТЕРПРЕТАТОР PYTHON x32 (ПОДРОБНЕЕ СМ. ФУНКЦИЮ Configure())

        +
        # UIDesktop: Взаимодействие с UI объектами приложений
        +from pyOpenRPA.Robot import UIDesktop
        +# 1С: UIO Селектор выбора базы
        +lDemoBaseUIOSelector = [{"title":"Запуск 1С:Предприятия","class_name":"V8TopLevelFrameTaxiStarter","backend":"uia"}]            
        +UIDesktop.UIOSelector_FocusHighlight(lDemoBaseUIOSelector) # Установить фокус и подсветить UIO объект по UIO селектору
        +
        +
        Параметры
        -

        inUIOSelector – UIOSelector - List of items, which contains condition attributes

        -
        -
        Результат
        -

        +

        inUIOSelector (list, обязательный) – UIO селектор, который определяет UIO объект, для которого будет представлен перечень доступных активностей.

        @@ -414,16 +579,24 @@ Example: [{«title»:»notepad»},{«title»:»OK»}]

        pyOpenRPA.Robot.UIDesktop.UIOSelector_GetChildList_UIOList(inUIOSelector=None, inBackend='win32')[исходный код]
        -

        Get list of child UIO’s by the parent UIOSelector

        +

        Получить список дочерних UIO объектов по входящему UIO селектору inUIOSelector.

        +

        !ВНИМАНИЕ! ДАННАЯ ФУНКЦИОНАЛЬНОСТЬ В АВТОМАТИЧЕСКОМ РЕЖИМЕ ПОДДЕРЖИВАЕТ ВСЕ РАЗРЯДНОСТИ ПРИЛОЖЕНИЙ (32|64), КОТОРЫЕ ЗАПУЩЕНЫ В СЕСИИ. PYTHON x64 ИМЕЕТ ВОЗМОЖНОСТЬ ВЗЗАИМОДЕЙСТВИЯ С x32 UIO ОБЪЕКТАМИ, НО МЫ РЕКОМЕНДУЕМ ДОПОЛНИТЕЛЬНО ИСПОЛЬЗОВАТЬ ИНТЕРПРЕТАТОР PYTHON x32 (ПОДРОБНЕЕ СМ. ФУНКЦИЮ Configure())

        +
        # UIDesktop: Взаимодействие с UI объектами приложений
        +from pyOpenRPA.Robot import UIDesktop
        +# 1С: UIO Селектор выбора базы
        +lDemoBaseUIOSelector = [{"title":"Запуск 1С:Предприятия","class_name":"V8TopLevelFrameTaxiStarter","backend":"uia"}]            
        +lUIOList = UIDesktop.UIOSelector_GetChildList_UIOList(lDemoBaseUIOSelector) # Получить список дочерних UIO объектов с помощью UIO селектора
        +
        +
        Параметры
          -
        • inUIOSelector – UIOSelector - List of items, which contains condition attributes

        • -
        • inBackend – «win32» or «uia»

        • +
        • inUIOSelector (list, обязательный) – родительский UIO объект, полученный ранее с помощью UIO селектора.

        • +
        • inBackend (str, необязательный) – вид backend «win32» или «uia». По умолчанию mDefaultPywinautoBackend («win32»)

        Результат
        -

        +

        список дочерних UIO объектов

        @@ -431,13 +604,20 @@ Example: [{«title»:»notepad»},{«title»:»OK»}]

        pyOpenRPA.Robot.UIDesktop.UIOSelector_Get_BitnessInt(inSpecificationList)[исходный код]
        -

        Detect process bitness by the UI Object UIO Selector.

        +

        Определить разрядность приложения по UIO селектору. Вернуть результат в формате целого числа (64 или 32)

        +
        # UIDesktop: Взаимодействие с UI объектами приложений
        +from pyOpenRPA.Robot import UIDesktop
        +# 1С: UIO Селектор выбора базы
        +lDemoBaseUIOSelector = [{"title":"Запуск 1С:Предприятия","class_name":"V8TopLevelFrameTaxiStarter","backend":"uia"},{"title":"DEMO", "depth_start": 5, "depth_end": 5}]         
        +lDemoBaseBitInt = UIDesktop.UIOSelector_Get_BitnessInt(lDemoBaseUIOSelector) # Определить разрядность приложения, в котором обнаружен UIO объект по селектору
        +
        +
        Параметры
        -

        inSpecificationList – UIOSelector. Example: [{«title»:»notepad»},{«title»:»OK»}]

        +

        inSpecificationList (list, обязательный) – UIO селектор, который определяет критерии поиска UIO объекта

        Результат
        -

        int 32 or int 64

        +

        None - UIO объект не обнаружен; 64 (int) - разрядность приложения равна 64 битам; 32 (int) - разрядность приложения равна 32 битам

        @@ -445,13 +625,20 @@ Example: [{«title»:»notepad»},{«title»:»OK»}]

        pyOpenRPA.Robot.UIDesktop.UIOSelector_Get_BitnessStr(inSpecificationList)[исходный код]
        -

        Detect process bitness by the UI Object UIO Selector.

        +

        Определить разрядность приложения по UIO селектору. Вернуть результат в формате строки («64» или «32»)

        +
        # UIDesktop: Взаимодействие с UI объектами приложений
        +from pyOpenRPA.Robot import UIDesktop
        +# 1С: UIO Селектор выбора базы
        +lDemoBaseUIOSelector = [{"title":"Запуск 1С:Предприятия","class_name":"V8TopLevelFrameTaxiStarter","backend":"uia"},{"title":"DEMO", "depth_start": 5, "depth_end": 5}]         
        +lDemoBaseBitStr = UIDesktop.UIOSelector_Get_BitnessStr(lDemoBaseUIOSelector) # Определить разрядность приложения, в котором обнаружен UIO объект по селектору
        +
        +
        Параметры
        -

        inSpecificationList – UIOSelector. Example: [{«title»:»notepad»},{«title»:»OK»}]

        +

        inSpecificationList (list, обязательный) – UIO селектор, который определяет критерии поиска UIO объекта

        Результат
        -

        str «32» or str «64»

        +

        None - UIO объект не обнаружен; «64» (str) - разрядность приложения равна 64 битам; «32» (str) - разрядность приложения равна 32 битам

        @@ -459,17 +646,24 @@ Example: [{«title»:»notepad»},{«title»:»OK»}]

        pyOpenRPA.Robot.UIDesktop.UIOSelector_Get_UIO(inSpecificationList, inElement=None, inFlagRaiseException=True)[исходный код]
        -

        Get the pywinauto object by the UIO selector.

        +

        Получить список UIO объект по UIO селектору. Если критериям UIO селектора удовлетворяет несколько UIO объектов - вернуть первый из списка

        +
        # UIDesktop: Взаимодействие с UI объектами приложений
        +from pyOpenRPA.Robot import UIDesktop
        +# 1С: UIO Селектор выбора базы
        +lDemoBaseUIOSelector = [{"title":"Запуск 1С:Предприятия","class_name":"V8TopLevelFrameTaxiStarter","backend":"uia"},{"title":"DEMO", "depth_start": 5, "depth_end": 5}]         
        +lDemoBaseUIOList = UIDesktop.UIOSelector_Get_UIO(lDemoBaseUIOSelector) #Получить 1-й UIO объект, которые удовлетворяет требованиям UIO селектора. В нашем примере либо None, либо UIO объект
        +
        +
        Параметры
          -
        • inSpecificationList

        • -
        • inElement

        • -
        • inFlagRaiseException

        • +
        • inSpecificationList (list, обязательный) – UIO Селектор, который определяет критерии поиска UI элементов

        • +
        • inElement (UIO объект, опциональный) – Родительский элемент, от которого выполнить поиск UIO объектов по заданному UIO селектору. Если аргумент не задан, платформа выполнит поиск UIO объектов среди всех доступных приложений windows, которые запущены на текущей сессии

        • +
        • inFlagRaiseException (bool, опциональный) – True - формировать ошибку exception, если платформа не обнаружина ни одного UIO объекта по заданному UIO селектору. False - обратный случай. По умолчанию True

        Результат
        -

        +

        UIO объект, которые удовлетворяют условиям UIO селектора, или None

        @@ -477,13 +671,18 @@ Example: [{«title»:»notepad»},{«title»:»OK»}]

        pyOpenRPA.Robot.UIDesktop.UIOSelector_Get_UIOActivityList(inUIOSelector)[исходный код]
        -

        Get the list of the UI object activities

        +

        Получить список доступных действий/функций по UIO селектору inUIOSelector. Описание возможных активностей см. ниже.

        +

        !ВНИМАНИЕ! ДАННАЯ ФУНКЦИОНАЛЬНОСТЬ В АВТОМАТИЧЕСКОМ РЕЖИМЕ ПОДДЕРЖИВАЕТ ВСЕ РАЗРЯДНОСТИ ПРИЛОЖЕНИЙ (32|64), КОТОРЫЕ ЗАПУЩЕНЫ В СЕСИИ. PYTHON x64 ИМЕЕТ ВОЗМОЖНОСТЬ ВЗЗАИМОДЕЙСТВИЯ С x32 UIO ОБЪЕКТАМИ, НО МЫ РЕКОМЕНДУЕМ ДОПОЛНИТЕЛЬНО ИСПОЛЬЗОВАТЬ ИНТЕРПРЕТАТОР PYTHON x32 (ПОДРОБНЕЕ СМ. ФУНКЦИЮ Configure())

        +
        # UIDesktop: Взаимодействие с UI объектами приложений
        +from pyOpenRPA.Robot import UIDesktop
        +# 1С: UIO Селектор выбора базы
        +lDemoBaseUIOSelector = [{"title":"Запуск 1С:Предприятия","class_name":"V8TopLevelFrameTaxiStarter","backend":"uia"}]            
        +lActivityList = UIDesktop.UIOSelector_Get_UIOActivityList(lDemoBaseUIOSelector) # Получить список активностей по UIO селектору.
        +
        +
        Параметры
        -

        inUIOSelector – UIOSelector - List of items, which contains condition attributes

        -
        -
        Результат
        -

        +

        inUIOSelector (list, обязательный) – UIO селектор, который определяет UIO объект, для которого будет представлен перечень доступных активностей.

        @@ -491,13 +690,79 @@ Example: [{«title»:»notepad»},{«title»:»OK»}]

        pyOpenRPA.Robot.UIDesktop.UIOSelector_Get_UIOInfo(inUIOSelector)[исходный код]
        -

        Get the UIO dict of the attributes

        +

        Получить свойства UIO объекта (element_info), по заданному UIO селектору. Ниже представлен перечень возвращаемых свойств.

        +

        Для backend = win32:

        +
          +
        • automation_id (int)

        • +
        • class_name (str)

        • +
        • control_id (int)

        • +
        • control_type (str)

        • +
        • full_control_type (str)

        • +
        • enabled (bool)

        • +
        • handle (int)

        • +
        • name (str)

        • +
        • parent (object/UIO)

        • +
        • process_id (int)

        • +
        • rectangle (object/rect)

        • +
        • rich_text (str)

        • +
        • visible (bool)

        • +
        +

        Для backend = uia:

        +
          +
        • automation_id (int)

        • +
        • class_name (str)

        • +
        • control_id (int)

        • +
        • control_type (str)

        • +
        • enabled (bool)

        • +
        • framework_id (int)

        • +
        • handle (int)

        • +
        • name (str)

        • +
        • parent (object/UIO)

        • +
        • process_id (int)

        • +
        • rectangle (object/rect)

        • +
        • rich_text (str)

        • +
        • runtime_id (int)

        • +
        • visible (bool)

        • +
        +

        !ВНИМАНИЕ! ДАННАЯ ФУНКЦИОНАЛЬНОСТЬ В АВТОМАТИЧЕСКОМ РЕЖИМЕ ПОДДЕРЖИВАЕТ ВСЕ РАЗРЯДНОСТИ ПРИЛОЖЕНИЙ (32|64), КОТОРЫЕ ЗАПУЩЕНЫ В СЕСИИ. PYTHON x64 ИМЕЕТ ВОЗМОЖНОСТЬ ВЗЗАИМОДЕЙСТВИЯ С x32 UIO ОБЪЕКТАМИ, НО МЫ РЕКОМЕНДУЕМ ДОПОЛНИТЕЛЬНО ИСПОЛЬЗОВАТЬ ИНТЕРПРЕТАТОР PYTHON x32 (ПОДРОБНЕЕ СМ. ФУНКЦИЮ Configure())

        +
        # UIDesktop: Взаимодействие с UI объектами приложений
        +from pyOpenRPA.Robot import UIDesktop
        +# 1С: UIO Селектор выбора базы
        +lDemoBaseUIOSelector = [{"title":"Запуск 1С:Предприятия","class_name":"V8TopLevelFrameTaxiStarter","backend":"uia"}]            
        +lUIOElementInfoDict = UIDesktop.UIOSelector_Get_UIOInfo(lDemoBaseUIOSelector) #Получить свойства над UIO объектом с помощью UIO селектора.
        +
        +
        +
        +
        Параметры
        +

        inUIOSelector (list, обязательный) – UIO селектор, который определяет UIO объект, для которого будет представлен перечень доступных активностей.

        +
        +
        Результат
        +

        словарь свойств element_info: Пример {«control_id»: …, «process_id»: …}

        +
        +
        +
        + +
        +
        +pyOpenRPA.Robot.UIDesktop.UIOSelector_Get_UIOInfoList(inUIOSelector, inElement=None)[исходный код]
        +

        Техническая функция: Получить список параметров последних уровней UIO селектора по UIO объектам, которые удовлетворяют входящим inUIOSelector, поиск по которым будет производится от уровня inElement.

        +

        !ВНИМАНИЕ! ДАННАЯ ФУНКЦИОНАЛЬНОСТЬ В АВТОМАТИЧЕСКОМ РЕЖИМЕ ПОДДЕРЖИВАЕТ ВСЕ РАЗРЯДНОСТИ ПРИЛОЖЕНИЙ (32|64), КОТОРЫЕ ЗАПУЩЕНЫ В СЕСИИ. PYTHON x64 ИМЕЕТ ВОЗМОЖНОСТЬ ВЗЗАИМОДЕЙСТВИЯ С x32 UIO ОБЪЕКТАМИ, НО МЫ РЕКОМЕНДУЕМ ДОПОЛНИТЕЛЬНО ИСПОЛЬЗОВАТЬ ИНТЕРПРЕТАТОР PYTHON x32 (ПОДРОБНЕЕ СМ. ФУНКЦИЮ Configure())

        +
        # UIDesktop: Взаимодействие с UI объектами приложений
        +from pyOpenRPA.Robot import UIDesktop
        +# 1С: UIO Селектор выбора базы
        +lDemoBaseUIOSelector = [{"title":"Запуск 1С:Предприятия","class_name":"V8TopLevelFrameTaxiStarter","backend":"uia"}]            
        +lUIOInfoList = UIDesktop.UIOSelector_Get_UIOInfoList(lDemoBaseUIOSelector) # Получить словарь параметров по UIO селектору.
        +
        +
        Параметры
        -

        inUIOSelector – UIOSelector - List of items, which contains condition attributes

        +
          +
        • inUIOSelector (list, обязательный) – UIO селектор, который определяет UIO объект, для которого будет произведено извлечение всех атрибутов на всех уровнях.

        • +
        • inElement (UIO объект, необязательный) – UIO объект, от которого выполнить поиск дочерних UIO объектов по UIO селектору inUIOSelector. По умолчанию None - поиск среди всех приложений.

        • +
        Результат
        -

        +

        dict, пример: {«title»:None,»rich_text»:None,»process_id»:None,»process»:None,»handle»:None,»class_name»:None,»control_type»:None,»control_id»:None,»rectangle»:{«left»:None,»top»:None,»right»:None,»bottom»:None}, „runtime_id“:None}

        @@ -505,17 +770,24 @@ Example: [{«title»:»notepad»},{«title»:»OK»}]

        pyOpenRPA.Robot.UIDesktop.UIOSelector_Get_UIOList(inSpecificationList, inElement=None, inFlagRaiseException=True)[исходный код]
        -

        Get the UIO list by the selector

        +

        Получить список UIO объектов по UIO селектору

        +
        # UIDesktop: Взаимодействие с UI объектами приложений
        +from pyOpenRPA.Robot import UIDesktop
        +# 1С: UIO Селектор выбора базы
        +lDemoBaseUIOSelector = [{"title":"Запуск 1С:Предприятия","class_name":"V8TopLevelFrameTaxiStarter","backend":"uia"},{"title":"DEMO", "depth_start": 5, "depth_end": 5}]         
        +lDemoBaseUIOList = UIDesktop.UIOSelector_Get_UIOList(lDemoBaseUIOSelector) #Получить список UIO объектов, которые удовлетворяют требованиям UIO селектора. В нашем примере либо [], либо [UIO объект]
        +
        +
        Параметры
          -
        • inSpecificationList – UIO Selector

        • -
        • inElement – Входной элемент - показатель, что не требуется выполнять коннект к процессу

        • -
        • inFlagRaiseException – Флаг True - выкинуть ошибку в случае обнаружении пустого списка

        • +
        • inSpecificationList (list, обязательный) – UIO Селектор, который определяет критерии поиска UI элементов

        • +
        • inElement (UIO объект, опциональный) – Родительский элемент, от которого выполнить поиск UIO объектов по заданному UIO селектору. Если аргумент не задан, платформа выполнит поиск UIO объектов среди всех доступных приложений windows, которые запущены на текущей сессии

        • +
        • inFlagRaiseException (bool, опциональный) – True - формировать ошибку exception, если платформа не обнаружина ни одного UIO объекта по заданному UIO селектору. False - обратный случай. По умолчанию True

        Результат
        -

        +

        Список UIO объектов, которые удовлетворяют условиям UIO селектора

        @@ -523,13 +795,18 @@ Example: [{«title»:»notepad»},{«title»:»OK»}]

        pyOpenRPA.Robot.UIDesktop.UIOSelector_Highlight(inUIOSelector)[исходный код]
        -

        Highlight (draw outline) the element (in app) by the UIO selector.

        +

        Подсветить на несколько секунд на экране зеленой рамкой UIO объект, который соответствует входящему UIO селектору inUIOSelector

        +

        !ВНИМАНИЕ! ДАННАЯ ФУНКЦИОНАЛЬНОСТЬ В АВТОМАТИЧЕСКОМ РЕЖИМЕ ПОДДЕРЖИВАЕТ ВСЕ РАЗРЯДНОСТИ ПРИЛОЖЕНИЙ (32|64), КОТОРЫЕ ЗАПУЩЕНЫ В СЕСИИ. PYTHON x64 ИМЕЕТ ВОЗМОЖНОСТЬ ВЗЗАИМОДЕЙСТВИЯ С x32 UIO ОБЪЕКТАМИ, НО МЫ РЕКОМЕНДУЕМ ДОПОЛНИТЕЛЬНО ИСПОЛЬЗОВАТЬ ИНТЕРПРЕТАТОР PYTHON x32 (ПОДРОБНЕЕ СМ. ФУНКЦИЮ Configure())

        +
        # UIDesktop: Взаимодействие с UI объектами приложений
        +from pyOpenRPA.Robot import UIDesktop
        +# 1С: UIO Селектор выбора базы
        +lDemoBaseUIOSelector = [{"title":"Запуск 1С:Предприятия","class_name":"V8TopLevelFrameTaxiStarter","backend":"uia"}]            
        +UIDesktop.UIOSelector_Highlight(lDemoBaseUIOSelector) # Подсветить UIO объект по UIO селектору
        +
        +
        Параметры
        -

        inUIOSelector – UIOSelector - List of items, which contains condition attributes

        -
        -
        Результат
        -

        +

        inUIOSelector (list, обязательный) – UIO селектор, который определяет UIO объект, для которого будет представлен перечень доступных активностей.

        @@ -537,13 +814,20 @@ Example: [{«title»:»notepad»},{«title»:»OK»}]

        pyOpenRPA.Robot.UIDesktop.UIOSelector_SafeOtherGet_Process(inUIOSelector)[исходный код]
        -

        Safe get other process or None if destination app is the other/same bitness

        +

        Получить процесс робота другой разрядности (если приложение UIO объекта выполняется в другой разрядности). Функция возвращает None, если разрядность робота совпадает с разрядностью приложения UIO объекта, либо если при инициализации робота не устанавливался интерпретатор другой разрядности.

        +
        # UIDesktop: Взаимодействие с UI объектами приложений
        +from pyOpenRPA.Robot import UIDesktop
        +# 1С: UIO Селектор выбора базы
        +lDemoBaseUIOSelector = [{"title":"Запуск 1С:Предприятия","class_name":"V8TopLevelFrameTaxiStarter","backend":"uia"},{"title":"DEMO", "depth_start": 5, "depth_end": 5}]         
        +lOtherBitnessProcess = UIDesktop.UIOSelector_SafeOtherGet_Process(lDemoBaseUIOSelector) # Вернуть процесс робота, схожей разрядности
        +
        +
        Параметры
        -

        inUIOSelector – UIO Selector of the UI object

        +

        inUIOSelector (list, обязательный) – UIO селектор, который определяет критерии поиска UIO объекта

        Результат
        -

        None or process (of the other bitness)

        +

        Процесс робота схожей разрядности

        @@ -551,14 +835,20 @@ Example: [{«title»:»notepad»},{«title»:»OK»}]

        pyOpenRPA.Robot.UIDesktop.UIOSelector_SearchChildByMouse_UIO(inElementSpecification)[исходный код]
        -

        UIOSelector (see description on the top of the document) -#old name - AutomationSearchMouseElement

        +

        Инициировать визуальный поиск UIO объекта с помощью указателя мыши. При наведении указателя мыши UIO объект выделяется зеленой рамкой. Остановить режим поиска можно с помощью зажима клавиши ctrl left на протяжении нескольких секунд. После этого в веб окне студии будет отображено дерево расположения искомого UIO объекта.

        +
        # UIDesktop: Взаимодействие с UI объектами приложений
        +from pyOpenRPA.Robot import UIDesktop
        +# 1С: UIO Селектор выбора базы
        +lDemoBaseUIOSelector = [{"title":"Запуск 1С:Предприятия","class_name":"V8TopLevelFrameTaxiStarter","backend":"uia"}]            
        +lUIO = UIDesktop.UIOSelector_SearchChildByMouse_UIO(lDemoBaseUIOSelector) # Инициировать поиск дочернего UIO объекта, который расположен внутри lDemoBaseUIOSelector.
        +
        +
        Параметры
        -

        inElementSpecification – UIOSelector of the UI Object

        +

        inElementSpecification (list, обязательный) – UIO селектор, который определяет критерии поиска родительского UIO объекта, в котором будет производиться поиск дочернего UIO объекта

        Результат
        -

        pywinauto element wrapper instance or None

        +

        UIO объект или None (если UIO не был обнаружен)

        @@ -566,95 +856,410 @@ Example: [{«title»:»notepad»},{«title»:»OK»}]

        pyOpenRPA.Robot.UIDesktop.UIOSelector_SearchChildByMouse_UIOTree(inUIOSelector)[исходный код]
        -

        !!!!Safe call is included (you can set activity and UIDesktop will choose the bitness and return the result)!!!!!

        +

        Получить список уровней UIO объекта с указнием всех имеющихся атрибутов по входящему UIO селектору.

        +

        !ВНИМАНИЕ! ДАННАЯ ФУНКЦИОНАЛЬНОСТЬ В АВТОМАТИЧЕСКОМ РЕЖИМЕ ПОДДЕРЖИВАЕТ ВСЕ РАЗРЯДНОСТИ ПРИЛОЖЕНИЙ (32|64), КОТОРЫЕ ЗАПУЩЕНЫ В СЕСИИ. PYTHON x64 ИМЕЕТ ВОЗМОЖНОСТЬ ВЗЗАИМОДЕЙСТВИЯ С x32 UIO ОБЪЕКТАМИ, НО МЫ РЕКОМЕНДУЕМ ДОПОЛНИТЕЛЬНО ИСПОЛЬЗОВАТЬ ИНТЕРПРЕТАТОР PYTHON x32 (ПОДРОБНЕЕ СМ. ФУНКЦИЮ Configure())

        +
        # UIDesktop: Взаимодействие с UI объектами приложений
        +from pyOpenRPA.Robot import UIDesktop
        +# 1С: UIO Селектор выбора базы
        +lDemoBaseUIOSelector = [{"title":"Запуск 1С:Предприятия","class_name":"V8TopLevelFrameTaxiStarter","backend":"uia"}]            
        +lBackendStr = UIDesktop.UIOSelector_SearchChildByMouse_UIOTree(lDemoBaseUIOSelector) # Получить список атрибутов всех родительских элементов lDemoBaseUIOSelector.
        +
        +
        Параметры
        -

        inUIOSelector – UIOSelector of the UI Object

        +

        inUIOSelector (list, обязательный) – UIO селектор, который определяет UIO объект, для которого будет произведено извлечение всех атрибутов на всех уровнях.

        Результат
        -

        ?

        -

        +

        list, список атрибутов на каждом уровне UIO объекта

        -
        -pyOpenRPA.Robot.UIDesktop.UIOSelector_TryRestore_Dict(inSpecificationList)[исходный код]
        -

        Try to restore (maximize) window, if it’s minimized. (!IMPORTANT! When use UIA framework minimized windows doesn’t appear by the UIOSelector. You need to try restore windows and after that try to get UIO)

        +
        +pyOpenRPA.Robot.UIDesktop.UIOSelector_SearchProcessNormalize_UIOSelector(inControlSpecificationArray)[исходный код]
        +

        Нормализовать UIO селектор для дальнейшего использования в функциях поиска процесса, в котором находится искомый UIO объект. Если недопустимых атрибутов не присутствует, то оставить как есть.

        +
        # UIDesktop: Взаимодействие с UI объектами приложений
        +from pyOpenRPA.Robot import UIDesktop
        +# 1С: UIO Селектор выбора базы
        +lDemoBaseUIOSelectorDitry = [{"title":"Запуск 1С:Предприятия","class_name":"V8TopLevelFrameTaxiStarter","backend":"uia"}]               
        +lDemoBaseUIOSelectorClean = UIDesktop.UIOSelector_SearchProcessNormalize_UIOSelector(lDemoBaseUIOSelectorDitry) # Очистить UIO селектор от недопустимых ключей для дальнейшего использования
        +
        +
        +
        +
        Параметры
        +

        inControlSpecificationArray (list, обязательный) – UIO селектор, который определяет UIO объект, для которого будет представлен перечень доступных активностей.

        +
        +
        Результат
        +

        нормализованный UIO селектор

        +
        +
        +
        + +
        +
        +pyOpenRPA.Robot.UIDesktop.UIOSelector_SearchUIONormalize_UIOSelector(inControlSpecificationArray)[исходный код]
        +

        Нормализовать UIO селектор для дальнейшего использования в функциях поиск UIO объекта. Если недопустимых атрибутов не присутствует, то оставить как есть.

        +
        # UIDesktop: Взаимодействие с UI объектами приложений
        +from pyOpenRPA.Robot import UIDesktop
        +# 1С: UIO Селектор выбора базы
        +lDemoBaseUIOSelectorDitry = [{"title":"Запуск 1С:Предприятия","class_name":"V8TopLevelFrameTaxiStarter","backend":"uia"}]               
        +lDemoBaseUIOSelectorClean = UIDesktop.UIOSelector_SearchUIONormalize_UIOSelector(lDemoBaseUIOSelectorDitry) # Очистить UIO селектор от недопустимых ключей для дальнейшего использования
        +
        +
        Параметры
        -

        inSpecificationList – UIOSelector - List of items, which contains condition attributes

        +

        inControlSpecificationArray (list, обязательный) – UIO селектор, который определяет UIO объект, для которого будет представлен перечень доступных активностей.

        Результат
        -

        +

        нормализованный UIO селектор

        +
        +
        +
        + +
        +
        +pyOpenRPA.Robot.UIDesktop.UIOSelector_TryRestore_Dict(inSpecificationList)[исходный код]
        +

        Восстановить окно приложения на экране по UIO селектору inSpecificationList, если оно было свернуто. Функция обернута в try .. except - ошибок не возникнет.

        +

        !ВНИМАНИЕ! ДАННАЯ ФУНКЦИОНАЛЬНОСТЬ УЖЕ ИСПОЛЬЗУЕТСЯ В РЯДЕ ДРУГИХ ФУНКЦИЙ ТАК КАК АДРЕССАЦИЯ ПО UIA FRAMEWORK НЕДОСТУПНА, ЕСЛИ ПРИЛОЖЕНИЕ СВЕРНУТО.

        +

        !ВНИМАНИЕ! ДАННАЯ ФУНКЦИОНАЛЬНОСТЬ В АВТОМАТИЧЕСКОМ РЕЖИМЕ ПОДДЕРЖИВАЕТ ВСЕ РАЗРЯДНОСТИ ПРИЛОЖЕНИЙ (32|64), КОТОРЫЕ ЗАПУЩЕНЫ В СЕСИИ. PYTHON x64 ИМЕЕТ ВОЗМОЖНОСТЬ ВЗЗАИМОДЕЙСТВИЯ С x32 UIO ОБЪЕКТАМИ, НО МЫ РЕКОМЕНДУЕМ ДОПОЛНИТЕЛЬНО ИСПОЛЬЗОВАТЬ ИНТЕРПРЕТАТОР PYTHON x32 (ПОДРОБНЕЕ СМ. ФУНКЦИЮ Configure())

        +
        # UIDesktop: Взаимодействие с UI объектами приложений
        +from pyOpenRPA.Robot import UIDesktop
        +# 1С: UIO Селектор выбора базы
        +lDemoBaseUIOSelector = [{"title":"Запуск 1С:Предприятия","class_name":"V8TopLevelFrameTaxiStarter","backend":"uia"}]            
        +UIDesktop.UIOSelector_TryRestore_Dict(lDemoBaseUIOSelector) # Попытка восстановления свернутого окна по UIO селектору.
        +
        +
        +
        +
        Параметры
        +

        inSpecificationList (list, обязательный) – UIO селектор, который определяет UIO объект, для которого будет произведено извлечение всех атрибутов на всех уровнях.

        -pyOpenRPA.Robot.UIDesktop.UIOSelectorsSecs_WaitAppear_List(inSpecificationListList, inWaitSecs, inFlagWaitAllInMoment=False)[исходный код]
        -

        Wait for many UI object will appear in GUI for inWaitSecs seconds.

        +pyOpenRPA.Robot.UIDesktop.UIOSelectorsSecs_WaitAppear_List(inSpecificationListList, inWaitSecs=86400.0, inFlagWaitAllInMoment=False)[исходный код] +

        Ожидать появление хотя бы 1-го / всех UIO объектов по заданным UIO селекторам

        +

        !ВНИМАНИЕ! ДАННАЯ ФУНКЦИОНАЛЬНОСТЬ В АВТОМАТИЧЕСКОМ РЕЖИМЕ ПОДДЕРЖИВАЕТ ВСЕ РАЗРЯДНОСТИ ПРИЛОЖЕНИЙ (32|64), КОТОРЫЕ ЗАПУЩЕНЫ В СЕСИИ. PYTHON x64 ИМЕЕТ ВОЗМОЖНОСТЬ ВЗЗАИМОДЕЙСТВИЯ С x32 UIO ОБЪЕКТАМИ, НО МЫ РЕКОМЕНДУЕМ ДОПОЛНИТЕЛЬНО ИСПОЛЬЗОВАТЬ ИНТЕРПРЕТАТОР PYTHON x32 (ПОДРОБНЕЕ СМ. ФУНКЦИЮ Configure())

        +
        # UIDesktop: Взаимодействие с UI объектами приложений
        +from pyOpenRPA.Robot import UIDesktop
        +# 1С: UIO Селектор выбора базы
        +lDemoBaseUIOSelector = [{"title":"Запуск 1С:Предприятия","class_name":"V8TopLevelFrameTaxiStarter","backend":"uia"},{"title":"DEMO", "depth_start": 5, "depth_end": 5}]         
        +lNotepadOKSelector = [{"title":"notepad"},{"title":"OK"}]
        +lNotepadCancelSelector = [{"title":"notepad"},{"title":"Cancel"}]
        +lDemoBaseUIOExistList = UIDesktop.UIOSelectorsSecs_WaitAppear_List([lDemoBaseUIOSelector, lNotepadOKSelector, lNotepadCancelSelector]) # Ожидать появление UIO объекта
        +
        +
        Параметры
          -
        • inSpecificationListList

          UIOSelector list. -Example: [

          -
          -

          [{«title»:»notepad»},{«title»:»OK»}], +

        • inSpecificationListList (list, обязательный) –

          +
          Список UIO селекторов, которые определяют критерии поиска UIO объектов

          Пример: [ +[{«title»:»notepad»},{«title»:»OK»}], [{«title»:»notepad»},{«title»:»Cancel»}]

          -
        • +
        +

        ]

        -
      • inWaitSecs – Float value (seconds) for wait UI element appear in GUI

      • -
      • inFlagWaitAllInMoment – True - Wait all UI objects from the UIOSelector list to be appeared

      • +
      • inWaitSecs (float, необязательный) – Количество секунд, которые отвести на ожидание UIO объектов. По умолчанию 24 часа (86400 секунд)

      • +
      • inFlagWaitAllInMoment – True - Ожидать до того момента, пока не появятся все запрашиваемые UIO объекты на рабочей области

  • Результат
    -

    List of index, which UI object UIO will be appeared. Example: [1] # Appear only UI object with UIO selector: [{«title»:»notepad»},{«title»:»Cancel»}]

    +

    Список индексов, которые указывают на номер входящих UIO селекторов, которые были обнаружены на рабочей области. Пример: [0,2]

    -pyOpenRPA.Robot.UIDesktop.UIOSelectorsSecs_WaitDisappear_List(inSpecificationListList, inWaitSecs, inFlagWaitAllInMoment=False)[исходный код]
    -

    Wait for many UI object will disappear in GUI for inWaitSecs seconds.

    +pyOpenRPA.Robot.UIDesktop.UIOSelectorsSecs_WaitDisappear_List(inSpecificationListList, inWaitSecs=86400.0, inFlagWaitAllInMoment=False)[исходный код] +

    Ожидать исчезновение хотя бы 1-го / всех UIO объектов по заданным UIO селекторам

    +

    !ВНИМАНИЕ! ДАННАЯ ФУНКЦИОНАЛЬНОСТЬ В АВТОМАТИЧЕСКОМ РЕЖИМЕ ПОДДЕРЖИВАЕТ ВСЕ РАЗРЯДНОСТИ ПРИЛОЖЕНИЙ (32|64), КОТОРЫЕ ЗАПУЩЕНЫ В СЕСИИ. PYTHON x64 ИМЕЕТ ВОЗМОЖНОСТЬ ВЗЗАИМОДЕЙСТВИЯ С x32 UIO ОБЪЕКТАМИ, НО МЫ РЕКОМЕНДУЕМ ДОПОЛНИТЕЛЬНО ИСПОЛЬЗОВАТЬ ИНТЕРПРЕТАТОР PYTHON x32 (ПОДРОБНЕЕ СМ. ФУНКЦИЮ Configure())

    +
    # UIDesktop: Взаимодействие с UI объектами приложений
    +from pyOpenRPA.Robot import UIDesktop
    +# 1С: UIO Селектор выбора базы
    +lDemoBaseUIOSelector = [{"title":"Запуск 1С:Предприятия","class_name":"V8TopLevelFrameTaxiStarter","backend":"uia"},{"title":"DEMO", "depth_start": 5, "depth_end": 5}]         
    +lNotepadOKSelector = [{"title":"notepad"},{"title":"OK"}]
    +lNotepadCancelSelector = [{"title":"notepad"},{"title":"Cancel"}]
    +lDemoBaseUIOExistList = UIDesktop.UIOSelectorsSecs_WaitDisappear_List([lDemoBaseUIOSelector, lNotepadOKSelector, lNotepadCancelSelector]) # Ожидать исчезновение UIO объектов
    +
    +
    Параметры
      -
    • inSpecificationListList

      UIOSelector list. -Example: [

      -
      -

      [{«title»:»notepad»},{«title»:»OK»}], +

    • inSpecificationListList (list, обязательный) –

      +
      Список UIO селекторов, которые определяют критерии поиска UIO объектов

      Пример: [ +[{«title»:»notepad»},{«title»:»OK»}], [{«title»:»notepad»},{«title»:»Cancel»}]

      -
    • +
    +

    ]

    -
  • inWaitSecs – Float value (seconds) for wait UI element disappear in GUI

  • -
  • inFlagWaitAllInMoment – True - Wait all UI objects from the UIOSelector list to be disappeared.

  • +
  • inWaitSecs (float, необязательный) – Количество секунд, которые отвести на ожидание исчезновения UIO объектов. По умолчанию 24 часа (86400 секунд)

  • +
  • inFlagWaitAllInMoment – True - Ожидать до того момента, пока не исчезнут все запрашиваемые UIO объекты на рабочей области

  • Результат
    -

    List of index, which UI object UIO will be disappeared. Example: [1] # Disappear only UI object with UIO selector: [{«title»:»notepad»},{«title»:»Cancel»}]

    +

    Список индексов, которые указывают на номер входящих UIO селекторов, которые были обнаружены на рабочей области. Пример: [0,2]

    -
    Результат
    -

    +
    +
    + +
    +
    +pyOpenRPA.Robot.UIDesktop.UIOXY_SearchChild_ListDict(inRootElement, inX, inY, inHierarchyList=None)[исходный код]
    +

    Техническая функция: Получить иерархию вложенности UIO объекта по заданным корневому UIO объекту, координатам X и Y.

    +
    # UIDesktop: Взаимодействие с UI объектами приложений
    +from pyOpenRPA.Robot import UIDesktop
    +# 1С: UIO Селектор выбора базы
    +lDemoBaseUIOSelector = [{"title":"Запуск 1С:Предприятия","class_name":"V8TopLevelFrameTaxiStarter","backend":"uia"}]            
    +lUIO = UIDesktop.UIOSelector_Get_UIO(lDemoBaseUIOSelector) # Получить UIO объект с помощью UIO селектора
    +lUIOHierarchyList = UIDesktop.UIOXY_SearchChild_ListDict(lUIO, 100, 200) # Получить UIO объект с помощью UIO селектора родительского элемента и координат X / Y
    +
    +
    +
    +
    Параметры
    +
      +
    • inRootElement (object UIO, обязательный) – родительский UIO объект, полученный ранее с помощью UIO селектора.

    • +
    • inX (int, обязательный) – родительский UIO объект, полученный ранее с помощью UIO селектора.

    • +
    • inY (int, обязательный) – родительский UIO объект, полученный ранее с помощью UIO селектора.

    • +
    +
    +
    Результат
    +

    Список словарей - уровней UIO объектов

    +
    +
    +
    + +
    +
    +pyOpenRPA.Robot.UIDesktop.UIO_FocusHighlight(lWrapperObject, colour='green', thickness=2, fill=1, rect=None)[исходный код]
    +

    Установить фокус и выполнить подсветку UIO объекта на экране

    +
    # UIDesktop: Взаимодействие с UI объектами приложений
    +from pyOpenRPA.Robot import UIDesktop
    +# 1С: UIO Селектор выбора базы
    +lDemoBaseUIOSelector = [{"title":"Запуск 1С:Предприятия","class_name":"V8TopLevelFrameTaxiStarter","backend":"uia"}]            
    +lUIO = UIDesktop.UIOSelector_Get_UIO(lDemoBaseUIOSelector) # Получить UIO объект по UIO селектору
    +UIDesktop.UIO_FocusHighlight(lUIO) # Установить фокус и подсветить UIO объект по UIO селектору зеленым цветом с толщиной подсветки 2 px.
    +
    +
    +
    +
    Параметры
    +
      +
    • lWrapperObject (object UIO, обязательный) – UIO объект, который будет подсвечен

    • +
    • colour (str, необязательный) – цвет подсветки UIO объекта. Варианты: „red“, „green“, „blue“. По умолчанию „green“

    • +
    • thickness (int, необязательный) – толщина подсветки UIO объекта. По умолчанию 2

    • +
    +
    +
    +
    + +
    +
    +pyOpenRPA.Robot.UIDesktop.UIO_GetCtrlIndex_Int(inElement)[исходный код]
    +

    Получить индекс UIO объекта inElement в списке родительского UIO объекта.

    +
    # UIDesktop: Взаимодействие с UI объектами приложений
    +from pyOpenRPA.Robot import UIDesktop
    +# 1С: UIO Селектор выбора базы
    +lDemoBaseUIOSelector = [{"title":"Запуск 1С:Предприятия","class_name":"V8TopLevelFrameTaxiStarter","backend":"uia"}]            
    +lUIO = UIDesktop.UIOSelector_Get_UIO(lDemoBaseUIOSelector) # Получить UIO объект по UIO селектору.
    +lUIOIndexInt = UIDesktop.UIO_GetCtrlIndex_Int(lUIO) # Получить индекс UIO объекта в списке у родительского UIO объекта.
    +
    +
    +
    +
    Параметры
    +

    inElement (list, обязательный) – UIO объект, для которого требуется определить индекс в списке родительского UIO объекта.

    +
    +
    Результат
    +

    int, индекс UIO объекта в списке родительского UIO объекта

    +
    +
    +
    + +
    +
    +pyOpenRPA.Robot.UIDesktop.UIO_Highlight(lWrapperObject, colour='green', thickness=2, fill=1, rect=None, inFlagSetFocus=False)[исходный код]
    +

    Выполнить подсветку UIO объекта на экране

    +
    # UIDesktop: Взаимодействие с UI объектами приложений
    +from pyOpenRPA.Robot import UIDesktop
    +# 1С: UIO Селектор выбора базы
    +lDemoBaseUIOSelector = [{"title":"Запуск 1С:Предприятия","class_name":"V8TopLevelFrameTaxiStarter","backend":"uia"}]            
    +lUIO = UIDesktop.UIOSelector_Get_UIO(lDemoBaseUIOSelector) # Получить UIO объект по UIO селектору
    +UIDesktop.UIO_Highlight(lUIO) # Подсветить UIO объект по UIO селектору зеленым цветом с толщиной подсветки 2 px.
    +
    +
    +
    +
    Параметры
    +
      +
    • lWrapperObject (object UIO, обязательный) – UIO объект, который будет подсвечен

    • +
    • colour (str, необязательный) – цвет подсветки UIO объекта. Варианты: „red“, „green“, „blue“. По умолчанию „green“

    • +
    • thickness (int, необязательный) – толщина подсветки UIO объекта. По умолчанию 2

    • +
    • inFlagSetFocus (bool, необязательный) – признак установки фокуса на UIO объект перед подсветкой. По умолчанию False

    • +
    - +
    +

    Селектор UIO

    +

    Селектор UIO - адрес одного и/или более UIO объектов. Селектор представлен в формате списка (list) словарей (dict) атрибутивных критериев. Поддерживает формат JSON, что позволяет обеспечить удобство форматирования и передачи через web интерфейс студии / оркестратора.

    +

    UIO селектор — это список характеристических словарей (спецификаций UIO). Данные спецификации UIO содержат условия, с помощью которых библиотека pyOpenRPA определит UIO, удовлетворяющий условиям, заданным в спецификации UIO. Индекс спецификации UIO в списке UIO селектора харакетризует уровень вложенности целевого UIO. Говоря другим языком, UIO селектор — это перечень условий, под которые может попасть 0, 1 или n UIO.

    +

    Ниже приведен перечень атрибутов — условий, которые можно использовать в спецификациях UIO:

    +

    Формат селектора:

    +
    +
    [

    {

    +
    +

    «depth_start» :: [int, начинается с 1] :: глубина, с которой начинается поиск (по умолчанию 1),

    +

    «depth_end» :: [int, начинается с 1] :: глубина, до которой ведется поиск (по умолчанию 1),

    +

    «ctrl_index» || «index» :: [int, начинается с 0] :: индекс UIO в списке у родительского UIO,

    +

    «title» :: [str] :: идентичное наименование атрибута title искомого объекта UIO,

    +

    «title_re» :: [str] :: регулярное выражение (python диалект) для отбора UIO, у которого атрибут title должен удовлетворять условию данного регулярного выражения,

    +

    «rich_text» :: [str] :: идентичное наименование атрибута rich_text искомого объекта UIO,

    +

    «rich_text_re» :: [str] :: регулярное выражение (python диалект) для отбора UIO, у которого атрибут rich_text должен удовлетворять условию данного регулярного выражения,

    +

    «class_name» :: [str] :: идентичное наименование атрибута class_name искомого объекта UIO,

    +

    «class_name_re» :: [str] :: регулярное выражение (python диалект) для отбора UIO, у которого атрибут class_name должен удовлетворять условию данного регулярного выражения,

    +

    «friendly_class_name» :: [str] :: идентичное наименование атрибута friendly_class_name искомого объекта UIO,

    +

    «friendly_class_name_re» :: [str] :: регулярное выражение (python диалект) для отбора UIO, у которого атрибут friendly_class_name должен удовлетворять условию данного регулярного выражения,

    +

    «control_type» :: [str] :: идентичное наименование атрибута control_type искомого объекта UIO,

    +

    «control_type_re» :: [str] :: регулярное выражение (python диалект) для отбора UIO, у которого атрибут control_type должен удовлетворять условию данного регулярного выражения,

    +

    «is_enabled» :: [bool] :: признак, что UIO доступен для выполнения действий,

    +

    «is_visible» :: [bool] :: признак, что UIO отображается на экране,

    +

    «backend» :: [str, «win32» || «uia»] :: вид способа адресации к UIO (по умолчанию «win32»). Внимание! Данный атрибут может быть указан только для первого элемента списка UIO селектора. Для остальных элементов списка данный атрибут будет проигнорирован.

    +
    +

    }, +{ … спецификация UIO следующего уровня иерархии }

    -

    .. v1.2.12 replace:: v1.2.12 - .. |author| replace:: Ivan Maslov <ivan.maslov@unicodelabs.ru>

    +

    ]

    +

    Пример UIO селектора: +[

    +
    +

    {«class_name»:»CalcFrame», «backend»:»win32»}, # Спецификация UIO 1-го уровня вложенности +{«title»:»Hex», «depth_start»:3, «depth_end»: 3} # Спецификация UIO 1+3-го уровня вложенности (так как установлены атрибуты depth_start|depth_stop, определяющие глубину поиска UIO)

    +
    +

    ]

    +

    UIO объект - свойства и методы (общие)

    +
      +
    • process_id(): Возвращает идентификатор процесса, которому принадлежит это окно

    • +
    • window_text(): Текст окна элемента. Довольно много элементов управления имеют другой текст, который виден, например, элементы управления редактированием обычно имеют пустую строку для window_text, но все равно имеют текст, отображаемый в окне редактирования.

    • +
    • rectangle(): Возвращает прямоугольник элемента: {«сверху», «слева», «справа», «снизу»} Прямоугольник() - это прямоугольник элемента на экране. Координаты указаны в левом верхнем углу экрана. Этот метод возвращает прямоугольную структуру, которая имеет атрибуты - top, left, right, bottom. и имеет методы width() и height(). См. раздел win32structures.Прямую кишку для получения дополнительной информации.

    • +
    • right_click_input(coords=(None, None)): Щелкните правой кнопкой мыши на указанных координатах

    • +
    • click_input(button=“left“, coords=(None, None), button_down=True, button_up=True, double=False, wheel_dist=0, use_log=True, pressed=““, absolute=False, key_down=True, key_up=True): Щелкните по указанным координатам кнопкой мыши, чтобы щелкнуть. Один из «влево», «вправо», «посередине» или «x» (по умолчанию: «влево», «переместить» - это особый случай) определяет координаты, по которым нужно щелкнуть.(По умолчанию: центр элемента управления) дважды Укажите, следует ли выполнять двойной щелчок или нет (по умолчанию: False) wheel_dist Расстояние для перемещения колеса мыши (по умолчанию: 0) Внимание: Этот метод отличается от метода щелчка тем, что он требует, чтобы элемент управления был виден на экране, но выполняет более реалистичную симуляцию щелчка. Этот метод также уязвим, если пользователь перемещает мышь, поскольку это может легко переместить мышь с элемента управления до завершения click_input.

    • +
    • double_click_input(button=“left“, coords=(None, None)): Дважды щелкните по указанным координатам

    • +
    • press_mouse_input(button=“left“, coords=(None, None), pressed=““, absolute=True, key_down=True, key_up=True): Нажмите кнопку мыши с помощью SendInput

    • +
    • drag_mouse_input(dst=(0, 0), src=None, button=“left“, pressed=““, absolute=True): Нажмите на src, перетащите его и перетащите на dst dst - это объект-оболочка назначения или просто координаты. src - это исходный объект-оболочка или координаты. Если src равен None, self используется в качестве исходного объекта. кнопка - это кнопка мыши, которую нужно удерживать во время перетаскивания. Это может быть “влево”, “вправо”, “посередине” или “x”. Нажата клавиша на клавиатуре, которую нужно нажимать во время перетаскивания. абсолютные указывает, следует ли использовать абсолютные координаты для расположения указателя мыши

    • +
    • wheel_mouse_input(coords=(None, None), wheel_dist=1, pressed=““): Прокрутить колесо мыши

    • +
    • draw_outline(colour=“green“, thickness=2, fill=<MagicMock name=“mock.win32defines.BS_NULL“ id=“140124673757368“>, rect=None): Нарисуйте контур вокруг окна. цвет может быть либо целым числом, либо одним из «красного», «зеленого», «синего» (по умолчанию «зеленый») толщина толщина прямоугольника (по умолчанию 2) заливка как заполнить прямоугольник (по умолчанию BS_NULL) укажите координаты прямоугольника для рисования (по умолчанию используется прямоугольник элемента управления)

    • +
    • element_info: Свойство, доступное только для чтения, для получения объекта ElementInfo

    • +
    • from_point(x, y): Получить объект-оболочку для элемента в заданных координатах экрана (x, y)

    • +
    • get_properties(): Возвращает свойства элемента управления в виде словаря.

    • +
    • is_child(parent): Возвращает значение True, если этот элемент является дочерним элементом ‘parent’. Элемент является дочерним элементом другого элемента, когда он является прямым элементом другого элемента. Элемент является прямым потомком данного элемента, если родительский элемент является цепочкой родительских элементов для дочернего элемента.

    • +
    • is_dialog(): Возвращает значение True, если элемент управления является окном верхнего уровня

    • +
    • is_enabled(): Независимо от того, включен элемент или нет. Проверяет, что как родительский элемент верхнего уровня (возможно, диалоговое окно), которому принадлежит этот элемент, так и сам элемент включены.Если вы хотите дождаться, пока элемент станет включенным (или дождаться, пока он станет отключенным), используйте Application.wait(„visible“) или Application.wait_not(„visible“).Если вы хотите немедленно вызвать исключение, если элемент не включен, вы можете использовать BaseWrapper.verify_enabled(). Функция BaseWrapper.Verify Ready() вызывается, если окно одновременно не видно и не включено.

    • +
    • is_visible(): Является ли элемент видимым или нет. Проверяет, видны ли как родительский элемент верхнего уровня (возможно, диалоговое окно), которому принадлежит этот элемент, так и сам элемент. Если вы хотите дождаться, пока элемент станет видимым (или дождаться, пока он станет скрытым), используйте Application.wait(„visible“) или Application.wait_not(„visible“). Если вы хотите немедленно вызвать исключение, если элемент не виден, вы можете использовать BaseWrapper.verify_visible(). Базовая оболочка.verify_actible() вызывается, если элемент одновременно не виден и не включен.

    • +
    • parent(): Возвращает родительский элемент этого элемента Обратите внимание, что родительским элементом элемента управления не обязательно является диалоговое окно или другое главное окно. Например, поле группы может быть родительским для некоторых переключателей. Чтобы получить главное (или окно верхнего уровня), затем используйте BaseWrapper.top_level_parent().

    • +
    • root(): Возвращаемая оболочка для корневого элемента (рабочий стол)

    • +
    • set_focus(): Установить фокус на этот элемент

    • +
    • texts(): Возвращает текст для каждого элемента этого элемента управления Это список строк для элемента управления. Часто переопределяется извлечение всех строк из элемента управления с несколькими элементами. Это всегда список с одной или несколькими строками: Первый элемент - это текст окна элемента управления Последующие элементы содержат текст любых элементов элемента управления (например, элементы в listbox/combobox, вкладки в tabcontrol)

    • +
    • type_keys(keys, pause=None, with_spaces=False, with_tabs=False, with_newlines=False, turn_off_numlock=True, set_foreground=True, vk_packet=True): Введите ключи для элемента с помощью клавиатуры.send_keys. Ограниченная функциональность. Для более полной функциональности рекомендуем ознакомится с pyOpenPRA.Robot.Keyboard

    • +
    • was_maximized(): Проверить, было ли окно развернуто перед сворачиванием или нет

    • +
    +

    UIO свойства и методы (дополнение к базовым методам для win32 элементов)

    +

    Кнопка (Button || CheckBox || RadioButton || GroupBox)

    +
      +
    • check(): Установить флажок

    • +
    • uncheck(): Снять флажок

    • +
    • get_check_state(): Вернуть состояние проверки флажка. Состояние проверки представлено целым числом 0 - непроверено 1 - проверено 2 - неопределенно. Следующие константы определены в модуле win32defines BST_UNCHECKED = 0 BST_CHECKED = 1 BST_INDETERMINATE = 2

    • +
    • click(button=“left“, pressed=““, coords=(0, 0), double=False, absolute=False): Клик на кнопку управления

    • +
    • is_checked(): Возвращает True, если флажок установлен, False, если флажок не установлен, None, если значение не определено

    • +
    • is_dialog(): Кнопки никогда не являются диалоговыми окнами, поэтому возвращайте значение False

    • +
    • set_check_indeterminate(): Установить флажок в положение неопределенный

    • +
    • friendly_class_name(): Возвращает имя класса кнопки. Они могут выглядеть следующим образом: Кнопки, этот метод возвращает “Button”; Флажки, этот метод возвращает “флажок”; RadioButtons, этот метод возвращает “RadioButton”; GroupBoxes, этот метод возвращает “GroupBox”

    • +
    +

    Поле выбора нескольких значений из списка (ComboBox)

    +
      +
    • friendlyclassname = „ComboBox“

    • +
    • windowclasses = [„ComboBox“, „WindowsForms\d*.COMBOBOX..*“, „.*ComboBox“]

    • +
    • dropped_rect(): Получить выпадающий прямоугольник в поле со списком

    • +
    • get_properties(): Возвращает свойства элемента управления в виде словаря

    • +
    • item_count(): Возвращает количество элементов в поле со списком

    • +
    • item_data(item): Возвращает данные элемента, связанные с элементом, если таковые имеются

    • +
    • item_texts(): Возвращает текст элементов выпадающего списка

    • +
    • select(item): Выбрать элемент со списком элемент может быть либо индексом элемента для выбора на основе 0, либо строкой, которую вы хотите выбрать

    • +
    • selected_index(): Возвращает выбранный индекс

    • +
    • selected_text():Возвращает выделенный текст

    • +
    • texts(): Возвращает текст элементов в выпадающем списке

    • +
    +

    Поле ввода (Edit)

    +
      +
    • friendlyclassname = „Edit“

    • +
    • windowclasses = [„Edit“, „.*Edit“, „TMemo“, „WindowsForms\d*.EDIT..*“, „ThunderTextBox“, „ThunderRT6TextBox“]

    • +
    • get_line(line_index): Возвращает указанную строку

    • +
    • line_count(): Возвращает, сколько строк есть в редактировании

    • +
    • line_length(line_index): Возвращает количество символов в строке

    • +
    • select(start=0, end=None): Установите выбор редактирования элемента управления редактированием

    • +
    • selection_indices(): Начальный и конечный индексы текущего выбора

    • +
    • set_edit_text(text, pos_start=None, pos_end=None): Задать текст элемента управления редактированием

    • +
    • set_text(text, pos_start=None, pos_end=None): Задать текст элемента управления редактированием

    • +
    • set_window_text(text, append=False): Переопределите set_window_text для элементов управления редактированием, поскольку он не должен использоваться для элементов управления редактированием. Элементы управления редактированием должны использовать либо set_edit_text(), либо type_keys() для изменения содержимого элемента управления редактированием.

    • +
    • text_block(): Получить текст элемента управления редактированием

    • +
    • texts(): Получить текст элемента управления редактированием

    • +
    +

    Поле выбора 1-го значения из списка (ListBox)

    +
      +
    • friendlyclassname = „ListBox“

    • +
    • windowclasses = [„ListBox“, „WindowsForms\d*.LISTBOX..*“, „.*ListBox“]

    • +
    • get_item_focus(): Возвращает индекс текущего выбора в списке

    • +
    • is_single_selection(): Проверить, имеет ли поле списка режим одиночного выбора

    • +
    • item_count(): Возвращает количество элементов в списке

    • +
    • item_data(i): Возвращает item_data, если таковые имеются, связанные с элементом

    • +
    • item_texts(): Возвращает текст элементов списка

    • +
    • select(item, select=True): Выбрать элемент списка элемент может быть либо индексом элемента для выбора на основе 0, либо строкой, которую вы хотите выбрать

    • +
    • selected_indices(): Выбранные в данный момент индексы списка

    • +
    • set_item_focus(item): Установить фокус по элементу

    • +
    • texts(): Получить текст элемента управления редактированием

    • +
    +

    Выпадающее меню (PopupMenu)

    +
      +
    • friendlyclassname = „PopupMenu“

    • +
    • windowclasses = [„#32768“]

    • +
    • is_dialog(): Возвращает, является ли это диалогом

    • +
    +

    Текст (Static)

    +
      +
    • friendlyclassname= „Static“

    • +
    • windowclasses= [„Static“, „WindowsForms\d*.STATIC..*“, „TPanel“, „.*StaticText“]

    • +
    +

    Инициализация 2-х разрядностей для UIO

    +

    pyOpenRPA позволяет обеспечить максимальную совместимость со всеми приложениями, которые выполняются на компьютере. Мы рекомендуем разрабатывать робота под интерпретатором Python x64. В дополнение к нему Вы можете подключить Python x32 (см. ниже пример подключения). Если планируемый робот не будет взаимодействовать через pyOpenRPA.Robot.UIDesktop с другой разрядность, то эту настройку можно не применять.

    +
    from pyOpenRPA.Robot import UIDesktop
    +# В нашем случае процесс робота будет исполняться на Python x64. Дополнительно подключим Python x32 (делать это только, если вы планируете работать в другой разрядностью в рамках робота)
    +lPyOpenRPA_SettingsDict = {
    +        "Python32FullPath": "..\\Resources\\WPy32-3720\\python-3.7.2\\python.exe",# Путь к интерпретатору Python.exe x32
    +        "Python64FullPath": "..\\Resources\\WPy64-3720\\python-3.7.2.amd64\\python.exe", # Путь к интерпретатору Python.exe x64
    +        "Python32ProcessName": "pyOpenRPA_UIDesktopX32.exe", # Наименование процесса робота x32 в диспетчере задач. Установите свое наименование
    +        "Python64ProcessName": "pyOpenRPA_UIDesktopX64.exe" # Наименование процесса робота x64 в диспетчере задач. Установите свое наименование
    +}
    +# Инициализировать 2-й разрядность.
    +UIDesktop.Utils.ProcessBitness.SettingsInit(lPyOpenRPA_SettingsDict)
    +# Теперь при вызове функций pyOpenRPA.Robot.UIDesktop платформа pyOpenRPA будет отслеживать разрядность приложения и отправлять соответсвующий вызов на идентичную разрядность.
    +
    +
    +
    + @@ -665,8 +1270,8 @@ Example: [