uipath 2.1.21__py3-none-any.whl → 2.1.23__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.
- uipath/_cli/_push/sw_file_handler.py +97 -56
- uipath/_cli/_utils/_studio_project.py +79 -32
- uipath/tracing/_utils.py +1 -1
- {uipath-2.1.21.dist-info → uipath-2.1.23.dist-info}/METADATA +1 -1
- {uipath-2.1.21.dist-info → uipath-2.1.23.dist-info}/RECORD +8 -8
- {uipath-2.1.21.dist-info → uipath-2.1.23.dist-info}/WHEEL +0 -0
- {uipath-2.1.21.dist-info → uipath-2.1.23.dist-info}/entry_points.txt +0 -0
- {uipath-2.1.21.dist-info → uipath-2.1.23.dist-info}/licenses/LICENSE +0 -0
@@ -133,12 +133,14 @@ class SwFileHandler:
|
|
133
133
|
self,
|
134
134
|
local_files: list[FileInfo],
|
135
135
|
source_code_files: Dict[str, ProjectFile],
|
136
|
+
root_files: Dict[str, ProjectFile],
|
136
137
|
) -> None:
|
137
138
|
"""Process all file uploads to the source_code folder.
|
138
139
|
|
139
140
|
Args:
|
140
141
|
local_files: List of files to upload
|
141
142
|
source_code_files: Dictionary of existing remote files
|
143
|
+
root_files: Dictionary of existing root-level files
|
142
144
|
|
143
145
|
Returns:
|
144
146
|
Set of processed file names
|
@@ -186,13 +188,25 @@ class SwFileHandler:
|
|
186
188
|
)
|
187
189
|
)
|
188
190
|
self.console.info(
|
189
|
-
f"Uploading {click.style(local_file.
|
191
|
+
f"Uploading {click.style(local_file.relative_path, fg='cyan')}"
|
190
192
|
)
|
191
193
|
|
192
194
|
# identify and add deleted files
|
193
195
|
structural_migration.deleted_resources.extend(
|
194
196
|
self._collect_deleted_files(source_code_files, processed_source_files)
|
195
197
|
)
|
198
|
+
|
199
|
+
with open(os.path.join(self.directory, "uipath.json"), "r") as f:
|
200
|
+
uipath_config = json.load(f)
|
201
|
+
|
202
|
+
await self._prepare_agent_json_migration(
|
203
|
+
structural_migration, root_files, uipath_config
|
204
|
+
)
|
205
|
+
|
206
|
+
await self._prepare_entrypoints_json_migration(
|
207
|
+
structural_migration, root_files, uipath_config
|
208
|
+
)
|
209
|
+
|
196
210
|
await self._studio_client.perform_structural_migration_async(
|
197
211
|
structural_migration
|
198
212
|
)
|
@@ -303,40 +317,65 @@ class SwFileHandler:
|
|
303
317
|
|
304
318
|
return True
|
305
319
|
|
306
|
-
async def
|
320
|
+
async def _prepare_entrypoints_json_migration(
|
307
321
|
self,
|
308
|
-
|
322
|
+
structural_migration: StructuralMigration,
|
323
|
+
root_files: Dict[str, ProjectFile],
|
324
|
+
uipath_config: Dict[str, Any],
|
309
325
|
) -> None:
|
310
|
-
"""
|
326
|
+
"""Prepare entry-points.json to be included in the same structural migration."""
|
327
|
+
existing = root_files.get("entry-points.json")
|
328
|
+
if existing:
|
329
|
+
try:
|
330
|
+
entry_points_json = (
|
331
|
+
await self._studio_client.download_file_async(existing.id)
|
332
|
+
).json()
|
333
|
+
entry_points_json["entryPoints"] = uipath_config["entryPoints"]
|
311
334
|
|
312
|
-
|
313
|
-
|
314
|
-
|
315
|
-
|
316
|
-
|
317
|
-
|
335
|
+
except Exception:
|
336
|
+
self.console.warning(
|
337
|
+
"Could not parse existing entry-points.json file, using default version"
|
338
|
+
)
|
339
|
+
structural_migration.modified_resources.append(
|
340
|
+
ModifiedResource(
|
341
|
+
id=existing.id,
|
342
|
+
content_string=json.dumps(entry_points_json),
|
343
|
+
)
|
344
|
+
)
|
345
|
+
self.console.info(
|
346
|
+
f"Updating {click.style('entry-points.json', fg='yellow')}"
|
347
|
+
)
|
318
348
|
|
319
|
-
|
320
|
-
|
349
|
+
else:
|
350
|
+
self.console.warning(
|
351
|
+
"'entry-points.json' file does not exist in Studio Web project, initializing using default version"
|
352
|
+
)
|
353
|
+
entry_points_json = {
|
354
|
+
"$schema": "https://cloud.uipath.com/draft/2024-12/entry-point",
|
355
|
+
"$id": "entry-points.json",
|
356
|
+
"entryPoints": uipath_config["entryPoints"],
|
357
|
+
}
|
358
|
+
structural_migration.added_resources.append(
|
359
|
+
AddedResource(
|
360
|
+
file_name="entry-points.json",
|
361
|
+
content_string=json.dumps(entry_points_json),
|
362
|
+
)
|
363
|
+
)
|
364
|
+
self.console.info(
|
365
|
+
f"Uploading {click.style('entry-points.json', fg='cyan')}"
|
366
|
+
)
|
321
367
|
|
322
|
-
|
323
|
-
|
324
|
-
|
325
|
-
|
326
|
-
|
368
|
+
async def _prepare_agent_json_migration(
|
369
|
+
self,
|
370
|
+
structural_migration: StructuralMigration,
|
371
|
+
root_files: Dict[str, ProjectFile],
|
372
|
+
uipath_config: Dict[str, Any],
|
373
|
+
) -> None:
|
374
|
+
"""Prepare agent.json to be included in the same structural migration."""
|
327
375
|
|
328
376
|
def get_author_from_token_or_toml() -> str:
|
329
377
|
import jwt
|
330
378
|
|
331
|
-
"""Extract preferred_username from JWT token or fall back to pyproject.toml author.
|
332
|
-
|
333
|
-
Args:
|
334
|
-
directory: Project directory containing pyproject.toml
|
335
|
-
|
336
|
-
Returns:
|
337
|
-
str: Author name from JWT preferred_username or pyproject.toml authors field
|
338
|
-
"""
|
339
|
-
# Try to get author from JWT token first
|
340
379
|
token = os.getenv("UIPATH_ACCESS_TOKEN")
|
341
380
|
if token:
|
342
381
|
try:
|
@@ -350,19 +389,15 @@ class SwFileHandler:
|
|
350
389
|
# If JWT decoding fails, fall back to toml
|
351
390
|
pass
|
352
391
|
|
353
|
-
toml_data = read_toml_project(
|
354
|
-
|
392
|
+
toml_data = read_toml_project(
|
393
|
+
os.path.join(self.directory, "pyproject.toml")
|
394
|
+
)
|
355
395
|
return toml_data.get("authors", "").strip()
|
356
396
|
|
357
|
-
# Read uipath.json
|
358
|
-
directory = os.getcwd()
|
359
|
-
with open(os.path.join(directory, "uipath.json"), "r") as f:
|
360
|
-
uipath_config = json.load(f)
|
361
|
-
|
362
397
|
try:
|
363
398
|
entrypoints = [
|
364
|
-
{"input":
|
365
|
-
for
|
399
|
+
{"input": entrypoint["input"], "output": entrypoint["output"]}
|
400
|
+
for entrypoint in uipath_config["entryPoints"]
|
366
401
|
]
|
367
402
|
except (FileNotFoundError, KeyError) as e:
|
368
403
|
self.console.error(
|
@@ -388,14 +423,12 @@ class SwFileHandler:
|
|
388
423
|
),
|
389
424
|
}
|
390
425
|
|
391
|
-
|
392
|
-
|
393
|
-
existing_agent_json = (
|
394
|
-
await self._studio_client.download_file_async(agent_json_file.id)
|
395
|
-
).json()
|
396
|
-
|
426
|
+
existing = root_files.get("agent.json")
|
427
|
+
if existing:
|
397
428
|
try:
|
398
|
-
|
429
|
+
existing_agent_json = (
|
430
|
+
await self._studio_client.download_file_async(existing.id)
|
431
|
+
).json()
|
399
432
|
version_parts = existing_agent_json["metadata"]["codeVersion"].split(
|
400
433
|
"."
|
401
434
|
)
|
@@ -403,20 +436,32 @@ class SwFileHandler:
|
|
403
436
|
version_parts[-1] = str(int(version_parts[-1]) + 1)
|
404
437
|
agent_json["metadata"]["codeVersion"] = ".".join(version_parts)
|
405
438
|
else:
|
406
|
-
# If version format is invalid, start from initial version + 1
|
407
439
|
agent_json["metadata"]["codeVersion"] = (
|
408
440
|
AGENT_INITIAL_CODE_VERSION[:-1] + "1"
|
409
441
|
)
|
410
|
-
except
|
442
|
+
except Exception:
|
411
443
|
self.console.warning(
|
412
|
-
"Could not parse existing agent.json, using default version"
|
444
|
+
"Could not parse existing agent.json file, using default version"
|
413
445
|
)
|
414
|
-
|
415
|
-
|
416
|
-
|
417
|
-
|
418
|
-
|
419
|
-
|
446
|
+
|
447
|
+
structural_migration.modified_resources.append(
|
448
|
+
ModifiedResource(
|
449
|
+
id=existing.id,
|
450
|
+
content_string=json.dumps(agent_json),
|
451
|
+
)
|
452
|
+
)
|
453
|
+
self.console.info(f"Updating {click.style('agent.json', fg='yellow')}")
|
454
|
+
else:
|
455
|
+
self.console.warning(
|
456
|
+
"'agent.json' file does not exist in Studio Web project, initializing using default version"
|
457
|
+
)
|
458
|
+
structural_migration.added_resources.append(
|
459
|
+
AddedResource(
|
460
|
+
file_name="agent.json",
|
461
|
+
content_string=json.dumps(agent_json),
|
462
|
+
)
|
463
|
+
)
|
464
|
+
self.console.info(f"Uploading {click.style('agent.json', fg='cyan')}")
|
420
465
|
|
421
466
|
async def upload_source_files(self, config_data: dict[str, Any]) -> None:
|
422
467
|
"""Main method to upload source files to the UiPath project.
|
@@ -457,8 +502,4 @@ class SwFileHandler:
|
|
457
502
|
self.include_uv_lock,
|
458
503
|
directories_to_ignore=["evals"],
|
459
504
|
)
|
460
|
-
await self._process_file_uploads(files, source_code_files)
|
461
|
-
|
462
|
-
await self._update_agent_json(
|
463
|
-
root_files.get("agent.json", None),
|
464
|
-
)
|
505
|
+
await self._process_file_uploads(files, source_code_files, root_files)
|
@@ -175,13 +175,20 @@ def get_folder_by_name(
|
|
175
175
|
|
176
176
|
|
177
177
|
class AddedResource(BaseModel):
|
178
|
-
|
178
|
+
"""Represents a new file to be added during a structural migration."""
|
179
|
+
|
180
|
+
content_file_path: Optional[str] = None
|
179
181
|
parent_path: Optional[str] = None
|
182
|
+
file_name: Optional[str] = None
|
183
|
+
content_string: Optional[str] = None
|
180
184
|
|
181
185
|
|
182
186
|
class ModifiedResource(BaseModel):
|
187
|
+
"""Represents a file update during a structural migration."""
|
188
|
+
|
183
189
|
id: str
|
184
|
-
content_file_path: str
|
190
|
+
content_file_path: Optional[str] = None
|
191
|
+
content_string: Optional[str] = None
|
185
192
|
|
186
193
|
|
187
194
|
class StructuralMigration(BaseModel):
|
@@ -336,6 +343,53 @@ class StudioClient:
|
|
336
343
|
headers=headers or {},
|
337
344
|
)
|
338
345
|
|
346
|
+
def _resolve_content_and_filename(
|
347
|
+
self,
|
348
|
+
*,
|
349
|
+
content_string: Optional[str],
|
350
|
+
content_file_path: Optional[str],
|
351
|
+
file_name: Optional[str] = None,
|
352
|
+
modified: bool = False,
|
353
|
+
) -> tuple[bytes, Optional[str]]:
|
354
|
+
"""Resolve multipart content bytes and filename for a resource.
|
355
|
+
|
356
|
+
Args:
|
357
|
+
content_string: Inline content as a string.
|
358
|
+
content_file_path: Path to a local file to read if inline content is not provided.
|
359
|
+
file_name: Explicit filename to use when adding a new resource.
|
360
|
+
|
361
|
+
Returns:
|
362
|
+
A tuple of (content_bytes, filename).
|
363
|
+
|
364
|
+
Raises:
|
365
|
+
FileNotFoundError: If a provided file path does not exist.
|
366
|
+
ValueError: If a filename cannot be determined.
|
367
|
+
"""
|
368
|
+
content_bytes: bytes = b""
|
369
|
+
resolved_name: Optional[str] = None
|
370
|
+
if content_string is not None:
|
371
|
+
content_bytes = content_string.encode("utf-8")
|
372
|
+
elif content_file_path:
|
373
|
+
if os.path.exists(content_file_path):
|
374
|
+
with open(content_file_path, "rb") as f:
|
375
|
+
content_bytes = f.read()
|
376
|
+
else:
|
377
|
+
raise FileNotFoundError(f"File not found: {content_file_path}")
|
378
|
+
|
379
|
+
if file_name:
|
380
|
+
resolved_name = file_name
|
381
|
+
elif content_file_path:
|
382
|
+
resolved_name = os.path.basename(content_file_path)
|
383
|
+
elif not modified:
|
384
|
+
raise ValueError(
|
385
|
+
"Unable to determine filename for multipart upload. "
|
386
|
+
"When providing inline content (content_string), you must also provide file_name. "
|
387
|
+
"Alternatively, set content_file_path so the filename can be inferred. "
|
388
|
+
f"Received file_name={file_name!r}, content_file_path={content_file_path!r}."
|
389
|
+
)
|
390
|
+
|
391
|
+
return content_bytes, resolved_name
|
392
|
+
|
339
393
|
@with_lock_retry
|
340
394
|
async def perform_structural_migration_async(
|
341
395
|
self,
|
@@ -360,44 +414,37 @@ class StudioClient:
|
|
360
414
|
(None, deleted_resources_json),
|
361
415
|
)
|
362
416
|
)
|
363
|
-
|
364
417
|
for i, added_resource in enumerate(structural_migration.added_resources):
|
365
|
-
|
366
|
-
|
367
|
-
|
368
|
-
|
369
|
-
|
370
|
-
files.append((f"AddedResources[{i}].Content", (filename, content)))
|
371
|
-
|
372
|
-
if added_resource.parent_path:
|
373
|
-
files.append(
|
374
|
-
(
|
375
|
-
f"AddedResources[{i}].ParentPath",
|
376
|
-
(None, added_resource.parent_path),
|
377
|
-
)
|
378
|
-
)
|
379
|
-
else:
|
380
|
-
raise FileNotFoundError(
|
381
|
-
f"File not found: {added_resource.content_file_path}"
|
382
|
-
)
|
418
|
+
content_bytes, filename = self._resolve_content_and_filename(
|
419
|
+
content_string=added_resource.content_string,
|
420
|
+
content_file_path=added_resource.content_file_path,
|
421
|
+
file_name=added_resource.file_name,
|
422
|
+
)
|
383
423
|
|
384
|
-
|
385
|
-
if os.path.exists(modified_resource.content_file_path):
|
386
|
-
with open(modified_resource.content_file_path, "rb") as f:
|
387
|
-
content = f.read()
|
424
|
+
files.append((f"AddedResources[{i}].Content", (filename, content_bytes)))
|
388
425
|
|
389
|
-
|
390
|
-
files.append((f"ModifiedResources[{i}].Content", (filename, content)))
|
426
|
+
if added_resource.parent_path:
|
391
427
|
files.append(
|
392
428
|
(
|
393
|
-
f"
|
394
|
-
(None,
|
429
|
+
f"AddedResources[{i}].ParentPath",
|
430
|
+
(None, added_resource.parent_path),
|
395
431
|
)
|
396
432
|
)
|
397
|
-
|
398
|
-
|
399
|
-
|
433
|
+
|
434
|
+
for i, modified_resource in enumerate(structural_migration.modified_resources):
|
435
|
+
content_bytes, _ = self._resolve_content_and_filename(
|
436
|
+
content_string=modified_resource.content_string,
|
437
|
+
content_file_path=modified_resource.content_file_path,
|
438
|
+
modified=True,
|
439
|
+
)
|
440
|
+
|
441
|
+
files.append((f"ModifiedResources[{i}].Content", content_bytes))
|
442
|
+
files.append(
|
443
|
+
(
|
444
|
+
f"ModifiedResources[{i}].Id",
|
445
|
+
(None, modified_resource.id),
|
400
446
|
)
|
447
|
+
)
|
401
448
|
|
402
449
|
response = await self.uipath.api_client.request_async(
|
403
450
|
"POST",
|
uipath/tracing/_utils.py
CHANGED
@@ -37,7 +37,7 @@ class UiPathSpan:
|
|
37
37
|
)
|
38
38
|
expiry_time_utc: Optional[str] = None
|
39
39
|
folder_key: Optional[str] = field(
|
40
|
-
default_factory=lambda: env.get("
|
40
|
+
default_factory=lambda: env.get("UIPATH_FOLDER_KEY", "")
|
41
41
|
)
|
42
42
|
source: Optional[str] = None
|
43
43
|
span_type: str = "Coded Agents"
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.4
|
2
2
|
Name: uipath
|
3
|
-
Version: 2.1.
|
3
|
+
Version: 2.1.23
|
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
|
@@ -42,7 +42,7 @@ uipath/_cli/_evals/_evaluators/_trajectory_evaluator.py,sha256=dnogQTOskpI4_cNF0
|
|
42
42
|
uipath/_cli/_evals/_models/__init__.py,sha256=Ewjp3u2YeTH2MmzY9LWf7EIbAoIf_nW9fMYbj7pGlPs,420
|
43
43
|
uipath/_cli/_evals/_models/_evaluation_set.py,sha256=tVHykSget-G3sOCs9bSchMYUTpFqzXVlYYbY8L9SI0c,1518
|
44
44
|
uipath/_cli/_evals/_models/_evaluators.py,sha256=l57NEVyYmzSKuoIXuGkE94Br01hAMg35fiS2MlTkaQM,2115
|
45
|
-
uipath/_cli/_push/sw_file_handler.py,sha256=
|
45
|
+
uipath/_cli/_push/sw_file_handler.py,sha256=5zAt03gSlni7RnJmZJP4d4RVC33u8lZWj3W9xwx-CFM,18064
|
46
46
|
uipath/_cli/_runtime/_contracts.py,sha256=WlpaiQAMWCo-JFHjee35Klf49A3GsKjOU1Mf2IpUGHY,16033
|
47
47
|
uipath/_cli/_runtime/_escalation.py,sha256=x3vI98qsfRA-fL_tNkRVTFXioM5Gv2w0GFcXJJ5eQtg,7981
|
48
48
|
uipath/_cli/_runtime/_hitl.py,sha256=aexwe0dIXvh6SlVS1jVnO_aGZc6e3gLsmGkCyha5AHo,11300
|
@@ -62,7 +62,7 @@ uipath/_cli/_utils/_input_args.py,sha256=3LGNqVpJItvof75VGm-ZNTUMUH9-c7-YgleM5b2
|
|
62
62
|
uipath/_cli/_utils/_parse_ast.py,sha256=8Iohz58s6bYQ7rgWtOTjrEInLJ-ETikmOMZzZdIY2Co,20072
|
63
63
|
uipath/_cli/_utils/_processes.py,sha256=q7DfEKHISDWf3pngci5za_z0Pbnf_shWiYEcTOTCiyk,1855
|
64
64
|
uipath/_cli/_utils/_project_files.py,sha256=MMexSE6BapxitYBl1UUWy_AgkJMdGNFD1t2MkU0hwz4,13115
|
65
|
-
uipath/_cli/_utils/_studio_project.py,sha256=
|
65
|
+
uipath/_cli/_utils/_studio_project.py,sha256=X4X9HbdbGgLQtJRE-h8rcALCrupWkrpqOfSnt9c-hlo,15541
|
66
66
|
uipath/_cli/_utils/_tracing.py,sha256=2igb03j3EHjF_A406UhtCKkPfudVfFPjUq5tXUEG4oo,1541
|
67
67
|
uipath/_cli/_utils/_uv_helpers.py,sha256=6SvoLnZPoKIxW0sjMvD1-ENV_HOXDYzH34GjBqwT138,3450
|
68
68
|
uipath/_services/__init__.py,sha256=10xtw3ENC30yR9CCq_b94RMZ3YrUeyfHV33yWYUd8tU,896
|
@@ -112,11 +112,11 @@ uipath/telemetry/_track.py,sha256=I8SzROQcySAXNfxx4QgZlJ6ib8DjTKn50CiZYsbjjr8,45
|
|
112
112
|
uipath/tracing/__init__.py,sha256=GKRINyWdHVrDsI-8mrZDLdf0oey6GHGlNZTOADK-kgc,224
|
113
113
|
uipath/tracing/_otel_exporters.py,sha256=X7cnuGqvxGbACZuFD2XYTWXwIse8pokOEAjeTPE6DCQ,3158
|
114
114
|
uipath/tracing/_traced.py,sha256=qeVDrds2OUnpdUIA0RhtF0kg2dlAZhyC1RRkI-qivTM,18528
|
115
|
-
uipath/tracing/_utils.py,sha256=
|
115
|
+
uipath/tracing/_utils.py,sha256=wJRELaPu69iY0AhV432Dk5QYf_N_ViRU4kAUG1BI1ew,10384
|
116
116
|
uipath/utils/__init__.py,sha256=VD-KXFpF_oWexFg6zyiWMkxl2HM4hYJMIUDZ1UEtGx0,105
|
117
117
|
uipath/utils/_endpoints_manager.py,sha256=iRTl5Q0XAm_YgcnMcJOXtj-8052sr6jpWuPNz6CgT0Q,8408
|
118
|
-
uipath-2.1.
|
119
|
-
uipath-2.1.
|
120
|
-
uipath-2.1.
|
121
|
-
uipath-2.1.
|
122
|
-
uipath-2.1.
|
118
|
+
uipath-2.1.23.dist-info/METADATA,sha256=CEP-ypBLLKYH4Tkpc9iWDIUx-uWRHty7PqgnuX3CcTg,6367
|
119
|
+
uipath-2.1.23.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
120
|
+
uipath-2.1.23.dist-info/entry_points.txt,sha256=9C2_29U6Oq1ExFu7usihR-dnfIVNSKc-0EFbh0rskB4,43
|
121
|
+
uipath-2.1.23.dist-info/licenses/LICENSE,sha256=-KBavWXepyDjimmzH5fVAsi-6jNVpIKFc2kZs0Ri4ng,1058
|
122
|
+
uipath-2.1.23.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|