robo_appian 0.0.27__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.
@@ -0,0 +1,93 @@
1
+ from robo_appian.components.ButtonUtils import ButtonUtils
2
+ from selenium.webdriver.support.ui import WebDriverWait
3
+ from robo_appian.components.DateUtils import DateUtils
4
+ from robo_appian.components.DropdownUtils import DropdownUtils
5
+ from robo_appian.components.InputUtils import InputUtils
6
+ from robo_appian.components.LabelUtils import LabelUtils
7
+ from robo_appian.components.LinkUtils import LinkUtils
8
+ from robo_appian.components.TabUtils import TabUtils
9
+ from robo_appian.components.SearchInputUtils import SearchInputUtils
10
+ from robo_appian.components.SearchDropdownUtils import SearchDropdownUtils
11
+
12
+
13
+ class ComponentDriver:
14
+ """
15
+ Utility class for interacting with various components in Appian UI.
16
+ Usage Example:
17
+ from robo_appian.utils.controllers.ComponentDriver import ComponentDriver
18
+ # Set a date value
19
+ ComponentDriver.execute(wait, "Date", "Set Value", "Start Date", "01/01/2024")
20
+ """
21
+
22
+ @staticmethod
23
+ def execute(wait: WebDriverWait, type, action, label, value):
24
+ """
25
+ Executes an action on a specified component type.
26
+ Parameters:
27
+ wait: Selenium WebDriverWait instance.
28
+ type: The type of component (e.g., "Date", "Input Text", "Search Input Text", etc.).
29
+ action: The action to perform on the component (e.g., "Set Value", "Click", "Select").
30
+ label: The visible text label of the component.
31
+ value: The value to set in the component (if applicable).
32
+ Example:
33
+ ComponentDriver.execute(wait, "Date", "Set Value", "Start Date", "01/01/2024")
34
+ """
35
+ # This method executes an action on a specified component type based on the provided parameters.
36
+
37
+ match type:
38
+ case "Date":
39
+ match action:
40
+ case "Set Value":
41
+ DateUtils.setValueByLabelText(wait, label, value)
42
+ case _:
43
+ raise ValueError(f"Unsupported action for {type}: {action}")
44
+ case "Input Text":
45
+ match action:
46
+ case "Set Value":
47
+ InputUtils.setValueByLabelText(wait, label, value)
48
+ case _:
49
+ raise ValueError(f"Unsupported action for {type}: {action}")
50
+ case "Search Input Text":
51
+ match action:
52
+ case "Select":
53
+ SearchInputUtils.selectSearchDropdownByLabelText(wait, label, value)
54
+ case _:
55
+ raise ValueError(f"Unsupported action for {type}: {action}")
56
+ case "Label":
57
+ match action:
58
+ case "Find":
59
+ LabelUtils.isLabelExists(wait, label)
60
+ case _:
61
+ raise ValueError(f"Unsupported action for {type}: {action}")
62
+ case "Link":
63
+ match action:
64
+ case "Click":
65
+ LinkUtils.click(wait, label)
66
+ case _:
67
+ raise ValueError(f"Unsupported action for {type}: {action}")
68
+ case "Drop Down":
69
+ match action:
70
+ case "Select":
71
+ DropdownUtils.selectDropdownValueByLabelText(wait, label, value)
72
+ case _:
73
+ raise ValueError(f"Unsupported action for {type}: {action}")
74
+ case "Search Drop Down":
75
+ match action:
76
+ case "Select":
77
+ SearchDropdownUtils.selectSearchDropdownValueByLabelText(wait, label, value)
78
+ case _:
79
+ raise ValueError(f"Unsupported action for {type}: {action}")
80
+ case "Button":
81
+ match action:
82
+ case "Click":
83
+ ButtonUtils.clickByLabelText(wait, label)
84
+ case _:
85
+ raise ValueError(f"Unsupported action for {type}: {action}")
86
+ case "Tab":
87
+ match action:
88
+ case "Find":
89
+ TabUtils.selectTabByLabelText(wait, label)
90
+ case _:
91
+ raise ValueError(f"Unsupported action for {type}: {action}")
92
+ case _:
93
+ raise ValueError(f"Unsupported component type: {type}")
File without changes
@@ -0,0 +1,6 @@
1
+ class MyCustomError(Exception):
2
+ """A custom exception for specific error conditions."""
3
+
4
+ def __init__(self, message="This is a custom error!"):
5
+ self.message = message
6
+ super().__init__(self.message)
File without changes
@@ -0,0 +1,52 @@
1
+ from selenium.webdriver.support.ui import WebDriverWait
2
+
3
+
4
+ class BrowserUtils:
5
+ @staticmethod
6
+ def switch_to_Tab(wait: WebDriverWait, tab_number):
7
+ """
8
+ Switches to the specified browser tab.
9
+
10
+ :param wait: WebDriverWait instance
11
+ :param tab_number: The index of the tab to switch to
12
+ :return: None
13
+ Example usage:
14
+ BrowserUtils.switch_to_Tab(wait, 1)
15
+ """
16
+
17
+ # Switch to the specified browser tab
18
+ handler = wait._driver.window_handles[tab_number]
19
+ wait._driver.switch_to.window(handler)
20
+
21
+ @staticmethod
22
+ def switch_to_next_tab(wait: WebDriverWait):
23
+ """
24
+ Switches to the next browser tab.
25
+
26
+ :param wait: WebDriverWait instance
27
+ :return: None
28
+ Example usage:
29
+ BrowserUtils.switch_to_next_tab(wait)
30
+ """
31
+ current_tab_index = wait._driver.window_handles.index(
32
+ wait._driver.current_window_handle
33
+ )
34
+ next_tab_index = (current_tab_index + 1) % len(wait._driver.window_handles)
35
+ BrowserUtils.switch_to_Tab(wait, next_tab_index)
36
+
37
+ @staticmethod
38
+ def close_current_tab_and_switch_back(wait: WebDriverWait):
39
+ """
40
+ Closes the current browser tab and switches back to the original tab.
41
+
42
+ :param wait: WebDriverWait instance
43
+ :return: None
44
+ Example usage:
45
+ BrowserUtils.close_current_tab_and_switch_back(wait)
46
+ """
47
+ current_tab_index = wait._driver.window_handles.index(
48
+ wait._driver.current_window_handle
49
+ )
50
+ wait._driver.close()
51
+ original_tab_index = (current_tab_index - 1) % len(wait._driver.window_handles)
52
+ BrowserUtils.switch_to_Tab(wait, original_tab_index)
@@ -0,0 +1,292 @@
1
+
2
+ import tomllib
3
+ from pathlib import Path
4
+ from selenium.common.exceptions import NoSuchElementException
5
+ from selenium.webdriver import ActionChains
6
+ from selenium.webdriver.common.by import By
7
+ from selenium.webdriver.common.keys import Keys
8
+ from selenium.webdriver.support import expected_conditions as EC
9
+ from selenium.webdriver.remote.webdriver import WebDriver
10
+ from selenium.webdriver.remote.webelement import WebElement
11
+ from selenium.webdriver.support.ui import WebDriverWait
12
+
13
+
14
+ class ComponentUtils:
15
+
16
+ @staticmethod
17
+ def get_version():
18
+ try:
19
+ toml_path = Path(__file__).parent.parent / "pyproject.toml"
20
+ with open(toml_path, "rb") as f:
21
+ data = tomllib.load(f)
22
+ return data.get("project", {}).get("version", "0.0.0")
23
+ except Exception:
24
+ return "0.0.0"
25
+
26
+ @staticmethod
27
+ def today():
28
+ """
29
+ Returns today's date formatted as MM/DD/YYYY.
30
+ """
31
+
32
+ from datetime import date
33
+
34
+ today = date.today()
35
+ yesterday_formatted = today.strftime("%m/%d/%Y")
36
+ return yesterday_formatted
37
+
38
+ @staticmethod
39
+ def yesterday():
40
+ """
41
+ Returns yesterday's date formatted as MM/DD/YYYY.
42
+ """
43
+
44
+ from datetime import date, timedelta
45
+
46
+ yesterday = date.today() - timedelta(days=1)
47
+ yesterday_formatted = yesterday.strftime("%m/%d/%Y")
48
+ return yesterday_formatted
49
+
50
+ @staticmethod
51
+ def findChildComponentByXpath(
52
+ wait: WebDriverWait, component: WebElement, xpath: str
53
+ ):
54
+ """Finds a child component using the given XPath within a parent component.
55
+
56
+ :param wait: WebDriverWait instance to wait for elements
57
+ :param component: Parent WebElement to search within
58
+ :param xpath: XPath string to locate the child component
59
+ :return: WebElement if found, raises NoSuchElementException otherwise
60
+ Example usage:
61
+ from selenium.webdriver.support.ui import WebDriverWait
62
+ from selenium import webdriver
63
+
64
+ driver = webdriver.Chrome()
65
+ wait = WebDriverWait(driver, 10)
66
+ parent_component = driver.find_element(By.ID, "parent")
67
+ xpath = ".//button[@class='child']"
68
+ child_component = ComponentUtils.findChildComponentByXpath(wait, parent_component, xpath)
69
+ """
70
+ try:
71
+ component = wait.until(lambda comp: component.find_element(By.XPATH, xpath))
72
+ except Exception:
73
+ raise Exception(
74
+ f"Child component with XPath '{xpath}' not found within the given parent component."
75
+ )
76
+ return component
77
+
78
+ @staticmethod
79
+ def findComponentById(wait: WebDriverWait, id: str):
80
+ try:
81
+ component = wait.until(EC.presence_of_element_located((By.ID, id)))
82
+ except Exception:
83
+ raise Exception(f"Component with ID '{id}' not found.")
84
+ return component
85
+
86
+ @staticmethod
87
+ def waitForComponentToBeVisibleByXpath(wait: WebDriverWait, xpath: str):
88
+ try:
89
+ component = wait.until(EC.visibility_of_element_located((By.XPATH, xpath)))
90
+ except Exception:
91
+ raise Exception(f"Component with XPath '{xpath}' not visible.")
92
+ return component
93
+
94
+ # @staticmethod
95
+ # def waitForComponentToBeVisibleByXpath(wait: WebDriverWait, xpath: str):
96
+ # """
97
+ # Finds a component using the given XPath in the current WebDriver instance.
98
+
99
+ # :param wait: WebDriverWait instance to wait for elements
100
+ # :param xpath: XPath string to locate the component
101
+ # :return: WebElement if found, raises NoSuchElementException otherwise
102
+
103
+ # Example usage:
104
+ # component = ComponentUtils.waitForComponentToBeVisibleByXpath(wait, "//button[@id='submit']")
105
+ # component.click()
106
+ # """
107
+ # try:
108
+ # component = wait.until(EC.visibility_of_element_located((By.XPATH, xpath)))
109
+ # except Exception:
110
+ # raise Exception(f"Component with XPath '{xpath}' not visible.")
111
+ # return component
112
+
113
+ @staticmethod
114
+ def checkComponentExistsByXpath(wait: WebDriverWait, xpath: str):
115
+ """Checks if a component with the given XPath exists in the current WebDriver instance."""
116
+ status = False
117
+ try:
118
+ ComponentUtils.waitForComponentToBeVisibleByXpath(wait, xpath)
119
+ status = True
120
+ except NoSuchElementException:
121
+ pass
122
+
123
+ return status
124
+
125
+ @staticmethod
126
+ def checkComponentExistsById(driver: WebDriver, id: str):
127
+ """Checks if a component with the given ID exists in the current WebDriver instance.
128
+
129
+ :param driver: WebDriver instance to check for the component
130
+ :param id: ID of the component to check
131
+ :return: True if the component exists, False otherwise
132
+ Example usage:
133
+ exists = ComponentUtils.checkComponentExistsById(driver, "submit-button")
134
+ print(f"Component exists: {exists}")
135
+ """
136
+ status = False
137
+ try:
138
+ driver.find_element(By.ID, id)
139
+ status = True
140
+ except NoSuchElementException:
141
+ pass
142
+
143
+ return status
144
+
145
+ @staticmethod
146
+ def findCount(wait: WebDriverWait, xpath: str):
147
+ """Finds the count of components matching the given XPath.
148
+
149
+ :param wait: WebDriverWait instance to wait for elements
150
+ :param xpath: XPath string to locate components
151
+ :return: Count of components matching the XPath
152
+ Example usage:
153
+ count = ComponentUtils.findCount(wait, "//div[@class='item']")
154
+ print(f"Number of items found: {count}")
155
+ """
156
+
157
+ length = 0
158
+
159
+ try:
160
+ component = wait.until(
161
+ EC.presence_of_all_elements_located((By.XPATH, xpath))
162
+ )
163
+ length = len(component)
164
+ except NoSuchElementException:
165
+ pass
166
+
167
+ return length
168
+
169
+ @staticmethod
170
+ def tab(wait: WebDriverWait):
171
+ """Simulates a tab key press in the current WebDriver instance.
172
+
173
+ :param wait: WebDriverWait instance to wait for elements
174
+ :return: None
175
+ Example usage:
176
+ ComponentUtils.tab(wait)
177
+ """
178
+ driver = wait._driver
179
+ actions = ActionChains(driver)
180
+ actions.send_keys(Keys.TAB).perform()
181
+
182
+ @staticmethod
183
+ def findComponentsByXPath(wait: WebDriverWait, xpath: str):
184
+ """Finds all components matching the given XPath and returns a list of valid components
185
+ that are clickable and displayed.
186
+
187
+ :param wait: WebDriverWait instance to wait for elements
188
+ :param xpath: XPath string to locate components
189
+ :return: List of valid WebElement components
190
+ Example usage:
191
+ components = ComponentUtils.findComponentsByXPath(wait, "//button[@class='submit']")
192
+ for component in components:
193
+ component.click()
194
+ """
195
+ # Wait for the presence of elements matching the XPath
196
+ wait.until(EC.presence_of_element_located((By.XPATH, xpath)))
197
+
198
+ # Find all matching elements
199
+ driver = wait._driver
200
+ components = driver.find_elements(By.XPATH, xpath)
201
+
202
+ # Filter for clickable and displayed components
203
+ valid_components = []
204
+ for component in components:
205
+ try:
206
+ if component.is_displayed() and component.is_enabled():
207
+ valid_components.append(component)
208
+ except Exception:
209
+ continue
210
+
211
+ if len(valid_components) > 0:
212
+ return valid_components
213
+
214
+ raise Exception(f"No valid components found for XPath: {xpath}")
215
+
216
+ @staticmethod
217
+ def findComponentByXPath(wait: WebDriverWait, xpath: str):
218
+ # component = wait.until(EC.presence_of_element_located((By.XPATH, xpath)))
219
+ component = wait._driver.find_element(By.XPATH, xpath)
220
+ return component
221
+
222
+ @staticmethod
223
+ def findComponentUsingXpathAndClick(wait: WebDriverWait, xpath: str):
224
+ """Finds a component using the given XPath and clicks it.
225
+
226
+ :param wait: WebDriverWait instance to wait for elements
227
+ :param xpath: XPath string to locate the component
228
+ :return: None
229
+ Example usage:
230
+ from selenium.webdriver.support.ui import WebDriverWait
231
+ from selenium import webdriver
232
+
233
+ driver = webdriver.Chrome()
234
+ wait = WebDriverWait(driver, 10)
235
+ xpath = "//button[@id='submit']"
236
+ ComponentUtils.findComponentUsingXpathAndClick(wait, xpath)
237
+ """
238
+
239
+ component = ComponentUtils.waitForComponentToBeVisibleByXpath(wait, xpath)
240
+ ComponentUtils.click(wait, component)
241
+
242
+ @staticmethod
243
+ def click(wait: WebDriverWait, component: WebElement):
244
+ """
245
+ Clicks the given component after waiting for it to be clickable.
246
+
247
+ :param wait: WebDriverWait instance to wait for elements
248
+ :param component: WebElement representing the component to click
249
+ :return: None
250
+ Example usage:
251
+ ComponentUtils.click(wait, component)
252
+ """
253
+ wait.until(EC.element_to_be_clickable(component))
254
+ component.click()
255
+
256
+ @staticmethod
257
+ def waitForComponentToBeInVisible(wait: WebDriverWait, component: WebElement):
258
+ try:
259
+ wait.until(EC.staleness_of(component))
260
+ except Exception:
261
+ raise Exception(
262
+ "Component did not become invisible (stale) within the timeout period."
263
+ )
264
+
265
+ @staticmethod
266
+ def isComponentPresentByXpath(wait: WebDriverWait, xpath: str):
267
+ status = False
268
+ try:
269
+ wait.until(EC.presence_of_element_located((By.XPATH, xpath)))
270
+ status = True
271
+ except NoSuchElementException:
272
+ pass
273
+
274
+ return status
275
+
276
+ @staticmethod
277
+ def waitForElementToBeVisibleById(wait: WebDriverWait, id: str):
278
+ return wait.until(EC.visibility_of_element_located((By.ID, id)))
279
+
280
+ @staticmethod
281
+ def waitForElementNotToBeVisibleById(wait: WebDriverWait, id: str):
282
+ return wait.until(EC.invisibility_of_element_located((By.ID, id)))
283
+
284
+ @staticmethod
285
+ def waitForElementToBeVisibleByText(wait: WebDriverWait, text: str):
286
+ xpath = f'//*[normalize-space(translate(., "\u00a0", " "))="{text}" and not(*[normalize-space(translate(., "\u00a0", " "))="{text}"]) and not(ancestor-or-self::*[contains(@class, "---hidden")])]'
287
+ return wait.until(EC.visibility_of_element_located((By.XPATH, xpath)))
288
+
289
+ @staticmethod
290
+ def waitForElementNotToBeVisibleByText(wait: WebDriverWait, text: str):
291
+ xpath = f'//*[normalize-space(translate(., "\u00a0", " "))="{text}" and not(*[normalize-space(translate(., "\u00a0", " "))="{text}"]) and not(ancestor-or-self::*[contains(@class, "---hidden")])]'
292
+ return wait.until(EC.invisibility_of_element_located((By.XPATH, xpath)))
File without changes
@@ -0,0 +1,68 @@
1
+ Metadata-Version: 2.4
2
+ Name: robo_appian
3
+ Version: 0.0.27
4
+ Summary: Automate your Appian code testing with Python. Boost quality, save time.
5
+ License-File: LICENSE
6
+ Author: Dinil Mithra
7
+ Author-email: dinilmithra@mailme@gmail.com
8
+ Requires-Python: >=3.12,<4.0
9
+ Classifier: Operating System :: OS Independent
10
+ Classifier: Programming Language :: Python :: 3
11
+ Classifier: Programming Language :: Python :: 3.12
12
+ Classifier: Programming Language :: Python :: 3.13
13
+ Classifier: Programming Language :: Python :: 3.14
14
+ Requires-Dist: numpy
15
+ Requires-Dist: requests (>=2.25.1,<3.0.0)
16
+ Requires-Dist: selenium (>=4.34.0)
17
+ Project-URL: Homepage, https://github.com/dinilmithra/robo_appian
18
+ Project-URL: Repository, https://github.com/dinilmithra/robo_appian.git
19
+ Description-Content-Type: text/markdown
20
+
21
+ # Robo Appian
22
+
23
+ Robo Appian is a Python library for automated UI testing of Appian applications. It provides user-friendly utilities and best practices to help you write robust, maintainable, and business-focused test automation.
24
+
25
+ ## Features
26
+ - Simple, readable API for Appian UI automation
27
+ - Utilities for buttons, inputs, dropdowns, tables, tabs, and more
28
+ - Data-driven and workflow testing support
29
+ - Error handling and debugging helpers
30
+ - Designed for both technical and business users
31
+
32
+ ## Documentation
33
+ Full documentation, guides, and API reference are available at:
34
+
35
+ ➡️ [Robo Appian Documentation](https://dinilmithra.github.io/robo_appian/)
36
+
37
+ ## Quick Start
38
+ 1. Install Robo Appian:
39
+ ```bash
40
+ pip install robo_appian
41
+ ```
42
+ 2. See the [Getting Started Guide](docs/getting-started/installation.md) for setup and your first test.
43
+
44
+ ## Example Usage
45
+ ```python
46
+ from robo_appian.components import InputUtils, ButtonUtils
47
+
48
+ # Set value in a text field by label
49
+ InputUtils.setValueByLabelText(wait, "Username", "testuser")
50
+
51
+ # Click a button by label
52
+ ButtonUtils.clickByLabelText(wait, "Sign In")
53
+ ```
54
+
55
+ ## Project Structure
56
+ - `robo_appian/` - Library source code
57
+ - `docs/` - Documentation and guides
58
+
59
+ ## Contributing
60
+ Contributions are welcome! Please see the [contributing guidelines](CONTRIBUTING.md) or open an issue to get started.
61
+
62
+ ## License
63
+ MIT License. See [LICENSE](LICENSE) for details.
64
+
65
+ ---
66
+
67
+ For questions or support, contact [Dinil Mithra](mailto:dinilmithra.mailme@gmail.com) or connect on [LinkedIn](https://www.linkedin.com/in/dinilmithra).
68
+
@@ -0,0 +1,23 @@
1
+ robo_appian/__init__.py,sha256=29XO60v2ci41N1dsWjsIXHdiLPbg7K34ckyHjceTVOc,1011
2
+ robo_appian/components/ButtonUtils.py,sha256=SmvpqLUjk728b3Xp2ydw56hZEB4HE_P0WGaS5iwUWXI,4931
3
+ robo_appian/components/DateUtils.py,sha256=N9XseKlgnCyOVowO9lQ_C7Nhv7xhAForoBa7D3MhhVo,2476
4
+ robo_appian/components/DropdownUtils.py,sha256=hi3gJuWjwKLEc5qQiIf70ffv6ouacawV9HLxTuQU78w,16184
5
+ robo_appian/components/InputUtils.py,sha256=EqAECJ-8VKRJKI6sJ8e5pYI9lTAuXHDQEYZKIW8ls5I,6071
6
+ robo_appian/components/LabelUtils.py,sha256=pC7odt10hgBG8Td8zu71IqJQ0h7YHN9O-sLbtnqE-tk,2430
7
+ robo_appian/components/LinkUtils.py,sha256=32_0mW-j624Be9xlFZAkZsLjJ2OaORfp-ePSRyFwTfs,1549
8
+ robo_appian/components/SearchDropdownUtils.py,sha256=sX9b__Rir7feH1SkCd53EeLJXO7OTLkeA1FMbZU_CNs,4504
9
+ robo_appian/components/SearchInputUtils.py,sha256=2mg1QkEZGVJ-rLTvB0pMNSKvNhiqOU9QrUH0CNr4la4,3260
10
+ robo_appian/components/TabUtils.py,sha256=k-HkIK8ca-KnHXSDTXDV4190jT5P84tZ3frWSCndn5I,2257
11
+ robo_appian/components/TableUtils.py,sha256=_NBytGtP0EzBkjzrffpQ-pm3PoRPUykUvEwTcXu0xPk,6322
12
+ robo_appian/components/__init__.py,sha256=BW-fDKwq9Ntq-F7qAt-kDUudowOJBHr4sLiPV9Rjo_M,718
13
+ robo_appian/controllers/ComponentDriver.py,sha256=4zKn6Jy71cFsGWqOh7EgQ6NYfRIVvi5l5Pn31tLLM9s,4350
14
+ robo_appian/controllers/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
15
+ robo_appian/exceptions/MyCustomError.py,sha256=DVAkytXNNQNjqyTyCjk6FFd6fr3AsBe57Y19erDSqVs,222
16
+ robo_appian/exceptions/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
17
+ robo_appian/utils/BrowserUtils.py,sha256=Lp0yeHjqstdyA5POqFv4TxGY1TKixApMT6G_nnWadXs,1747
18
+ robo_appian/utils/ComponentUtils.py,sha256=NBdqfpetJBmorLWEiOgc3fJWhun4d8aIkUcERf0_vIg,10873
19
+ robo_appian/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
20
+ robo_appian-0.0.27.dist-info/METADATA,sha256=XocLA7aAC_1jjPF26UHnye_ZHoxmYGQxp_gFrjNRzz8,2334
21
+ robo_appian-0.0.27.dist-info/WHEEL,sha256=zp0Cn7JsFoX2ATtOhtaFYIiE2rmFAD4OcMhtUki8W3U,88
22
+ robo_appian-0.0.27.dist-info/licenses/LICENSE,sha256=g-xR4dRa9_4iFkMoJmED-wE-J5hoxbk3105Knhfpjm0,1068
23
+ robo_appian-0.0.27.dist-info/RECORD,,
@@ -0,0 +1,4 @@
1
+ Wheel-Version: 1.0
2
+ Generator: poetry-core 2.2.1
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 dinilmithra
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.