def set_content(self, value: Any): if not self._closed: raise ValueError() with transaction_context(self._env, write = True): metadata = self.metadata for key in reserved_metadata_keys: if key in metadata: del metadata[key] if isinstance(value, str): self._size = len(value) self._content_binary = memoryview(value.encode(self.encoding)) metadata['content-type'] = 'text/plain' metadata['content-encoding'] = self.encoding elif isinstance(value, (memoryview, bytes, bytearray)): self._size = len(value) self._content_binary = memoryview(value) metadata['content-type'] = 'application/octet-stream' elif isinstance(value, pd.DataFrame): self.__set_pandas_dataframe(value, metadata) elif isinstance(value, np.ndarray): self.__set_numpy_ndarray(value, metadata) else: pickled = pickle.dumps(value) self._size = len(pickled) self._content_binary = memoryview(pickled) metadata['content-type'] = 'application/python-pickle' metadata['content-properties'] = dict( type = get_qualified_class_name(value) ) metadata['last-modified'] = str(datetime.datetime.now()) super(File, self.__class__).metadata.fset(self, metadata) # type: ignore
def __create_or_bind(self, *, db_properties: List[LMDBProperties], versioned: bool, metadata: Dict[str, Any], on_init: Optional[Callable[[bool], None]], bind: bool = True): with transaction_context(self._env, write=True) as (txn, _, _): obj_uuid = txn.get(key=self._encname, db=self._namedb) if obj_uuid: if bind: return self.__bind_or_create(db_properties=db_properties, versioned=versioned, metadata=metadata, on_init=on_init, create=False) raise ObjectExistsError() obj_uuid = uuid.uuid4().bytes assert txn.put(key=self._encname, value=obj_uuid, db=self._namedb) assert txn.put(key=obj_uuid, value=struct.pack('@N', 0), db=self._versdb) basename = str(uuid.uuid4()) descriptor: Descriptor = dict(databases=list( zip([ create_string_digest(''.join([basename, str(i)])) for i in range(len(db_properties)) ], db_properties)), uuid=str(uuid.UUID(bytes=obj_uuid)), versioned=versioned, created=str(datetime.datetime.now()), type=get_qualified_class_name(self), metadata=metadata) assert txn.put(key=obj_uuid, value=orjson.dumps(descriptor), db=self._descdb) for dbuid, props in descriptor['databases']: self._userdb.append( open_database_threadsafe(txn, self._env, dbuid, props, create=True)) self._uuid_bytes = obj_uuid self._versioned = descriptor['versioned'] if on_init: self._create = True on_init(True) self._create = False return None
def __set_numpy_ndarray( self, data: np.ndarray, metadata: Dict[str, Any] ): if not data.flags.c_contiguous: data = np.ascontiguousarray(data) self._content_binary = data.data self._size = data.data.nbytes metadata['content-type'] = 'application/python-numpy-ndarray' metadata['content-properties'] = dict( shape = data.shape, strides = data.strides, dtype = str(data.dtype), type = get_qualified_class_name(data) )
def __set_pandas_dataframe( self, data: pd.DataFrame, metadata: Dict[str, Any] ): try: stash = self.mode self.mode = 'wb' with self: data.to_feather(self) metadata['content-type'] = 'application/python-pandas-dataframe' metadata['content-properties'] = dict( columns = data.columns.to_list(), type = get_qualified_class_name(data), nrows = len(data) ) finally: self.mode = stash
def __bind_or_create(self, *, db_properties: List[LMDBProperties], versioned: bool, metadata: Dict[str, Any], on_init: Optional[Callable[[bool], None]] = None, create: bool = True): with transaction_context(self._env, write=False) as (txn, _, _): result = txn.get(key=self._encname, db=self._namedb) if result: obj_uuid = bytes(result) if isinstance(result, memoryview) else result result = txn.get(key=obj_uuid, db=self._descdb) result = bytes(result) if isinstance(result, memoryview) else result descriptor = orjson.loads(result) my_class_name = get_qualified_class_name(self) if descriptor['type'] != my_class_name: try: if my_class_name not in \ get_qualified_base_names(create_class(descriptor['type'])): raise TypeError() except AttributeError as exc: if my_class_name != 'parkit.storage.entity.Entity': raise TypeError() from exc self._uuid_bytes = obj_uuid self._versioned = descriptor['versioned'] self.__bind_databases(descriptor=descriptor, on_init=on_init) return None if create: return self.__create_or_bind(db_properties=db_properties, versioned=versioned, metadata=metadata, on_init=on_init, bind=True) raise ObjectNotFoundError()