# Path: loompy/utils.py
# def timestamp() -> str:
# 	return datetime.datetime.utcnow().strftime("%Y%m%dT%H%M%S.%fZ")
# 
# Path: loompy/utils.py
# def compare_loom_spec_version(f: HDF5File, v: str) -> int:
# 	vf = int("".join(get_loom_spec_version(f).split(".")))
# 	vc = int("".join(v.split(".")))
# 	if vf == vc:
# 		return 0
# 	if vf > vc:
# 		return 1
# 	return -1


from typing import *
from loompy import timestamp
from .utils import compare_loom_spec_version
import numpy as np
import h5py
import loompy
			name (str) 			Name of the attribute
			val (np.ndarray)	Value of the attribute

		Remarks:
			Length must match the corresponding matrix dimension
			The values are automatically HMTL escaped and converted to ASCII for storage
		"""
		if name.startswith("!"):
			super(AttributeManager, self).__setattr__(name[1:], val)
		elif "/" in name:
			raise KeyError("Attribute name cannot contain slash (/)")
		else:
			if self.ds is not None:
				values = loompy.normalize_attr_values(val, compare_loom_spec_version(self.ds._file, "3.0.0") >= 0)
				a = ["/row_attrs/", "/col_attrs/"][self.axis]
				if self.ds.shape[self.axis] != 0 and values.shape[0] != self.ds.shape[self.axis]:
					raise ValueError(f"Attribute '{name}' must have exactly {self.ds.shape[self.axis]} values but {len(values)} were given")
				if self.ds._file[a].__contains__(name):
					del self.ds._file[a + name]

				self.ds._file.create_dataset(
					a + name,
					data=values,
					dtype=h5py.special_dtype(vlen=str) if values.dtype == np.object_ else values.dtype,
					maxshape=(values.shape[0], ) if len(values.shape) == 1 else (values.shape[0], None),
					fletcher32=False,
					compression="gzip",
					shuffle=False,
					compression_opts=2
				)

# Path: loompy/utils.py
# def timestamp() -> str:
# 	return datetime.datetime.utcnow().strftime("%Y%m%dT%H%M%S.%fZ")
# 
# Path: loompy/utils.py
# def compare_loom_spec_version(f: HDF5File, v: str) -> int:
# 	vf = int("".join(get_loom_spec_version(f).split(".")))
# 	vc = int("".join(v.split(".")))
# 	if vf == vc:
# 		return 0
# 	if vf > vc:
# 		return 1
# 	return -1


# Path: loompy/attribute_manager.py
from typing import *
from loompy import timestamp
from .utils import compare_loom_spec_version
import numpy as np
import h5py
import loompy

			name (str) 			Name of the attribute
			val (np.ndarray)	Value of the attribute

		Remarks:
			Length must match the corresponding matrix dimension
			The values are automatically HMTL escaped and converted to ASCII for storage
		"""
		if name.startswith("!"):
			super(AttributeManager, self).__setattr__(name[1:], val)
		elif "/" in name:
			raise KeyError("Attribute name cannot contain slash (/)")
		else:
			if self.ds is not None:
				values = loompy.normalize_attr_values(val, compare_loom_spec_version(self.ds._file, "3.0.0") >= 0)
				a = ["/row_attrs/", "/col_attrs/"][self.axis]
				if self.ds.shape[self.axis] != 0 and values.shape[0] != self.ds.shape[self.axis]:
					raise ValueError(f"Attribute '{name}' must have exactly {self.ds.shape[self.axis]} values but {len(values)} were given")
				if self.ds._file[a].__contains__(name):
					del self.ds._file[a + name]

				self.ds._file.create_dataset(
					a + name,
					data=values,
					dtype=h5py.special_dtype(vlen=str) if values.dtype == np.object_ else values.dtype,
					maxshape=(values.shape[0], ) if len(values.shape) == 1 else (values.shape[0], None),
					fletcher32=False,
					compression="gzip",
					shuffle=False,
					compression_opts=2
				)

				self.ds._file[a + name].attrs["last_modified"] = timestamp()