Source code for aiida.repository.common

###########################################################################
# Copyright (c), The AiiDA team. All rights reserved.                     #
# This file is part of the AiiDA code.                                    #
#                                                                         #
# The code is hosted on GitHub at https://github.com/aiidateam/aiida-core #
# For further information on the license, see the LICENSE.txt file        #
# For further information please visit http://www.aiida.net               #
###########################################################################
"""Module with resources common to the repository."""

import enum
import typing

__all__ = ('FileType', 'File')


[docs] class FileType(enum.Enum): """Enumeration to represent the type of a file object.""" DIRECTORY = 0 FILE = 1
[docs] class File: """Data class representing a file object."""
[docs] def __init__( self, name: str = '', file_type: FileType = FileType.DIRECTORY, key: typing.Union[str, None] = None, objects: typing.Optional[typing.Dict[str, 'File']] = None, ) -> None: """Construct a new instance. :param name: The final element of the file path :param file_type: Identifies whether the File is a file or a directory :param key: A key to map the file to its contents in the backend repository (file only) :param objects: Mapping of child names to child Files (directory only) :raises ValueError: If a key is defined for a directory, or objects are defined for a file """ if not isinstance(name, str): raise TypeError('name should be a string.') if not isinstance(file_type, FileType): raise TypeError('file_type should be an instance of `FileType`.') if key is not None and not isinstance(key, str): raise TypeError('key should be `None` or a string.') if objects is not None and any(not isinstance(obj, self.__class__) for obj in objects.values()): raise TypeError('objects should be `None` or a dictionary of `File` instances.') if file_type == FileType.DIRECTORY and key is not None: raise ValueError('an object of type `FileType.DIRECTORY` cannot define a key.') if file_type == FileType.FILE and objects is not None: raise ValueError('an object of type `FileType.FILE` cannot define any objects.') self._name = name self._file_type = file_type self._key = key self._objects = objects or {}
[docs] @classmethod def from_serialized(cls, serialized: dict, name='') -> 'File': """Construct a new instance from a serialized instance. :param serialized: the serialized instance. :return: the reconstructed file object. """ if 'k' in serialized: file_type = FileType.FILE key = serialized['k'] objects = None else: file_type = FileType.DIRECTORY key = None objects = {name: File.from_serialized(obj, name) for name, obj in serialized.get('o', {}).items()} instance = cls.__new__(cls) instance.__init__(name, file_type, key, objects) # type: ignore[misc] return instance
[docs] def serialize(self) -> dict: """Serialize the metadata into a JSON-serializable format. .. note:: the serialization format is optimized to reduce the size in bytes. :return: dictionary with the content metadata. """ if self.file_type == FileType.DIRECTORY: if self.objects: return {'o': {key: obj.serialize() for key, obj in self.objects.items()}} return {} return {'k': self.key}
@property def name(self) -> str: """Return the name of the file object.""" return self._name @property def file_type(self) -> FileType: """Return the file type of the file object.""" return self._file_type
[docs] def is_file(self) -> bool: """Return whether this instance is a file object.""" return self.file_type == FileType.FILE
[docs] def is_dir(self) -> bool: """Return whether this instance is a directory object.""" return self.file_type == FileType.DIRECTORY
@property def key(self) -> typing.Union[str, None]: """Return the key of the file object.""" return self._key @property def objects(self) -> typing.Dict[str, 'File']: """Return the objects of the file object.""" return self._objects
[docs] def __eq__(self, other) -> bool: """Return whether this instance is equal to another file object instance.""" if not isinstance(other, self.__class__): return False equal_attributes = all(getattr(self, key) == getattr(other, key) for key in ['name', 'file_type', 'key']) equal_object_keys = sorted(self.objects) == sorted(other.objects) equal_objects = equal_object_keys and all(obj == other.objects[key] for key, obj in self.objects.items()) return equal_attributes and equal_objects
[docs] def __repr__(self): args = (self.name, self.file_type.value, self.key, self.objects.items()) return 'File<name={}, file_type={}, key={}, objects={}>'.format(*args)