docs: def deserialize_properties(props_struct: struct_pb2.Struct) -> Any:
      """
      Deserializes a protobuf `struct_pb2.Struct` into a Python dictionary containing normal
      Python types.
      """
      # Check out this link for details on what sort of types Protobuf is going to generate:
      # https://developers.google.com/protocol-buffers/docs/reference/python-generated
      #
      # We assume that we are deserializing properties that we got from a Resource RPC endpoint,
      # which has type `Struct` in our gRPC proto definition.
      if _special_sig_key in props_struct:
          if props_struct[_special_sig_key] == _special_asset_sig:
              # This is an asset. Re-hydrate this object into an Asset.
              if "path" in props_struct:
                  return known_types.new_file_asset(props_struct["path"])
              if "text" in props_struct:
                  return known_types.new_string_asset(props_struct["text"])
              if "uri" in props_struct:
                  return known_types.new_remote_asset(props_struct["uri"])
              raise AssertionError("Invalid asset encountered when unmarshaling resource property")
          elif props_struct[_special_sig_key] == _special_archive_sig:
              # This is an archive. Re-hydrate this object into an Archive.
              if "assets" in props_struct:
                  return known_types.new_asset_archive(deserialize_property(props_struct["assets"]))
              if "path" in props_struct:
                  return known_types.new_file_archive(props_struct["path"])
              if "uri" in props_struct:
                  return known_types.new_remote_archive(props_struct["uri"])
          elif props_struct[_special_sig_key] == _special_secret_sig:
              raise AssertionError("this version of the Pulumi SDK does not support first-class secrets")
  
          raise AssertionError("Unrecognized signature when unmarshaling resource property")
  
      # Struct is duck-typed like a dictionary, so we can iterate over it in the normal ways.
      output = {}
      for k, v in list(props_struct.items()):
          value = deserialize_property(v)
          # We treat values that deserialize to "None" as if they don't exist.
          if value is not None:
              output[k] = value
  
      return output