Skip to content

Commit 9a2aa7f

Browse files
committed
adding get_url operator
1 parent 86786bf commit 9a2aa7f

3 files changed

Lines changed: 113 additions & 0 deletions

File tree

plugins/io/README.md

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -158,3 +158,25 @@ dataset_or_view.draw_labels(
158158
where the operator's form allows you to configure the output directory on disk,
159159
the label field(s) to render, and any other optional arguments for
160160
`draw_labels()`.
161+
162+
### get_url (Enterprise-only)
163+
164+
[FiftyOne Enterprise](https://docs.voxel51.com/enterprise/index.html) users can
165+
use this operator to retrieve signed URLs to read/write/delete assets in cloud
166+
storage.
167+
168+
This operator is essentially a wrapper around the
169+
`fiftyone.core.storage.get_url()` method:
170+
171+
```py
172+
import fiftyone.core.storage as fos
173+
174+
path = "s3://..."
175+
method = "GET" # GET|PUT|DELETE
176+
hours = 24
177+
178+
url = fos.get_url(path, method=method, hours=hours)
179+
```
180+
181+
where the operator's form allows you to select the path, HTTP verb, and desired
182+
expiration time of the URL.

plugins/io/__init__.py

Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2795,6 +2795,94 @@ def _draw_labels_inputs(ctx, inputs):
27952795
return True
27962796

27972797

2798+
class GetURL(foo.Operator):
2799+
@property
2800+
def config(self):
2801+
return foo.OperatorConfig(
2802+
name="get_url",
2803+
label="Get URL",
2804+
light_icon="/assets/icon-light.svg",
2805+
dark_icon="/assets/icon-dark.svg",
2806+
allow_delegated_execution=False,
2807+
allow_immediate_execution=True,
2808+
default_choice_to_delegated=False,
2809+
dynamic=True,
2810+
)
2811+
2812+
def resolve_input(self, ctx):
2813+
inputs = types.Object()
2814+
2815+
_get_url_inputs(ctx, inputs)
2816+
2817+
return types.Property(inputs, view=types.View(label="Get URL"))
2818+
2819+
def execute(self, ctx):
2820+
filepath = _parse_path(ctx, "filepath")
2821+
hours = ctx.params.get("hours", 24)
2822+
method = ctx.params.get("method", "GET")
2823+
2824+
# pylint: disable=no-member
2825+
url = fos.get_url(filepath, hours=hours, method=method)
2826+
2827+
return {"url": url}
2828+
2829+
def resolve_output(self, ctx):
2830+
outputs = types.Object()
2831+
2832+
# @todo if method=GET, render a download button
2833+
outputs.str("url", label="URL", view=types.MarkdownView())
2834+
2835+
return types.Property(
2836+
outputs, view=types.View(label="Get URL samples")
2837+
)
2838+
2839+
2840+
def _get_url_inputs(ctx, inputs):
2841+
file_explorer = types.FileExplorerView(button_label="Choose a file...")
2842+
prop = inputs.file(
2843+
"filepath",
2844+
required=True,
2845+
label="File",
2846+
description="Choose a file for which to generate a signed URL",
2847+
view=file_explorer,
2848+
)
2849+
filepath = _parse_path(ctx, "filepath")
2850+
2851+
inputs.int(
2852+
"hours",
2853+
default=24,
2854+
label="Hours",
2855+
description="The number of hours that the URL should be valid",
2856+
)
2857+
hours = ctx.params.get("hours", 24)
2858+
2859+
method_choices = types.Choices()
2860+
method_choices.add_choice("GET", label="GET")
2861+
method_choices.add_choice("PUT", label="PUT")
2862+
method_choices.add_choice("DELETE", label="DELETE")
2863+
2864+
inputs.enum(
2865+
"method",
2866+
method_choices.values(),
2867+
required=True,
2868+
default="GET",
2869+
label="Method",
2870+
description="The HTTP verb (GET, PUT, DELETE) to authorize",
2871+
view=method_choices,
2872+
)
2873+
method = ctx.params.get("method", "GET")
2874+
2875+
try:
2876+
# pylint: disable=no-member
2877+
url = fos.get_url(filepath, hours=hours, method=method)
2878+
view = types.Notice(label=f"[{url}]({url})")
2879+
except Exception as e:
2880+
view = types.Error(label=str(e))
2881+
2882+
prop = inputs.view("result", view)
2883+
prop.invalid = True
2884+
2885+
27982886
def _parse_path(ctx, key):
27992887
value = ctx.params.get(key, None)
28002888
return value.get("absolute_path", None) if value else None
@@ -2833,3 +2921,5 @@ def register(p):
28332921
p.register(MergeLabels)
28342922
p.register(ExportSamples)
28352923
p.register(DrawLabels)
2924+
if hasattr(foc, "TEAMS_VERSION"):
2925+
p.register(GetURL)

plugins/io/fiftyone.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,3 +11,4 @@ operators:
1111
- merge_labels
1212
- export_samples
1313
- draw_labels
14+
- get_url

0 commit comments

Comments
 (0)