code: def test_artifacts(self):
      # given
      processor = OperationsPreprocessor()
      project_uuid = str(uuid.uuid4())
  
      operations = [
          TrackFilesToArtifact(["a"], project_uuid, [("dir1/", None)]),
          DeleteAttribute(["a"]),
          TrackFilesToArtifact(["b"], project_uuid, [("dir1/", None)]),
          TrackFilesToArtifact(
              ["b"], project_uuid, [("dir2/dir3/", "dir2/")]
          ),
          TrackFilesToArtifact(
              ["b"], project_uuid, [("dir4/dir5/", "dir4/")]
          ),
          AssignFloat(["c"], 5),
          TrackFilesToArtifact(["c"], project_uuid, [("dir1/", None)]),
          TrackFilesToArtifact(
              ["d"], project_uuid, [("dir2/dir3/", "dir2/")]
          ),
          TrackFilesToArtifact(["d"], project_uuid, [("dir4/", None)]),
          TrackFilesToArtifact(["e"], project_uuid, [("dir1/", None)]),
          TrackFilesToArtifact(
              ["e"], project_uuid, [("dir2/dir3/", "dir2/")]
          ),
          TrackFilesToArtifact(["f"], project_uuid, [("dir1/", None)]),
          TrackFilesToArtifact(
              ["f"], project_uuid, [("dir2/dir3/", "dir2/")]
          ),
          TrackFilesToArtifact(["f"], project_uuid, [("dir4/", None)]),
          TrackFilesToArtifact(["a"], project_uuid, [("dir1/", None)]),
      ]
  
      # when
      processor.process(operations)
  
      # then: there's a cutoff before second TrackFilesToArtifact(["a"]) due to DeleteAttribute(["a"])
      result = processor.get_operations()
      self.assertEqual(result.upload_operations, [])
      self.assertEqual(
          result.artifact_operations,
          [
              TrackFilesToArtifact(
                  ["a"], project_uuid, [("dir1/", None)]
              ),
              TrackFilesToArtifact(
                  ["b"],
                  project_uuid,
                  [
                      ("dir1/", None),
                      ("dir2/dir3/", "dir2/"),
                      ("dir4/dir5/", "dir4/"),
                  ],
              ),
              TrackFilesToArtifact(
                  ["d"],
                  project_uuid,
                  [("dir2/dir3/", "dir2/"), ("dir4/", None)],
              ),
              TrackFilesToArtifact(
                  ["e"],
                  project_uuid,
                  [("dir1/", None), ("dir2/dir3/", "dir2/")],
              ),
              TrackFilesToArtifact(
                  ["f"],
                  project_uuid,
                  [
                      ("dir1/", None),
                      ("dir2/dir3/", "dir2/"),
                      ("dir4/", None),
                  ],
              ),
          ],
      )
      self.assertEqual(
          result.other_operations,
          [
              DeleteAttribute(["a"]),
              AssignFloat(["c"], 5),
          ],
      )
      self.assertEqual(
          result.errors,
          [
              MetadataInconsistency(
                  "Cannot perform TrackFilesToArtifact operation on c: Attribute is not a Artifact"
              ),
          ],
      )
      self.assertEqual(
          processor.processed_ops_count, len(operations) - 1
      )
  
file_path: neptune-client/tests/unit/neptune/new/internal/backends/test_operations_preprocessor.py
imports: import uuid
  from neptune.exceptions import MetadataInconsistency
  from neptune.internal.backends.operations_preprocessor import OperationsPreprocessor
  from neptune.internal.operation import AddStrings, AssignFloat, AssignString, ClearFloatLog, ClearImageLog, ClearStringSet, ConfigFloatSeries, DeleteAttribute, LogFloats, LogImages, LogStrings, RemoveStrings, TrackFilesToArtifact, UploadFileSet
  from tests.unit.neptune.new.attributes.test_attribute_base import TestAttributeBase
label_desc: Use image node_id 7 for calling the TestOperationsPreprocessor obj's underlying member method code with example usage: obj.test_artifacts() without return types