uipath 2.0.71__py3-none-any.whl → 2.0.73__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.

@@ -0,0 +1,147 @@
1
+ from typing import Optional
2
+ from urllib.parse import urlparse
3
+
4
+ import httpx
5
+
6
+ from .._utils._console import ConsoleLogger
7
+ from ._models import TokenData
8
+ from ._utils import parse_access_token, update_env_file
9
+
10
+ console = ConsoleLogger()
11
+
12
+
13
+ class ClientCredentialsService:
14
+ """Service for client credentials authentication flow."""
15
+
16
+ def __init__(self, domain: str):
17
+ self.domain = domain
18
+
19
+ def get_token_url(self) -> str:
20
+ """Get the token URL for the specified domain."""
21
+ match self.domain:
22
+ case "alpha":
23
+ return "https://alpha.uipath.com/identity_/connect/token"
24
+ case "staging":
25
+ return "https://staging.uipath.com/identity_/connect/token"
26
+ case _: # cloud (default)
27
+ return "https://cloud.uipath.com/identity_/connect/token"
28
+
29
+ def _is_valid_domain_or_subdomain(self, hostname: str, domain: str) -> bool:
30
+ """Check if hostname is either an exact match or a valid subdomain of the domain.
31
+
32
+ Args:
33
+ hostname: The hostname to check
34
+ domain: The domain to validate against
35
+
36
+ Returns:
37
+ True if hostname is valid domain or subdomain, False otherwise
38
+ """
39
+ return hostname == domain or hostname.endswith(f".{domain}")
40
+
41
+ def extract_domain_from_base_url(self, base_url: str) -> str:
42
+ """Extract domain from base URL.
43
+
44
+ Args:
45
+ base_url: The base URL to extract domain from
46
+
47
+ Returns:
48
+ The domain (alpha, staging, or cloud)
49
+ """
50
+ try:
51
+ parsed = urlparse(base_url)
52
+ hostname = parsed.hostname
53
+
54
+ if hostname:
55
+ match hostname:
56
+ case h if self._is_valid_domain_or_subdomain(h, "alpha.uipath.com"):
57
+ return "alpha"
58
+ case h if self._is_valid_domain_or_subdomain(
59
+ h, "staging.uipath.com"
60
+ ):
61
+ return "staging"
62
+ case h if self._is_valid_domain_or_subdomain(h, "cloud.uipath.com"):
63
+ return "cloud"
64
+
65
+ # Default to cloud if we can't determine
66
+ return "cloud"
67
+ except Exception:
68
+ # Default to cloud if parsing fails
69
+ return "cloud"
70
+
71
+ def authenticate(
72
+ self, client_id: str, client_secret: str, scope: str = "OR.Execution"
73
+ ) -> Optional[TokenData]:
74
+ """Authenticate using client credentials flow.
75
+
76
+ Args:
77
+ client_id: The client ID for authentication
78
+ client_secret: The client secret for authentication
79
+ scope: The scope for the token (default: OR.Execution)
80
+
81
+ Returns:
82
+ Token data if successful, None otherwise
83
+ """
84
+ token_url = self.get_token_url()
85
+
86
+ data = {
87
+ "grant_type": "client_credentials",
88
+ "client_id": client_id,
89
+ "client_secret": client_secret,
90
+ "scope": scope,
91
+ }
92
+
93
+ try:
94
+ with httpx.Client(timeout=30.0) as client:
95
+ response = client.post(token_url, data=data)
96
+
97
+ match response.status_code:
98
+ case 200:
99
+ token_data = response.json()
100
+ # Convert to our TokenData format
101
+ return {
102
+ "access_token": token_data["access_token"],
103
+ "token_type": token_data.get("token_type", "Bearer"),
104
+ "expires_in": token_data.get("expires_in", 3600),
105
+ "scope": token_data.get("scope", scope),
106
+ # Client credentials flow doesn't provide these, but we need them for compatibility
107
+ "refresh_token": "",
108
+ "id_token": "",
109
+ }
110
+ case 400:
111
+ console.error(
112
+ "Invalid client credentials or request parameters."
113
+ )
114
+ return None
115
+ case 401:
116
+ console.error("Unauthorized: Invalid client credentials.")
117
+ return None
118
+ case _:
119
+ console.error(
120
+ f"Authentication failed: {response.status_code} - {response.text}"
121
+ )
122
+ return None
123
+
124
+ except httpx.RequestError as e:
125
+ console.error(f"Network error during authentication: {e}")
126
+ return None
127
+ except Exception as e:
128
+ console.error(f"Unexpected error during authentication: {e}")
129
+ return None
130
+
131
+ def setup_environment(self, token_data: TokenData, base_url: str):
132
+ """Setup environment variables for client credentials authentication.
133
+
134
+ Args:
135
+ token_data: The token data from authentication
136
+ base_url: The base URL for the UiPath instance
137
+ """
138
+ parsed_access_token = parse_access_token(token_data["access_token"])
139
+
140
+ env_vars = {
141
+ "UIPATH_ACCESS_TOKEN": token_data["access_token"],
142
+ "UIPATH_URL": base_url,
143
+ "UIPATH_ORGANIZATION_ID": parsed_access_token.get("prt_id", ""),
144
+ "UIPATH_TENANT_ID": "",
145
+ }
146
+
147
+ update_env_file(env_vars)
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "client_id": "36dea5b8-e8bb-423d-8e7b-c808df8f1c00",
3
3
  "redirect_uri": "http://localhost:__PY_REPLACE_PORT__/oidc/login",
4
- "scope": "offline_access OrchestratorApiUserAccess ConnectionService DataService DocumentUnderstanding EnterpriseContextService Directory JamJamApi LLMGateway LLMOps OMS RCS.FolderAuthorization",
4
+ "scope": "offline_access OrchestratorApiUserAccess IdentityServerApi ConnectionService DataService DocumentUnderstanding EnterpriseContextService Directory JamJamApi LLMGateway LLMOps OMS RCS.FolderAuthorization",
5
5
  "port": 8104
6
- }
6
+ }
uipath/_cli/cli_auth.py CHANGED
@@ -9,6 +9,7 @@ from dotenv import load_dotenv
9
9
 
10
10
  from ..telemetry import track
11
11
  from ._auth._auth_server import HTTPServer
12
+ from ._auth._client_credentials import ClientCredentialsService
12
13
  from ._auth._oidc_utils import get_auth_config, get_auth_url
13
14
  from ._auth._portal_service import PortalService, select_tenant
14
15
  from ._auth._utils import update_auth_file, update_env_file
@@ -64,9 +65,67 @@ def set_port():
64
65
  required=False,
65
66
  help="Force new token",
66
67
  )
68
+ @click.option(
69
+ "--client-id",
70
+ required=False,
71
+ help="Client ID for client credentials authentication (unattended mode)",
72
+ )
73
+ @click.option(
74
+ "--client-secret",
75
+ required=False,
76
+ help="Client secret for client credentials authentication (unattended mode)",
77
+ )
78
+ @click.option(
79
+ "--base-url",
80
+ required=False,
81
+ help="Base URL for the UiPath tenant instance (required for client credentials)",
82
+ )
67
83
  @track
68
- def auth(domain, force: None | bool = False):
69
- """Authenticate with UiPath Cloud Platform."""
84
+ def auth(
85
+ domain,
86
+ force: None | bool = False,
87
+ client_id: str = None,
88
+ client_secret: str = None,
89
+ base_url: str = None,
90
+ ):
91
+ """Authenticate with UiPath Cloud Platform.
92
+
93
+ Interactive mode (default): Opens browser for OAuth authentication.
94
+ Unattended mode: Use --client-id, --client-secret and --base-url for client credentials flow.
95
+ """
96
+ # Check if client credentials are provided for unattended authentication
97
+ if client_id and client_secret:
98
+ if not base_url:
99
+ console.error(
100
+ "--base-url is required when using client credentials authentication."
101
+ )
102
+ return
103
+
104
+ with console.spinner("Authenticating with client credentials ..."):
105
+ # Create service instance
106
+ credentials_service = ClientCredentialsService(domain)
107
+
108
+ # If base_url is provided, extract domain from it to override the CLI domain parameter
109
+ if base_url:
110
+ extracted_domain = credentials_service.extract_domain_from_base_url(
111
+ base_url
112
+ )
113
+ credentials_service.domain = extracted_domain
114
+
115
+ token_data = credentials_service.authenticate(client_id, client_secret)
116
+
117
+ if token_data:
118
+ credentials_service.setup_environment(token_data, base_url)
119
+ console.success(
120
+ "Client credentials authentication successful.",
121
+ )
122
+ else:
123
+ console.error(
124
+ "Client credentials authentication failed. Please check your credentials.",
125
+ )
126
+ return
127
+
128
+ # Interactive authentication flow (existing logic)
70
129
  with console.spinner("Authenticating with UiPath ..."):
71
130
  portal_service = PortalService(domain)
72
131
 
uipath/_cli/cli_pack.py CHANGED
@@ -1,6 +1,7 @@
1
1
  # type: ignore
2
2
  import json
3
3
  import os
4
+ import subprocess
4
5
  import uuid
5
6
  import zipfile
6
7
  from string import Template
@@ -52,6 +53,66 @@ def check_config(directory):
52
53
  }
53
54
 
54
55
 
56
+ def is_uv_available():
57
+ """Check if uv command is available in the system."""
58
+ try:
59
+ subprocess.run(["uv", "--version"], capture_output=True, check=True, timeout=20)
60
+ return True
61
+ except (subprocess.CalledProcessError, FileNotFoundError):
62
+ return False
63
+ except Exception as e:
64
+ console.warning(
65
+ f"An unexpected error occurred while checking uv availability: {str(e)}"
66
+ )
67
+ return False
68
+
69
+
70
+ def is_uv_project(directory):
71
+ """Check if this is a uv project by looking for the uv.lock file."""
72
+ uv_lock_path = os.path.join(directory, "uv.lock")
73
+
74
+ # If uv.lock exists, it's definitely a uv project
75
+ if os.path.exists(uv_lock_path):
76
+ return True
77
+
78
+ return False
79
+
80
+
81
+ def run_uv_lock(directory):
82
+ """Run uv lock to update the lock file."""
83
+ try:
84
+ subprocess.run(
85
+ ["uv", "lock"],
86
+ cwd=directory,
87
+ capture_output=True,
88
+ text=True,
89
+ check=True,
90
+ timeout=60,
91
+ )
92
+ return True
93
+ except subprocess.CalledProcessError as e:
94
+ console.warning(f"uv lock failed: {e.stderr}")
95
+ return False
96
+ except FileNotFoundError:
97
+ console.warning("uv command not found. Skipping lock file update.")
98
+ return False
99
+ except Exception as e:
100
+ console.warning(f"An unexpected error occurred while running uv lock: {str(e)}")
101
+ return False
102
+
103
+
104
+ def handle_uv_operations(directory):
105
+ """Handle uv operations if uv is detected and available."""
106
+ if not is_uv_available():
107
+ return
108
+
109
+ if not is_uv_project(directory):
110
+ return
111
+
112
+ # Always run uv lock to ensure lock file is up to date
113
+ run_uv_lock(directory)
114
+
115
+
55
116
  def generate_operate_file(entryPoints):
56
117
  project_id = str(uuid.uuid4())
57
118
 
@@ -210,7 +271,15 @@ def is_venv_dir(d):
210
271
  )
211
272
 
212
273
 
213
- def pack_fn(projectName, description, entryPoints, version, authors, directory):
274
+ def pack_fn(
275
+ projectName,
276
+ description,
277
+ entryPoints,
278
+ version,
279
+ authors,
280
+ directory,
281
+ include_uv_lock=True,
282
+ ):
214
283
  operate_file = generate_operate_file(entryPoints)
215
284
  entrypoints_file = generate_entrypoints_file(entryPoints)
216
285
 
@@ -304,7 +373,11 @@ def pack_fn(projectName, description, entryPoints, version, authors, directory):
304
373
  with open(file_path, "r", encoding="latin-1") as f:
305
374
  z.writestr(f"content/{rel_path}", f.read())
306
375
 
376
+ # Handle optional files, conditionally including uv.lock
307
377
  optional_files = ["pyproject.toml", "README.md"]
378
+ if include_uv_lock:
379
+ optional_files.append("uv.lock")
380
+
308
381
  for file in optional_files:
309
382
  file_path = os.path.join(directory, file)
310
383
  if os.path.exists(file_path):
@@ -367,8 +440,13 @@ def display_project_info(config):
367
440
 
368
441
  @click.command()
369
442
  @click.argument("root", type=str, default="./")
443
+ @click.option(
444
+ "--nolock",
445
+ is_flag=True,
446
+ help="Skip running uv lock and exclude uv.lock from the package",
447
+ )
370
448
  @track
371
- def pack(root):
449
+ def pack(root, nolock):
372
450
  """Pack the project."""
373
451
  version = get_project_version(root)
374
452
 
@@ -403,6 +481,10 @@ def pack(root):
403
481
 
404
482
  with console.spinner("Packaging project ..."):
405
483
  try:
484
+ # Handle uv operations before packaging, unless nolock is specified
485
+ if not nolock:
486
+ handle_uv_operations(root)
487
+
406
488
  pack_fn(
407
489
  config["project_name"],
408
490
  config["description"],
@@ -410,6 +492,7 @@ def pack(root):
410
492
  version or config["version"],
411
493
  config["authors"],
412
494
  root,
495
+ include_uv_lock=not nolock,
413
496
  )
414
497
  display_project_info(config)
415
498
  console.success("Project successfully packaged.")
@@ -1,4 +1,4 @@
1
- _CONNECTION_STRING = "InstrumentationKey=0d8dca8b-9a76-4f2e-adeb-09d9e2c210a0;IngestionEndpoint=https://northeurope-2.in.applicationinsights.azure.com/;LiveEndpoint=https://northeurope.livediagnostics.monitor.azure.com/;ApplicationId=ff68f440-0d82-4bab-9192-ad91f67e0835"
1
+ _CONNECTION_STRING = "InstrumentationKey=4128b5ed-f5ec-4612-ac32-b8cff0f2de93;IngestionEndpoint=https://northeurope-2.in.applicationinsights.azure.com/;LiveEndpoint=https://northeurope.livediagnostics.monitor.azure.com/;ApplicationId=f448014b-2abf-4681-8e48-583e33f7d173"
2
2
 
3
3
  _APP_INSIGHTS_EVENT_MARKER_ATTRIBUTE = "APPLICATION_INSIGHTS_EVENT_MARKER_ATTRIBUTE"
4
4
  _OTEL_RESOURCE_ATTRIBUTES = "OTEL_RESOURCE_ATTRIBUTES"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: uipath
3
- Version: 2.0.71
3
+ Version: 2.0.73
4
4
  Summary: Python SDK and CLI for UiPath Platform, enabling programmatic interaction with automation services, process management, and deployment tools.
5
5
  Project-URL: Homepage, https://uipath.com
6
6
  Project-URL: Repository, https://github.com/UiPath/uipath-python
@@ -38,6 +38,8 @@ A Python SDK that enables programmatic interaction with UiPath Cloud Platform se
38
38
 
39
39
  Use the [UiPath LangChain SDK](https://github.com/UiPath/uipath-langchain-python) to pack and publish LangGraph Agents.
40
40
 
41
+ Use the [UiPath LlamaIndex SDK](https://github.com/UiPath/uipath-llamaindex-python) to pack and publish LlamaIndex Agents.
42
+
41
43
  This [quickstart guide](https://uipath.github.io/uipath-python/) walks you through deploying your first agent to UiPath Cloud Platform.
42
44
 
43
45
  ## Table of Contents
@@ -6,22 +6,23 @@ uipath/_uipath.py,sha256=54u-aPF29DE3fOn8yM1pjVTqSZxSSaIsifiZG9Mt_YM,3824
6
6
  uipath/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
7
7
  uipath/_cli/README.md,sha256=GLtCfbeIKZKNnGTCsfSVqRQ27V1btT1i2bSAyW_xZl4,474
8
8
  uipath/_cli/__init__.py,sha256=vGz3vJHkUvgK9_lKdzqiwwHkge1TCALRiOzGGwyr-8E,1885
9
- uipath/_cli/cli_auth.py,sha256=aIecyySuGXJEQHnS6b-M6sxM7ki5trjqq_J7s-sCdQE,3966
9
+ uipath/_cli/cli_auth.py,sha256=J6r-R87QdnKBRpASGgyxsOPpbBv-M4meTDoi6Wa-cZ8,6047
10
10
  uipath/_cli/cli_deploy.py,sha256=KPCmQ0c_NYD5JofSDao5r6QYxHshVCRxlWDVnQvlp5w,645
11
11
  uipath/_cli/cli_init.py,sha256=SmB7VplpXRSa5sgqgzojNsZDw0zfsEi2TfkMx3eQpTo,5132
12
12
  uipath/_cli/cli_invoke.py,sha256=IjndcDWBpvAqGCRanQU1vfmxaBF8FhyZ7gWuZqwjHrU,3812
13
13
  uipath/_cli/cli_new.py,sha256=9378NYUBc9j-qKVXV7oja-jahfJhXBg8zKVyaon7ctY,2102
14
- uipath/_cli/cli_pack.py,sha256=-Otnb-oI--D7kkRir9P_-PygmHGdblO8JOPrZLm7DIk,15035
14
+ uipath/_cli/cli_pack.py,sha256=qqmh7v0j4_vA4Xko5PgKFEbJIOXlmJBGd9IRnDi-wtA,17285
15
15
  uipath/_cli/cli_publish.py,sha256=Ba0TJ1TSfuQbLU2AIgtM8QWkLHgr4tsAP1CaX12113U,6010
16
16
  uipath/_cli/cli_run.py,sha256=zYg-9U6mkofdGsE0IGjYi1dOMlG8CdBxiVGxfFiLq5Y,5882
17
17
  uipath/_cli/middlewares.py,sha256=f7bVODO9tgdtWNepG5L58-B-VgBSU6Ek2tIU6wLz0xA,4905
18
18
  uipath/_cli/spinner.py,sha256=bS-U_HA5yne11ejUERu7CQoXmWdabUD2bm62EfEdV8M,1107
19
19
  uipath/_cli/_auth/_auth_server.py,sha256=p93_EvJpdoLLkiVmLygHRKo9ru1-PZOEAaEhNFN3j6c,6424
20
+ uipath/_cli/_auth/_client_credentials.py,sha256=C2j3VBIwOGV2vB_p3WvCsJtMciTiLbaV28rkG50tvKY,5397
20
21
  uipath/_cli/_auth/_models.py,sha256=sYMCfvmprIqnZxStlD_Dxx2bcxgn0Ri4D7uwemwkcNg,948
21
22
  uipath/_cli/_auth/_oidc_utils.py,sha256=WaX9jDlXrlX6yD8i8gsocV8ngjaT72Xd1tvsZMmSbco,2127
22
23
  uipath/_cli/_auth/_portal_service.py,sha256=80W0cn3rx6NEi_b15aSQ0ZQWFv7Om7SaOlkUUk2k7pA,7240
23
24
  uipath/_cli/_auth/_utils.py,sha256=9nb76xe5XmDZ0TAncp-_1SKqL6FdwRi9eS3C2noN1lY,1591
24
- uipath/_cli/_auth/auth_config.json,sha256=OCNp3tTF2WL83pyJlZw-Wt8Slao9IpmmZJonl2OvaRw,340
25
+ uipath/_cli/_auth/auth_config.json,sha256=ib1qYxU6Totvl2pxFkqqmjVe3tOYR98mFFsUska9lOA,359
25
26
  uipath/_cli/_auth/index.html,sha256=ML_xDOcKs0ETYucufJskiYfWSvdrD_E26C0Qd3qpGj8,6280
26
27
  uipath/_cli/_auth/localhost.crt,sha256=oGl9oLLOiouHubAt39B4zEfylFvKEtbtr_43SIliXJc,1226
27
28
  uipath/_cli/_auth/localhost.key,sha256=X31VYXD8scZtmGA837dGX5l6G-LXHLo5ItWJhZXaz3c,1679
@@ -85,14 +86,14 @@ uipath/models/llm_gateway.py,sha256=0sl5Wtve94V14H3AHwmJSoXAhoc-Fai3wJxP8HrnBPg,
85
86
  uipath/models/processes.py,sha256=Atvfrt6X4TYST3iA62jpS_Uxc3hg6uah11p-RaKZ6dk,2029
86
87
  uipath/models/queues.py,sha256=N_s0GKucbyjh0RnO8SxPk6wlRgvq8KIIYsfaoIY46tM,6446
87
88
  uipath/telemetry/__init__.py,sha256=Wna32UFzZR66D-RzTKlPWlvji9i2HJb82NhHjCCXRjY,61
88
- uipath/telemetry/_constants.py,sha256=8HZvzef7DSJjntOLYMP53U2jvXgdFcsilGANdE5asOQ,680
89
+ uipath/telemetry/_constants.py,sha256=z7taKsKM3CrMEa6gXBgK8otumT2dIXrw7WXc0XE9zYA,680
89
90
  uipath/telemetry/_track.py,sha256=v0e3hgwtetMsUco4yosBzNU00Ek5SI9RxUTumrTTNyo,3872
90
91
  uipath/tracing/__init__.py,sha256=GKRINyWdHVrDsI-8mrZDLdf0oey6GHGlNZTOADK-kgc,224
91
92
  uipath/tracing/_otel_exporters.py,sha256=x0PDPmDKJcxashsuehVsSsqBCzRr6WsNFaq_3_HS5F0,3014
92
93
  uipath/tracing/_traced.py,sha256=qeVDrds2OUnpdUIA0RhtF0kg2dlAZhyC1RRkI-qivTM,18528
93
94
  uipath/tracing/_utils.py,sha256=ZeensQexnw69jVcsVrGyED7mPlAU-L1agDGm6_1A3oc,10388
94
- uipath-2.0.71.dist-info/METADATA,sha256=_bR9eWn4qxgIu4nIFPRtRJQZVWmaxFfCv19I-F4Q5Rw,6304
95
- uipath-2.0.71.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
96
- uipath-2.0.71.dist-info/entry_points.txt,sha256=9C2_29U6Oq1ExFu7usihR-dnfIVNSKc-0EFbh0rskB4,43
97
- uipath-2.0.71.dist-info/licenses/LICENSE,sha256=-KBavWXepyDjimmzH5fVAsi-6jNVpIKFc2kZs0Ri4ng,1058
98
- uipath-2.0.71.dist-info/RECORD,,
95
+ uipath-2.0.73.dist-info/METADATA,sha256=WuV2BhLmHwzOPtYx_Hc57dbZYpnU_-HAQraU0vnj4_o,6428
96
+ uipath-2.0.73.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
97
+ uipath-2.0.73.dist-info/entry_points.txt,sha256=9C2_29U6Oq1ExFu7usihR-dnfIVNSKc-0EFbh0rskB4,43
98
+ uipath-2.0.73.dist-info/licenses/LICENSE,sha256=-KBavWXepyDjimmzH5fVAsi-6jNVpIKFc2kZs0Ri4ng,1058
99
+ uipath-2.0.73.dist-info/RECORD,,