workato-platform-cli 1.0.0rc5.dev5__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.
Files changed (306) hide show
  1. workato_platform_cli/__init__.py +135 -0
  2. workato_platform_cli/_version.py +34 -0
  3. workato_platform_cli/cli/__init__.py +126 -0
  4. workato_platform_cli/cli/commands/__init__.py +0 -0
  5. workato_platform_cli/cli/commands/api_clients.py +627 -0
  6. workato_platform_cli/cli/commands/api_collections.py +497 -0
  7. workato_platform_cli/cli/commands/assets.py +82 -0
  8. workato_platform_cli/cli/commands/connections.py +1205 -0
  9. workato_platform_cli/cli/commands/connectors/__init__.py +0 -0
  10. workato_platform_cli/cli/commands/connectors/command.py +178 -0
  11. workato_platform_cli/cli/commands/connectors/connector_manager.py +351 -0
  12. workato_platform_cli/cli/commands/data_tables.py +345 -0
  13. workato_platform_cli/cli/commands/guide.py +315 -0
  14. workato_platform_cli/cli/commands/init.py +229 -0
  15. workato_platform_cli/cli/commands/profiles.py +364 -0
  16. workato_platform_cli/cli/commands/projects/__init__.py +0 -0
  17. workato_platform_cli/cli/commands/projects/command.py +513 -0
  18. workato_platform_cli/cli/commands/projects/project_manager.py +338 -0
  19. workato_platform_cli/cli/commands/properties.py +174 -0
  20. workato_platform_cli/cli/commands/pull.py +327 -0
  21. workato_platform_cli/cli/commands/push/__init__.py +0 -0
  22. workato_platform_cli/cli/commands/push/command.py +320 -0
  23. workato_platform_cli/cli/commands/recipes/__init__.py +0 -0
  24. workato_platform_cli/cli/commands/recipes/command.py +847 -0
  25. workato_platform_cli/cli/commands/recipes/validator.py +1740 -0
  26. workato_platform_cli/cli/commands/workspace.py +73 -0
  27. workato_platform_cli/cli/containers.py +80 -0
  28. workato_platform_cli/cli/resources/data/connection-data.json +7364 -0
  29. workato_platform_cli/cli/resources/data/picklist-data.json +3706 -0
  30. workato_platform_cli/cli/resources/docs/README.md +178 -0
  31. workato_platform_cli/cli/resources/docs/actions.md +452 -0
  32. workato_platform_cli/cli/resources/docs/block-structure.md +424 -0
  33. workato_platform_cli/cli/resources/docs/connections-parameters.md +11946 -0
  34. workato_platform_cli/cli/resources/docs/data-mapping.md +779 -0
  35. workato_platform_cli/cli/resources/docs/formulas/array-list-formulas.md +1276 -0
  36. workato_platform_cli/cli/resources/docs/formulas/conditions.md +102 -0
  37. workato_platform_cli/cli/resources/docs/formulas/date-formulas.md +798 -0
  38. workato_platform_cli/cli/resources/docs/formulas/number-formulas.md +507 -0
  39. workato_platform_cli/cli/resources/docs/formulas/other-formulas.md +419 -0
  40. workato_platform_cli/cli/resources/docs/formulas/string-formulas.md +1353 -0
  41. workato_platform_cli/cli/resources/docs/formulas.md +214 -0
  42. workato_platform_cli/cli/resources/docs/naming-conventions.md +163 -0
  43. workato_platform_cli/cli/resources/docs/recipe-deployment-workflow.md +352 -0
  44. workato_platform_cli/cli/resources/docs/recipe-fundamentals.md +179 -0
  45. workato_platform_cli/cli/resources/docs/triggers.md +360 -0
  46. workato_platform_cli/cli/utils/__init__.py +10 -0
  47. workato_platform_cli/cli/utils/config/__init__.py +33 -0
  48. workato_platform_cli/cli/utils/config/manager.py +1001 -0
  49. workato_platform_cli/cli/utils/config/models.py +89 -0
  50. workato_platform_cli/cli/utils/config/profiles.py +491 -0
  51. workato_platform_cli/cli/utils/config/workspace.py +113 -0
  52. workato_platform_cli/cli/utils/exception_handler.py +531 -0
  53. workato_platform_cli/cli/utils/gitignore.py +32 -0
  54. workato_platform_cli/cli/utils/ignore_patterns.py +44 -0
  55. workato_platform_cli/cli/utils/spinner.py +63 -0
  56. workato_platform_cli/cli/utils/version_checker.py +237 -0
  57. workato_platform_cli/client/__init__.py +0 -0
  58. workato_platform_cli/client/workato_api/__init__.py +202 -0
  59. workato_platform_cli/client/workato_api/api/__init__.py +15 -0
  60. workato_platform_cli/client/workato_api/api/api_platform_api.py +2875 -0
  61. workato_platform_cli/client/workato_api/api/connections_api.py +1807 -0
  62. workato_platform_cli/client/workato_api/api/connectors_api.py +840 -0
  63. workato_platform_cli/client/workato_api/api/data_tables_api.py +604 -0
  64. workato_platform_cli/client/workato_api/api/export_api.py +621 -0
  65. workato_platform_cli/client/workato_api/api/folders_api.py +621 -0
  66. workato_platform_cli/client/workato_api/api/packages_api.py +1197 -0
  67. workato_platform_cli/client/workato_api/api/projects_api.py +590 -0
  68. workato_platform_cli/client/workato_api/api/properties_api.py +620 -0
  69. workato_platform_cli/client/workato_api/api/recipes_api.py +1379 -0
  70. workato_platform_cli/client/workato_api/api/users_api.py +285 -0
  71. workato_platform_cli/client/workato_api/api_client.py +807 -0
  72. workato_platform_cli/client/workato_api/api_response.py +21 -0
  73. workato_platform_cli/client/workato_api/configuration.py +601 -0
  74. workato_platform_cli/client/workato_api/docs/APIPlatformApi.md +844 -0
  75. workato_platform_cli/client/workato_api/docs/ApiClient.md +46 -0
  76. workato_platform_cli/client/workato_api/docs/ApiClientApiCollectionsInner.md +30 -0
  77. workato_platform_cli/client/workato_api/docs/ApiClientApiPoliciesInner.md +30 -0
  78. workato_platform_cli/client/workato_api/docs/ApiClientCreateRequest.md +46 -0
  79. workato_platform_cli/client/workato_api/docs/ApiClientListResponse.md +32 -0
  80. workato_platform_cli/client/workato_api/docs/ApiClientResponse.md +29 -0
  81. workato_platform_cli/client/workato_api/docs/ApiCollection.md +38 -0
  82. workato_platform_cli/client/workato_api/docs/ApiCollectionCreateRequest.md +32 -0
  83. workato_platform_cli/client/workato_api/docs/ApiEndpoint.md +41 -0
  84. workato_platform_cli/client/workato_api/docs/ApiKey.md +36 -0
  85. workato_platform_cli/client/workato_api/docs/ApiKeyCreateRequest.md +32 -0
  86. workato_platform_cli/client/workato_api/docs/ApiKeyListResponse.md +32 -0
  87. workato_platform_cli/client/workato_api/docs/ApiKeyResponse.md +29 -0
  88. workato_platform_cli/client/workato_api/docs/Asset.md +39 -0
  89. workato_platform_cli/client/workato_api/docs/AssetReference.md +37 -0
  90. workato_platform_cli/client/workato_api/docs/Connection.md +44 -0
  91. workato_platform_cli/client/workato_api/docs/ConnectionCreateRequest.md +35 -0
  92. workato_platform_cli/client/workato_api/docs/ConnectionUpdateRequest.md +34 -0
  93. workato_platform_cli/client/workato_api/docs/ConnectionsApi.md +526 -0
  94. workato_platform_cli/client/workato_api/docs/ConnectorAction.md +33 -0
  95. workato_platform_cli/client/workato_api/docs/ConnectorVersion.md +32 -0
  96. workato_platform_cli/client/workato_api/docs/ConnectorsApi.md +249 -0
  97. workato_platform_cli/client/workato_api/docs/CreateExportManifestRequest.md +29 -0
  98. workato_platform_cli/client/workato_api/docs/CreateFolderRequest.md +30 -0
  99. workato_platform_cli/client/workato_api/docs/CustomConnector.md +35 -0
  100. workato_platform_cli/client/workato_api/docs/CustomConnectorCodeResponse.md +29 -0
  101. workato_platform_cli/client/workato_api/docs/CustomConnectorCodeResponseData.md +29 -0
  102. workato_platform_cli/client/workato_api/docs/CustomConnectorListResponse.md +29 -0
  103. workato_platform_cli/client/workato_api/docs/DataTable.md +34 -0
  104. workato_platform_cli/client/workato_api/docs/DataTableColumn.md +37 -0
  105. workato_platform_cli/client/workato_api/docs/DataTableColumnRequest.md +37 -0
  106. workato_platform_cli/client/workato_api/docs/DataTableCreateRequest.md +31 -0
  107. workato_platform_cli/client/workato_api/docs/DataTableCreateResponse.md +29 -0
  108. workato_platform_cli/client/workato_api/docs/DataTableListResponse.md +29 -0
  109. workato_platform_cli/client/workato_api/docs/DataTableRelation.md +30 -0
  110. workato_platform_cli/client/workato_api/docs/DataTablesApi.md +172 -0
  111. workato_platform_cli/client/workato_api/docs/DeleteProject403Response.md +29 -0
  112. workato_platform_cli/client/workato_api/docs/Error.md +29 -0
  113. workato_platform_cli/client/workato_api/docs/ExportApi.md +175 -0
  114. workato_platform_cli/client/workato_api/docs/ExportManifestRequest.md +35 -0
  115. workato_platform_cli/client/workato_api/docs/ExportManifestResponse.md +29 -0
  116. workato_platform_cli/client/workato_api/docs/ExportManifestResponseResult.md +36 -0
  117. workato_platform_cli/client/workato_api/docs/Folder.md +35 -0
  118. workato_platform_cli/client/workato_api/docs/FolderAssetsResponse.md +29 -0
  119. workato_platform_cli/client/workato_api/docs/FolderAssetsResponseResult.md +29 -0
  120. workato_platform_cli/client/workato_api/docs/FolderCreationResponse.md +35 -0
  121. workato_platform_cli/client/workato_api/docs/FoldersApi.md +176 -0
  122. workato_platform_cli/client/workato_api/docs/ImportResults.md +32 -0
  123. workato_platform_cli/client/workato_api/docs/OAuthUrlResponse.md +29 -0
  124. workato_platform_cli/client/workato_api/docs/OAuthUrlResponseData.md +29 -0
  125. workato_platform_cli/client/workato_api/docs/OpenApiSpec.md +30 -0
  126. workato_platform_cli/client/workato_api/docs/PackageDetailsResponse.md +35 -0
  127. workato_platform_cli/client/workato_api/docs/PackageDetailsResponseRecipeStatusInner.md +30 -0
  128. workato_platform_cli/client/workato_api/docs/PackageResponse.md +33 -0
  129. workato_platform_cli/client/workato_api/docs/PackagesApi.md +364 -0
  130. workato_platform_cli/client/workato_api/docs/PicklistRequest.md +30 -0
  131. workato_platform_cli/client/workato_api/docs/PicklistResponse.md +29 -0
  132. workato_platform_cli/client/workato_api/docs/PlatformConnector.md +36 -0
  133. workato_platform_cli/client/workato_api/docs/PlatformConnectorListResponse.md +32 -0
  134. workato_platform_cli/client/workato_api/docs/Project.md +32 -0
  135. workato_platform_cli/client/workato_api/docs/ProjectsApi.md +173 -0
  136. workato_platform_cli/client/workato_api/docs/PropertiesApi.md +186 -0
  137. workato_platform_cli/client/workato_api/docs/Recipe.md +58 -0
  138. workato_platform_cli/client/workato_api/docs/RecipeConfigInner.md +33 -0
  139. workato_platform_cli/client/workato_api/docs/RecipeConnectionUpdateRequest.md +30 -0
  140. workato_platform_cli/client/workato_api/docs/RecipeListResponse.md +29 -0
  141. workato_platform_cli/client/workato_api/docs/RecipeStartResponse.md +31 -0
  142. workato_platform_cli/client/workato_api/docs/RecipesApi.md +367 -0
  143. workato_platform_cli/client/workato_api/docs/RuntimeUserConnectionCreateRequest.md +34 -0
  144. workato_platform_cli/client/workato_api/docs/RuntimeUserConnectionResponse.md +29 -0
  145. workato_platform_cli/client/workato_api/docs/RuntimeUserConnectionResponseData.md +30 -0
  146. workato_platform_cli/client/workato_api/docs/SuccessResponse.md +29 -0
  147. workato_platform_cli/client/workato_api/docs/UpsertProjectPropertiesRequest.md +29 -0
  148. workato_platform_cli/client/workato_api/docs/User.md +48 -0
  149. workato_platform_cli/client/workato_api/docs/UsersApi.md +84 -0
  150. workato_platform_cli/client/workato_api/docs/ValidationError.md +30 -0
  151. workato_platform_cli/client/workato_api/docs/ValidationErrorErrorsValue.md +28 -0
  152. workato_platform_cli/client/workato_api/exceptions.py +216 -0
  153. workato_platform_cli/client/workato_api/models/__init__.py +83 -0
  154. workato_platform_cli/client/workato_api/models/api_client.py +185 -0
  155. workato_platform_cli/client/workato_api/models/api_client_api_collections_inner.py +89 -0
  156. workato_platform_cli/client/workato_api/models/api_client_api_policies_inner.py +89 -0
  157. workato_platform_cli/client/workato_api/models/api_client_create_request.py +138 -0
  158. workato_platform_cli/client/workato_api/models/api_client_list_response.py +101 -0
  159. workato_platform_cli/client/workato_api/models/api_client_response.py +91 -0
  160. workato_platform_cli/client/workato_api/models/api_collection.py +110 -0
  161. workato_platform_cli/client/workato_api/models/api_collection_create_request.py +97 -0
  162. workato_platform_cli/client/workato_api/models/api_endpoint.py +117 -0
  163. workato_platform_cli/client/workato_api/models/api_key.py +102 -0
  164. workato_platform_cli/client/workato_api/models/api_key_create_request.py +93 -0
  165. workato_platform_cli/client/workato_api/models/api_key_list_response.py +101 -0
  166. workato_platform_cli/client/workato_api/models/api_key_response.py +91 -0
  167. workato_platform_cli/client/workato_api/models/asset.py +124 -0
  168. workato_platform_cli/client/workato_api/models/asset_reference.py +110 -0
  169. workato_platform_cli/client/workato_api/models/connection.py +173 -0
  170. workato_platform_cli/client/workato_api/models/connection_create_request.py +99 -0
  171. workato_platform_cli/client/workato_api/models/connection_update_request.py +97 -0
  172. workato_platform_cli/client/workato_api/models/connector_action.py +100 -0
  173. workato_platform_cli/client/workato_api/models/connector_version.py +99 -0
  174. workato_platform_cli/client/workato_api/models/create_export_manifest_request.py +91 -0
  175. workato_platform_cli/client/workato_api/models/create_folder_request.py +89 -0
  176. workato_platform_cli/client/workato_api/models/custom_connector.py +117 -0
  177. workato_platform_cli/client/workato_api/models/custom_connector_code_response.py +91 -0
  178. workato_platform_cli/client/workato_api/models/custom_connector_code_response_data.py +87 -0
  179. workato_platform_cli/client/workato_api/models/custom_connector_list_response.py +95 -0
  180. workato_platform_cli/client/workato_api/models/data_table.py +107 -0
  181. workato_platform_cli/client/workato_api/models/data_table_column.py +125 -0
  182. workato_platform_cli/client/workato_api/models/data_table_column_request.py +130 -0
  183. workato_platform_cli/client/workato_api/models/data_table_create_request.py +99 -0
  184. workato_platform_cli/client/workato_api/models/data_table_create_response.py +91 -0
  185. workato_platform_cli/client/workato_api/models/data_table_list_response.py +95 -0
  186. workato_platform_cli/client/workato_api/models/data_table_relation.py +90 -0
  187. workato_platform_cli/client/workato_api/models/delete_project403_response.py +87 -0
  188. workato_platform_cli/client/workato_api/models/error.py +87 -0
  189. workato_platform_cli/client/workato_api/models/export_manifest_request.py +107 -0
  190. workato_platform_cli/client/workato_api/models/export_manifest_response.py +91 -0
  191. workato_platform_cli/client/workato_api/models/export_manifest_response_result.py +112 -0
  192. workato_platform_cli/client/workato_api/models/folder.py +110 -0
  193. workato_platform_cli/client/workato_api/models/folder_assets_response.py +91 -0
  194. workato_platform_cli/client/workato_api/models/folder_assets_response_result.py +95 -0
  195. workato_platform_cli/client/workato_api/models/folder_creation_response.py +110 -0
  196. workato_platform_cli/client/workato_api/models/import_results.py +93 -0
  197. workato_platform_cli/client/workato_api/models/o_auth_url_response.py +91 -0
  198. workato_platform_cli/client/workato_api/models/o_auth_url_response_data.py +87 -0
  199. workato_platform_cli/client/workato_api/models/open_api_spec.py +96 -0
  200. workato_platform_cli/client/workato_api/models/package_details_response.py +126 -0
  201. workato_platform_cli/client/workato_api/models/package_details_response_recipe_status_inner.py +99 -0
  202. workato_platform_cli/client/workato_api/models/package_response.py +109 -0
  203. workato_platform_cli/client/workato_api/models/picklist_request.py +89 -0
  204. workato_platform_cli/client/workato_api/models/picklist_response.py +88 -0
  205. workato_platform_cli/client/workato_api/models/platform_connector.py +116 -0
  206. workato_platform_cli/client/workato_api/models/platform_connector_list_response.py +101 -0
  207. workato_platform_cli/client/workato_api/models/project.py +93 -0
  208. workato_platform_cli/client/workato_api/models/recipe.py +174 -0
  209. workato_platform_cli/client/workato_api/models/recipe_config_inner.py +100 -0
  210. workato_platform_cli/client/workato_api/models/recipe_connection_update_request.py +89 -0
  211. workato_platform_cli/client/workato_api/models/recipe_list_response.py +95 -0
  212. workato_platform_cli/client/workato_api/models/recipe_start_response.py +91 -0
  213. workato_platform_cli/client/workato_api/models/runtime_user_connection_create_request.py +97 -0
  214. workato_platform_cli/client/workato_api/models/runtime_user_connection_response.py +91 -0
  215. workato_platform_cli/client/workato_api/models/runtime_user_connection_response_data.py +89 -0
  216. workato_platform_cli/client/workato_api/models/success_response.py +87 -0
  217. workato_platform_cli/client/workato_api/models/upsert_project_properties_request.py +88 -0
  218. workato_platform_cli/client/workato_api/models/user.py +151 -0
  219. workato_platform_cli/client/workato_api/models/validation_error.py +102 -0
  220. workato_platform_cli/client/workato_api/models/validation_error_errors_value.py +143 -0
  221. workato_platform_cli/client/workato_api/rest.py +213 -0
  222. workato_platform_cli/client/workato_api/test/__init__.py +0 -0
  223. workato_platform_cli/client/workato_api/test/test_api_client.py +94 -0
  224. workato_platform_cli/client/workato_api/test/test_api_client_api_collections_inner.py +52 -0
  225. workato_platform_cli/client/workato_api/test/test_api_client_api_policies_inner.py +52 -0
  226. workato_platform_cli/client/workato_api/test/test_api_client_create_request.py +75 -0
  227. workato_platform_cli/client/workato_api/test/test_api_client_list_response.py +114 -0
  228. workato_platform_cli/client/workato_api/test/test_api_client_response.py +104 -0
  229. workato_platform_cli/client/workato_api/test/test_api_collection.py +72 -0
  230. workato_platform_cli/client/workato_api/test/test_api_collection_create_request.py +57 -0
  231. workato_platform_cli/client/workato_api/test/test_api_endpoint.py +75 -0
  232. workato_platform_cli/client/workato_api/test/test_api_key.py +64 -0
  233. workato_platform_cli/client/workato_api/test/test_api_key_create_request.py +56 -0
  234. workato_platform_cli/client/workato_api/test/test_api_key_list_response.py +78 -0
  235. workato_platform_cli/client/workato_api/test/test_api_key_response.py +68 -0
  236. workato_platform_cli/client/workato_api/test/test_api_platform_api.py +101 -0
  237. workato_platform_cli/client/workato_api/test/test_asset.py +67 -0
  238. workato_platform_cli/client/workato_api/test/test_asset_reference.py +62 -0
  239. workato_platform_cli/client/workato_api/test/test_connection.py +81 -0
  240. workato_platform_cli/client/workato_api/test/test_connection_create_request.py +59 -0
  241. workato_platform_cli/client/workato_api/test/test_connection_update_request.py +56 -0
  242. workato_platform_cli/client/workato_api/test/test_connections_api.py +73 -0
  243. workato_platform_cli/client/workato_api/test/test_connector_action.py +59 -0
  244. workato_platform_cli/client/workato_api/test/test_connector_version.py +58 -0
  245. workato_platform_cli/client/workato_api/test/test_connectors_api.py +52 -0
  246. workato_platform_cli/client/workato_api/test/test_create_export_manifest_request.py +88 -0
  247. workato_platform_cli/client/workato_api/test/test_create_folder_request.py +53 -0
  248. workato_platform_cli/client/workato_api/test/test_custom_connector.py +76 -0
  249. workato_platform_cli/client/workato_api/test/test_custom_connector_code_response.py +54 -0
  250. workato_platform_cli/client/workato_api/test/test_custom_connector_code_response_data.py +52 -0
  251. workato_platform_cli/client/workato_api/test/test_custom_connector_list_response.py +82 -0
  252. workato_platform_cli/client/workato_api/test/test_data_table.py +88 -0
  253. workato_platform_cli/client/workato_api/test/test_data_table_column.py +72 -0
  254. workato_platform_cli/client/workato_api/test/test_data_table_column_request.py +64 -0
  255. workato_platform_cli/client/workato_api/test/test_data_table_create_request.py +82 -0
  256. workato_platform_cli/client/workato_api/test/test_data_table_create_response.py +90 -0
  257. workato_platform_cli/client/workato_api/test/test_data_table_list_response.py +94 -0
  258. workato_platform_cli/client/workato_api/test/test_data_table_relation.py +54 -0
  259. workato_platform_cli/client/workato_api/test/test_data_tables_api.py +45 -0
  260. workato_platform_cli/client/workato_api/test/test_delete_project403_response.py +51 -0
  261. workato_platform_cli/client/workato_api/test/test_error.py +52 -0
  262. workato_platform_cli/client/workato_api/test/test_export_api.py +45 -0
  263. workato_platform_cli/client/workato_api/test/test_export_manifest_request.py +69 -0
  264. workato_platform_cli/client/workato_api/test/test_export_manifest_response.py +68 -0
  265. workato_platform_cli/client/workato_api/test/test_export_manifest_response_result.py +66 -0
  266. workato_platform_cli/client/workato_api/test/test_folder.py +64 -0
  267. workato_platform_cli/client/workato_api/test/test_folder_assets_response.py +80 -0
  268. workato_platform_cli/client/workato_api/test/test_folder_assets_response_result.py +78 -0
  269. workato_platform_cli/client/workato_api/test/test_folder_creation_response.py +64 -0
  270. workato_platform_cli/client/workato_api/test/test_folders_api.py +45 -0
  271. workato_platform_cli/client/workato_api/test/test_import_results.py +58 -0
  272. workato_platform_cli/client/workato_api/test/test_o_auth_url_response.py +54 -0
  273. workato_platform_cli/client/workato_api/test/test_o_auth_url_response_data.py +52 -0
  274. workato_platform_cli/client/workato_api/test/test_open_api_spec.py +54 -0
  275. workato_platform_cli/client/workato_api/test/test_package_details_response.py +64 -0
  276. workato_platform_cli/client/workato_api/test/test_package_details_response_recipe_status_inner.py +52 -0
  277. workato_platform_cli/client/workato_api/test/test_package_response.py +58 -0
  278. workato_platform_cli/client/workato_api/test/test_packages_api.py +59 -0
  279. workato_platform_cli/client/workato_api/test/test_picklist_request.py +53 -0
  280. workato_platform_cli/client/workato_api/test/test_picklist_response.py +52 -0
  281. workato_platform_cli/client/workato_api/test/test_platform_connector.py +94 -0
  282. workato_platform_cli/client/workato_api/test/test_platform_connector_list_response.py +106 -0
  283. workato_platform_cli/client/workato_api/test/test_project.py +57 -0
  284. workato_platform_cli/client/workato_api/test/test_projects_api.py +45 -0
  285. workato_platform_cli/client/workato_api/test/test_properties_api.py +45 -0
  286. workato_platform_cli/client/workato_api/test/test_recipe.py +124 -0
  287. workato_platform_cli/client/workato_api/test/test_recipe_config_inner.py +55 -0
  288. workato_platform_cli/client/workato_api/test/test_recipe_connection_update_request.py +54 -0
  289. workato_platform_cli/client/workato_api/test/test_recipe_list_response.py +134 -0
  290. workato_platform_cli/client/workato_api/test/test_recipe_start_response.py +54 -0
  291. workato_platform_cli/client/workato_api/test/test_recipes_api.py +59 -0
  292. workato_platform_cli/client/workato_api/test/test_runtime_user_connection_create_request.py +59 -0
  293. workato_platform_cli/client/workato_api/test/test_runtime_user_connection_response.py +56 -0
  294. workato_platform_cli/client/workato_api/test/test_runtime_user_connection_response_data.py +54 -0
  295. workato_platform_cli/client/workato_api/test/test_success_response.py +52 -0
  296. workato_platform_cli/client/workato_api/test/test_upsert_project_properties_request.py +52 -0
  297. workato_platform_cli/client/workato_api/test/test_user.py +85 -0
  298. workato_platform_cli/client/workato_api/test/test_users_api.py +38 -0
  299. workato_platform_cli/client/workato_api/test/test_validation_error.py +52 -0
  300. workato_platform_cli/client/workato_api/test/test_validation_error_errors_value.py +50 -0
  301. workato_platform_cli/client/workato_api_README.md +205 -0
  302. workato_platform_cli-1.0.0rc5.dev5.dist-info/METADATA +185 -0
  303. workato_platform_cli-1.0.0rc5.dev5.dist-info/RECORD +306 -0
  304. workato_platform_cli-1.0.0rc5.dev5.dist-info/WHEEL +4 -0
  305. workato_platform_cli-1.0.0rc5.dev5.dist-info/entry_points.txt +2 -0
  306. workato_platform_cli-1.0.0rc5.dev5.dist-info/licenses/LICENSE +7 -0
@@ -0,0 +1,345 @@
1
+ import json
2
+ import re
3
+
4
+ from typing import Any
5
+
6
+ import asyncclick as click
7
+
8
+ from dependency_injector.wiring import Provide, inject
9
+
10
+ from workato_platform_cli import Workato
11
+ from workato_platform_cli.cli.commands.projects.project_manager import ProjectManager
12
+ from workato_platform_cli.cli.containers import Container
13
+ from workato_platform_cli.cli.utils import Spinner
14
+ from workato_platform_cli.cli.utils.config import ConfigManager
15
+ from workato_platform_cli.cli.utils.exception_handler import (
16
+ handle_api_exceptions,
17
+ handle_cli_exceptions,
18
+ )
19
+ from workato_platform_cli.client.workato_api.models.data_table import DataTable
20
+ from workato_platform_cli.client.workato_api.models.data_table_column_request import (
21
+ DataTableColumnRequest,
22
+ )
23
+ from workato_platform_cli.client.workato_api.models.data_table_create_request import (
24
+ DataTableCreateRequest,
25
+ )
26
+
27
+
28
+ @click.group(name="data-tables")
29
+ def data_tables() -> None:
30
+ """Manage data tables"""
31
+ pass
32
+
33
+
34
+ @data_tables.command(name="list")
35
+ @handle_cli_exceptions
36
+ @inject
37
+ @handle_api_exceptions
38
+ async def list_data_tables(
39
+ workato_api_client: Workato = Provide[Container.workato_api_client],
40
+ ) -> None:
41
+ """List all data tables using the Workato API"""
42
+ spinner = Spinner("Fetching data tables")
43
+ spinner.start()
44
+
45
+ try:
46
+ response = await workato_api_client.data_tables_api.list_data_tables()
47
+ tables = response.data
48
+ finally:
49
+ elapsed = spinner.stop()
50
+
51
+ click.echo(f"📊 Data Tables ({len(tables)} found) - ({elapsed:.1f}s)")
52
+
53
+ if not tables:
54
+ click.echo(" ℹ️ No data tables found")
55
+ click.echo(
56
+ " 💡 Create one: workato data-tables create --name 'Table Name' "
57
+ "--schema-json '[...]'"
58
+ )
59
+ return
60
+
61
+ click.echo()
62
+
63
+ # Display tables
64
+ for table in tables:
65
+ display_table_summary(table)
66
+ click.echo()
67
+
68
+ click.echo("💡 Commands:")
69
+ click.echo(
70
+ " • Create table: workato data-tables create --name 'Table Name' "
71
+ "--schema-json '[...]'"
72
+ )
73
+
74
+
75
+ @data_tables.command(name="create")
76
+ @click.option("--name", required=True, help="Name of the data table")
77
+ @click.option(
78
+ "--folder-id",
79
+ type=int,
80
+ help="Folder ID (uses current project folder if not specified)",
81
+ )
82
+ @click.option(
83
+ "--schema-json", required=True, help="JSON string containing table schema"
84
+ )
85
+ @handle_cli_exceptions
86
+ @inject
87
+ @handle_api_exceptions
88
+ async def create_data_table(
89
+ name: str,
90
+ schema_json: str,
91
+ folder_id: int | None = None,
92
+ config_manager: ConfigManager = Provide[Container.config_manager],
93
+ ) -> None:
94
+ """Create a new data table with schema definition
95
+
96
+ Schema can be provided via --schema-json (JSON string).
97
+
98
+ Schema format example:
99
+ [
100
+ {
101
+ "name": "id",
102
+ "type": "integer",
103
+ "optional": false,
104
+ "hint": "Unique identifier"
105
+ },
106
+ {
107
+ "name": "name",
108
+ "type": "string",
109
+ "optional": false,
110
+ "default_value": "Unknown"
111
+ },
112
+ {
113
+ "name": "created_at",
114
+ "type": "date_time",
115
+ "optional": true
116
+ }
117
+ ]
118
+ """
119
+
120
+ if not schema_json:
121
+ click.echo("❌ Schema is required. Provide --schema-json")
122
+ return
123
+
124
+ # Get folder ID from parameter or meta file
125
+ if not folder_id:
126
+ meta_data = config_manager.load_config()
127
+
128
+ if not meta_data.folder_id:
129
+ click.echo("❌ No folder ID provided and no project configured.")
130
+ click.echo("💡 Either specify --folder-id or run 'workato init' first.")
131
+ return
132
+
133
+ folder_id = meta_data.folder_id
134
+
135
+ # Parse schema
136
+ try:
137
+ schema = json.loads(schema_json)
138
+ except json.JSONDecodeError as e:
139
+ click.echo(f"❌ Invalid JSON in schema: {str(e)}")
140
+ return
141
+
142
+ if not isinstance(schema, list):
143
+ click.echo("❌ Schema must be an array of column definitions")
144
+ return
145
+
146
+ # Validate schema
147
+ validation_errors = validate_schema(schema)
148
+ if validation_errors:
149
+ click.echo("❌ Schema validation failed:")
150
+ for error in validation_errors:
151
+ click.echo(f" • {error}")
152
+ return
153
+
154
+ # Create data table
155
+ await create_table(name, folder_id, schema)
156
+
157
+
158
+ @inject
159
+ @handle_api_exceptions
160
+ async def create_table(
161
+ name: str,
162
+ folder_id: int,
163
+ schema: list[DataTableColumnRequest],
164
+ workato_api_client: Workato = Provide[Container.workato_api_client],
165
+ project_manager: ProjectManager = Provide[Container.project_manager],
166
+ ) -> None:
167
+ """Create a data table using the Workato API"""
168
+ spinner = Spinner(f"Creating data table '{name}'")
169
+ spinner.start()
170
+
171
+ try:
172
+ response = await workato_api_client.data_tables_api.create_data_table(
173
+ data_table_create_request=DataTableCreateRequest(
174
+ name=name,
175
+ folder_id=folder_id,
176
+ var_schema=schema,
177
+ )
178
+ )
179
+ table_data = response.data
180
+ finally:
181
+ elapsed = spinner.stop()
182
+
183
+ click.echo(f"✅ Data table created successfully ({elapsed:.1f}s)")
184
+
185
+ # Display table details
186
+ click.echo(f" 📄 Name: {table_data.name}")
187
+ click.echo(f" 🆔 ID: {table_data.id}")
188
+ click.echo(f" 📁 Folder ID: {table_data.folder_id}")
189
+
190
+ # Show schema summary
191
+ column_count = len(table_data.var_schema)
192
+ column_names = [col.name for col in table_data.var_schema[:5]]
193
+ if column_count <= 5:
194
+ click.echo(f" 📊 Columns: {', '.join(column_names)}")
195
+ else:
196
+ click.echo(f" 📊 Columns: {', '.join(column_names)} +{column_count - 5} more")
197
+
198
+ click.echo()
199
+ click.echo("💡 Next steps:")
200
+ click.echo(" • Add data to the table via recipes or API")
201
+ click.echo(" • Configure table permissions if needed")
202
+ click.echo(" • Use table in recipe actions and triggers")
203
+
204
+ # Handle post-creation sync
205
+ await project_manager.handle_post_api_sync()
206
+
207
+
208
+ def validate_schema(schema: list[dict[str, Any]]) -> list[str]:
209
+ """Validate schema structure and field types"""
210
+ errors: list[str] = []
211
+ valid_types = [
212
+ "boolean",
213
+ "date",
214
+ "date_time",
215
+ "integer",
216
+ "number",
217
+ "string",
218
+ "file",
219
+ "relation",
220
+ ]
221
+ uuid_pattern = r"^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$"
222
+
223
+ if not schema:
224
+ errors.append("Schema cannot be empty")
225
+ return errors
226
+
227
+ for i, column in enumerate(schema):
228
+ # Check required fields
229
+ if "name" not in column:
230
+ errors.append(f"Column {i + 1}: 'name' is required")
231
+ elif not isinstance(column["name"], str) or not column["name"].strip():
232
+ errors.append(f"Column {i + 1}: 'name' must be a non-empty string")
233
+
234
+ if "type" not in column:
235
+ errors.append(f"Column {i + 1}: 'type' is required")
236
+ elif column["type"] not in valid_types:
237
+ errors.append(f"Column {i + 1}: 'type' must be one of {valid_types}")
238
+
239
+ if "optional" not in column:
240
+ errors.append(f"Column {i + 1}: 'optional' is required")
241
+ elif not isinstance(column["optional"], bool | int) or column[
242
+ "optional"
243
+ ] not in [True, False, 0, 1]:
244
+ errors.append(f"Column {i + 1}: 'optional' must be true, false, 0, or 1")
245
+
246
+ # Check optional fields
247
+ if "field_id" in column:
248
+ field_id = column["field_id"]
249
+ if not isinstance(field_id, str) or not re.match(uuid_pattern, field_id):
250
+ errors.append(f"Column {i + 1}: 'field_id' must be a valid UUID format")
251
+
252
+ if "hint" in column and not isinstance(column["hint"], str):
253
+ errors.append(f"Column {i + 1}: 'hint' must be a string")
254
+
255
+ if "multivalue" in column and not isinstance(column["multivalue"], bool):
256
+ errors.append(f"Column {i + 1}: 'multivalue' must be a boolean")
257
+
258
+ # Validate relation fields
259
+ if column.get("type") == "relation":
260
+ if "relation" not in column:
261
+ errors.append(
262
+ f"Column {i + 1}: 'relation' object required for relation type"
263
+ )
264
+ else:
265
+ relation = column["relation"]
266
+ if not isinstance(relation, dict):
267
+ errors.append(f"Column {i + 1}: 'relation' must be an object")
268
+ else:
269
+ if "field_id" not in relation:
270
+ errors.append(
271
+ f"Column {i + 1}: 'relation.field_id' is required"
272
+ )
273
+ if "table_id" in relation and not isinstance(
274
+ relation["table_id"], str
275
+ ):
276
+ errors.append(
277
+ f"Column {i + 1}: 'relation.table_id' must be a string"
278
+ )
279
+
280
+ # Validate default_value matches type
281
+ if "default_value" in column and "type" in column:
282
+ default_val = column["default_value"]
283
+ col_type = column["type"]
284
+
285
+ type_checks = {
286
+ "boolean": lambda x: isinstance(x, bool),
287
+ "integer": lambda x: isinstance(x, int),
288
+ "number": lambda x: isinstance(x, int | float),
289
+ "string": lambda x: isinstance(x, str),
290
+ "date": lambda x: isinstance(x, str), # Should be date string
291
+ "date_time": lambda x: isinstance(x, str), # Should be datetime string
292
+ }
293
+
294
+ if col_type in type_checks and not type_checks[col_type](default_val):
295
+ errors.append(
296
+ f"Column {i + 1}: 'default_value' type doesn't match column "
297
+ f"type '{col_type}'"
298
+ )
299
+
300
+ return errors
301
+
302
+
303
+ def display_table_summary(table: DataTable) -> None:
304
+ """Display a summary of a data table"""
305
+ name = table.name
306
+ table_id = table.id
307
+ folder_id = table.folder_id
308
+
309
+ click.echo(f" 📊 {name}")
310
+ click.echo(f" 🆔 ID: {table_id}")
311
+ click.echo(f" 📁 Folder ID: {folder_id}")
312
+
313
+ schema = table.var_schema
314
+ column_count = len(schema)
315
+
316
+ # Show column summary
317
+ if column_count <= 5:
318
+ column_names = [col.name for col in schema]
319
+ click.echo(f" 📊 Columns ({column_count}): {', '.join(column_names)}")
320
+ else:
321
+ column_names = [col.name for col in schema[:3]]
322
+ click.echo(
323
+ f" 📊 Columns ({column_count}): {', '.join(column_names)} "
324
+ f"+{column_count - 3} more"
325
+ )
326
+
327
+ # Show column types summary
328
+ type_counts: dict[str, int] = {}
329
+ for col in schema:
330
+ col_type = col.type
331
+ type_counts[col_type] = type_counts.get(col_type, 0) + 1
332
+
333
+ type_summary = ", ".join([f"{count} {type}" for type, count in type_counts.items()])
334
+ click.echo(f" 🔧 Types: {type_summary}")
335
+
336
+ # Show metadata if available
337
+ if table.created_at:
338
+ click.echo(
339
+ f" 🕐 Created: {table.created_at.strftime('%Y-%m-%d')}"
340
+ ) # Just the date part
341
+
342
+ if table.updated_at:
343
+ click.echo(
344
+ f" 🔄 Updated: {table.updated_at.strftime('%Y-%m-%d')}"
345
+ ) # Just the date part
@@ -0,0 +1,315 @@
1
+ import json
2
+ import re
3
+
4
+ from pathlib import Path
5
+ from typing import Any
6
+
7
+ import asyncclick as click
8
+
9
+
10
+ @click.group()
11
+ async def guide() -> None:
12
+ """AI agent documentation interface"""
13
+ pass
14
+
15
+
16
+ @guide.command()
17
+ async def topics() -> None:
18
+ """List all available documentation topics"""
19
+ docs_dir = Path(__file__).parent.parent / "resources" / "docs"
20
+
21
+ if not docs_dir.exists():
22
+ click.echo("ERROR: Documentation not found")
23
+ return
24
+
25
+ # Core topics
26
+ core_topics = [
27
+ "recipe-fundamentals",
28
+ "block-structure",
29
+ "triggers",
30
+ "actions",
31
+ "data-mapping",
32
+ "formulas",
33
+ "naming-conventions",
34
+ "recipe-deployment-workflow",
35
+ ]
36
+
37
+ # Formula topics
38
+ formula_topics = [
39
+ "string-formulas",
40
+ "number-formulas",
41
+ "date-formulas",
42
+ "array-list-formulas",
43
+ "conditions",
44
+ "other-formulas",
45
+ ]
46
+
47
+ # Output as structured data for AI parsing
48
+ result = {
49
+ "core_topics": core_topics,
50
+ "formula_topics": formula_topics,
51
+ "total_topics": len(core_topics) + len(formula_topics),
52
+ }
53
+
54
+ click.echo(json.dumps(result, indent=2))
55
+
56
+
57
+ @guide.command()
58
+ @click.argument("topic")
59
+ async def content(topic: str) -> None:
60
+ """Get full content of a specific topic"""
61
+ docs_dir = Path(__file__).parent.parent / "resources" / "docs"
62
+
63
+ if not docs_dir.exists():
64
+ click.echo("ERROR: Documentation not found")
65
+ return
66
+
67
+ # Try to find the topic file
68
+ topic_file = None
69
+
70
+ # Check core topics first (with and without numbers)
71
+ topic_file = None
72
+
73
+ # Try exact match first
74
+ core_file = docs_dir / f"{topic}.md"
75
+ if core_file.exists():
76
+ topic_file = core_file
77
+ else:
78
+ # Try with number prefixes
79
+ for file_path in docs_dir.glob("*.md"):
80
+ if file_path.stem.endswith(f"-{topic}"):
81
+ topic_file = file_path
82
+ break
83
+
84
+ # If still not found, check formulas
85
+ if not topic_file:
86
+ formula_file = docs_dir / "formulas" / f"{topic}.md"
87
+ if formula_file.exists():
88
+ topic_file = formula_file
89
+
90
+ if not topic_file:
91
+ click.echo(f"ERROR: Topic '{topic}' not found")
92
+ return
93
+
94
+ content = topic_file.read_text(encoding="utf-8")
95
+
96
+ # Clean up content for AI consumption
97
+ lines = content.split("\n")
98
+ cleaned_lines: list[str] = []
99
+
100
+ for line in lines:
101
+ # Skip frontmatter
102
+ if line.startswith("---"):
103
+ continue
104
+ # Skip empty lines at start
105
+ if not cleaned_lines and not line.strip():
106
+ continue
107
+ cleaned_lines.append(line)
108
+
109
+ # Output clean content
110
+ click.echo("".join(cleaned_lines))
111
+
112
+
113
+ @guide.command()
114
+ @click.argument("query")
115
+ @click.option("--topic", help="Limit to specific topic")
116
+ @click.option("--max-results", default=10, help="Maximum results to return")
117
+ async def search(query: str, topic: str | None, max_results: int) -> None:
118
+ """Search documentation content"""
119
+ docs_dir = Path(__file__).parent.parent / "resources" / "docs"
120
+
121
+ if not docs_dir.exists():
122
+ click.echo("ERROR: Documentation not found")
123
+ return
124
+
125
+ results = []
126
+
127
+ def search_file(file_path: Path, search_query: str) -> list[dict]:
128
+ """Search single file and return structured results"""
129
+ content = file_path.read_text(encoding="utf-8")
130
+ lines = content.split("\n")
131
+ matches = []
132
+
133
+ for i, line in enumerate(lines):
134
+ if search_query.lower() in line.lower():
135
+ # Get context (2 lines before, 2 lines after)
136
+ start = max(0, i - 2)
137
+ end = min(len(lines), i + 3)
138
+ context = lines[start:end]
139
+
140
+ matches.append(
141
+ {
142
+ "file": str(file_path.relative_to(docs_dir)),
143
+ "line": i + 1,
144
+ "match": line.strip(),
145
+ "context": context,
146
+ }
147
+ )
148
+
149
+ return matches
150
+
151
+ # Search core topics
152
+ if not topic or topic in ["core", "concepts"]:
153
+ for file_path in docs_dir.glob("*.md"):
154
+ matches = search_file(file_path, query)
155
+ results.extend(matches)
156
+
157
+ # Search specific topic
158
+ elif topic and topic != "formulas":
159
+ topic_file = docs_dir / f"{topic}.md"
160
+ if topic_file.exists():
161
+ matches = search_file(topic_file, query)
162
+ results.extend(matches)
163
+
164
+ # Search formulas
165
+ if not topic or topic in ["formulas", "formula"]:
166
+ formulas_dir = docs_dir / "formulas"
167
+ if formulas_dir.exists():
168
+ for file_path in formulas_dir.glob("*.md"):
169
+ matches = search_file(file_path, query)
170
+ results.extend(matches)
171
+
172
+ # Limit results
173
+ results = results[:max_results]
174
+
175
+ # Output structured results for AI parsing
176
+ output = {"query": query, "results_count": len(results), "results": results}
177
+
178
+ click.echo(json.dumps(output, indent=2))
179
+
180
+
181
+ @guide.command()
182
+ @click.argument("topic")
183
+ async def structure(topic: str) -> None:
184
+ """Show structure and relationships for a topic"""
185
+ docs_dir = Path(__file__).parent.parent / "resources" / "docs"
186
+
187
+ if not docs_dir.exists():
188
+ click.echo("ERROR: Documentation not found")
189
+ return
190
+
191
+ # Find the topic file
192
+ topic_file: Path | None = None
193
+ if (docs_dir / f"{topic}.md").exists():
194
+ topic_file = docs_dir / f"{topic}.md"
195
+ elif (docs_dir / "formulas" / f"{topic}.md").exists():
196
+ topic_file = docs_dir / "formulas" / f"{topic}.md"
197
+
198
+ if not topic_file:
199
+ click.echo(f"ERROR: Topic '{topic}' not found")
200
+ return
201
+
202
+ content = topic_file.read_text(encoding="utf-8")
203
+
204
+ # Extract structure information
205
+ structure_info: dict[str, Any] = {
206
+ "topic": topic,
207
+ "file": str(topic_file.relative_to(docs_dir)),
208
+ "sections": [],
209
+ "links": [],
210
+ "code_blocks": 0,
211
+ }
212
+
213
+ lines = content.split("\n")
214
+ current_section: str | None = None
215
+
216
+ for line in lines:
217
+ # Track sections
218
+ if line.startswith("## "):
219
+ current_section = line[3:].strip()
220
+ structure_info["sections"].append(current_section)
221
+ elif line.startswith("### "):
222
+ if current_section:
223
+ structure_info["sections"].append(f" {line[4:].strip()}")
224
+
225
+ # Track links
226
+ links = re.findall(r"\[([^\]]+)\]\(([^)]+)\)", line)
227
+ for link_text, link_path in links:
228
+ structure_info["links"].append({"text": link_text, "path": link_path})
229
+
230
+ # Track code blocks
231
+ if line.startswith("```"):
232
+ structure_info["code_blocks"] += 1
233
+
234
+ click.echo(json.dumps(structure_info, indent=2))
235
+
236
+
237
+ @guide.command()
238
+ async def index() -> None:
239
+ """Generate full documentation index for AI consumption"""
240
+ docs_dir = Path(__file__).parent.parent / "resources" / "docs"
241
+
242
+ if not docs_dir.exists():
243
+ click.echo("ERROR: Documentation not found")
244
+ return
245
+
246
+ index_data: dict[str, Any] = {
247
+ "documentation_index": {},
248
+ "formula_index": {},
249
+ "cross_references": {},
250
+ }
251
+
252
+ # Index core topics
253
+ for file_path in docs_dir.glob("*.md"):
254
+ content = file_path.read_text(encoding="utf-8")
255
+ lines = content.split("\n")
256
+
257
+ # Extract title
258
+ title = ""
259
+ for line in lines:
260
+ if line.startswith("# "):
261
+ title = line[2:].strip()
262
+ break
263
+
264
+ # Extract key sections
265
+ sections = []
266
+ for line in lines:
267
+ if line.startswith("## "):
268
+ sections.append(line[3:].strip())
269
+
270
+ # Extract links
271
+ links = re.findall(r"\[([^\]]+)\]\(([^)]+)\)", content)
272
+
273
+ index_data["documentation_index"][file_path.stem] = {
274
+ "title": title,
275
+ "sections": sections,
276
+ "links": links,
277
+ "file": str(file_path.relative_to(docs_dir)),
278
+ }
279
+
280
+ # Index formulas
281
+ formulas_dir = docs_dir / "formulas"
282
+ if formulas_dir.exists():
283
+ for file_path in formulas_dir.glob("*.md"):
284
+ content = file_path.read_text(encoding="utf-8")
285
+ lines = content.split("\n")
286
+
287
+ # Extract title
288
+ title = ""
289
+ for line in lines:
290
+ if line.startswith("# "):
291
+ title = line[2:].strip()
292
+ break
293
+
294
+ # Extract formula examples
295
+ examples = []
296
+ in_code_block = False
297
+ current_example: list[str] = []
298
+
299
+ for line in lines:
300
+ if line.startswith("```"):
301
+ in_code_block = not in_code_block
302
+ if not in_code_block and current_example:
303
+ examples.append("\n".join(current_example))
304
+ current_example = []
305
+ elif in_code_block:
306
+ current_example.append(line)
307
+
308
+ index_data["formula_index"][file_path.stem] = {
309
+ "title": title,
310
+ "examples": examples,
311
+ "file": str(file_path.relative_to(docs_dir)),
312
+ }
313
+
314
+ # Output complete index
315
+ click.echo(json.dumps(index_data, indent=2))