uipath 2.1.130__py3-none-any.whl → 2.1.132__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/__init__.py +45 -3
- uipath/_cli/_auth/auth_config_cloud.json +1 -1
- uipath/_cli/_runtime/_contracts.py +12 -10
- uipath/_cli/_utils/_context.py +65 -0
- uipath/_cli/_utils/_formatters.py +173 -0
- uipath/_cli/_utils/_service_base.py +340 -0
- uipath/_cli/_utils/_service_cli_generator.py +705 -0
- uipath/_cli/_utils/_service_metadata.py +218 -0
- uipath/_cli/_utils/_service_protocol.py +223 -0
- uipath/_cli/_utils/_type_registry.py +106 -0
- uipath/_cli/_utils/_validators.py +127 -0
- uipath/_cli/services/__init__.py +38 -0
- uipath/_cli/services/_buckets_metadata.py +53 -0
- uipath/_cli/services/cli_buckets.py +526 -0
- uipath/_resources/CLI_REFERENCE.md +340 -0
- uipath/_resources/SDK_REFERENCE.md +14 -2
- uipath/_services/buckets_service.py +169 -6
- {uipath-2.1.130.dist-info → uipath-2.1.132.dist-info}/METADATA +1 -1
- {uipath-2.1.130.dist-info → uipath-2.1.132.dist-info}/RECORD +22 -11
- {uipath-2.1.130.dist-info → uipath-2.1.132.dist-info}/WHEEL +0 -0
- {uipath-2.1.130.dist-info → uipath-2.1.132.dist-info}/entry_points.txt +0 -0
- {uipath-2.1.130.dist-info → uipath-2.1.132.dist-info}/licenses/LICENSE +0 -0
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
"""Service command groups for UiPath CLI.
|
|
2
|
+
|
|
3
|
+
All services are explicitly imported to ensure:
|
|
4
|
+
- File renames break loudly (import error) not silently
|
|
5
|
+
- Clear dependency graph
|
|
6
|
+
- Fast startup (no auto-discovery overhead)
|
|
7
|
+
- Debuggable registration
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
from .cli_buckets import buckets
|
|
11
|
+
|
|
12
|
+
__all__ = ["buckets", "register_service_commands"]
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
def register_service_commands(cli_group):
|
|
16
|
+
"""Register all service command groups with the root CLI.
|
|
17
|
+
|
|
18
|
+
This function maintains explicitness while reducing registration boilerplate.
|
|
19
|
+
Benefits:
|
|
20
|
+
- File renames break loudly (import error) not silently
|
|
21
|
+
- Clear list of all registered services
|
|
22
|
+
- Easy to comment out services during development
|
|
23
|
+
|
|
24
|
+
Args:
|
|
25
|
+
cli_group: The root Click group to register services with
|
|
26
|
+
|
|
27
|
+
Returns:
|
|
28
|
+
The cli_group for method chaining
|
|
29
|
+
|
|
30
|
+
Industry Precedent:
|
|
31
|
+
AWS CLI, Azure CLI, and gcloud all use explicit registration.
|
|
32
|
+
"""
|
|
33
|
+
services = [buckets]
|
|
34
|
+
|
|
35
|
+
for service in services:
|
|
36
|
+
cli_group.add_command(service)
|
|
37
|
+
|
|
38
|
+
return cli_group
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
"""Metadata configuration for Buckets service CLI.
|
|
2
|
+
|
|
3
|
+
This module defines the ServiceMetadata for the buckets service, which is used
|
|
4
|
+
by ServiceCLIGenerator to auto-generate standard CRUD commands.
|
|
5
|
+
|
|
6
|
+
The buckets service was the first service migrated to the Service CLI Generator
|
|
7
|
+
architecture and serves as the reference implementation for future migrations.
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
from uipath._cli._utils._service_metadata import (
|
|
11
|
+
CreateParameter,
|
|
12
|
+
DeleteCommandConfig,
|
|
13
|
+
ExistsCommandConfig,
|
|
14
|
+
ServiceMetadata,
|
|
15
|
+
)
|
|
16
|
+
from uipath._cli._utils._service_protocol import validate_service_protocol
|
|
17
|
+
|
|
18
|
+
__all__ = ["BUCKETS_METADATA"]
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
BUCKETS_METADATA = ServiceMetadata(
|
|
22
|
+
service_name="buckets",
|
|
23
|
+
service_attr="buckets",
|
|
24
|
+
resource_type="Bucket",
|
|
25
|
+
resource_plural="Buckets",
|
|
26
|
+
create_params={
|
|
27
|
+
"description": CreateParameter(
|
|
28
|
+
type="str",
|
|
29
|
+
required=False,
|
|
30
|
+
help="Bucket description",
|
|
31
|
+
default=None,
|
|
32
|
+
),
|
|
33
|
+
},
|
|
34
|
+
delete_cmd=DeleteCommandConfig(
|
|
35
|
+
confirmation_required=True,
|
|
36
|
+
dry_run_supported=True,
|
|
37
|
+
confirmation_prompt=None,
|
|
38
|
+
),
|
|
39
|
+
exists_cmd=ExistsCommandConfig(
|
|
40
|
+
identifier_arg_name="name",
|
|
41
|
+
return_format="dict",
|
|
42
|
+
),
|
|
43
|
+
)
|
|
44
|
+
|
|
45
|
+
BUCKETS_METADATA.validate_types()
|
|
46
|
+
|
|
47
|
+
try:
|
|
48
|
+
from uipath.sdk import SDK # type: ignore[import-not-found]
|
|
49
|
+
|
|
50
|
+
sdk = SDK()
|
|
51
|
+
validate_service_protocol(sdk.client.buckets, "buckets")
|
|
52
|
+
except Exception:
|
|
53
|
+
pass
|
|
@@ -0,0 +1,526 @@
|
|
|
1
|
+
"""Buckets service commands for UiPath CLI.
|
|
2
|
+
|
|
3
|
+
Buckets are cloud storage containers for files used by automation processes.
|
|
4
|
+
Similar to AWS S3 or Azure Blob Storage.
|
|
5
|
+
|
|
6
|
+
This module uses the Service CLI Generator to auto-generate standard CRUD commands
|
|
7
|
+
for bucket management, with custom implementations for file operations.
|
|
8
|
+
|
|
9
|
+
Architecture:
|
|
10
|
+
- Auto-generated commands: list, create, delete, exists (via ServiceCLIGenerator)
|
|
11
|
+
- Overridden command: retrieve (custom --name/--key dual-option support)
|
|
12
|
+
- Manual nested group: files (with 6 custom file operation commands)
|
|
13
|
+
"""
|
|
14
|
+
# ruff: noqa: D301 - Using regular """ strings (not r""") for Click \b formatting
|
|
15
|
+
|
|
16
|
+
from itertools import islice
|
|
17
|
+
|
|
18
|
+
import click
|
|
19
|
+
|
|
20
|
+
from .._utils._service_base import (
|
|
21
|
+
ServiceCommandBase,
|
|
22
|
+
common_service_options,
|
|
23
|
+
handle_not_found_error,
|
|
24
|
+
service_command,
|
|
25
|
+
)
|
|
26
|
+
from .._utils._service_cli_generator import ServiceCLIGenerator
|
|
27
|
+
from ._buckets_metadata import BUCKETS_METADATA
|
|
28
|
+
|
|
29
|
+
_cli = click.Group()
|
|
30
|
+
generator = ServiceCLIGenerator(BUCKETS_METADATA)
|
|
31
|
+
buckets = generator.register(_cli)
|
|
32
|
+
buckets.help = """Manage UiPath storage buckets and files.
|
|
33
|
+
|
|
34
|
+
Buckets are cloud storage containers for files used by automation processes.
|
|
35
|
+
|
|
36
|
+
\b
|
|
37
|
+
Bucket Operations:
|
|
38
|
+
list - List all buckets
|
|
39
|
+
create - Create a new bucket
|
|
40
|
+
delete - Delete a bucket
|
|
41
|
+
retrieve - Get bucket details
|
|
42
|
+
exists - Check if bucket exists
|
|
43
|
+
|
|
44
|
+
\b
|
|
45
|
+
File Operations (use 'buckets files' subcommand):
|
|
46
|
+
files list - List files in a bucket
|
|
47
|
+
files search - Search files using glob patterns
|
|
48
|
+
files upload - Upload a file to a bucket
|
|
49
|
+
files download - Download a file from a bucket
|
|
50
|
+
files delete - Delete a file from a bucket
|
|
51
|
+
files exists - Check if a file exists
|
|
52
|
+
|
|
53
|
+
\b
|
|
54
|
+
Examples:
|
|
55
|
+
\b
|
|
56
|
+
# Bucket operations with explicit folder
|
|
57
|
+
uipath buckets list --folder-path "Shared"
|
|
58
|
+
uipath buckets create my-bucket --description "Data storage"
|
|
59
|
+
uipath buckets exists my-bucket
|
|
60
|
+
uipath buckets delete my-bucket --confirm
|
|
61
|
+
\b
|
|
62
|
+
# Using environment variable for folder context
|
|
63
|
+
export UIPATH_FOLDER_PATH="Shared"
|
|
64
|
+
uipath buckets list
|
|
65
|
+
uipath buckets create my-bucket --description "Data storage"
|
|
66
|
+
\b
|
|
67
|
+
# File operations
|
|
68
|
+
uipath buckets files list my-bucket
|
|
69
|
+
uipath buckets files search my-bucket "*.pdf"
|
|
70
|
+
uipath buckets files upload my-bucket ./data.csv remote/data.csv
|
|
71
|
+
uipath buckets files download my-bucket data.csv ./local.csv
|
|
72
|
+
uipath buckets files delete my-bucket old-data.csv --confirm
|
|
73
|
+
uipath buckets files exists my-bucket data.csv
|
|
74
|
+
"""
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
@click.command()
|
|
78
|
+
@click.option("--name", help="Bucket name")
|
|
79
|
+
@click.option("--key", help="Bucket key (UUID)")
|
|
80
|
+
@common_service_options
|
|
81
|
+
@service_command
|
|
82
|
+
def retrieve(ctx, name, key, folder_path, folder_key, format, output):
|
|
83
|
+
"""Retrieve a bucket by name or key.
|
|
84
|
+
|
|
85
|
+
\b
|
|
86
|
+
Examples:
|
|
87
|
+
uipath buckets retrieve --name "my-bucket"
|
|
88
|
+
uipath buckets retrieve --key "abc-123-def-456" --format json
|
|
89
|
+
"""
|
|
90
|
+
from httpx import HTTPStatusError
|
|
91
|
+
|
|
92
|
+
if not name and not key:
|
|
93
|
+
raise click.UsageError("Either --name or --key must be provided")
|
|
94
|
+
|
|
95
|
+
if name and key:
|
|
96
|
+
raise click.UsageError("Provide either --name or --key, not both")
|
|
97
|
+
|
|
98
|
+
client = ServiceCommandBase.get_client(ctx)
|
|
99
|
+
|
|
100
|
+
try:
|
|
101
|
+
bucket = client.buckets.retrieve(
|
|
102
|
+
name=name,
|
|
103
|
+
key=key,
|
|
104
|
+
folder_path=folder_path,
|
|
105
|
+
folder_key=folder_key,
|
|
106
|
+
)
|
|
107
|
+
except LookupError:
|
|
108
|
+
handle_not_found_error("Bucket", name or key)
|
|
109
|
+
except HTTPStatusError as e:
|
|
110
|
+
if e.response.status_code == 404:
|
|
111
|
+
handle_not_found_error("Bucket", name or key, e)
|
|
112
|
+
raise
|
|
113
|
+
|
|
114
|
+
return bucket
|
|
115
|
+
|
|
116
|
+
|
|
117
|
+
generator.override_command(buckets, "retrieve", retrieve)
|
|
118
|
+
|
|
119
|
+
|
|
120
|
+
@click.command()
|
|
121
|
+
@click.argument("name")
|
|
122
|
+
@click.option("--confirm", is_flag=True, help="Skip confirmation prompt")
|
|
123
|
+
@click.option(
|
|
124
|
+
"--dry-run", is_flag=True, help="Show what would be deleted without deleting"
|
|
125
|
+
)
|
|
126
|
+
@common_service_options
|
|
127
|
+
@service_command
|
|
128
|
+
def delete(ctx, name, confirm, dry_run, folder_path, folder_key, format, output):
|
|
129
|
+
"""Delete a bucket.
|
|
130
|
+
|
|
131
|
+
\b
|
|
132
|
+
Examples:
|
|
133
|
+
uipath buckets delete my-bucket --confirm
|
|
134
|
+
uipath buckets delete my-bucket --dry-run
|
|
135
|
+
"""
|
|
136
|
+
from httpx import HTTPStatusError
|
|
137
|
+
|
|
138
|
+
client = ServiceCommandBase.get_client(ctx)
|
|
139
|
+
|
|
140
|
+
# First retrieve to verify bucket exists
|
|
141
|
+
try:
|
|
142
|
+
client.buckets.retrieve(
|
|
143
|
+
name=name,
|
|
144
|
+
folder_path=folder_path,
|
|
145
|
+
folder_key=folder_key,
|
|
146
|
+
)
|
|
147
|
+
except LookupError:
|
|
148
|
+
handle_not_found_error("Bucket", name)
|
|
149
|
+
except HTTPStatusError as e:
|
|
150
|
+
if e.response.status_code == 404:
|
|
151
|
+
handle_not_found_error("Bucket", name, e)
|
|
152
|
+
raise
|
|
153
|
+
|
|
154
|
+
# Handle dry-run
|
|
155
|
+
if dry_run:
|
|
156
|
+
click.echo(f"Would delete bucket '{name}'", err=True)
|
|
157
|
+
return
|
|
158
|
+
|
|
159
|
+
# Handle confirmation
|
|
160
|
+
if not confirm:
|
|
161
|
+
if not click.confirm(f"Delete bucket '{name}'?"):
|
|
162
|
+
click.echo("Deletion cancelled.")
|
|
163
|
+
return
|
|
164
|
+
|
|
165
|
+
# Perform delete
|
|
166
|
+
client.buckets.delete(
|
|
167
|
+
name=name,
|
|
168
|
+
folder_path=folder_path,
|
|
169
|
+
folder_key=folder_key,
|
|
170
|
+
)
|
|
171
|
+
|
|
172
|
+
click.echo(f"Deleted bucket '{name}'", err=True)
|
|
173
|
+
|
|
174
|
+
|
|
175
|
+
generator.override_command(buckets, "delete", delete)
|
|
176
|
+
|
|
177
|
+
|
|
178
|
+
@click.group()
|
|
179
|
+
def files():
|
|
180
|
+
"""Manage files within buckets.
|
|
181
|
+
|
|
182
|
+
\b
|
|
183
|
+
Examples:
|
|
184
|
+
\b
|
|
185
|
+
# List files in a bucket
|
|
186
|
+
uipath buckets files list my-bucket
|
|
187
|
+
\b
|
|
188
|
+
# Search for files with glob pattern
|
|
189
|
+
uipath buckets files search my-bucket "*.pdf"
|
|
190
|
+
\b
|
|
191
|
+
# Upload a file
|
|
192
|
+
uipath buckets files upload my-bucket ./data.csv remote/data.csv
|
|
193
|
+
\b
|
|
194
|
+
# Download a file
|
|
195
|
+
uipath buckets files download my-bucket data.csv ./local.csv
|
|
196
|
+
\b
|
|
197
|
+
# Delete a file
|
|
198
|
+
uipath buckets files delete my-bucket old-data.csv --confirm
|
|
199
|
+
\b
|
|
200
|
+
# Check if file exists
|
|
201
|
+
uipath buckets files exists my-bucket data.csv
|
|
202
|
+
"""
|
|
203
|
+
pass
|
|
204
|
+
|
|
205
|
+
|
|
206
|
+
@files.command(name="list")
|
|
207
|
+
@click.argument("bucket_name")
|
|
208
|
+
@click.option("--prefix", default="", help="Filter files by prefix")
|
|
209
|
+
@click.option(
|
|
210
|
+
"--limit",
|
|
211
|
+
type=click.IntRange(min=0),
|
|
212
|
+
help="Maximum number of files to return",
|
|
213
|
+
)
|
|
214
|
+
@click.option(
|
|
215
|
+
"--offset",
|
|
216
|
+
type=click.IntRange(min=0),
|
|
217
|
+
default=0,
|
|
218
|
+
help="Number of files to skip",
|
|
219
|
+
)
|
|
220
|
+
@click.option(
|
|
221
|
+
"--all", "fetch_all", is_flag=True, help="Fetch all files (auto-paginate)"
|
|
222
|
+
)
|
|
223
|
+
@common_service_options
|
|
224
|
+
@service_command
|
|
225
|
+
def list_files(
|
|
226
|
+
ctx,
|
|
227
|
+
bucket_name,
|
|
228
|
+
prefix,
|
|
229
|
+
limit,
|
|
230
|
+
offset,
|
|
231
|
+
fetch_all,
|
|
232
|
+
folder_path,
|
|
233
|
+
folder_key,
|
|
234
|
+
format,
|
|
235
|
+
output,
|
|
236
|
+
):
|
|
237
|
+
"""List files in a bucket.
|
|
238
|
+
|
|
239
|
+
\b
|
|
240
|
+
Arguments:
|
|
241
|
+
BUCKET_NAME: Name of the bucket
|
|
242
|
+
|
|
243
|
+
\b
|
|
244
|
+
Examples:
|
|
245
|
+
uipath buckets files list my-bucket
|
|
246
|
+
uipath buckets files list my-bucket --prefix "data/"
|
|
247
|
+
uipath buckets files list reports --limit 10 --format json
|
|
248
|
+
uipath buckets files list my-bucket --all
|
|
249
|
+
"""
|
|
250
|
+
from httpx import HTTPStatusError
|
|
251
|
+
|
|
252
|
+
client = ServiceCommandBase.get_client(ctx)
|
|
253
|
+
|
|
254
|
+
try:
|
|
255
|
+
files_iterator = client.buckets.list_files(
|
|
256
|
+
name=bucket_name,
|
|
257
|
+
prefix=prefix,
|
|
258
|
+
folder_path=folder_path,
|
|
259
|
+
folder_key=folder_key,
|
|
260
|
+
)
|
|
261
|
+
|
|
262
|
+
if not fetch_all and limit == 0:
|
|
263
|
+
return []
|
|
264
|
+
|
|
265
|
+
start = offset
|
|
266
|
+
stop = None if fetch_all or limit is None else start + limit
|
|
267
|
+
return list(islice(files_iterator, start, stop))
|
|
268
|
+
except LookupError:
|
|
269
|
+
handle_not_found_error("Bucket", bucket_name)
|
|
270
|
+
except HTTPStatusError as e:
|
|
271
|
+
if e.response.status_code == 404:
|
|
272
|
+
handle_not_found_error("Bucket", bucket_name, e)
|
|
273
|
+
raise
|
|
274
|
+
|
|
275
|
+
|
|
276
|
+
@files.command(name="search")
|
|
277
|
+
@click.argument("bucket_name")
|
|
278
|
+
@click.argument("pattern")
|
|
279
|
+
@click.option("--prefix", default="", help="Directory path to search in")
|
|
280
|
+
@click.option(
|
|
281
|
+
"--recursive/--no-recursive",
|
|
282
|
+
default=False,
|
|
283
|
+
help="Search subdirectories recursively",
|
|
284
|
+
)
|
|
285
|
+
@click.option(
|
|
286
|
+
"--limit",
|
|
287
|
+
type=click.IntRange(min=0),
|
|
288
|
+
help="Maximum number of files to return",
|
|
289
|
+
)
|
|
290
|
+
@common_service_options
|
|
291
|
+
@service_command
|
|
292
|
+
def search_files(
|
|
293
|
+
ctx,
|
|
294
|
+
bucket_name,
|
|
295
|
+
pattern,
|
|
296
|
+
prefix,
|
|
297
|
+
recursive,
|
|
298
|
+
limit,
|
|
299
|
+
folder_path,
|
|
300
|
+
folder_key,
|
|
301
|
+
format,
|
|
302
|
+
output,
|
|
303
|
+
):
|
|
304
|
+
"""Search for files using glob patterns.
|
|
305
|
+
|
|
306
|
+
Uses the GetFiles API which supports glob patterns like *.pdf or data_*.csv.
|
|
307
|
+
|
|
308
|
+
\b
|
|
309
|
+
Arguments:
|
|
310
|
+
BUCKET_NAME: Name of the bucket
|
|
311
|
+
PATTERN: Glob pattern to match files (e.g., "*.pdf", "data_*.csv")
|
|
312
|
+
|
|
313
|
+
\b
|
|
314
|
+
Examples:
|
|
315
|
+
uipath buckets files search my-bucket "*.pdf"
|
|
316
|
+
uipath buckets files search reports "*.csv" --recursive
|
|
317
|
+
uipath buckets files search my-bucket "data_*.json" --prefix "archive/"
|
|
318
|
+
"""
|
|
319
|
+
from httpx import HTTPStatusError
|
|
320
|
+
|
|
321
|
+
client = ServiceCommandBase.get_client(ctx)
|
|
322
|
+
|
|
323
|
+
try:
|
|
324
|
+
files_iterator = client.buckets.get_files(
|
|
325
|
+
name=bucket_name,
|
|
326
|
+
prefix=prefix,
|
|
327
|
+
recursive=recursive,
|
|
328
|
+
file_name_glob=pattern,
|
|
329
|
+
folder_path=folder_path,
|
|
330
|
+
folder_key=folder_key,
|
|
331
|
+
)
|
|
332
|
+
|
|
333
|
+
files = (
|
|
334
|
+
list(files_iterator)
|
|
335
|
+
if limit is None
|
|
336
|
+
else list(islice(files_iterator, limit))
|
|
337
|
+
)
|
|
338
|
+
return files
|
|
339
|
+
except LookupError:
|
|
340
|
+
handle_not_found_error("Bucket", bucket_name)
|
|
341
|
+
except HTTPStatusError as e:
|
|
342
|
+
if e.response.status_code == 404:
|
|
343
|
+
handle_not_found_error("Bucket", bucket_name, e)
|
|
344
|
+
raise
|
|
345
|
+
|
|
346
|
+
|
|
347
|
+
@files.command(name="upload")
|
|
348
|
+
@click.argument("bucket_name")
|
|
349
|
+
@click.argument("local_path", type=click.Path(exists=True))
|
|
350
|
+
@click.argument("remote_path")
|
|
351
|
+
@common_service_options
|
|
352
|
+
@service_command
|
|
353
|
+
def upload_file(
|
|
354
|
+
ctx, bucket_name, local_path, remote_path, folder_path, folder_key, format, output
|
|
355
|
+
):
|
|
356
|
+
"""Upload a file to a bucket.
|
|
357
|
+
|
|
358
|
+
\b
|
|
359
|
+
Arguments:
|
|
360
|
+
BUCKET_NAME: Name of the bucket
|
|
361
|
+
LOCAL_PATH: Local file to upload
|
|
362
|
+
REMOTE_PATH: Destination path in bucket
|
|
363
|
+
|
|
364
|
+
\b
|
|
365
|
+
Examples:
|
|
366
|
+
uipath buckets files upload my-bucket ./data.csv remote/data.csv
|
|
367
|
+
uipath buckets files upload reports ./report.pdf monthly/report.pdf
|
|
368
|
+
"""
|
|
369
|
+
client = ServiceCommandBase.get_client(ctx)
|
|
370
|
+
|
|
371
|
+
click.echo(f"Uploading {local_path}...", err=True)
|
|
372
|
+
client.buckets.upload(
|
|
373
|
+
name=bucket_name,
|
|
374
|
+
source_path=local_path,
|
|
375
|
+
blob_file_path=remote_path,
|
|
376
|
+
folder_path=folder_path,
|
|
377
|
+
folder_key=folder_key,
|
|
378
|
+
)
|
|
379
|
+
|
|
380
|
+
click.echo(f"Uploaded to {remote_path}", err=True)
|
|
381
|
+
|
|
382
|
+
|
|
383
|
+
@files.command(name="download")
|
|
384
|
+
@click.argument("bucket_name")
|
|
385
|
+
@click.argument("remote_path")
|
|
386
|
+
@click.argument("local_path", type=click.Path())
|
|
387
|
+
@common_service_options
|
|
388
|
+
@service_command
|
|
389
|
+
def download_file(
|
|
390
|
+
ctx, bucket_name, remote_path, local_path, folder_path, folder_key, format, output
|
|
391
|
+
):
|
|
392
|
+
"""Download a file from a bucket.
|
|
393
|
+
|
|
394
|
+
\b
|
|
395
|
+
Arguments:
|
|
396
|
+
BUCKET_NAME: Name of the bucket
|
|
397
|
+
REMOTE_PATH: Path to file in bucket
|
|
398
|
+
LOCAL_PATH: Local destination path
|
|
399
|
+
|
|
400
|
+
\b
|
|
401
|
+
Examples:
|
|
402
|
+
uipath buckets files download my-bucket data.csv ./downloads/data.csv
|
|
403
|
+
uipath buckets files download reports monthly/report.pdf ./report.pdf
|
|
404
|
+
"""
|
|
405
|
+
client = ServiceCommandBase.get_client(ctx)
|
|
406
|
+
|
|
407
|
+
click.echo(f"Downloading {remote_path}...", err=True)
|
|
408
|
+
client.buckets.download(
|
|
409
|
+
name=bucket_name,
|
|
410
|
+
blob_file_path=remote_path,
|
|
411
|
+
destination_path=local_path,
|
|
412
|
+
folder_path=folder_path,
|
|
413
|
+
folder_key=folder_key,
|
|
414
|
+
)
|
|
415
|
+
|
|
416
|
+
click.echo(f"Downloaded to {local_path}", err=True)
|
|
417
|
+
|
|
418
|
+
|
|
419
|
+
@files.command(name="delete")
|
|
420
|
+
@click.argument("bucket_name")
|
|
421
|
+
@click.argument("file_path")
|
|
422
|
+
@click.option("--confirm", is_flag=True, help="Skip confirmation prompt")
|
|
423
|
+
@click.option("--dry-run", is_flag=True, help="Show what would be deleted")
|
|
424
|
+
@common_service_options
|
|
425
|
+
@service_command
|
|
426
|
+
def delete_file(
|
|
427
|
+
ctx,
|
|
428
|
+
bucket_name,
|
|
429
|
+
file_path,
|
|
430
|
+
confirm,
|
|
431
|
+
dry_run,
|
|
432
|
+
folder_path,
|
|
433
|
+
folder_key,
|
|
434
|
+
format,
|
|
435
|
+
output,
|
|
436
|
+
):
|
|
437
|
+
"""Delete a file from a bucket.
|
|
438
|
+
|
|
439
|
+
\b
|
|
440
|
+
Arguments:
|
|
441
|
+
BUCKET_NAME: Name of the bucket
|
|
442
|
+
FILE_PATH: Path to file in bucket
|
|
443
|
+
|
|
444
|
+
\b
|
|
445
|
+
Examples:
|
|
446
|
+
uipath buckets files delete my-bucket old-data.csv --confirm
|
|
447
|
+
uipath buckets files delete reports archive/old.pdf --dry-run
|
|
448
|
+
"""
|
|
449
|
+
from httpx import HTTPStatusError
|
|
450
|
+
|
|
451
|
+
client = ServiceCommandBase.get_client(ctx)
|
|
452
|
+
|
|
453
|
+
if dry_run:
|
|
454
|
+
click.echo(
|
|
455
|
+
f"Would delete file: {file_path} from bucket {bucket_name}", err=True
|
|
456
|
+
)
|
|
457
|
+
return
|
|
458
|
+
|
|
459
|
+
if not confirm:
|
|
460
|
+
if not click.confirm(f"Delete file '{file_path}' from bucket '{bucket_name}'?"):
|
|
461
|
+
click.echo("Aborted", err=True)
|
|
462
|
+
return
|
|
463
|
+
|
|
464
|
+
try:
|
|
465
|
+
client.buckets.delete_file(
|
|
466
|
+
name=bucket_name,
|
|
467
|
+
blob_file_path=file_path,
|
|
468
|
+
folder_path=folder_path,
|
|
469
|
+
folder_key=folder_key,
|
|
470
|
+
)
|
|
471
|
+
click.echo(f"Deleted file '{file_path}' from bucket '{bucket_name}'", err=True)
|
|
472
|
+
except LookupError:
|
|
473
|
+
handle_not_found_error("Bucket", bucket_name)
|
|
474
|
+
except HTTPStatusError as e:
|
|
475
|
+
if e.response.status_code == 404:
|
|
476
|
+
handle_not_found_error("File or Bucket", f"{bucket_name}/{file_path}", e)
|
|
477
|
+
raise
|
|
478
|
+
|
|
479
|
+
|
|
480
|
+
@files.command(name="exists")
|
|
481
|
+
@click.argument("bucket_name")
|
|
482
|
+
@click.argument("file_path")
|
|
483
|
+
@common_service_options
|
|
484
|
+
@service_command
|
|
485
|
+
def file_exists(ctx, bucket_name, file_path, folder_path, folder_key, format, output):
|
|
486
|
+
"""Check if a file exists in a bucket.
|
|
487
|
+
|
|
488
|
+
\b
|
|
489
|
+
Arguments:
|
|
490
|
+
BUCKET_NAME: Name of the bucket
|
|
491
|
+
FILE_PATH: Path to file in bucket
|
|
492
|
+
|
|
493
|
+
\b
|
|
494
|
+
Examples:
|
|
495
|
+
uipath buckets files exists my-bucket data.csv
|
|
496
|
+
uipath buckets files exists reports monthly/report.pdf
|
|
497
|
+
"""
|
|
498
|
+
from httpx import HTTPStatusError
|
|
499
|
+
|
|
500
|
+
client = ServiceCommandBase.get_client(ctx)
|
|
501
|
+
|
|
502
|
+
try:
|
|
503
|
+
file_exists_result = client.buckets.exists_file(
|
|
504
|
+
name=bucket_name,
|
|
505
|
+
blob_file_path=file_path,
|
|
506
|
+
folder_path=folder_path,
|
|
507
|
+
folder_key=folder_key,
|
|
508
|
+
)
|
|
509
|
+
|
|
510
|
+
if file_exists_result:
|
|
511
|
+
click.echo(f"File '{file_path}' exists in bucket '{bucket_name}'", err=True)
|
|
512
|
+
return {"exists": True, "bucket": bucket_name, "file": file_path}
|
|
513
|
+
else:
|
|
514
|
+
click.echo(
|
|
515
|
+
f"File '{file_path}' does not exist in bucket '{bucket_name}'", err=True
|
|
516
|
+
)
|
|
517
|
+
return {"exists": False, "bucket": bucket_name, "file": file_path}
|
|
518
|
+
except LookupError:
|
|
519
|
+
handle_not_found_error("Bucket", bucket_name)
|
|
520
|
+
except HTTPStatusError as e:
|
|
521
|
+
if e.response.status_code == 404:
|
|
522
|
+
handle_not_found_error("Bucket", bucket_name, e)
|
|
523
|
+
raise
|
|
524
|
+
|
|
525
|
+
|
|
526
|
+
generator.add_nested_group(buckets, "files", files)
|