Skip to content

Commit 800b85e

Browse files
Merge pull request #411 from UiPath/feat/no-infer-bindings
chore: enhance CLI documentation and add settings retrieval functiona…
2 parents 0569311 + 6bc7bb3 commit 800b85e

4 files changed

Lines changed: 85 additions & 10 deletions

File tree

docs/cli/index.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,10 @@ Selected tenant: Tenant1
2727
:depth: 1
2828
:style: table
2929

30+
Package requirements (bindings) are dependencies that are required by the automation package for successful execution.
31+
32+
For more information about package requirements, see [the official documentation](https://docs.uipath.com/orchestrator/automation-cloud/latest/user-guide/managing-package-requirements)
33+
3034
/// warning
3135

3236
The `uipath init` command executes your `main.py` file to analyze its structure and collect information about inputs and outputs.

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[project]
22
name = "uipath"
3-
version = "2.0.70"
3+
version = "2.0.71"
44
description = "Python SDK and CLI for UiPath Platform, enabling programmatic interaction with automation services, process management, and deployment tools."
55
readme = { file = "README.md", content-type = "text/markdown" }
66
requires-python = ">=3.10"

src/uipath/_cli/cli_init.py

Lines changed: 53 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
import os
44
import uuid
55
from pathlib import Path
6-
from typing import Optional
6+
from typing import Any, Dict, Optional
77

88
import click
99
from dotenv import load_dotenv
@@ -16,6 +16,8 @@
1616

1717
console = ConsoleLogger()
1818

19+
CONFIG_PATH = "uipath.json"
20+
1921

2022
def generate_env_file(target_directory):
2123
env_path = os.path.join(target_directory, ".env")
@@ -27,6 +29,26 @@ def generate_env_file(target_directory):
2729
console.success(f" Created '{relative_path}' file.")
2830

2931

32+
def get_existing_settings(config_path: str) -> Optional[Dict[str, Any]]:
33+
"""Read existing settings from uipath.json if it exists.
34+
35+
Args:
36+
config_path: Path to the uipath.json file.
37+
38+
Returns:
39+
The settings dictionary if it exists, None otherwise.
40+
"""
41+
if not os.path.exists(config_path):
42+
return None
43+
44+
try:
45+
with open(config_path, "r") as config_file:
46+
existing_config = json.load(config_file)
47+
return existing_config.get("settings")
48+
except (json.JSONDecodeError, IOError):
49+
return None
50+
51+
3052
def get_user_script(directory: str, entrypoint: Optional[str] = None) -> Optional[str]:
3153
"""Find the Python script to process."""
3254
if entrypoint:
@@ -52,10 +74,28 @@ def get_user_script(directory: str, entrypoint: Optional[str] = None) -> Optiona
5274
return None
5375

5476

77+
def write_config_file(config_data: Dict[str, Any]) -> None:
78+
existing_settings = get_existing_settings(CONFIG_PATH)
79+
if existing_settings is not None:
80+
config_data["settings"] = existing_settings
81+
82+
with open(CONFIG_PATH, "w") as config_file:
83+
json.dump(config_data, config_file, indent=4)
84+
85+
return CONFIG_PATH
86+
87+
5588
@click.command()
5689
@click.argument("entrypoint", required=False, default=None)
90+
@click.option(
91+
"--infer-bindings/--no-infer-bindings",
92+
is_flag=True,
93+
required=False,
94+
default=True,
95+
help="Infer bindings from the script.",
96+
)
5797
@track
58-
def init(entrypoint: str) -> None:
98+
def init(entrypoint: str, infer_bindings: bool) -> None:
5999
"""Create uipath.json with input/output schemas and bindings."""
60100
current_path = os.getcwd()
61101
load_dotenv(os.path.join(current_path, ".env"), override=True)
@@ -64,7 +104,12 @@ def init(entrypoint: str) -> None:
64104
current_directory = os.getcwd()
65105
generate_env_file(current_directory)
66106

67-
result = Middlewares.next("init", entrypoint)
107+
result = Middlewares.next(
108+
"init",
109+
entrypoint,
110+
options={"infer_bindings": infer_bindings},
111+
write_config=write_config_file,
112+
)
68113

69114
if result.error_message:
70115
console.error(
@@ -102,16 +147,16 @@ def init(entrypoint: str) -> None:
102147

103148
# Generate bindings JSON based on the script path
104149
try:
105-
bindings_data = generate_bindings_json(script_path)
150+
if infer_bindings:
151+
bindings_data = generate_bindings_json(script_path)
152+
else:
153+
bindings_data = {}
106154
# Add bindings to the config data
107155
config_data["bindings"] = bindings_data
108156
except Exception as e:
109157
console.warning(f"Warning: Could not generate bindings: {str(e)}")
110158

111-
config_path = "uipath.json"
112-
with open(config_path, "w") as config_file:
113-
json.dump(config_data, config_file, indent=4)
114-
159+
config_path = write_config_file(config_data)
115160
console.success(f"Created '{config_path}' file.")
116161
except Exception as e:
117162
console.error(f"Error creating configuration file:\n {str(e)}")

src/uipath/_cli/middlewares.py

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,13 @@
11
import importlib.metadata
2+
import inspect
23
import logging
34
from dataclasses import dataclass
45
from typing import Any, Callable, Dict, List, Optional
56

7+
from ._utils._console import ConsoleLogger
8+
69
logger = logging.getLogger(__name__)
10+
console = ConsoleLogger()
711

812

913
@dataclass
@@ -50,8 +54,30 @@ def next(cls, command: str, *args: Any, **kwargs: Any) -> MiddlewareResult:
5054

5155
middlewares = cls.get(command)
5256
for middleware in middlewares:
57+
sig = inspect.signature(middleware)
58+
59+
# handle older versions of plugins that don't support the new signature
60+
try:
61+
bound = sig.bind(*args, **kwargs)
62+
new_args = bound.args
63+
new_kwargs = bound.kwargs
64+
except TypeError:
65+
console.warning("Install the latest version for uipath packages")
66+
accepted_args = [
67+
name
68+
for name, param in sig.parameters.items()
69+
if param.kind
70+
in (param.POSITIONAL_ONLY, param.POSITIONAL_OR_KEYWORD)
71+
]
72+
73+
trimmed_args = args[: len(accepted_args)]
74+
trimmed_kwargs = {k: v for k, v in kwargs.items() if k in accepted_args}
75+
76+
new_args = trimmed_args
77+
new_kwargs = trimmed_kwargs
78+
5379
try:
54-
result = middleware(*args, **kwargs)
80+
result = middleware(*new_args, **new_kwargs)
5581
if not result.should_continue:
5682
logger.debug(
5783
f"Command '{command}' stopped by {middleware.__name__}"

0 commit comments

Comments
 (0)