Repository: voxel51/fiftyone

Issue:
[BUG] Python <3.9 issues with saved views (dacite and strawberry)
Saved views are not functional in the GraphQL Schema (and App) due to an inconsistency with `dacite` and `strawberry` private fields.

When saving a view in a Python 3.8 environment, the following occurs:

```
wrong value type for field "_id" - should be "typing_extensions.Annotated[typing.Union[bson.objectid.ObjectId, NoneType], <strawberry.private.StrawberryPrivate object at 0x7f04aa7268b0>]" instead of value "63fe44c169001c8bae74bda7" of type "ObjectId"

  File "/home/user/system/miniconda3/envs/efi-ml/lib/python3.8/site-packages/graphql/execution/execute.py", line 528, in await_result
    return_type, field_nodes, info, path, await result

  File "/home/user/system/miniconda3/envs/efi-ml/lib/python3.8/site-packages/strawberry/schema/schema_converter.py", line 513, in _async_resolver
    return await await_maybe(_get_result(_source, strawberry_info, **kwargs))

  File "/home/user/system/miniconda3/envs/efi-ml/lib/python3.8/site-packages/strawberry/utils/await_maybe.py", line 12, in await_maybe
    return await value

  File "/home/user/system/miniconda3/envs/efi-ml/lib/python3.8/site-packages/fiftyone/server/mutation.py", line 303, in create_saved_view
    return next(

  File "/home/user/system/miniconda3/envs/efi-ml/lib/python3.8/site-packages/fiftyone/server/mutation.py", line 305, in <genexpr>
    SavedView.from_doc(view_doc)

  File "/home/user/system/miniconda3/envs/efi-ml/lib/python3.8/site-packages/fiftyone/server/query.py", line 149, in from_doc
    saved_view = from_dict(data_class=cls, data=doc.to_dict())

  File "/home/user/system/miniconda3/envs/efi-ml/lib/python3.8/site-packages/dacite/core.py", line 74, in from_dict
    raise WrongTypeError(field_path=field.name, field_type=field.type, value=value)
```


Discussion:

Resolving patch:
diff --git a/fiftyone/server/query.py b/fiftyone/server/query.py
--- a/fiftyone/server/query.py
+++ b/fiftyone/server/query.py
@@ -110,8 +110,8 @@ class EvaluationRun(Run):
 
 @gql.type
 class SavedView:
-    _id: gql.Private[t.Optional[ObjectId]]
-    _dataset_id: gql.Private[t.Optional[ObjectId]]
+    id: t.Optional[str]
+    dataset_id: t.Optional[str]
     name: t.Optional[str]
     description: t.Optional[str]
     color: t.Optional[str]
@@ -121,18 +121,6 @@ class SavedView:
     last_modified_at: t.Optional[datetime]
     last_loaded_at: t.Optional[datetime]
 
-    @gql.field
-    def id(self) -> t.Optional[str]:
-        if isinstance(self, ObjectId):
-            return str(self)
-        return str(self._id)
-
-    @gql.field
-    def dataset_id(self) -> t.Optional[str]:
-        if isinstance(self, ObjectId):
-            return None
-        return str(self._dataset_id)
-
     @gql.field
     def view_name(self) -> t.Optional[str]:
         if isinstance(self, ObjectId):
@@ -146,7 +134,10 @@ def stage_dicts(self) -> t.Optional[BSONArray]:
     @classmethod
     def from_doc(cls, doc: SavedViewDocument):
         stage_dicts = [json_util.loads(x) for x in doc.view_stages]
-        saved_view = from_dict(data_class=cls, data=doc.to_dict())
+        data = doc.to_dict()
+        data["id"] = str(data.pop("_id"))
+        data["dataset_id"] = str(data.pop("_dataset_id"))
+        saved_view = from_dict(data_class=cls, data=data)
         saved_view.stage_dicts = stage_dicts
         return saved_view
 


Test patch: