uipath 0.0.1__py3-none-any.whl → 1.1.1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of uipath might be problematic. Click here for more details.
- uipath/__init__.py +9 -1
- uipath/__version__.py +3 -0
- {uipath-0.0.1.dist-info → uipath-1.1.1.dist-info}/LICENSE +2 -2
- uipath-1.1.1.dist-info/METADATA +177 -0
- uipath-1.1.1.dist-info/RECORD +7 -0
- {uipath-0.0.1.dist-info → uipath-1.1.1.dist-info}/WHEEL +5 -5
- uipath/sequence.py +0 -483
- uipath/uipath.py +0 -483
- uipath-0.0.1.dist-info/METADATA +0 -21
- uipath-0.0.1.dist-info/RECORD +0 -8
- {uipath-0.0.1.dist-info → uipath-1.1.1.dist-info}/top_level.txt +0 -0
uipath/__init__.py
CHANGED
uipath/__version__.py
ADDED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
MIT License
|
|
2
2
|
|
|
3
|
-
Copyright (c)
|
|
3
|
+
Copyright (c) 2024 Your Name
|
|
4
4
|
|
|
5
5
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
6
|
of this software and associated documentation files (the "Software"), to deal
|
|
@@ -18,4 +18,4 @@ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
|
18
18
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
19
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
20
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
-
SOFTWARE.
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,177 @@
|
|
|
1
|
+
Metadata-Version: 2.2
|
|
2
|
+
Name: uipath
|
|
3
|
+
Version: 1.1.1
|
|
4
|
+
Summary: A Python SDK for UiPath
|
|
5
|
+
Home-page: https://github.com/christianblandford/uipath
|
|
6
|
+
Author: Christian Blandford
|
|
7
|
+
Author-email: christianblandford@me.com
|
|
8
|
+
Keywords: uipath,rpa,robotic process automation,automation,robotics,orchestrator,process-automation,api-client,api-wrapper,uipath-api,uipath-orchestrator,workflow-automation
|
|
9
|
+
Classifier: Development Status :: 3 - Alpha
|
|
10
|
+
Classifier: Intended Audience :: Developers
|
|
11
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
12
|
+
Classifier: Operating System :: OS Independent
|
|
13
|
+
Classifier: Programming Language :: Python :: 3
|
|
14
|
+
Classifier: Programming Language :: Python :: 3.7
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.8
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
19
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
20
|
+
Requires-Python: >=3.7
|
|
21
|
+
Description-Content-Type: text/markdown
|
|
22
|
+
License-File: LICENSE
|
|
23
|
+
Requires-Dist: requests>=2.25.0
|
|
24
|
+
Provides-Extra: dev
|
|
25
|
+
Requires-Dist: mkdocs-material; extra == "dev"
|
|
26
|
+
Requires-Dist: mkdocs-autorefs; extra == "dev"
|
|
27
|
+
Requires-Dist: mkdocstrings[python]; extra == "dev"
|
|
28
|
+
Dynamic: author
|
|
29
|
+
Dynamic: author-email
|
|
30
|
+
Dynamic: classifier
|
|
31
|
+
Dynamic: description
|
|
32
|
+
Dynamic: description-content-type
|
|
33
|
+
Dynamic: home-page
|
|
34
|
+
Dynamic: keywords
|
|
35
|
+
Dynamic: provides-extra
|
|
36
|
+
Dynamic: requires-dist
|
|
37
|
+
Dynamic: requires-python
|
|
38
|
+
Dynamic: summary
|
|
39
|
+
|
|
40
|
+
# 🤖 UiPath Python SDK
|
|
41
|
+
|
|
42
|
+
The most awesome Python SDK for UiPath Orchestrator! Automate all the things with simple Python code.
|
|
43
|
+
|
|
44
|
+
[](https://badge.fury.io/py/uipath)
|
|
45
|
+
[](https://christianblandford.github.io/uipath/)
|
|
46
|
+
|
|
47
|
+
## 🚀 Quick Install
|
|
48
|
+
|
|
49
|
+
```bash
|
|
50
|
+
pip install uipath
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
## ⚡ Quick Start
|
|
54
|
+
|
|
55
|
+
```python
|
|
56
|
+
from uipath import UiPathClient
|
|
57
|
+
|
|
58
|
+
# Connect to UiPath in just 3 lines! 🎉
|
|
59
|
+
client = UiPathClient(
|
|
60
|
+
organization_id="your_organization_id",
|
|
61
|
+
tenant_id="your_tenant_id",
|
|
62
|
+
client_id="your_client_id",
|
|
63
|
+
client_secret="your_client_secret"
|
|
64
|
+
)
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
## 🎯 Why Choose This SDK?
|
|
68
|
+
|
|
69
|
+
- 🔥 **Complete API Coverage** - Access everything UiPath Orchestrator offers
|
|
70
|
+
- 🎈 **Super Simple Interface** - Designed for humans, by humans
|
|
71
|
+
- 🛡️ **Type Hints** - Get awesome IDE support
|
|
72
|
+
- 📚 **Amazing Docs** - [Check them out here!](https://christianblandford.github.io/uipath/)
|
|
73
|
+
|
|
74
|
+
## 🎨 Features
|
|
75
|
+
|
|
76
|
+
Manage all your UiPath resources with Python:
|
|
77
|
+
|
|
78
|
+
- 🤖 Robots
|
|
79
|
+
- 📦 Packages
|
|
80
|
+
- 📋 Jobs
|
|
81
|
+
- 📁 Folders
|
|
82
|
+
- 🎮 Processes
|
|
83
|
+
- 🔑 Assets
|
|
84
|
+
- 📥 Queues
|
|
85
|
+
- 📚 Libraries
|
|
86
|
+
- 💻 Machines
|
|
87
|
+
- ...and more!
|
|
88
|
+
|
|
89
|
+
## 📖 Examples
|
|
90
|
+
|
|
91
|
+
### Managing Robots
|
|
92
|
+
|
|
93
|
+
```python
|
|
94
|
+
# List all your robot friends
|
|
95
|
+
robots = client.robots.get_all()
|
|
96
|
+
|
|
97
|
+
# Create a new robot buddy
|
|
98
|
+
new_robot = client.robots.create({
|
|
99
|
+
"Name": "Wall-E",
|
|
100
|
+
"Type": "Unattended",
|
|
101
|
+
"Username": "domain\\wall-e"
|
|
102
|
+
})
|
|
103
|
+
|
|
104
|
+
# Update robot status
|
|
105
|
+
client.robots.toggle_enabled(robot_id=123, enabled=True)
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
### Working with Queues
|
|
109
|
+
|
|
110
|
+
```python
|
|
111
|
+
# Add items to your queue
|
|
112
|
+
client.queues.add_queue_item(
|
|
113
|
+
queue_name="TPS_Reports",
|
|
114
|
+
reference="TPS-001",
|
|
115
|
+
priority="High",
|
|
116
|
+
specific_content={
|
|
117
|
+
"ReportNumber": "TPS-001",
|
|
118
|
+
"Urgent": True
|
|
119
|
+
}
|
|
120
|
+
)
|
|
121
|
+
|
|
122
|
+
# Process queue items
|
|
123
|
+
items = client.queues.get_queue_items(
|
|
124
|
+
queue_name="TPS_Reports",
|
|
125
|
+
status="New"
|
|
126
|
+
)
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
## 🔧 Configuration
|
|
130
|
+
|
|
131
|
+
```python
|
|
132
|
+
client = UiPathClient(
|
|
133
|
+
organization_id="org_id",
|
|
134
|
+
tenant_id="tenant_id",
|
|
135
|
+
client_id="client_id",
|
|
136
|
+
client_secret="shhh_its_a_secret",
|
|
137
|
+
base_url="https://cloud.uipath.com" # Optional
|
|
138
|
+
)
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
## 📚 Documentation
|
|
142
|
+
|
|
143
|
+
For full documentation, visit our [awesome docs page](https://christianblandford.github.io/uipath/)!
|
|
144
|
+
|
|
145
|
+
## 🤝 Contributing
|
|
146
|
+
|
|
147
|
+
We love contributions! Here's how:
|
|
148
|
+
|
|
149
|
+
1. 🍴 Fork it
|
|
150
|
+
2. 🌱 Create your feature branch (`git checkout -b feature/CoolFeature`)
|
|
151
|
+
3. 💾 Commit your changes (`git commit -m 'Add CoolFeature'`)
|
|
152
|
+
4. 📤 Push to the branch (`git push origin feature/CoolFeature`)
|
|
153
|
+
5. 🎁 Open a Pull Request
|
|
154
|
+
|
|
155
|
+
## 📝 License
|
|
156
|
+
|
|
157
|
+
MIT License - go wild! See [LICENSE](LICENSE) for more details.
|
|
158
|
+
|
|
159
|
+
## 💪 Support
|
|
160
|
+
|
|
161
|
+
Need help? We've got your back!
|
|
162
|
+
|
|
163
|
+
1. 📚 [Check out our docs](https://christianblandford.github.io/uipath/)
|
|
164
|
+
2. 🎫 [Open an issue](https://github.com/christianblandford/uipath/issues)
|
|
165
|
+
3. 💬 [Start a discussion](https://github.com/christianblandford/uipath/discussions)
|
|
166
|
+
|
|
167
|
+
## ⚡ Requirements
|
|
168
|
+
|
|
169
|
+
- Python 3.7+
|
|
170
|
+
- A love for automation! 🤖
|
|
171
|
+
|
|
172
|
+
## 📢 Disclaimer
|
|
173
|
+
|
|
174
|
+
This is an unofficial SDK created with ❤️ by the community. Not affiliated with UiPath Inc.
|
|
175
|
+
|
|
176
|
+
---
|
|
177
|
+
Made with 🦾 by developers, for developers
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
uipath/__init__.py,sha256=j2gsFvg5BudvoZxfNncyip-FBq9PqdM39hvCJzS6k0k,215
|
|
2
|
+
uipath/__version__.py,sha256=Q1SV_A_xAMGhRrDOq-kOmB2-vbVwqaYR7R11-BM4jq8,63
|
|
3
|
+
uipath-1.1.1.dist-info/LICENSE,sha256=FyuBsNr3YLXHPRQfWIpCAC4brUeSdYelr01V-Fkog8U,1066
|
|
4
|
+
uipath-1.1.1.dist-info/METADATA,sha256=vuwysUqqyDmdjLWXbmsXaGwEgdOFH3d1LdMtv6IxR7w,4675
|
|
5
|
+
uipath-1.1.1.dist-info/WHEEL,sha256=In9FTNxeP60KnTkGw7wk6mJPYd_dQSjEZmXdBdMCI-8,91
|
|
6
|
+
uipath-1.1.1.dist-info/top_level.txt,sha256=cO-fuTo_YlozqaZ6VNk0ST79wuBjLkcTRzYpXLM6rRg,7
|
|
7
|
+
uipath-1.1.1.dist-info/RECORD,,
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
Wheel-Version: 1.0
|
|
2
|
-
Generator:
|
|
3
|
-
Root-Is-Purelib: true
|
|
4
|
-
Tag: py3-none-any
|
|
5
|
-
|
|
1
|
+
Wheel-Version: 1.0
|
|
2
|
+
Generator: setuptools (75.8.0)
|
|
3
|
+
Root-Is-Purelib: true
|
|
4
|
+
Tag: py3-none-any
|
|
5
|
+
|
uipath/sequence.py
DELETED
|
@@ -1,483 +0,0 @@
|
|
|
1
|
-
from bs4 import BeautifulSoup
|
|
2
|
-
|
|
3
|
-
class Sequence:
|
|
4
|
-
def __init__(self, file):
|
|
5
|
-
self.file = file
|
|
6
|
-
|
|
7
|
-
self.init_vars() # load all the vars from the xaml file
|
|
8
|
-
|
|
9
|
-
#Initializes all variables for the class file
|
|
10
|
-
def init_vars(self):
|
|
11
|
-
self.xaml = self.read_xaml() # Read xaml file
|
|
12
|
-
self.name = self.get_class_name() # get class name from XAML file
|
|
13
|
-
self.arguments = self.build_arguments(self.get_arguments())
|
|
14
|
-
self.sequences = self.create_sequences(self.get_sequences())
|
|
15
|
-
|
|
16
|
-
#Gets the existing XAML
|
|
17
|
-
def get_xaml(self):
|
|
18
|
-
return self.xaml
|
|
19
|
-
|
|
20
|
-
#Reads an XAML file
|
|
21
|
-
def read_xaml(self):
|
|
22
|
-
infile = open(self.file, "r")
|
|
23
|
-
data = infile.read()
|
|
24
|
-
infile.close()
|
|
25
|
-
|
|
26
|
-
data = data[data.find("<"):len(data)] # remove garbage from start of file
|
|
27
|
-
xaml = BeautifulSoup(data, "xml");
|
|
28
|
-
return xaml
|
|
29
|
-
|
|
30
|
-
#Updates a node of the XAML stored in memory
|
|
31
|
-
def update_xaml_node(self, node, new_xaml):
|
|
32
|
-
self.xaml = new_xaml
|
|
33
|
-
self.save()
|
|
34
|
-
|
|
35
|
-
#Saves the raw XAML in memory to the XAML file
|
|
36
|
-
def save(self):
|
|
37
|
-
#First we need to strip the <XML> tag that our xaml parser adds
|
|
38
|
-
xml_string = '<?xml version="1.0" encoding="utf-8"?>\n' # The XML encoding tag we need to remove
|
|
39
|
-
data = str(self.xaml).replace(xml_string, "", 1)
|
|
40
|
-
|
|
41
|
-
file = open(self.file,"w+")
|
|
42
|
-
file.write(str(data))
|
|
43
|
-
file.close()
|
|
44
|
-
|
|
45
|
-
return file
|
|
46
|
-
|
|
47
|
-
#Get classname from raw XAML
|
|
48
|
-
def get_class_name(self):
|
|
49
|
-
return self.xaml.find_all("Activity")[0]["x:Class"]
|
|
50
|
-
|
|
51
|
-
#Sets a class name for the file
|
|
52
|
-
def set_class_name(self, new_name):
|
|
53
|
-
self.xaml.find("Activity")["x:Class"] = new_name
|
|
54
|
-
self.save()
|
|
55
|
-
return new_name
|
|
56
|
-
|
|
57
|
-
#Returns the first sequece/block/whatever in the class. The outmost layer
|
|
58
|
-
def get_first_block(self):
|
|
59
|
-
return self.xaml.find("TextExpression.ReferencesForImplementation").next_sibling.next_sibling
|
|
60
|
-
|
|
61
|
-
#Get annotation for node
|
|
62
|
-
def get_annotation(self, node):
|
|
63
|
-
return node["sap2010:Annotation.AnnotationText"]
|
|
64
|
-
|
|
65
|
-
#Set annotation for node
|
|
66
|
-
def set_annotation(self, node, text):
|
|
67
|
-
node["sap2010:Annotation.AnnotationText"] = text
|
|
68
|
-
self.save()
|
|
69
|
-
|
|
70
|
-
#Gets node name
|
|
71
|
-
def get_node_name(self, node):
|
|
72
|
-
return node["DisplayName"]
|
|
73
|
-
|
|
74
|
-
#Sets node name
|
|
75
|
-
def set_node_name(self, node, new_name):
|
|
76
|
-
node["DisplayName"] = new_name
|
|
77
|
-
return new_name
|
|
78
|
-
|
|
79
|
-
#Returns an argument by name
|
|
80
|
-
def get_argument_by_name(self, name):
|
|
81
|
-
if not self.arguments is None:
|
|
82
|
-
for item in self.arguments:
|
|
83
|
-
if item.name == name:
|
|
84
|
-
return item
|
|
85
|
-
|
|
86
|
-
#Gets arguments of sequence
|
|
87
|
-
def get_arguments(self):
|
|
88
|
-
return self.xaml.find_all("x:Property")
|
|
89
|
-
|
|
90
|
-
#Builds the argument objects for the main class
|
|
91
|
-
def build_arguments(self, argument_list):
|
|
92
|
-
if not argument_list is None and len(argument_list) > 0:
|
|
93
|
-
args = []
|
|
94
|
-
for item in argument_list:
|
|
95
|
-
args.append(Sequence.Argument(self, item))
|
|
96
|
-
return args
|
|
97
|
-
|
|
98
|
-
#Creates and adds a new argument for the sequence
|
|
99
|
-
def add_argument(self, name, string_direction, datatype):
|
|
100
|
-
new_arg = self.xaml.new_tag("x:Property")
|
|
101
|
-
new_arg["Name"] = name
|
|
102
|
-
|
|
103
|
-
#build XAML friendly variables for the passed in arguments
|
|
104
|
-
new_arg_type_end = ")"
|
|
105
|
-
if string_direction == "in":
|
|
106
|
-
new_arg_type_start = "InArgument("
|
|
107
|
-
elif string_direction == "out":
|
|
108
|
-
new_arg_type_start = "OutArgument("
|
|
109
|
-
elif string_direction == "io":
|
|
110
|
-
new_arg_type_start = "InOutArgument("
|
|
111
|
-
else:
|
|
112
|
-
new_arg_type_end = ""
|
|
113
|
-
new_arg_type_start = ""
|
|
114
|
-
|
|
115
|
-
# Type="InArgument(scg:Dictionary(x:String, x:Object))"
|
|
116
|
-
new_arg["Type"] = new_arg_type_start + datatype + new_arg_type_end
|
|
117
|
-
|
|
118
|
-
#Add to array in XAML
|
|
119
|
-
self.xaml.find("x:Members").append(new_arg)
|
|
120
|
-
#Rebuild all arguments from the XAML
|
|
121
|
-
self.arguments = self.build_arguments(self.get_arguments())
|
|
122
|
-
|
|
123
|
-
self.save()
|
|
124
|
-
|
|
125
|
-
#Gets a block by its Displayname
|
|
126
|
-
def get_node_by_display_name(self, display_name):
|
|
127
|
-
return self.xaml.find(DisplayName=display_name)
|
|
128
|
-
|
|
129
|
-
#Gets nested sequences
|
|
130
|
-
def get_sequences(self):
|
|
131
|
-
return self.xaml.find_all("Sequence")
|
|
132
|
-
|
|
133
|
-
#Builds the argument objects for the main class
|
|
134
|
-
def create_sequences(self, sequence_list):
|
|
135
|
-
if not sequence_list is None and len(sequence_list) > 0:
|
|
136
|
-
sequences = []
|
|
137
|
-
for item in sequence_list:
|
|
138
|
-
sequences.append(Sequence.Inner_Sequence(self, item))
|
|
139
|
-
return sequences
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
#To String.
|
|
143
|
-
def __str__(self):
|
|
144
|
-
to_return = "{" + "\n"
|
|
145
|
-
for key in self.__dict__.keys():
|
|
146
|
-
if key != "xaml":
|
|
147
|
-
if isinstance(self.__dict__[key], (list,)):
|
|
148
|
-
to_return = to_return + "\t" + key + ": [" + "\n"
|
|
149
|
-
for item in self.__dict__[key]:
|
|
150
|
-
to_return = to_return + "\t\t" + str(item) + "\n"
|
|
151
|
-
to_return = to_return + "\t]" + "\n"
|
|
152
|
-
else:
|
|
153
|
-
to_return = to_return + "\t" + key + ":" + str(self.__dict__[key]) + "\n"
|
|
154
|
-
|
|
155
|
-
to_return = to_return + "}"
|
|
156
|
-
return to_return
|
|
157
|
-
|
|
158
|
-
#-----------------------------------------------------------------------------------------------------------------------
|
|
159
|
-
# Subclass: Variable
|
|
160
|
-
# Description: Stores the data about a variable in a sequence
|
|
161
|
-
#-----------------------------------------------------------------------------------------------------------------------
|
|
162
|
-
class Variable():
|
|
163
|
-
def __init__(self, parent=None, xaml = None, name=None, type_arg=None, default=None):
|
|
164
|
-
self.parent = parent #Store the calling sequence
|
|
165
|
-
|
|
166
|
-
#If xaml was passed in just use that
|
|
167
|
-
self.xaml = xaml
|
|
168
|
-
if not self.xaml is None:
|
|
169
|
-
self.name = self.xaml["Name"]
|
|
170
|
-
self.type = self.xaml["x:TypeArguments"]
|
|
171
|
-
#Else build new xaml based on the name and type passed in
|
|
172
|
-
else:
|
|
173
|
-
self.name = name
|
|
174
|
-
self.type = type_arg
|
|
175
|
-
self.default = default
|
|
176
|
-
self.xaml = self.build_xaml()
|
|
177
|
-
|
|
178
|
-
#Builds XAML for a name and type
|
|
179
|
-
def build_xaml(self):
|
|
180
|
-
new_node = self.parent.xaml.new_tag("Variable") # have the beautiful soup instance from the parent create a new tag
|
|
181
|
-
new_node["Name"] = self.name
|
|
182
|
-
new_node["x:TypeArguments"] = self.type
|
|
183
|
-
if not self.default is None:
|
|
184
|
-
new_node["Default"] = self.default
|
|
185
|
-
return new_node
|
|
186
|
-
|
|
187
|
-
#-----------------------------------------------------------------------------------------------------------------------
|
|
188
|
-
# Subclass: Argument
|
|
189
|
-
# Description: Stores the arguments and their default values from the xaml file
|
|
190
|
-
#-----------------------------------------------------------------------------------------------------------------------
|
|
191
|
-
|
|
192
|
-
#Define subclass for the arguments
|
|
193
|
-
class Argument():
|
|
194
|
-
def __init__(self, outer_sequence, xaml, default_value=None):
|
|
195
|
-
self.outer_sequence = outer_sequence #the containing sequence
|
|
196
|
-
|
|
197
|
-
self.xaml = xaml
|
|
198
|
-
self.init_vars()
|
|
199
|
-
self.default_value = self.get_default_value_for_attr()
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
#Creates a new argument
|
|
203
|
-
|
|
204
|
-
#Get default value for attribute
|
|
205
|
-
def get_default_value_for_attr(self):
|
|
206
|
-
values_string = self.outer_sequence.xaml.find_all("Activity")[0]
|
|
207
|
-
key = "this:" + self.outer_sequence.name + "." + self.name
|
|
208
|
-
|
|
209
|
-
if key in values_string:
|
|
210
|
-
return values_string["this:" + self.outer_sequence.name + "." + self.name]
|
|
211
|
-
|
|
212
|
-
#Decodes XAML into python friendly strings
|
|
213
|
-
def init_vars(self):
|
|
214
|
-
self.name = self.xaml["Name"]
|
|
215
|
-
self.direction = self.get_direction_from_xaml()
|
|
216
|
-
self.type = self.get_datatype_from_xaml()
|
|
217
|
-
|
|
218
|
-
#Converts string direction to xaml direction
|
|
219
|
-
def convert_string_direction_to_xaml(self, string_direction):
|
|
220
|
-
if string_direction == "in":
|
|
221
|
-
return "InArgument"
|
|
222
|
-
elif string_direction == "out":
|
|
223
|
-
return "OutArgument"
|
|
224
|
-
elif string_direction == "io":
|
|
225
|
-
return "InOutArgument"
|
|
226
|
-
else:
|
|
227
|
-
return "Property"
|
|
228
|
-
|
|
229
|
-
#Gets direction of argument
|
|
230
|
-
def get_direction_from_xaml(self):
|
|
231
|
-
temp = self.xaml["Type"]
|
|
232
|
-
|
|
233
|
-
if "InArgument" in temp:
|
|
234
|
-
return "InArgument"
|
|
235
|
-
elif "OutArgument" in temp:
|
|
236
|
-
return "OutArgument"
|
|
237
|
-
elif "InOutArgument" in temp:
|
|
238
|
-
return "InOutArgument"
|
|
239
|
-
else:
|
|
240
|
-
return "Property"
|
|
241
|
-
|
|
242
|
-
#Gets the datatype of the argument
|
|
243
|
-
def get_datatype_from_xaml(self):
|
|
244
|
-
return self.xaml["Type"].replace("(", "").replace(")", "").replace(self.direction, "")
|
|
245
|
-
|
|
246
|
-
#Sets a new name value for this Class instance, as well as updating the parent raw XAML.
|
|
247
|
-
def set_name(self, new_name):
|
|
248
|
-
self.update_default_value_name(self.name, new_name)
|
|
249
|
-
self.xaml["Name"] = new_name
|
|
250
|
-
self.name = new_name
|
|
251
|
-
self.update_outer_sequence()
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
#Sets a new direction value for this Class instance, as well as updating the parent raw XAML.
|
|
255
|
-
def set_direction(self, direction_string):
|
|
256
|
-
self.direction = direction_string #update class' variable
|
|
257
|
-
|
|
258
|
-
new_direction_xaml = ""
|
|
259
|
-
if self.direction == "InArgument":
|
|
260
|
-
new_direction_xaml = "InArgument(" + self.type + ")"
|
|
261
|
-
elif self.direction == "InOutArgument":
|
|
262
|
-
self.delete_default_value() #delete default value as it is not supported by this direction type
|
|
263
|
-
new_direction_xaml = "InOutArgument(" + self.type + ")"
|
|
264
|
-
elif self.direction == "OutArgument":
|
|
265
|
-
self.delete_default_value() #delete default value as it is not supported by this direction type
|
|
266
|
-
new_direction_xaml = "OutArgument(" + self.type + ")"
|
|
267
|
-
else:
|
|
268
|
-
new_direction_xaml = self.type
|
|
269
|
-
|
|
270
|
-
self.xaml["Type"] = new_direction_xaml
|
|
271
|
-
self.update_outer_sequence()
|
|
272
|
-
|
|
273
|
-
#Creates a default value when one does not yet exist
|
|
274
|
-
#STUB
|
|
275
|
-
|
|
276
|
-
#Sets a new default value for this Class instance, as well as updating the parent raw XAML.
|
|
277
|
-
def update_default_value(self, new_value):
|
|
278
|
-
self.default_value = new_value
|
|
279
|
-
values_string = self.outer_sequence.xaml.find_all("Activity")[0]
|
|
280
|
-
values_string["this:" + self.outer_sequence.name + "." + self.name] = new_value
|
|
281
|
-
self.update_outer_sequence()
|
|
282
|
-
|
|
283
|
-
#Changes the name of default values to match the argument name when it is changed
|
|
284
|
-
def update_default_value_name(self, old_name, new_name):
|
|
285
|
-
values_string = self.outer_sequence.xaml.find_all("Activity")[0]
|
|
286
|
-
key = "this:" + self.outer_sequence.name + "." + self.name
|
|
287
|
-
|
|
288
|
-
if key in values_string:
|
|
289
|
-
self.delete_default_value()
|
|
290
|
-
values_string["this:" + self.outer_sequence.name + "." + new_name] = self.default_value
|
|
291
|
-
#values_string["this:" + self.outer_sequence.name + "." + self.name] = new_value
|
|
292
|
-
|
|
293
|
-
#Deletes the default value
|
|
294
|
-
def delete_default_value(self):
|
|
295
|
-
values_string = self.outer_sequence.xaml.find_all("Activity")[0]
|
|
296
|
-
key = "this:" + self.outer_sequence.name + "." + self.name
|
|
297
|
-
|
|
298
|
-
if key in values_string:
|
|
299
|
-
del self.outer_sequence.xaml.find_all("Activity")[0]["this:" + self.outer_sequence.name + "." + self.name]
|
|
300
|
-
|
|
301
|
-
if not self.default_value is None:
|
|
302
|
-
del self.default_value
|
|
303
|
-
|
|
304
|
-
#Update parent Sequence XAML. Do this when using any setter method defined above
|
|
305
|
-
def update_outer_sequence(self):
|
|
306
|
-
#if not self.outer_sequence.xaml.find(attrs={"Name":self.name})["Name"] is None:
|
|
307
|
-
self.outer_sequence.xaml.find(attrs={"Name":self.name}).replace_with(self.xaml)
|
|
308
|
-
self.outer_sequence.save()
|
|
309
|
-
|
|
310
|
-
#override to string method
|
|
311
|
-
def __str__(self):
|
|
312
|
-
if self.default_value is None: # check if self has default_value
|
|
313
|
-
return "{name: \"" + self.name + "\", direction: \"" + self.direction + "\", type: \"" + self.type + "\"}"
|
|
314
|
-
else:
|
|
315
|
-
return "{name: \"" + self.name + "\", direction: \"" + self.direction + "\", type: \"" + self.type + "\", default_value: \"" + self.default_value + "\"}"
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
#-----------------------------------------------------------------------------------------------------------------------
|
|
319
|
-
# Subclass: Argument
|
|
320
|
-
# Description: Stores the arguments and their default values from the xaml file
|
|
321
|
-
#-----------------------------------------------------------------------------------------------------------------------
|
|
322
|
-
|
|
323
|
-
#Define subclass for the arguments
|
|
324
|
-
class Inner_Sequence():
|
|
325
|
-
def __init__(self, outer_sequence, xaml):
|
|
326
|
-
self.outer_sequence = outer_sequence
|
|
327
|
-
self.xaml = xaml
|
|
328
|
-
self.id = xaml["sap2010:WorkflowViewState.IdRef"]
|
|
329
|
-
self.get_invoked_workflow()
|
|
330
|
-
self.variables = self.get_sequence_variables()
|
|
331
|
-
|
|
332
|
-
#Get the invoked workflow for the sequences, if applicable
|
|
333
|
-
def get_invoked_workflow(self):
|
|
334
|
-
self.invoked_workflow = self.xaml.find("ui:InvokeWorkflowFile")
|
|
335
|
-
|
|
336
|
-
if not self.invoked_workflow is None:
|
|
337
|
-
#Get path to invoked workflow
|
|
338
|
-
self.invoked_workflow_path = self.invoked_workflow["WorkflowFileName"]
|
|
339
|
-
|
|
340
|
-
#get arguments of invoked workflow
|
|
341
|
-
self.invoked_workflow_arguments_xaml = self.invoked_workflow.find("ui:InvokeWorkflowFile.Arguments")
|
|
342
|
-
|
|
343
|
-
if len(self.invoked_workflow_arguments_xaml.findChildren()) > 0:
|
|
344
|
-
self.invoked_workflow_arguments = []
|
|
345
|
-
for index,child in enumerate(self.invoked_workflow_arguments_xaml.findChildren()):
|
|
346
|
-
self.invoked_workflow_arguments.append(Sequence.Inner_Sequence.Invoked_Workflow_Argument(self, child, index))
|
|
347
|
-
|
|
348
|
-
#Get variables in this sequence
|
|
349
|
-
def get_sequence_variables(self):
|
|
350
|
-
vars_from_xaml = self.xaml.find_all("Variable")
|
|
351
|
-
|
|
352
|
-
#If there are any variables, we will build an array of variable objects and return them
|
|
353
|
-
if len(vars_from_xaml) > 0:
|
|
354
|
-
all_vars = []
|
|
355
|
-
|
|
356
|
-
for item in self.xaml.find_all("Variable"):
|
|
357
|
-
all_vars.append(self.outer_sequence.Variable(self.outer_sequence, xaml=item))
|
|
358
|
-
|
|
359
|
-
return all_vars
|
|
360
|
-
|
|
361
|
-
#Add variable to sequence
|
|
362
|
-
def create_variable(self, xaml=None, name=None, type=None, default=None):
|
|
363
|
-
#If xaml is None, build new BS node
|
|
364
|
-
if xaml is None:
|
|
365
|
-
xaml = self.outer_sequence.xaml.new_tag("Variable")
|
|
366
|
-
xaml["Name"] = name
|
|
367
|
-
xaml["x:TypeArguments"] = type
|
|
368
|
-
|
|
369
|
-
if not default is None:
|
|
370
|
-
xaml["Default"] = default
|
|
371
|
-
|
|
372
|
-
self.xaml.find("Sequence.Variables").append(xaml) #Add new variable to xaml file
|
|
373
|
-
self.variables = self.get_sequence_variables() #Regenerate vars from xaml
|
|
374
|
-
self.update_outer_sequence()
|
|
375
|
-
|
|
376
|
-
return xaml #return the new variable
|
|
377
|
-
|
|
378
|
-
#Deletes a variable by name
|
|
379
|
-
def delete_variable(self, var_name):
|
|
380
|
-
self.xaml.find_all("Variable", Name=var_name)[0].decompose() #Deletes the variable from the XAML
|
|
381
|
-
self.variables = self.get_sequence_variables() #Regenerate vars from xaml
|
|
382
|
-
self.update_outer_sequence()
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
#Imports arguments from invoked function. Just like the button in UiPath
|
|
386
|
-
def import_arguments(self):
|
|
387
|
-
#Clear the array of invoked workflow argument objects
|
|
388
|
-
self.invoked_workflow_arguments = []
|
|
389
|
-
self.invoked_workflow_arguments_xaml.clear()
|
|
390
|
-
#clear the array of
|
|
391
|
-
invoked_sequence = Sequence(self.invoked_workflow_path) #Load the invoked sequence
|
|
392
|
-
|
|
393
|
-
#Create new nodes for each of the imported arguments
|
|
394
|
-
for index,item in enumerate(invoked_sequence.arguments):
|
|
395
|
-
#Determine new node type
|
|
396
|
-
new_node_type = item.direction
|
|
397
|
-
|
|
398
|
-
#build a new Invoked_Workflow_Argument object
|
|
399
|
-
new_node = self.outer_sequence.xaml.new_tag(new_node_type) # have the beautiful soup instance from the parent create a new tag
|
|
400
|
-
new_node["x:Key"] = item.name
|
|
401
|
-
new_node["x:TypeArguments"] = item.type
|
|
402
|
-
new_node.string = "" #Add this so BS adds a closing tag
|
|
403
|
-
|
|
404
|
-
#Add it to this sequence's invoked workflow arguments
|
|
405
|
-
self.invoked_workflow_arguments.append(Sequence.Inner_Sequence.Invoked_Workflow_Argument(self, new_node, index))
|
|
406
|
-
#Add new node to the invoked_arguments_xaml
|
|
407
|
-
self.invoked_workflow_arguments_xaml.append(new_node)
|
|
408
|
-
|
|
409
|
-
self.update_outer_sequence()
|
|
410
|
-
return self.invoked_workflow_arguments
|
|
411
|
-
|
|
412
|
-
#Update parent Sequence XAML. Do this when using any setter method defined above
|
|
413
|
-
def update_outer_sequence(self):
|
|
414
|
-
#if not self.outer_sequence.xaml.find(attrs={"Name":self.name})["Name"] is None:
|
|
415
|
-
self.outer_sequence.xaml.find(attrs={"sap2010:WorkflowViewState.IdRef":self.id}).replace_with(self.xaml)
|
|
416
|
-
self.outer_sequence.save()
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
#Define inner class for invoked_argument
|
|
420
|
-
class Invoked_Workflow_Argument():
|
|
421
|
-
def __init__(self, parent, xaml, index):
|
|
422
|
-
self.parent = parent
|
|
423
|
-
self.xaml = xaml
|
|
424
|
-
self.name = xaml.name
|
|
425
|
-
self.index = index
|
|
426
|
-
self.key = self.xaml["x:Key"]
|
|
427
|
-
self.type = self.xaml["x:TypeArguments"]
|
|
428
|
-
self.value = self.xaml.getText()
|
|
429
|
-
self.value_type = "value" # if the value is a pre-entered value and not a variable
|
|
430
|
-
|
|
431
|
-
#Check if the value is a variable (denoted by square braces)
|
|
432
|
-
if "[" in self.value:
|
|
433
|
-
self.value = self.value[1:(len(self.value) - 1)]
|
|
434
|
-
self.value_type = "variable"
|
|
435
|
-
|
|
436
|
-
#Change the value of the argument (passing a value, not a variable)
|
|
437
|
-
def set_value(self, new_value):
|
|
438
|
-
self.value = new_value
|
|
439
|
-
self.value_type = "value"
|
|
440
|
-
self.xaml.string = new_value
|
|
441
|
-
self.update_parent()
|
|
442
|
-
|
|
443
|
-
#Change the value of the argument (the variable that is entered)
|
|
444
|
-
def set_value_to_variable(self, variable):
|
|
445
|
-
self.value = variable
|
|
446
|
-
self.value_type = "variable"
|
|
447
|
-
self.xaml.string = "[" + variable + "]"
|
|
448
|
-
self.update_parent()
|
|
449
|
-
|
|
450
|
-
#Change the key that the argument is pointing to
|
|
451
|
-
def set_key(self, new_value):
|
|
452
|
-
self.key = new_value
|
|
453
|
-
self.xaml["x:Key"] = new_value
|
|
454
|
-
self.update_parent()
|
|
455
|
-
|
|
456
|
-
#Change the data type of the argument
|
|
457
|
-
def set_type(self, new_type):
|
|
458
|
-
if new_type == "InArgument":
|
|
459
|
-
self.name = "InArgument"
|
|
460
|
-
self.xaml.name = "InArgument"
|
|
461
|
-
elif new_type == "OutArgument":
|
|
462
|
-
self.name = "OutArgument"
|
|
463
|
-
self.xaml.name = "OutArgument"
|
|
464
|
-
elif new_type == "InOutArgument":
|
|
465
|
-
self.name = "InOutArgument"
|
|
466
|
-
self.xaml.name = "InOutArgument"
|
|
467
|
-
self.update_parent()
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
#Update parent Sequence XAML. Do this when using any setter method defined above
|
|
472
|
-
def update_parent(self):
|
|
473
|
-
self.parent.invoked_workflow.find("ui:InvokeWorkflowFile.Arguments").findChildren()[self.index].replace_with(self.xaml)
|
|
474
|
-
self.parent.update_outer_sequence()
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
uipath/uipath.py
DELETED
|
@@ -1,483 +0,0 @@
|
|
|
1
|
-
from bs4 import BeautifulSoup
|
|
2
|
-
|
|
3
|
-
class Sequence:
|
|
4
|
-
def __init__(self, file):
|
|
5
|
-
self.file = file
|
|
6
|
-
|
|
7
|
-
self.init_vars() # load all the vars from the xaml file
|
|
8
|
-
|
|
9
|
-
#Initializes all variables for the class file
|
|
10
|
-
def init_vars(self):
|
|
11
|
-
self.xaml = self.read_xaml() # Read xaml file
|
|
12
|
-
self.name = self.get_class_name() # get class name from XAML file
|
|
13
|
-
self.arguments = self.build_arguments(self.get_arguments())
|
|
14
|
-
self.sequences = self.create_sequences(self.get_sequences())
|
|
15
|
-
|
|
16
|
-
#Gets the existing XAML
|
|
17
|
-
def get_xaml(self):
|
|
18
|
-
return self.xaml
|
|
19
|
-
|
|
20
|
-
#Reads an XAML file
|
|
21
|
-
def read_xaml(self):
|
|
22
|
-
infile = open(self.file, "r")
|
|
23
|
-
data = infile.read()
|
|
24
|
-
infile.close()
|
|
25
|
-
|
|
26
|
-
data = data[data.find("<"):len(data)] # remove garbage from start of file
|
|
27
|
-
xaml = BeautifulSoup(data, "xml");
|
|
28
|
-
return xaml
|
|
29
|
-
|
|
30
|
-
#Updates a node of the XAML stored in memory
|
|
31
|
-
def update_xaml_node(self, node, new_xaml):
|
|
32
|
-
self.xaml = new_xaml
|
|
33
|
-
self.save()
|
|
34
|
-
|
|
35
|
-
#Saves the raw XAML in memory to the XAML file
|
|
36
|
-
def save(self):
|
|
37
|
-
#First we need to strip the <XML> tag that our xaml parser adds
|
|
38
|
-
xml_string = '<?xml version="1.0" encoding="utf-8"?>\n' # The XML encoding tag we need to remove
|
|
39
|
-
data = str(self.xaml).replace(xml_string, "", 1)
|
|
40
|
-
|
|
41
|
-
file = open(self.file,"w+")
|
|
42
|
-
file.write(str(data))
|
|
43
|
-
file.close()
|
|
44
|
-
|
|
45
|
-
return file
|
|
46
|
-
|
|
47
|
-
#Get classname from raw XAML
|
|
48
|
-
def get_class_name(self):
|
|
49
|
-
return self.xaml.find_all("Activity")[0]["x:Class"]
|
|
50
|
-
|
|
51
|
-
#Sets a class name for the file
|
|
52
|
-
def set_class_name(self, new_name):
|
|
53
|
-
self.xaml.find("Activity")["x:Class"] = new_name
|
|
54
|
-
self.save()
|
|
55
|
-
return new_name
|
|
56
|
-
|
|
57
|
-
#Returns the first sequece/block/whatever in the class. The outmost layer
|
|
58
|
-
def get_first_block(self):
|
|
59
|
-
return self.xaml.find("TextExpression.ReferencesForImplementation").next_sibling.next_sibling
|
|
60
|
-
|
|
61
|
-
#Get annotation for node
|
|
62
|
-
def get_annotation(self, node):
|
|
63
|
-
return node["sap2010:Annotation.AnnotationText"]
|
|
64
|
-
|
|
65
|
-
#Set annotation for node
|
|
66
|
-
def set_annotation(self, node, text):
|
|
67
|
-
node["sap2010:Annotation.AnnotationText"] = text
|
|
68
|
-
self.save()
|
|
69
|
-
|
|
70
|
-
#Gets node name
|
|
71
|
-
def get_node_name(self, node):
|
|
72
|
-
return node["DisplayName"]
|
|
73
|
-
|
|
74
|
-
#Sets node name
|
|
75
|
-
def set_node_name(self, node, new_name):
|
|
76
|
-
node["DisplayName"] = new_name
|
|
77
|
-
return new_name
|
|
78
|
-
|
|
79
|
-
#Returns an argument by name
|
|
80
|
-
def get_argument_by_name(self, name):
|
|
81
|
-
if not self.arguments is None:
|
|
82
|
-
for item in self.arguments:
|
|
83
|
-
if item.name == name:
|
|
84
|
-
return item
|
|
85
|
-
|
|
86
|
-
#Gets arguments of sequence
|
|
87
|
-
def get_arguments(self):
|
|
88
|
-
return self.xaml.find_all("x:Property")
|
|
89
|
-
|
|
90
|
-
#Builds the argument objects for the main class
|
|
91
|
-
def build_arguments(self, argument_list):
|
|
92
|
-
if not argument_list is None and len(argument_list) > 0:
|
|
93
|
-
args = []
|
|
94
|
-
for item in argument_list:
|
|
95
|
-
args.append(Sequence.Argument(self, item))
|
|
96
|
-
return args
|
|
97
|
-
|
|
98
|
-
#Creates and adds a new argument for the sequence
|
|
99
|
-
def add_argument(self, name, string_direction, datatype):
|
|
100
|
-
new_arg = self.xaml.new_tag("x:Property")
|
|
101
|
-
new_arg["Name"] = name
|
|
102
|
-
|
|
103
|
-
#build XAML friendly variables for the passed in arguments
|
|
104
|
-
new_arg_type_end = ")"
|
|
105
|
-
if string_direction == "in":
|
|
106
|
-
new_arg_type_start = "InArgument("
|
|
107
|
-
elif string_direction == "out":
|
|
108
|
-
new_arg_type_start = "OutArgument("
|
|
109
|
-
elif string_direction == "io":
|
|
110
|
-
new_arg_type_start = "InOutArgument("
|
|
111
|
-
else:
|
|
112
|
-
new_arg_type_end = ""
|
|
113
|
-
new_arg_type_start = ""
|
|
114
|
-
|
|
115
|
-
# Type="InArgument(scg:Dictionary(x:String, x:Object))"
|
|
116
|
-
new_arg["Type"] = new_arg_type_start + datatype + new_arg_type_end
|
|
117
|
-
|
|
118
|
-
#Add to array in XAML
|
|
119
|
-
self.xaml.find("x:Members").append(new_arg)
|
|
120
|
-
#Rebuild all arguments from the XAML
|
|
121
|
-
self.arguments = self.build_arguments(self.get_arguments())
|
|
122
|
-
|
|
123
|
-
self.save()
|
|
124
|
-
|
|
125
|
-
#Gets a block by its Displayname
|
|
126
|
-
def get_node_by_display_name(self, display_name):
|
|
127
|
-
return self.xaml.find(DisplayName=display_name)
|
|
128
|
-
|
|
129
|
-
#Gets nested sequences
|
|
130
|
-
def get_sequences(self):
|
|
131
|
-
return self.xaml.find_all("Sequence")
|
|
132
|
-
|
|
133
|
-
#Builds the argument objects for the main class
|
|
134
|
-
def create_sequences(self, sequence_list):
|
|
135
|
-
if not sequence_list is None and len(sequence_list) > 0:
|
|
136
|
-
sequences = []
|
|
137
|
-
for item in sequence_list:
|
|
138
|
-
sequences.append(Sequence.Inner_Sequence(self, item))
|
|
139
|
-
return sequences
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
#To String.
|
|
143
|
-
def __str__(self):
|
|
144
|
-
to_return = "{" + "\n"
|
|
145
|
-
for key in self.__dict__.keys():
|
|
146
|
-
if key != "xaml":
|
|
147
|
-
if isinstance(self.__dict__[key], (list,)):
|
|
148
|
-
to_return = to_return + "\t" + key + ": [" + "\n"
|
|
149
|
-
for item in self.__dict__[key]:
|
|
150
|
-
to_return = to_return + "\t\t" + str(item) + "\n"
|
|
151
|
-
to_return = to_return + "\t]" + "\n"
|
|
152
|
-
else:
|
|
153
|
-
to_return = to_return + "\t" + key + ":" + str(self.__dict__[key]) + "\n"
|
|
154
|
-
|
|
155
|
-
to_return = to_return + "}"
|
|
156
|
-
return to_return
|
|
157
|
-
|
|
158
|
-
#-----------------------------------------------------------------------------------------------------------------------
|
|
159
|
-
# Subclass: Variable
|
|
160
|
-
# Description: Stores the data about a variable in a sequence
|
|
161
|
-
#-----------------------------------------------------------------------------------------------------------------------
|
|
162
|
-
class Variable():
|
|
163
|
-
def __init__(self, parent=None, xaml = None, name=None, type_arg=None, default=None):
|
|
164
|
-
self.parent = parent #Store the calling sequence
|
|
165
|
-
|
|
166
|
-
#If xaml was passed in just use that
|
|
167
|
-
self.xaml = xaml
|
|
168
|
-
if not self.xaml is None:
|
|
169
|
-
self.name = self.xaml["Name"]
|
|
170
|
-
self.type = self.xaml["x:TypeArguments"]
|
|
171
|
-
#Else build new xaml based on the name and type passed in
|
|
172
|
-
else:
|
|
173
|
-
self.name = name
|
|
174
|
-
self.type = type_arg
|
|
175
|
-
self.default = default
|
|
176
|
-
self.xaml = self.build_xaml()
|
|
177
|
-
|
|
178
|
-
#Builds XAML for a name and type
|
|
179
|
-
def build_xaml(self):
|
|
180
|
-
new_node = self.parent.xaml.new_tag("Variable") # have the beautiful soup instance from the parent create a new tag
|
|
181
|
-
new_node["Name"] = self.name
|
|
182
|
-
new_node["x:TypeArguments"] = self.type
|
|
183
|
-
if not self.default is None:
|
|
184
|
-
new_node["Default"] = self.default
|
|
185
|
-
return new_node
|
|
186
|
-
|
|
187
|
-
#-----------------------------------------------------------------------------------------------------------------------
|
|
188
|
-
# Subclass: Argument
|
|
189
|
-
# Description: Stores the arguments and their default values from the xaml file
|
|
190
|
-
#-----------------------------------------------------------------------------------------------------------------------
|
|
191
|
-
|
|
192
|
-
#Define subclass for the arguments
|
|
193
|
-
class Argument():
|
|
194
|
-
def __init__(self, outer_sequence, xaml, default_value=None):
|
|
195
|
-
self.outer_sequence = outer_sequence #the containing sequence
|
|
196
|
-
|
|
197
|
-
self.xaml = xaml
|
|
198
|
-
self.init_vars()
|
|
199
|
-
self.default_value = self.get_default_value_for_attr()
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
#Creates a new argument
|
|
203
|
-
|
|
204
|
-
#Get default value for attribute
|
|
205
|
-
def get_default_value_for_attr(self):
|
|
206
|
-
values_string = self.outer_sequence.xaml.find_all("Activity")[0]
|
|
207
|
-
key = "this:" + self.outer_sequence.name + "." + self.name
|
|
208
|
-
|
|
209
|
-
if key in values_string:
|
|
210
|
-
return values_string["this:" + self.outer_sequence.name + "." + self.name]
|
|
211
|
-
|
|
212
|
-
#Decodes XAML into python friendly strings
|
|
213
|
-
def init_vars(self):
|
|
214
|
-
self.name = self.xaml["Name"]
|
|
215
|
-
self.direction = self.get_direction_from_xaml()
|
|
216
|
-
self.type = self.get_datatype_from_xaml()
|
|
217
|
-
|
|
218
|
-
#Converts string direction to xaml direction
|
|
219
|
-
def convert_string_direction_to_xaml(self, string_direction):
|
|
220
|
-
if string_direction == "in":
|
|
221
|
-
return "InArgument"
|
|
222
|
-
elif string_direction == "out":
|
|
223
|
-
return "OutArgument"
|
|
224
|
-
elif string_direction == "io":
|
|
225
|
-
return "InOutArgument"
|
|
226
|
-
else:
|
|
227
|
-
return "Property"
|
|
228
|
-
|
|
229
|
-
#Gets direction of argument
|
|
230
|
-
def get_direction_from_xaml(self):
|
|
231
|
-
temp = self.xaml["Type"]
|
|
232
|
-
|
|
233
|
-
if "InArgument" in temp:
|
|
234
|
-
return "InArgument"
|
|
235
|
-
elif "OutArgument" in temp:
|
|
236
|
-
return "OutArgument"
|
|
237
|
-
elif "InOutArgument" in temp:
|
|
238
|
-
return "InOutArgument"
|
|
239
|
-
else:
|
|
240
|
-
return "Property"
|
|
241
|
-
|
|
242
|
-
#Gets the datatype of the argument
|
|
243
|
-
def get_datatype_from_xaml(self):
|
|
244
|
-
return self.xaml["Type"].replace("(", "").replace(")", "").replace(self.direction, "")
|
|
245
|
-
|
|
246
|
-
#Sets a new name value for this Class instance, as well as updating the parent raw XAML.
|
|
247
|
-
def set_name(self, new_name):
|
|
248
|
-
self.update_default_value_name(self.name, new_name)
|
|
249
|
-
self.xaml["Name"] = new_name
|
|
250
|
-
self.name = new_name
|
|
251
|
-
self.update_outer_sequence()
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
#Sets a new direction value for this Class instance, as well as updating the parent raw XAML.
|
|
255
|
-
def set_direction(self, direction_string):
|
|
256
|
-
self.direction = direction_string #update class' variable
|
|
257
|
-
|
|
258
|
-
new_direction_xaml = ""
|
|
259
|
-
if self.direction == "InArgument":
|
|
260
|
-
new_direction_xaml = "InArgument(" + self.type + ")"
|
|
261
|
-
elif self.direction == "InOutArgument":
|
|
262
|
-
self.delete_default_value() #delete default value as it is not supported by this direction type
|
|
263
|
-
new_direction_xaml = "InOutArgument(" + self.type + ")"
|
|
264
|
-
elif self.direction == "OutArgument":
|
|
265
|
-
self.delete_default_value() #delete default value as it is not supported by this direction type
|
|
266
|
-
new_direction_xaml = "OutArgument(" + self.type + ")"
|
|
267
|
-
else:
|
|
268
|
-
new_direction_xaml = self.type
|
|
269
|
-
|
|
270
|
-
self.xaml["Type"] = new_direction_xaml
|
|
271
|
-
self.update_outer_sequence()
|
|
272
|
-
|
|
273
|
-
#Creates a default value when one does not yet exist
|
|
274
|
-
#STUB
|
|
275
|
-
|
|
276
|
-
#Sets a new default value for this Class instance, as well as updating the parent raw XAML.
|
|
277
|
-
def update_default_value(self, new_value):
|
|
278
|
-
self.default_value = new_value
|
|
279
|
-
values_string = self.outer_sequence.xaml.find_all("Activity")[0]
|
|
280
|
-
values_string["this:" + self.outer_sequence.name + "." + self.name] = new_value
|
|
281
|
-
self.update_outer_sequence()
|
|
282
|
-
|
|
283
|
-
#Changes the name of default values to match the argument name when it is changed
|
|
284
|
-
def update_default_value_name(self, old_name, new_name):
|
|
285
|
-
values_string = self.outer_sequence.xaml.find_all("Activity")[0]
|
|
286
|
-
key = "this:" + self.outer_sequence.name + "." + self.name
|
|
287
|
-
|
|
288
|
-
if key in values_string:
|
|
289
|
-
self.delete_default_value()
|
|
290
|
-
values_string["this:" + self.outer_sequence.name + "." + new_name] = self.default_value
|
|
291
|
-
#values_string["this:" + self.outer_sequence.name + "." + self.name] = new_value
|
|
292
|
-
|
|
293
|
-
#Deletes the default value
|
|
294
|
-
def delete_default_value(self):
|
|
295
|
-
values_string = self.outer_sequence.xaml.find_all("Activity")[0]
|
|
296
|
-
key = "this:" + self.outer_sequence.name + "." + self.name
|
|
297
|
-
|
|
298
|
-
if key in values_string:
|
|
299
|
-
del self.outer_sequence.xaml.find_all("Activity")[0]["this:" + self.outer_sequence.name + "." + self.name]
|
|
300
|
-
|
|
301
|
-
if not self.default_value is None:
|
|
302
|
-
del self.default_value
|
|
303
|
-
|
|
304
|
-
#Update parent Sequence XAML. Do this when using any setter method defined above
|
|
305
|
-
def update_outer_sequence(self):
|
|
306
|
-
#if not self.outer_sequence.xaml.find(attrs={"Name":self.name})["Name"] is None:
|
|
307
|
-
self.outer_sequence.xaml.find(attrs={"Name":self.name}).replace_with(self.xaml)
|
|
308
|
-
self.outer_sequence.save()
|
|
309
|
-
|
|
310
|
-
#override to string method
|
|
311
|
-
def __str__(self):
|
|
312
|
-
if self.default_value is None: # check if self has default_value
|
|
313
|
-
return "{name: \"" + self.name + "\", direction: \"" + self.direction + "\", type: \"" + self.type + "\"}"
|
|
314
|
-
else:
|
|
315
|
-
return "{name: \"" + self.name + "\", direction: \"" + self.direction + "\", type: \"" + self.type + "\", default_value: \"" + self.default_value + "\"}"
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
#-----------------------------------------------------------------------------------------------------------------------
|
|
319
|
-
# Subclass: Argument
|
|
320
|
-
# Description: Stores the arguments and their default values from the xaml file
|
|
321
|
-
#-----------------------------------------------------------------------------------------------------------------------
|
|
322
|
-
|
|
323
|
-
#Define subclass for the arguments
|
|
324
|
-
class Inner_Sequence():
|
|
325
|
-
def __init__(self, outer_sequence, xaml):
|
|
326
|
-
self.outer_sequence = outer_sequence
|
|
327
|
-
self.xaml = xaml
|
|
328
|
-
self.id = xaml["sap2010:WorkflowViewState.IdRef"]
|
|
329
|
-
self.get_invoked_workflow()
|
|
330
|
-
self.variables = self.get_sequence_variables()
|
|
331
|
-
|
|
332
|
-
#Get the invoked workflow for the sequences, if applicable
|
|
333
|
-
def get_invoked_workflow(self):
|
|
334
|
-
self.invoked_workflow = self.xaml.find("ui:InvokeWorkflowFile")
|
|
335
|
-
|
|
336
|
-
if not self.invoked_workflow is None:
|
|
337
|
-
#Get path to invoked workflow
|
|
338
|
-
self.invoked_workflow_path = self.invoked_workflow["WorkflowFileName"]
|
|
339
|
-
|
|
340
|
-
#get arguments of invoked workflow
|
|
341
|
-
self.invoked_workflow_arguments_xaml = self.invoked_workflow.find("ui:InvokeWorkflowFile.Arguments")
|
|
342
|
-
|
|
343
|
-
if len(self.invoked_workflow_arguments_xaml.findChildren()) > 0:
|
|
344
|
-
self.invoked_workflow_arguments = []
|
|
345
|
-
for index,child in enumerate(self.invoked_workflow_arguments_xaml.findChildren()):
|
|
346
|
-
self.invoked_workflow_arguments.append(Sequence.Inner_Sequence.Invoked_Workflow_Argument(self, child, index))
|
|
347
|
-
|
|
348
|
-
#Get variables in this sequence
|
|
349
|
-
def get_sequence_variables(self):
|
|
350
|
-
vars_from_xaml = self.xaml.find_all("Variable")
|
|
351
|
-
|
|
352
|
-
#If there are any variables, we will build an array of variable objects and return them
|
|
353
|
-
if len(vars_from_xaml) > 0:
|
|
354
|
-
all_vars = []
|
|
355
|
-
|
|
356
|
-
for item in self.xaml.find_all("Variable"):
|
|
357
|
-
all_vars.append(self.outer_sequence.Variable(self.outer_sequence, xaml=item))
|
|
358
|
-
|
|
359
|
-
return all_vars
|
|
360
|
-
|
|
361
|
-
#Add variable to sequence
|
|
362
|
-
def create_variable(self, xaml=None, name=None, type=None, default=None):
|
|
363
|
-
#If xaml is None, build new BS node
|
|
364
|
-
if xaml is None:
|
|
365
|
-
xaml = self.outer_sequence.xaml.new_tag("Variable")
|
|
366
|
-
xaml["Name"] = name
|
|
367
|
-
xaml["x:TypeArguments"] = type
|
|
368
|
-
|
|
369
|
-
if not default is None:
|
|
370
|
-
xaml["Default"] = default
|
|
371
|
-
|
|
372
|
-
self.xaml.find("Sequence.Variables").append(xaml) #Add new variable to xaml file
|
|
373
|
-
self.variables = self.get_sequence_variables() #Regenerate vars from xaml
|
|
374
|
-
self.update_outer_sequence()
|
|
375
|
-
|
|
376
|
-
return xaml #return the new variable
|
|
377
|
-
|
|
378
|
-
#Deletes a variable by name
|
|
379
|
-
def delete_variable(self, var_name):
|
|
380
|
-
self.xaml.find_all("Variable", Name=var_name)[0].decompose() #Deletes the variable from the XAML
|
|
381
|
-
self.variables = self.get_sequence_variables() #Regenerate vars from xaml
|
|
382
|
-
self.update_outer_sequence()
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
#Imports arguments from invoked function. Just like the button in UiPath
|
|
386
|
-
def import_arguments(self):
|
|
387
|
-
#Clear the array of invoked workflow argument objects
|
|
388
|
-
self.invoked_workflow_arguments = []
|
|
389
|
-
self.invoked_workflow_arguments_xaml.clear()
|
|
390
|
-
#clear the array of
|
|
391
|
-
invoked_sequence = Sequence(self.invoked_workflow_path) #Load the invoked sequence
|
|
392
|
-
|
|
393
|
-
#Create new nodes for each of the imported arguments
|
|
394
|
-
for index,item in enumerate(invoked_sequence.arguments):
|
|
395
|
-
#Determine new node type
|
|
396
|
-
new_node_type = item.direction
|
|
397
|
-
|
|
398
|
-
#build a new Invoked_Workflow_Argument object
|
|
399
|
-
new_node = self.outer_sequence.xaml.new_tag(new_node_type) # have the beautiful soup instance from the parent create a new tag
|
|
400
|
-
new_node["x:Key"] = item.name
|
|
401
|
-
new_node["x:TypeArguments"] = item.type
|
|
402
|
-
new_node.string = "" #Add this so BS adds a closing tag
|
|
403
|
-
|
|
404
|
-
#Add it to this sequence's invoked workflow arguments
|
|
405
|
-
self.invoked_workflow_arguments.append(Sequence.Inner_Sequence.Invoked_Workflow_Argument(self, new_node, index))
|
|
406
|
-
#Add new node to the invoked_arguments_xaml
|
|
407
|
-
self.invoked_workflow_arguments_xaml.append(new_node)
|
|
408
|
-
|
|
409
|
-
self.update_outer_sequence()
|
|
410
|
-
return self.invoked_workflow_arguments
|
|
411
|
-
|
|
412
|
-
#Update parent Sequence XAML. Do this when using any setter method defined above
|
|
413
|
-
def update_outer_sequence(self):
|
|
414
|
-
#if not self.outer_sequence.xaml.find(attrs={"Name":self.name})["Name"] is None:
|
|
415
|
-
self.outer_sequence.xaml.find(attrs={"sap2010:WorkflowViewState.IdRef":self.id}).replace_with(self.xaml)
|
|
416
|
-
self.outer_sequence.save()
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
#Define inner class for invoked_argument
|
|
420
|
-
class Invoked_Workflow_Argument():
|
|
421
|
-
def __init__(self, parent, xaml, index):
|
|
422
|
-
self.parent = parent
|
|
423
|
-
self.xaml = xaml
|
|
424
|
-
self.name = xaml.name
|
|
425
|
-
self.index = index
|
|
426
|
-
self.key = self.xaml["x:Key"]
|
|
427
|
-
self.type = self.xaml["x:TypeArguments"]
|
|
428
|
-
self.value = self.xaml.getText()
|
|
429
|
-
self.value_type = "value" # if the value is a pre-entered value and not a variable
|
|
430
|
-
|
|
431
|
-
#Check if the value is a variable (denoted by square braces)
|
|
432
|
-
if "[" in self.value:
|
|
433
|
-
self.value = self.value[1:(len(self.value) - 1)]
|
|
434
|
-
self.value_type = "variable"
|
|
435
|
-
|
|
436
|
-
#Change the value of the argument (passing a value, not a variable)
|
|
437
|
-
def set_value(self, new_value):
|
|
438
|
-
self.value = new_value
|
|
439
|
-
self.value_type = "value"
|
|
440
|
-
self.xaml.string = new_value
|
|
441
|
-
self.update_parent()
|
|
442
|
-
|
|
443
|
-
#Change the value of the argument (the variable that is entered)
|
|
444
|
-
def set_value_to_variable(self, variable):
|
|
445
|
-
self.value = variable
|
|
446
|
-
self.value_type = "variable"
|
|
447
|
-
self.xaml.string = "[" + variable + "]"
|
|
448
|
-
self.update_parent()
|
|
449
|
-
|
|
450
|
-
#Change the key that the argument is pointing to
|
|
451
|
-
def set_key(self, new_value):
|
|
452
|
-
self.key = new_value
|
|
453
|
-
self.xaml["x:Key"] = new_value
|
|
454
|
-
self.update_parent()
|
|
455
|
-
|
|
456
|
-
#Change the data type of the argument
|
|
457
|
-
def set_type(self, new_type):
|
|
458
|
-
if new_type == "InArgument":
|
|
459
|
-
self.name = "InArgument"
|
|
460
|
-
self.xaml.name = "InArgument"
|
|
461
|
-
elif new_type == "OutArgument":
|
|
462
|
-
self.name = "OutArgument"
|
|
463
|
-
self.xaml.name = "OutArgument"
|
|
464
|
-
elif new_type == "InOutArgument":
|
|
465
|
-
self.name = "InOutArgument"
|
|
466
|
-
self.xaml.name = "InOutArgument"
|
|
467
|
-
self.update_parent()
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
#Update parent Sequence XAML. Do this when using any setter method defined above
|
|
472
|
-
def update_parent(self):
|
|
473
|
-
self.parent.invoked_workflow.find("ui:InvokeWorkflowFile.Arguments").findChildren()[self.index].replace_with(self.xaml)
|
|
474
|
-
self.parent.update_outer_sequence()
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
uipath-0.0.1.dist-info/METADATA
DELETED
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
Metadata-Version: 2.1
|
|
2
|
-
Name: uipath
|
|
3
|
-
Version: 0.0.1
|
|
4
|
-
Summary: A python API for editing UiPath .xaml files programatically.
|
|
5
|
-
Home-page: https://github.com/christianblandford/UiPath-Python
|
|
6
|
-
Author: Christian Blandford
|
|
7
|
-
Author-email: christianblandford@me.com
|
|
8
|
-
License: UNKNOWN
|
|
9
|
-
Platform: UNKNOWN
|
|
10
|
-
Classifier: Programming Language :: Python :: 3
|
|
11
|
-
Classifier: License :: OSI Approved :: MIT License
|
|
12
|
-
Classifier: Operating System :: OS Independent
|
|
13
|
-
Description-Content-Type: text/markdown
|
|
14
|
-
Requires-Dist: beautifulsoup4 (>=4.7.1)
|
|
15
|
-
|
|
16
|
-
# UiPath_Python
|
|
17
|
-
|
|
18
|
-
A Python API for editing UiPath .xaml files.
|
|
19
|
-
|
|
20
|
-
Documentation coming soon!
|
|
21
|
-
|
uipath-0.0.1.dist-info/RECORD
DELETED
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
uipath/__init__.py,sha256=XCE4SE2Ptda40VfLHckUvbkDJ0f2pn6Js7KZVbDxOMQ,30
|
|
2
|
-
uipath/sequence.py,sha256=rkb5hadh1Hxddpkdn8bZpF2h0pyegzNtQd_e4vsF_lU,17569
|
|
3
|
-
uipath/uipath.py,sha256=rkb5hadh1Hxddpkdn8bZpF2h0pyegzNtQd_e4vsF_lU,17569
|
|
4
|
-
uipath-0.0.1.dist-info/LICENSE,sha256=LADYfaeSfJ_78McUNX4cM3TxzfFAbZ-zZzLDk8RqwFE,1074
|
|
5
|
-
uipath-0.0.1.dist-info/METADATA,sha256=RwIjWR93zOZm7cup-BWk4vMka4AWxl0OPfXrQgKdZJw,604
|
|
6
|
-
uipath-0.0.1.dist-info/WHEEL,sha256=qB97nP5e4MrOsXW5bIU5cUn_KSVr10EV0l-GCHG9qNs,97
|
|
7
|
-
uipath-0.0.1.dist-info/top_level.txt,sha256=cO-fuTo_YlozqaZ6VNk0ST79wuBjLkcTRzYpXLM6rRg,7
|
|
8
|
-
uipath-0.0.1.dist-info/RECORD,,
|
|
File without changes
|