uipath 2.0.26__py3-none-any.whl → 2.0.28__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of uipath might be problematic. Click here for more details.

uipath/_cli/cli_init.py CHANGED
@@ -1,17 +1,18 @@
1
1
  # type: ignore
2
2
  import json
3
3
  import os
4
- import traceback
5
4
  import uuid
6
5
  from pathlib import Path
7
6
  from typing import Optional
8
7
 
9
8
  import click
10
9
 
10
+ from ._utils._console import ConsoleLogger
11
11
  from ._utils._input_args import generate_args
12
12
  from ._utils._parse_ast import generate_bindings_json
13
13
  from .middlewares import Middlewares
14
- from .spinner import Spinner
14
+
15
+ console = ConsoleLogger()
15
16
 
16
17
 
17
18
  def generate_env_file(target_directory):
@@ -19,7 +20,7 @@ def generate_env_file(target_directory):
19
20
 
20
21
  if not os.path.exists(env_path):
21
22
  relative_path = os.path.relpath(env_path, target_directory)
22
- click.echo(f"Created {relative_path} file.")
23
+ console.success(f"Created {relative_path} file.")
23
24
  with open(env_path, "w") as f:
24
25
  f.write("UIPATH_ACCESS_TOKEN=YOUR_TOKEN_HERE\n")
25
26
  f.write("UIPATH_URL=https://cloud.uipath.com/ACCOUNT_NAME/TENANT_NAME\n")
@@ -30,20 +31,22 @@ def get_user_script(directory: str, entrypoint: Optional[str] = None) -> Optiona
30
31
  if entrypoint:
31
32
  script_path = os.path.join(directory, entrypoint)
32
33
  if not os.path.isfile(script_path):
33
- click.echo(f"The {entrypoint} file does not exist in the current directory")
34
+ console.error(
35
+ f"The {entrypoint} file does not exist in the current directory."
36
+ )
34
37
  return None
35
38
  return script_path
36
39
 
37
40
  python_files = [f for f in os.listdir(directory) if f.endswith(".py")]
38
41
 
39
42
  if not python_files:
40
- click.echo("No Python files found in the directory")
43
+ console.error("No python files found in the current directory.")
41
44
  return None
42
45
  elif len(python_files) == 1:
43
46
  return os.path.join(directory, python_files[0])
44
47
  else:
45
- click.echo(
46
- "Multiple Python files found in the current directory.\nPlease specify the entrypoint: `uipath init <entrypoint_path>`"
48
+ console.error(
49
+ "Multiple python files found in the current directory.\nPlease specify the entrypoint: `uipath init <entrypoint_path>`"
47
50
  )
48
51
  return None
49
52
 
@@ -51,67 +54,59 @@ def get_user_script(directory: str, entrypoint: Optional[str] = None) -> Optiona
51
54
  @click.command()
52
55
  @click.argument("entrypoint", required=False, default=None)
53
56
  def init(entrypoint: str) -> None:
54
- """Initialize a uipath.json configuration file for the script."""
55
- spinner = Spinner("Initializing UiPath project...")
56
- current_directory = os.getcwd()
57
- generate_env_file(current_directory)
58
-
59
- result = Middlewares.next("init", entrypoint)
60
-
61
- if result.error_message:
62
- click.echo(result.error_message)
63
- if result.should_include_stacktrace:
64
- click.echo(traceback.format_exc())
65
- click.get_current_context().exit(1)
66
-
67
- if result.info_message:
68
- click.echo(result.info_message)
69
-
70
- if not result.should_continue:
71
- return
72
- script_path = get_user_script(current_directory, entrypoint=entrypoint)
73
-
74
- if not script_path:
75
- click.get_current_context().exit(1)
76
- spinner.start()
77
- try:
78
- args = generate_args(script_path)
79
-
80
- relative_path = Path(script_path).relative_to(current_directory).as_posix()
81
-
82
- config_data = {
83
- "entryPoints": [
84
- {
85
- "filePath": relative_path,
86
- "uniqueId": str(uuid.uuid4()),
87
- # "type": "process", OR BE doesn't offer json schema support for type: Process
88
- "type": "agent",
89
- "input": args["input"],
90
- "output": args["output"],
91
- }
92
- ]
93
- }
94
-
95
- # Generate bindings JSON based on the script path
96
- try:
97
- bindings_data = generate_bindings_json(script_path)
98
- # Add bindings to the config data
99
- config_data["bindings"] = bindings_data
100
- except Exception as e:
101
- click.echo(f"⚠️ Warning: Could not generate bindings: {str(e)}")
57
+ """Create uipath.json with input/output schemas and bindings."""
58
+ with console.spinner("Initializing UiPath project ..."):
59
+ current_directory = os.getcwd()
60
+ generate_env_file(current_directory)
102
61
 
103
- config_path = "uipath.json"
104
- with open(config_path, "w") as config_file:
105
- json.dump(config_data, config_file, indent=4)
62
+ result = Middlewares.next("init", entrypoint)
106
63
 
107
- spinner.stop()
108
- click.echo(
109
- click.style("✓ ", fg="green", bold=True)
110
- + f"Configuration file {config_path} created successfully."
111
- )
64
+ if result.error_message:
65
+ console.error(
66
+ result.error_message, include_traceback=result.should_include_stacktrace
67
+ )
68
+
69
+ if result.info_message:
70
+ console.info(result.info_message)
112
71
 
113
- except Exception as e:
114
- spinner.stop()
115
- click.echo(f"❌ Error generating configuration: {str(e)}")
116
- click.echo(traceback.format_exc())
117
- click.get_current_context().exit(1)
72
+ if not result.should_continue:
73
+ return
74
+
75
+ script_path = get_user_script(current_directory, entrypoint=entrypoint)
76
+
77
+ if not script_path:
78
+ return
79
+
80
+ try:
81
+ args = generate_args(script_path)
82
+
83
+ relative_path = Path(script_path).relative_to(current_directory).as_posix()
84
+
85
+ config_data = {
86
+ "entryPoints": [
87
+ {
88
+ "filePath": relative_path,
89
+ "uniqueId": str(uuid.uuid4()),
90
+ # "type": "process", OR BE doesn't offer json schema support for type: Process
91
+ "type": "agent",
92
+ "input": args["input"],
93
+ "output": args["output"],
94
+ }
95
+ ]
96
+ }
97
+
98
+ # Generate bindings JSON based on the script path
99
+ try:
100
+ bindings_data = generate_bindings_json(script_path)
101
+ # Add bindings to the config data
102
+ config_data["bindings"] = bindings_data
103
+ except Exception as e:
104
+ console.warning(f"Warning: Could not generate bindings: {str(e)}")
105
+
106
+ config_path = "uipath.json"
107
+ with open(config_path, "w") as config_file:
108
+ json.dump(config_data, config_file, indent=4)
109
+
110
+ console.success(f"Created '{config_path}' file.")
111
+ except Exception as e:
112
+ console.error(f"Error creating configuration file: {str(e)}")
uipath/_cli/cli_invoke.py CHANGED
@@ -7,7 +7,7 @@ import click
7
7
  import requests
8
8
  from dotenv import load_dotenv
9
9
 
10
- from .spinner import Spinner
10
+ from ._utils._console import ConsoleLogger
11
11
 
12
12
  try:
13
13
  import tomllib
@@ -20,22 +20,21 @@ from ._utils._processes import get_release_info
20
20
 
21
21
  logger = logging.getLogger(__name__)
22
22
  load_dotenv()
23
+ console = ConsoleLogger()
23
24
 
24
25
 
25
26
  def _read_project_name() -> str:
26
27
  current_path = os.getcwd()
27
28
  toml_path = os.path.join(current_path, "pyproject.toml")
28
29
  if not os.path.isfile(toml_path):
29
- raise Exception("pyproject.toml not found")
30
+ console.error("pyproject.toml not found.")
30
31
 
31
32
  with open(toml_path, "rb") as f:
32
33
  content = tomllib.load(f)
33
34
  if "project" not in content:
34
- raise Exception("pyproject.toml is missing the required field: project")
35
+ console.error("pyproject.toml is missing the required field: project.")
35
36
  if "name" not in content["project"]:
36
- raise Exception(
37
- "pyproject.toml is missing the required field: project.name"
38
- )
37
+ console.error("pyproject.toml is missing the required field: project.name.")
39
38
 
40
39
  return content["project"]["name"]
41
40
 
@@ -44,60 +43,54 @@ def _read_project_name() -> str:
44
43
  @click.argument("entrypoint", required=False)
45
44
  @click.argument("input", required=False, default="{}")
46
45
  def invoke(entrypoint: Optional[str], input: Optional[str]) -> None:
47
- """Invoke a remote agent with JSON input."""
48
- spinner = Spinner("Starting job...")
49
- spinner.start()
46
+ """Invoke a published agent."""
47
+ with console.spinner("Loading configuration ..."):
48
+ current_path = os.getcwd()
49
+ load_dotenv(os.path.join(current_path, ".env"), override=True)
50
+ [base_url, token] = get_env_vars()
51
+
52
+ url = f"{base_url}/orchestrator_/odata/Jobs/UiPath.Server.Configuration.OData.StartJobs"
53
+ _, personal_workspace_folder_id = get_personal_workspace_info(base_url, token)
54
+ project_name = _read_project_name()
55
+
56
+ if not personal_workspace_folder_id:
57
+ console.error(
58
+ "No personal workspace found for user. Please try reauthenticating."
59
+ )
50
60
 
51
- current_path = os.getcwd()
52
- load_dotenv(os.path.join(current_path, ".env"), override=True)
53
- [base_url, token] = get_env_vars(spinner)
54
-
55
- url = f"{base_url}/orchestrator_/odata/Jobs/UiPath.Server.Configuration.OData.StartJobs"
56
- _, personal_workspace_folder_id = get_personal_workspace_info(
57
- base_url, token, spinner
58
- )
59
- project_name = _read_project_name()
60
-
61
- _, release_key = get_release_info(
62
- base_url, token, project_name, personal_workspace_folder_id, spinner
63
- )
64
- payload = {
65
- "StartInfo": {
66
- "ReleaseKey": str(release_key),
67
- "RunAsMe": True,
68
- "InputArguments": input,
69
- "EntryPointPath": entrypoint,
61
+ _, release_key = get_release_info(
62
+ base_url, token, project_name, personal_workspace_folder_id
63
+ )
64
+ payload = {
65
+ "StartInfo": {
66
+ "ReleaseKey": str(release_key),
67
+ "RunAsMe": True,
68
+ "InputArguments": input,
69
+ "EntryPointPath": entrypoint,
70
+ }
71
+ }
72
+ headers = {
73
+ "Authorization": f"Bearer {token}",
74
+ "x-uipath-organizationunitid": str(personal_workspace_folder_id),
70
75
  }
71
- }
72
- headers = {
73
- "Authorization": f"Bearer {token}",
74
- "x-uipath-organizationunitid": str(personal_workspace_folder_id),
75
- }
76
76
 
77
- response = requests.post(url, json=payload, headers=headers)
78
- spinner.stop()
77
+ response = requests.post(url, json=payload, headers=headers)
79
78
 
80
79
  if response.status_code == 201:
81
80
  job_key = None
82
81
  try:
83
82
  job_key = response.json()["value"][0]["Key"]
84
83
  except KeyError:
85
- click.echo("Error: Failed to get job key from response")
86
- click.Abort()
84
+ console.error("Error: Failed to get job key from response")
87
85
  if job_key:
88
- job_url = f"{base_url}/orchestrator_/jobs(sidepanel:sidepanel/jobs/{job_key}/details)?fid={personal_workspace_folder_id}"
89
- click.echo("✨ Job started successfully!")
90
- click.echo(
91
- "🔗 Monitor your job here: "
92
- + click.style(
93
- f"\u001b]8;;{job_url}\u001b\\{job_url}\u001b]8;;\u001b\\",
94
- fg="bright_blue",
95
- bold=True,
96
- )
97
- )
86
+ with console.spinner("Starting job ..."):
87
+ job_url = f"{base_url}/orchestrator_/jobs(sidepanel:sidepanel/jobs/{job_key}/details)?fid={personal_workspace_folder_id}"
88
+ console.magic("Job started successfully!")
89
+ console.link("Monitor your job here: ", job_url)
98
90
  else:
99
- click.echo(f"\n❌ Error starting job: {response.text}")
100
- click.Abort()
91
+ console.error(
92
+ f"Error: Failed to start job. Status code: {response.status_code} {response.text}"
93
+ )
101
94
 
102
95
 
103
96
  if __name__ == "__main__":
uipath/_cli/cli_new.py CHANGED
@@ -1,12 +1,13 @@
1
1
  # type: ignore
2
2
  import os
3
3
  import shutil
4
- import traceback
5
4
 
6
5
  import click
7
6
 
7
+ from ._utils._console import ConsoleLogger
8
8
  from .middlewares import Middlewares
9
- from .spinner import Spinner
9
+
10
+ console = ConsoleLogger()
10
11
 
11
12
 
12
13
  def generate_script(target_directory):
@@ -26,9 +27,9 @@ version = "0.0.1"
26
27
  description = "{project_name}"
27
28
  authors = [{{ name = "John Doe", email = "john.doe@myemail.com" }}]
28
29
  dependencies = [
29
- "uipath>=2.0.0"
30
+ "uipath>=2.0.26"
30
31
  ]
31
- requires-python = ">=3.9"
32
+ requires-python = ">=3.10"
32
33
  """
33
34
 
34
35
  with open(project_toml_path, "w") as f:
@@ -38,44 +39,38 @@ requires-python = ">=3.9"
38
39
  @click.command()
39
40
  @click.argument("name", type=str, default="")
40
41
  def new(name: str):
41
- spinner = Spinner("Creating new project...")
42
+ """Generate a quick-start project."""
42
43
  directory = os.getcwd()
43
44
 
44
45
  if not name:
45
- raise click.UsageError(
46
- "Please specify a name for your project\n`uipath new hello-world`"
46
+ console.error(
47
+ "Please specify a name for your project:\n`uipath new hello-world`"
47
48
  )
48
49
 
49
- click.echo(
50
- click.style("✓ ", fg="green", bold=True)
51
- + f"Initializing project {name} in current directory.."
52
- )
53
-
54
50
  result = Middlewares.next("new", name)
55
51
 
56
52
  if result.error_message:
57
- click.echo("❌ " + result.error_message)
58
- if result.should_include_stacktrace:
59
- click.echo(traceback.format_exc())
60
- click.get_current_context().exit(1)
53
+ console.error(
54
+ result.error_message, include_traceback=result.should_include_stacktrace
55
+ )
61
56
 
62
57
  if result.info_message:
63
- click.echo(result.info_message)
58
+ console.info(result.info_message)
64
59
 
65
60
  if not result.should_continue:
66
61
  return
67
62
 
68
- generate_script(directory)
69
- click.echo(click.style("✓ ", fg="green", bold=True) + "Created main.py file")
70
- generate_pyproject(directory, name)
71
- click.echo(click.style("✓ ", fg="green", bold=True) + "Created pyproject.toml file")
72
- spinner.start()
73
- ctx = click.get_current_context()
74
- init_cmd = ctx.parent.command.get_command(ctx, "init")
75
- ctx.invoke(init_cmd)
76
- spinner.stop()
77
-
78
- click.echo("""` uipath run main.py '{"message": "Hello World!"}' `""")
63
+ with console.spinner(f"Creating new project {name} in current directory ..."):
64
+ generate_script(directory)
65
+ console.success("Created 'main.py' file.")
66
+ generate_pyproject(directory, name)
67
+ console.success("Created 'pyproject.toml' file.")
68
+ ctx = click.get_current_context()
69
+ init_cmd = ctx.parent.command.get_command(ctx, "init")
70
+ ctx.invoke(init_cmd)
71
+ console.hint(
72
+ """Run project: uipath run main.py '{"message": "Hello World!"}'"""
73
+ )
79
74
 
80
75
 
81
76
  if __name__ == "__main__":
uipath/_cli/cli_pack.py CHANGED
@@ -12,7 +12,9 @@ try:
12
12
  except ImportError:
13
13
  import tomli as tomllib
14
14
 
15
- from .spinner import Spinner
15
+ from ._utils._console import ConsoleLogger
16
+
17
+ console = ConsoleLogger()
16
18
 
17
19
  schema = "https://cloud.uipath.com/draft/2024-12/entry-point"
18
20
 
@@ -21,7 +23,7 @@ def validate_config_structure(config_data):
21
23
  required_fields = ["entryPoints"]
22
24
  for field in required_fields:
23
25
  if field not in config_data:
24
- raise Exception(f"uipath.json is missing the required field: {field}")
26
+ console.error(f"uipath.json is missing the required field: {field}.")
25
27
 
26
28
 
27
29
  def check_config(directory):
@@ -29,9 +31,9 @@ def check_config(directory):
29
31
  toml_path = os.path.join(directory, "pyproject.toml")
30
32
 
31
33
  if not os.path.isfile(config_path):
32
- raise Exception("uipath.json not found, please run `uipath init`")
34
+ console.error("uipath.json not found, please run `uipath init`.")
33
35
  if not os.path.isfile(toml_path):
34
- raise Exception("pyproject.toml not found")
36
+ console.error("pyproject.toml not found.")
35
37
 
36
38
  with open(config_path, "r") as config_file:
37
39
  config_data = json.load(config_file)
@@ -206,7 +208,7 @@ def pack_fn(projectName, description, entryPoints, version, authors, directory):
206
208
  # Get bindings from uipath.json if available
207
209
  config_path = os.path.join(directory, "uipath.json")
208
210
  if not os.path.exists(config_path):
209
- raise Exception("uipath.json not found, please run `uipath init`")
211
+ console.error("uipath.json not found, please run `uipath init`.")
210
212
 
211
213
  # Define the allowlist of file extensions to include
212
214
  file_extensions_included = [".py", ".mermaid", ".json", ".yaml", ".yml"]
@@ -305,18 +307,16 @@ def read_toml_project(file_path: str) -> dict[str, any]:
305
307
  with open(file_path, "rb") as f:
306
308
  content = tomllib.load(f)
307
309
  if "project" not in content:
308
- raise Exception("pyproject.toml is missing the required field: project")
310
+ console.error("pyproject.toml is missing the required field: project.")
309
311
  if "name" not in content["project"]:
310
- raise Exception(
311
- "pyproject.toml is missing the required field: project.name"
312
- )
312
+ console.error("pyproject.toml is missing the required field: project.name.")
313
313
  if "description" not in content["project"]:
314
- raise Exception(
315
- "pyproject.toml is missing the required field: project.description"
314
+ console.error(
315
+ "pyproject.toml is missing the required field: project.description."
316
316
  )
317
317
  if "version" not in content["project"]:
318
- raise Exception(
319
- "pyproject.toml is missing the required field: project.version"
318
+ console.error(
319
+ "pyproject.toml is missing the required field: project.version."
320
320
  )
321
321
 
322
322
  return {
@@ -330,63 +330,80 @@ def read_toml_project(file_path: str) -> dict[str, any]:
330
330
  def get_project_version(directory):
331
331
  toml_path = os.path.join(directory, "pyproject.toml")
332
332
  if not os.path.exists(toml_path):
333
- click.echo("⚠️ Warning: No pyproject.toml found. Using default version 0.0.1")
333
+ console.warning("pyproject.toml not found. Using default version 0.0.1")
334
334
  return "0.0.1"
335
335
  toml_data = read_toml_project(toml_path)
336
336
  return toml_data["version"]
337
337
 
338
338
 
339
+ def display_project_info(config):
340
+ max_label_length = max(
341
+ len(label) for label in ["Name", "Version", "Description", "Authors"]
342
+ )
343
+
344
+ max_length = 100
345
+ description = config["description"]
346
+ if len(description) >= max_length:
347
+ description = description[: max_length - 3] + " ..."
348
+
349
+ console.log(f"{'Name'.ljust(max_label_length)}: {config['project_name']}")
350
+ console.log(f"{'Version'.ljust(max_label_length)}: {config['version']}")
351
+ console.log(f"{'Description'.ljust(max_label_length)}: {description}")
352
+ console.log(f"{'Authors'.ljust(max_label_length)}: {config['authors']}")
353
+
354
+
339
355
  @click.command()
340
356
  @click.argument("root", type=str, default="./")
341
357
  def pack(root):
358
+ """Pack the project."""
342
359
  version = get_project_version(root)
343
360
 
344
361
  while not os.path.isfile(os.path.join(root, "uipath.json")):
345
- click.echo(
346
- "uipath.json not found. Please run `uipath init` in the project directory."
362
+ console.error(
363
+ "uipath.json not found. Please run `uipath init` in the project directory."
347
364
  )
348
- return
349
365
  config = check_config(root)
350
366
  if not config["project_name"] or config["project_name"].strip() == "":
351
- raise Exception("❌ Project name cannot be empty")
367
+ console.error(
368
+ "Project name cannot be empty. Please specify a name in pyproject.toml."
369
+ )
352
370
 
353
371
  if not config["description"] or config["description"].strip() == "":
354
- raise Exception("❌ Project description cannot be empty")
372
+ console.error(
373
+ "Project description cannot be empty. Please specify a description in pyproject.toml."
374
+ )
355
375
 
356
376
  if not config["authors"] or config["authors"].strip() == "":
357
- raise Exception("❌ Project authors cannot be empty")
377
+ console.error(
378
+ 'Project authors cannot be empty. Please specify authors in pyproject.toml:\n authors = [{ name = "John Doe" }]'
379
+ )
358
380
 
359
381
  invalid_chars = ["&", "<", ">", '"', "'", ";"]
360
382
  for char in invalid_chars:
361
383
  if char in config["project_name"]:
362
- raise Exception(f"Project name contains invalid character: '{char}'")
384
+ console.error(f"Project name contains invalid character: '{char}'")
363
385
 
364
386
  for char in invalid_chars:
365
387
  if char in config["description"]:
366
- raise Exception(
367
- f"❌ Project description contains invalid character: '{char}'"
388
+ console.error(f"Project description contains invalid character: '{char}'")
389
+
390
+ with console.spinner("Packaging project ..."):
391
+ try:
392
+ pack_fn(
393
+ config["project_name"],
394
+ config["description"],
395
+ config["entryPoints"],
396
+ version or config["version"],
397
+ config["authors"],
398
+ root,
399
+ )
400
+ display_project_info(config)
401
+ console.success("Project successfully packaged.")
402
+
403
+ except Exception as e:
404
+ console.error(
405
+ f"Failed to create package {config['project_name']}.{version or config['version']}: {str(e)}"
368
406
  )
369
- spinner = Spinner(
370
- f"Packaging project {config['project_name']}:{version or config['version']} description {config['description']} authored by {config['authors']}"
371
- )
372
- try:
373
- spinner.start()
374
- pack_fn(
375
- config["project_name"],
376
- config["description"],
377
- config["entryPoints"],
378
- version or config["version"],
379
- config["authors"],
380
- root,
381
- )
382
- spinner.stop()
383
- click.echo(
384
- click.style("✓ ", fg="green", bold=True) + "Package created successfully!"
385
- )
386
- except Exception as e:
387
- spinner.stop()
388
- click.echo(f"\n❌ Error: {str(e)}")
389
- click.Abort()
390
407
 
391
408
 
392
409
  if __name__ == "__main__":