diff --git a/fiftyone/core/cli.py b/fiftyone/core/cli.py index 85912a875c1..5a7aa889bcc 100644 --- a/fiftyone/core/cli.py +++ b/fiftyone/core/cli.py @@ -7,7 +7,6 @@ """ import argparse -import warnings from collections import defaultdict from datetime import datetime import json @@ -19,8 +18,6 @@ import argcomplete from bson import ObjectId -import humanize -import pytz from tabulate import tabulate import webbrowser diff --git a/fiftyone/factory/repos/delegated_operation.py b/fiftyone/factory/repos/delegated_operation.py index 3355792c97a..ac2a9c20c18 100644 --- a/fiftyone/factory/repos/delegated_operation.py +++ b/fiftyone/factory/repos/delegated_operation.py @@ -15,6 +15,7 @@ from pymongo import IndexModel from pymongo.collection import Collection +from fiftyone.internal.util import is_remote_service from fiftyone.factory import DelegatedOperationPagingParams from fiftyone.factory.repos import DelegatedOperationDocument from fiftyone.operators.executor import ( @@ -134,7 +135,7 @@ def __init__(self, collection: Collection = None): self._collection = ( collection if collection is not None else self._get_collection() ) - + self.is_remote = is_remote_service() self._create_indexes() def _get_collection(self) -> Collection: @@ -170,7 +171,7 @@ def _create_indexes(self): self._collection.create_indexes(indices_to_create) def queue_operation(self, **kwargs: Any) -> DelegatedOperationDocument: - op = DelegatedOperationDocument() + op = DelegatedOperationDocument(is_remote=self.is_remote) for prop in self.required_props: if prop not in kwargs: raise ValueError("Missing required property '%s'" % prop) diff --git a/fiftyone/factory/repos/delegated_operation_doc.py b/fiftyone/factory/repos/delegated_operation_doc.py index 150b8a05dec..1360783ad3b 100644 --- a/fiftyone/factory/repos/delegated_operation_doc.py +++ b/fiftyone/factory/repos/delegated_operation_doc.py @@ -25,6 +25,7 @@ def __init__( operator: str = None, delegation_target: str = None, context: dict = None, + is_remote: bool = False, ): self.operator = operator self.label = None @@ -35,10 +36,12 @@ def __init__( else context ) self.run_state = ( - ExecutionRunState.QUEUED - ) # default to queued state on create + ExecutionRunState.SCHEDULED + if is_remote + else ExecutionRunState.QUEUED + ) # if running locally use QUEUED otherwise SCHEDULED self.run_link = None - self.queued_at = datetime.utcnow() + self.queued_at = datetime.utcnow() if not is_remote else None self.updated_at = datetime.utcnow() self.status = None self.dataset_id = None @@ -46,7 +49,7 @@ def __init__( self.pinned = False self.completed_at = None self.failed_at = None - self.scheduled_at = None + self.scheduled_at = datetime.utcnow() if is_remote else None self.result = None self.id = None self._doc = None diff --git a/fiftyone/internal/__init__.py b/fiftyone/internal/__init__.py index 948c11f1b2b..8d5a4915b3b 100644 --- a/fiftyone/internal/__init__.py +++ b/fiftyone/internal/__init__.py @@ -7,3 +7,4 @@ """ from .secrets import * +from .util import is_remote_service diff --git a/fiftyone/internal/util.py b/fiftyone/internal/util.py new file mode 100644 index 00000000000..bfde1b3db66 --- /dev/null +++ b/fiftyone/internal/util.py @@ -0,0 +1,34 @@ +""" +FiftyOne internal utilities. + +| Copyright 2017-2024, Voxel51, Inc. +| `voxel51.com `_ +| +""" + + +def is_remote_service(): + """Whether the SDK is running in a remote service context. + + Returns: + True/False + """ + return has_encryption_key() and has_api_key() + + +def has_encryption_key(): + """Whether the current environment has an encryption key. + + Returns: + True/False + """ + return False + + +def has_api_key(): + """Whether the current environment has an API key. + + Returns: + True/False + """ + return False diff --git a/tests/unittests/operators/delegated_tests.py b/tests/unittests/operators/delegated_tests.py index ef48c78ee96..4939124942a 100644 --- a/tests/unittests/operators/delegated_tests.py +++ b/tests/unittests/operators/delegated_tests.py @@ -28,6 +28,7 @@ ExecutionResult, ExecutionRunState, ) +from fiftyone.factory.repos import delegated_operation from fiftyone.operators.operator import Operator, OperatorConfig @@ -1333,3 +1334,25 @@ async def test_set_completed_in_async_context( doc = self.svc.set_completed(doc_id=doc.id) self.assertEqual(doc.run_state, ExecutionRunState.COMPLETED) + + @patch.object( + delegated_operation, + "is_remote_service", + return_value=True, + ) + def test_queue_op_remote_service( + self, mock_is_remote_service, mock_get_operator, mock_operator_exists + ): + db = delegated_operation.MongoDelegatedOperationRepo() + dos = DelegatedOperationService(repo=db) + ctx = ExecutionContext() + ctx.request_params = {"foo": "bar"} + doc = dos.queue_operation( + operator="@voxelfiftyone/operator/foo", + label=mock_get_operator.return_value.name, + delegation_target="test_target", + context=ctx.serialize(), + ) + self.docs_to_delete.append(doc) + self.assertTrue(db.is_remote) + self.assertEqual(doc.run_state, ExecutionRunState.SCHEDULED)