code: def test_example_restricting_label_edits(self):
      dataset = foz.load_zoo_dataset("quickstart").clone()
  
      # Grab a sample that contains at least 2 people
      view = dataset.match(
          F("ground_truth.detections")
          .filter(F("label") == "person")
          .length()
          > 1
      ).limit(1)
  
      previous_labels = view.values(
          "ground_truth.detections", unwind=True
      )
      previous_person_labels = view.filter_labels(
          "ground_truth", F("label") == "person"
      ).values("ground_truth.detections", unwind=True)
  
      anno_key = "cvat_edit_restrictions"
  
      # The new attributes that we want to populate
      attributes = {
          "sex": {
              "type": "select",
              "values": ["male", "female"],
          },
          "age": {
              "type": "text",
              "values": [],
          },
      }
  
      results = view.annotate(
          anno_key,
          label_field="ground_truth",
          classes=["person", "test"],
          attributes=attributes,
          allow_additions=False,
          allow_deletions=False,
          allow_label_edits=False,
          allow_spatial_edits=False,
      )
      self.assertIsNotNone(dataset.get_annotation_info(anno_key))
  
      task_id = results.task_ids[0]
      with results:
          api = results.connect_to_api()
  
          # Delete label
          deleted_id = previous_person_labels[0].id
          _delete_shape(api, task_id, deleted_id)
  
          # Add label
          _create_annotation(api, task_id, shape="person")
  
          # Edit label and bounding box
          edited_id = previous_person_labels[1].id
          _update_shape(
              api,
              task_id,
              edited_id,
              label="test",
              points=[10, 20, 30, 40],
              attributes=[("sex", "male")],
          )
  
          dataset.load_annotations(anno_key, cleanup=True)
  
      labels = view.values("ground_truth.detections", unwind=True)
      person_labels = view.filter_labels(
          "ground_truth", F("label") == "person"
      ).values("ground_truth.detections", unwind=True)
      self.assertListEqual(
          [d.label for d in labels],
          [d.label for d in previous_labels],
      )
      self.assertListEqual(
          [d.bounding_box for d in labels],
          [d.bounding_box for d in previous_labels],
      )
      self.assertListEqual(
          [d.id for d in labels],
          [d.id for d in previous_labels],
      )
      self.assertEqual(
          len(
              dataset.filter_labels("ground_truth", F("sex") == "male")
          ),
          1,
      )
  
imports: from bson import ObjectId
  from collections import defaultdict
  import numpy
  import os
  import unittest
  import eta.core.utils
  import fiftyone
  import fiftyone.utils.cvat
  import fiftyone.zoo
  from fiftyone.core.expressions import ViewField
label_desc: Use image node_id 7 for calling the CVATTests obj's underlying member method code with example usage: obj.test_example_restricting_label_edits() without return types