From bdef464acd53f523cf912e90f9d1243c473e3812 Mon Sep 17 00:00:00 2001 From: Sebastiaan Huber Date: Thu, 11 Jan 2024 12:30:39 +0100 Subject: [PATCH] ORM: Use `pydantic` to specify a schema for each ORM entity --- docs/source/nitpick-exceptions | 3 + pyproject.toml | 11 ++ src/aiida/cmdline/commands/cmd_code.py | 6 +- src/aiida/cmdline/commands/cmd_profile.py | 1 - src/aiida/cmdline/groups/dynamic.py | 20 +- src/aiida/common/pydantic.py | 58 +++++- src/aiida/orm/authinfos.py | 100 ++++++---- src/aiida/orm/comments.py | 75 ++++---- src/aiida/orm/computers.py | 56 ++---- src/aiida/orm/entities.py | 98 ++++++++-- src/aiida/orm/fields.py | 113 +++++++----- src/aiida/orm/groups.py | 77 ++++---- src/aiida/orm/implementation/groups.py | 6 + src/aiida/orm/logs.py | 54 +----- src/aiida/orm/nodes/data/array/array.py | 73 ++++++-- src/aiida/orm/nodes/data/array/bands.py | 19 +- src/aiida/orm/nodes/data/array/kpoints.py | 55 ++---- src/aiida/orm/nodes/data/array/trajectory.py | 23 +-- src/aiida/orm/nodes/data/base.py | 15 +- src/aiida/orm/nodes/data/cif.py | 40 ++-- src/aiida/orm/nodes/data/code/abstract.py | 21 +-- src/aiida/orm/nodes/data/code/installed.py | 44 +++-- src/aiida/orm/nodes/data/code/legacy.py | 51 ++---- src/aiida/orm/nodes/data/code/portable.py | 1 + src/aiida/orm/nodes/data/data.py | 14 +- src/aiida/orm/nodes/data/dict.py | 26 +-- src/aiida/orm/nodes/data/enum.py | 7 + src/aiida/orm/nodes/data/jsonable.py | 9 + src/aiida/orm/nodes/data/list.py | 16 ++ src/aiida/orm/nodes/data/remote/base.py | 4 + src/aiida/orm/nodes/data/remote/stash/base.py | 11 +- .../orm/nodes/data/remote/stash/folder.py | 17 +- src/aiida/orm/nodes/data/singlefile.py | 30 ++- src/aiida/orm/nodes/data/structure.py | 80 ++++---- src/aiida/orm/nodes/data/upf.py | 4 +- src/aiida/orm/nodes/node.py | 160 ++++++++++------ .../orm/nodes/process/calculation/calcjob.py | 91 ++++----- src/aiida/orm/nodes/process/process.py | 57 +----- src/aiida/orm/nodes/repository.py | 14 ++ src/aiida/orm/users.py | 39 ++-- src/aiida/orm/utils/mixins.py | 19 +- src/aiida/orm/utils/node.py | 2 +- src/aiida/plugins/entry_point.py | 1 + src/aiida/storage/psql_dos/orm/authinfos.py | 11 +- src/aiida/storage/psql_dos/orm/groups.py | 10 +- .../storage/psql_dos/orm/querybuilder/main.py | 1 - .../test_code/test_code_export___no_sort_.yml | 5 +- .../test_code/test_code_export___sort_.yml | 3 +- tests/orm/models/__init__.py | 1 + tests/orm/models/test_models.py | 173 ++++++++++++++++++ tests/orm/test_fields.py | 23 +-- tests/orm/test_fields/fields_AuthInfo.yml | 12 +- tests/orm/test_fields/fields_Comment.yml | 14 +- tests/orm/test_fields/fields_Computer.yml | 16 +- tests/orm/test_fields/fields_Group.yml | 17 +- tests/orm/test_fields/fields_Log.yml | 16 +- tests/orm/test_fields/fields_User.yml | 10 +- ...fields_aiida.data.core.array.ArrayData.yml | 32 ++-- ..._aiida.data.core.array.bands.BandsData.yml | 53 +++--- ...da.data.core.array.kpoints.KpointsData.yml | 48 +++-- ...a.core.array.projection.ProjectionData.yml | 32 ++-- ...a.core.array.trajectory.TrajectoryData.yml | 38 ++-- ...fields_aiida.data.core.array.xy.XyData.yml | 32 ++-- .../fields_aiida.data.core.base.BaseType.yml | 32 ++-- .../fields_aiida.data.core.bool.Bool.yml | 33 ++-- .../fields_aiida.data.core.cif.CifData.yml | 40 ++-- .../fields_aiida.data.core.code.Code.yml | 47 +++-- ...e.code.containerized.ContainerizedCode.yml | 47 +++-- ...data.core.code.installed.InstalledCode.yml | 44 +++-- ...a.data.core.code.portable.PortableCode.yml | 46 +++-- .../fields_aiida.data.core.dict.Dict.yml | 34 ++-- .../fields_aiida.data.core.enum.EnumData.yml | 32 ++-- .../fields_aiida.data.core.float.Float.yml | 33 ++-- ...elds_aiida.data.core.folder.FolderData.yml | 31 ++-- .../fields_aiida.data.core.int.Int.yml | 33 ++-- ..._aiida.data.core.jsonable.JsonableData.yml | 33 ++-- .../fields_aiida.data.core.list.List.yml | 32 ++-- ...ds_aiida.data.core.numeric.NumericType.yml | 32 ++-- ...ds_aiida.data.core.orbital.OrbitalData.yml | 31 ++-- ...elds_aiida.data.core.remote.RemoteData.yml | 33 ++-- ...data.core.remote.stash.RemoteStashData.yml | 33 ++-- ...ote.stash.folder.RemoteStashFolderData.yml | 37 ++-- ...da.data.core.singlefile.SinglefileData.yml | 33 ++-- .../fields_aiida.data.core.str.Str.yml | 33 ++-- ...iida.data.core.structure.StructureData.yml | 43 +++-- .../fields_aiida.data.core.upf.UpfData.yml | 33 ++-- .../fields_aiida.node.data.Data.yml | 31 ++-- .../fields_aiida.node.process.ProcessNode.yml | 47 ++--- ...de.process.calculation.CalculationNode.yml | 47 ++--- ...culation.calcfunction.CalcFunctionNode.yml | 47 ++--- ...rocess.calculation.calcjob.CalcJobNode.yml | 68 +++---- ...ida.node.process.workflow.WorkflowNode.yml | 47 ++--- ...ocess.workflow.workchain.WorkChainNode.yml | 47 ++--- ...workflow.workfunction.WorkFunctionNode.yml | 47 ++--- 94 files changed, 1988 insertions(+), 1386 deletions(-) create mode 100644 tests/orm/models/__init__.py create mode 100644 tests/orm/models/test_models.py diff --git a/docs/source/nitpick-exceptions b/docs/source/nitpick-exceptions index bf0ba64d66..2c31d76e06 100644 --- a/docs/source/nitpick-exceptions +++ b/docs/source/nitpick-exceptions @@ -140,7 +140,9 @@ py:meth click.Option.get_default py:meth fail py:class ComputedFieldInfo +py:class BaseModel py:class pydantic.fields.Field +py:class pydantic.fields.FieldInfo py:class pydantic.main.BaseModel py:class PluggableSchemaValidator @@ -157,6 +159,7 @@ py:class frozenset py:class numpy.bool_ py:class numpy.ndarray +py:class np.ndarray py:class ndarray py:class paramiko.proxy.ProxyCommand diff --git a/pyproject.toml b/pyproject.toml index 7641b7ed72..0b85ea4211 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -134,6 +134,17 @@ requires-python = '>=3.9' 'process.workflow.workchain' = 'aiida.orm.nodes.process.workflow.workchain:WorkChainNode' 'process.workflow.workfunction' = 'aiida.orm.nodes.process.workflow.workfunction:WorkFunctionNode' +[project.entry-points.'aiida.orm'] +'core.auth_info' = 'aiida.orm.authinfos:AuthInfo' +'core.comment' = 'aiida.orm.comments:Comment' +'core.computer' = 'aiida.orm.computers:Computer' +'core.data' = 'aiida.orm.nodes.data.data:Data' +'core.entity' = 'aiida.orm.entities:Entity' +'core.group' = 'aiida.orm.groups:Group' +'core.log' = 'aiida.orm.logs:Log' +'core.node' = 'aiida.orm.nodes.node:Node' +'core.user' = 'aiida.orm.users:User' + [project.entry-points.'aiida.parsers'] 'core.arithmetic.add' = 'aiida.parsers.plugins.arithmetic.add:ArithmeticAddParser' 'core.templatereplacer' = 'aiida.parsers.plugins.templatereplacer.parser:TemplatereplacerParser' diff --git a/src/aiida/cmdline/commands/cmd_code.py b/src/aiida/cmdline/commands/cmd_code.py index a5e384ed2a..38cf59c2fa 100644 --- a/src/aiida/cmdline/commands/cmd_code.py +++ b/src/aiida/cmdline/commands/cmd_code.py @@ -30,10 +30,10 @@ def verdi_code(): """Setup and manage codes.""" -def create_code(ctx: click.Context, cls, non_interactive: bool, **kwargs): +def create_code(ctx: click.Context, cls, **kwargs): """Create a new `Code` instance.""" try: - instance = cls(**kwargs) + instance = cls.from_model(cls.Model(**kwargs)) except (TypeError, ValueError) as exception: echo.echo_critical(f'Failed to create instance `{cls}`: {exception}') @@ -243,9 +243,7 @@ def show(code): @with_dbenv() def export(code, output_file, overwrite, sort): """Export code to a yaml file. If no output file is given, default name is created based on the code label.""" - other_args = {'sort': sort} - fileformat = 'yaml' if output_file is None: diff --git a/src/aiida/cmdline/commands/cmd_profile.py b/src/aiida/cmdline/commands/cmd_profile.py index 7cb0e018ae..a3f234f791 100644 --- a/src/aiida/cmdline/commands/cmd_profile.py +++ b/src/aiida/cmdline/commands/cmd_profile.py @@ -29,7 +29,6 @@ def verdi_profile(): def command_create_profile( ctx: click.Context, storage_cls, - non_interactive: bool, profile: Profile, set_as_default: bool = True, email: str | None = None, diff --git a/src/aiida/cmdline/groups/dynamic.py b/src/aiida/cmdline/groups/dynamic.py index 4a1e0eb600..f9f42a7ace 100644 --- a/src/aiida/cmdline/groups/dynamic.py +++ b/src/aiida/cmdline/groups/dynamic.py @@ -88,29 +88,25 @@ def get_command(self, ctx: click.Context, cmd_name: str) -> click.Command | None command = super().get_command(ctx, cmd_name) return command - def call_command(self, ctx, cls, **kwargs): + def call_command(self, ctx, cls, non_interactive, **kwargs): """Call the ``command`` after validating the provided inputs.""" from pydantic import ValidationError if hasattr(cls, 'Model'): # The plugin defines a pydantic model: use it to validate the provided arguments try: - model = cls.Model(**kwargs) + cls.Model(**kwargs) except ValidationError as exception: param_hint = [ f'--{loc.replace("_", "-")}' # type: ignore[union-attr] for loc in exception.errors()[0]['loc'] ] - message = '\n'.join([str(e['ctx']['error']) for e in exception.errors()]) + message = '\n'.join([str(e['msg']) for e in exception.errors()]) raise click.BadParameter( message, - param_hint=param_hint or 'multiple parameters', # type: ignore[arg-type] + param_hint=param_hint or 'one or more parameters', # type: ignore[arg-type] ) from exception - # Update the arguments with the dictionary representation of the model. This will include any type coercions - # that may have been applied with validators defined for the model. - kwargs.update(**model.model_dump()) - return self._command(ctx, cls, **kwargs) def create_command(self, ctx: click.Context, entry_point: str) -> click.Command: @@ -154,6 +150,8 @@ def list_options(self, entry_point: str) -> list: """ from pydantic_core import PydanticUndefined + from aiida.common.pydantic import get_metadata + cls = self.factory(entry_point) if not hasattr(cls, 'Model'): @@ -170,6 +168,9 @@ def list_options(self, entry_point: str) -> list: options_spec = {} for key, field_info in cls.Model.model_fields.items(): + if get_metadata(field_info, 'exclude_from_cli'): + continue + default = field_info.default_factory if field_info.default is PydanticUndefined else field_info.default # If the annotation has the ``__args__`` attribute it is an instance of a type from ``typing`` and the real @@ -194,7 +195,8 @@ def list_options(self, entry_point: str) -> list: } for metadata in field_info.metadata: for metadata_key, metadata_value in metadata.items(): - options_spec[key][metadata_key] = metadata_value + if metadata_key in ('priority', 'short_name', 'option_cls'): + options_spec[key][metadata_key] = metadata_value options_ordered = [] diff --git a/src/aiida/common/pydantic.py b/src/aiida/common/pydantic.py index 2fa3d2bd68..bd5d28ec9f 100644 --- a/src/aiida/common/pydantic.py +++ b/src/aiida/common/pydantic.py @@ -5,14 +5,41 @@ import typing as t from pydantic import Field +from pydantic_core import PydanticUndefined + +if t.TYPE_CHECKING: + from pydantic import BaseModel + + from aiida.orm import Entity + + +def get_metadata(field_info, key: str, default: t.Any | None = None): + """Return a the metadata of the given field for a particular key. + + :param field_info: The field from which to retrieve the metadata. + :param key: The metadata name. + :param default: Optional default value to return in case the metadata is not defined on the field. + :returns: The metadata if defined, otherwise the default. + """ + for element in field_info.metadata: + if key in element: + return element[key] + return default def MetadataField( # noqa: N802 - default: t.Any | None = None, + default: t.Any = PydanticUndefined, *, priority: int = 0, short_name: str | None = None, option_cls: t.Any | None = None, + orm_class: type['Entity'] | str | None = None, + orm_to_model: t.Callable[['Entity'], t.Any] | None = None, + model_to_orm: t.Callable[['BaseModel'], t.Any] | None = None, + exclude_to_orm: bool = False, + exclude_from_cli: bool = False, + is_attribute: bool = True, + is_subscriptable: bool = False, **kwargs, ): """Return a :class:`pydantic.fields.Field` instance with additional metadata. @@ -37,11 +64,36 @@ class Model(BaseModel): :param priority: Used to order the list of all fields in the model. Ordering is done from small to large priority. :param short_name: Optional short name to use for an option on a command line interface. :param option_cls: The :class:`click.Option` class to use to construct the option. + :param orm_class: The class, or entry point name thereof, to which the field should be converted. If this field is + defined, the value of this field should acccept an integer which will automatically be converted to an instance + of said ORM class using ``orm_class.collection.get(id={field_value})``. This is useful, for example, where a + field represents an instance of a different entity, such as an instance of ``User``. The serialized data would + store the ``pk`` of the user, but the ORM entity instance would receive the actual ``User`` instance with that + primary key. + :param orm_to_model: Optional callable to convert the value of a field from an ORM instance to a model instance. + :param model_to_orm: Optional callable to convert the value of a field from a model instance to an ORM instance. + :param exclude_to_orm: When set to ``True``, this field value will not be passed to the ORM entity constructor + through ``Entity.from_model``. + :param exclude_to_orm: When set to ``True``, this field value will not be exposed on the CLI command that is + dynamically generated to create a new instance. + :param is_attribute: Whether the field is stored as an attribute. + :param is_subscriptable: Whether the field can be indexed like a list or dictionary. """ field_info = Field(default, **kwargs) - for key, value in (('priority', priority), ('short_name', short_name), ('option_cls', option_cls)): - if value is not None and field_info is not None: + for key, value in ( + ('priority', priority), + ('short_name', short_name), + ('option_cls', option_cls), + ('orm_class', orm_class), + ('orm_to_model', orm_to_model), + ('model_to_orm', model_to_orm), + ('exclude_to_orm', exclude_to_orm), + ('exclude_from_cli', exclude_from_cli), + ('is_attribute', is_attribute), + ('is_subscriptable', is_subscriptable), + ): + if value is not None: field_info.metadata.append({key: value}) return field_info diff --git a/src/aiida/orm/authinfos.py b/src/aiida/orm/authinfos.py index e87be97367..35d0034ac5 100644 --- a/src/aiida/orm/authinfos.py +++ b/src/aiida/orm/authinfos.py @@ -8,17 +8,20 @@ ########################################################################### """Module for the `AuthInfo` ORM class.""" +from __future__ import annotations + from typing import TYPE_CHECKING, Any, Dict, Optional, Type from aiida.common import exceptions +from aiida.common.pydantic import MetadataField from aiida.manage import get_manager from aiida.plugins import TransportFactory from . import entities, users -from .fields import add_field +from .computers import Computer +from .users import User if TYPE_CHECKING: - from aiida.orm import Computer, User from aiida.orm.implementation import StorageBackend from aiida.orm.implementation.authinfos import BackendAuthInfo # noqa: F401 from aiida.transports import Transport @@ -45,43 +48,46 @@ class AuthInfo(entities.Entity['BackendAuthInfo', AuthInfoCollection]): """ORM class that models the authorization information that allows a `User` to connect to a `Computer`.""" _CLS_COLLECTION = AuthInfoCollection + PROPERTY_WORKDIR = 'workdir' - __qb_fields__ = [ - add_field( - 'enabled', - dtype=bool, + class Model(entities.Entity.Model): + computer: int = MetadataField( + description='The PK of the computer', is_attribute=False, - doc='Whether the instance is enabled', - ), - add_field( - 'auth_params', - dtype=Dict[str, Any], + orm_class=Computer, + orm_to_model=lambda auth_info: auth_info.computer.pk, # type: ignore[attr-defined] + ) + user: int = MetadataField( + description='The PK of the user', is_attribute=False, - doc='Dictionary of authentication parameters', - ), - add_field( - 'metadata', - dtype=Dict[str, Any], + orm_class=User, + orm_to_model=lambda auth_info: auth_info.user.pk, # type: ignore[attr-defined] + ) + enabled: bool = MetadataField( + True, + description='Whether the instance is enabled', is_attribute=False, - doc='Dictionary of metadata', - ), - add_field( - 'computer_pk', - dtype=int, + ) + auth_params: Dict[str, Any] = MetadataField( + default_factory=dict, + description='Dictionary of authentication parameters', is_attribute=False, - doc='The PK of the computer', - ), - add_field( - 'user_pk', - dtype=int, + ) + metadata: Dict[str, Any] = MetadataField( + default_factory=dict, + description='Dictionary of metadata', is_attribute=False, - doc='The PK of the user', - ), - ] - - PROPERTY_WORKDIR = 'workdir' - - def __init__(self, computer: 'Computer', user: 'User', backend: Optional['StorageBackend'] = None) -> None: + ) + + def __init__( + self, + computer: 'Computer', + user: 'User', + enabled: bool = True, + auth_params: Dict[str, Any] | None = None, + metadata: Dict[str, Any] | None = None, + backend: Optional['StorageBackend'] = None, + ) -> None: """Create an `AuthInfo` instance for the given computer and user. :param computer: a `Computer` instance @@ -89,7 +95,13 @@ def __init__(self, computer: 'Computer', user: 'User', backend: Optional['Storag :param backend: the backend to use for the instance, or use the default backend if None """ backend = backend or get_manager().get_profile_storage() - model = backend.authinfos.create(computer=computer.backend_entity, user=user.backend_entity) + model = backend.authinfos.create( + computer=computer.backend_entity, + user=user.backend_entity, + enabled=enabled, + auth_params=auth_params or {}, + metadata=metadata or {}, + ) super().__init__(model) def __str__(self) -> str: @@ -98,6 +110,18 @@ def __str__(self) -> str: return f'AuthInfo for {self.user.email} on {self.computer.label} [DISABLED]' + def __eq__(self, other) -> bool: + if not isinstance(other, AuthInfo): + return False + + return ( + self.user.pk == other.user.pk + and self.computer.pk == other.computer.pk + and self.enabled == other.enabled + and self.auth_params == other.auth_params + and self.metadata == other.metadata + ) + @property def enabled(self) -> bool: """Return whether this instance is enabled. @@ -126,6 +150,14 @@ def user(self) -> 'User': """Return the user associated with this instance.""" return entities.from_backend_entity(users.User, self._backend_entity.user) + @property + def auth_params(self) -> Dict[str, Any]: + return self._backend_entity.get_auth_params() + + @property + def metadata(self) -> Dict[str, Any]: + return self._backend_entity.get_metadata() + def get_auth_params(self) -> Dict[str, Any]: """Return the dictionary of authentication parameters diff --git a/src/aiida/orm/comments.py b/src/aiida/orm/comments.py index bc92351c54..6f285fa6aa 100644 --- a/src/aiida/orm/comments.py +++ b/src/aiida/orm/comments.py @@ -11,15 +11,17 @@ from datetime import datetime from typing import TYPE_CHECKING, List, Optional, Type +from aiida.common.pydantic import MetadataField from aiida.manage import get_manager -from . import entities, users -from .fields import add_field +from . import entities if TYPE_CHECKING: - from aiida.orm import Node, User from aiida.orm.implementation import StorageBackend + from .nodes.node import Node + from .users import User + __all__ = ('Comment',) @@ -65,44 +67,29 @@ class Comment(entities.Entity['BackendComment', CommentCollection]): _CLS_COLLECTION = CommentCollection - __qb_fields__ = [ - add_field( - 'uuid', - dtype=str, - is_attribute=False, - doc='The UUID of the comment', - ), - add_field( - 'ctime', - dtype=datetime, - is_attribute=False, - doc='Creation time of the comment', - ), - add_field( - 'mtime', - dtype=datetime, - is_attribute=False, - doc='Modified time of the comment', - ), - add_field( - 'content', - dtype=str, + class Model(entities.Entity.Model): + uuid: Optional[str] = MetadataField( + description='The UUID of the comment', is_attribute=False, exclude_to_orm=True + ) + ctime: Optional[datetime] = MetadataField( + description='Creation time of the comment', is_attribute=False, exclude_to_orm=True + ) + mtime: Optional[datetime] = MetadataField( + description='Modified time of the comment', is_attribute=False, exclude_to_orm=True + ) + node: int = MetadataField( + description='Node PK that the comment is attached to', is_attribute=False, - doc='Content of the comment', - ), - add_field( - 'user_pk', - dtype=int, + orm_class='core.node', + orm_to_model=lambda comment: comment.node.pk, + ) + user: int = MetadataField( + description='User PK that created the comment', is_attribute=False, - doc='User PK that created the comment', - ), - add_field( - 'node_pk', - dtype=int, - is_attribute=False, - doc='Node PK that the comment is attached to', - ), - ] + orm_class='core.user', + orm_to_model=lambda comment: comment.user.pk, + ) + content: str = MetadataField(description='Content of the comment', is_attribute=False) def __init__( self, node: 'Node', user: 'User', content: Optional[str] = None, backend: Optional['StorageBackend'] = None @@ -124,6 +111,12 @@ def __str__(self) -> str: arguments = [self.uuid, self.node.pk, self.user.email, self.content] return 'Comment<{}> for node<{}> and user<{}>: {}'.format(*arguments) + def __eq__(self, other) -> bool: + if not isinstance(other, Comment): + return False + + return self.uuid == other.uuid + @property def uuid(self) -> str: """Return the UUID for this comment. @@ -151,7 +144,9 @@ def node(self) -> 'Node': @property def user(self) -> 'User': - return entities.from_backend_entity(users.User, self._backend_entity.user) + from aiida.orm.users import User + + return entities.from_backend_entity(User, self._backend_entity.user) def set_user(self, value: 'User') -> None: self._backend_entity.user = value.backend_entity diff --git a/src/aiida/orm/computers.py b/src/aiida/orm/computers.py index bae925b25c..2d6407b07d 100644 --- a/src/aiida/orm/computers.py +++ b/src/aiida/orm/computers.py @@ -13,11 +13,11 @@ from typing import TYPE_CHECKING, Any, Dict, List, Optional, Tuple, Type, Union from aiida.common import exceptions +from aiida.common.pydantic import MetadataField from aiida.manage import get_manager from aiida.plugins import SchedulerFactory, TransportFactory from . import entities, users -from .fields import add_field if TYPE_CHECKING: from aiida.orm import AuthInfo, User @@ -73,50 +73,14 @@ class Computer(entities.Entity['BackendComputer', ComputerCollection]): _CLS_COLLECTION = ComputerCollection - __qb_fields__ = [ - add_field( - 'uuid', - dtype=str, - is_attribute=False, - doc='The UUID of the computer', - ), - add_field( - 'label', - dtype=str, - is_attribute=False, - doc='Label for the computer', - ), - add_field( - 'description', - dtype=str, - is_attribute=False, - doc='Description of the computer', - ), - add_field( - 'hostname', - dtype=str, - is_attribute=False, - doc='Hostname of the computer', - ), - add_field( - 'transport_type', - dtype=str, - is_attribute=False, - doc='Transport type of the computer', - ), - add_field( - 'scheduler_type', - dtype=str, - is_attribute=False, - doc='Scheduler type of the computer', - ), - add_field( - 'metadata', - dtype=Dict[str, Any], - is_attribute=False, - doc='Metadata of the computer', - ), - ] + class Model(entities.Entity.Model): + uuid: str = MetadataField(description='The UUID of the computer', is_attribute=False, exclude_to_orm=True) + label: str = MetadataField(description='Label for the computer', is_attribute=False) + description: str = MetadataField(description='Description of the computer', is_attribute=False) + hostname: str = MetadataField(description='Hostname of the computer', is_attribute=False) + transport_type: str = MetadataField(description='Transport type of the computer', is_attribute=False) + scheduler_type: str = MetadataField(description='Scheduler type of the computer', is_attribute=False) + metadata: Dict[str, Any] = MetadataField(description='Metadata of the computer', is_attribute=False) def __init__( self, @@ -126,6 +90,7 @@ def __init__( transport_type: str = '', scheduler_type: str = '', workdir: Optional[str] = None, + metadata: Optional[Dict[str, Any]] = None, backend: Optional['StorageBackend'] = None, ) -> None: """Construct a new computer.""" @@ -136,6 +101,7 @@ def __init__( description=description, transport_type=transport_type, scheduler_type=scheduler_type, + metadata=metadata, ) super().__init__(model) if workdir is not None: diff --git a/src/aiida/orm/entities.py b/src/aiida/orm/entities.py index a55f6f7b79..3c0704729e 100644 --- a/src/aiida/orm/entities.py +++ b/src/aiida/orm/entities.py @@ -13,16 +13,19 @@ import abc from enum import Enum from functools import lru_cache -from typing import TYPE_CHECKING, Any, Generic, List, Optional, Sequence, Type, TypeVar, Union, cast +from typing import TYPE_CHECKING, Any, Generic, List, Optional, Type, TypeVar, Union, cast from plumpy.base.utils import call_with_super_check, super_check +from pydantic import BaseModel +from pydantic.fields import FieldInfo -from aiida.common.exceptions import InvalidOperation +from aiida.common.exceptions import EntryPointError, InvalidOperation, NotExistent from aiida.common.lang import classproperty, type_check +from aiida.common.pydantic import MetadataField, get_metadata from aiida.common.warnings import warn_deprecation from aiida.manage import get_manager -from .fields import EntityFieldMeta, QbField, QbFields, add_field +from .fields import EntityFieldMeta if TYPE_CHECKING: from aiida.orm.implementation import BackendEntity, StorageBackend @@ -175,16 +178,78 @@ class Entity(abc.ABC, Generic[BackendEntityType, CollectionType], metaclass=Enti _CLS_COLLECTION: Type[CollectionType] = Collection # type: ignore[assignment] - fields: QbFields = QbFields() - - __qb_fields__: Sequence[QbField] = [ - add_field( - 'pk', - dtype=int, + class Model(BaseModel): + pk: Optional[int] = MetadataField( + None, + description='The primary key of the entity. Can be `None` if the entity is not yet stored.', is_attribute=False, - doc='The primary key of the entity', - ), - ] + exclude_to_orm=True, + exclude_from_cli=True, + ) + + @classmethod + def model_to_orm_fields(cls) -> dict[str, FieldInfo]: + return { + key: field for key, field in cls.Model.model_fields.items() if not get_metadata(field, 'exclude_to_orm') + } + + @classmethod + def model_to_orm_field_values(cls, model: Model) -> dict[str, Any]: + from aiida.plugins.factories import BaseFactory + + fields = {} + + for key, field in cls.model_to_orm_fields().items(): + field_value = getattr(model, key) + + if field_value is None: + continue + + if orm_class := get_metadata(field, 'orm_class'): + if isinstance(orm_class, str): + try: + orm_class = BaseFactory('aiida.orm', orm_class) + except EntryPointError as exception: + raise EntryPointError( + f'The `orm_class` of `{cls.__name__}.Model.{key} is invalid: {exception}' + ) from exception + try: + fields[key] = orm_class.collection.get(id=field_value) + except NotExistent as exception: + raise NotExistent(f'No `{orm_class}` found with pk={field_value}') from exception + elif model_to_orm := get_metadata(field, 'model_to_orm'): + fields[key] = model_to_orm(model) + else: + fields[key] = field_value + + return fields + + def to_model(self) -> Model: + """Return the entity instance as an instance of its model.""" + fields = {} + + for key, field in self.Model.model_fields.items(): + if orm_to_model := get_metadata(field, 'orm_to_model'): + fields[key] = orm_to_model(self) + else: + fields[key] = getattr(self, key) + + return self.Model(**fields) + + @classmethod + def from_model(cls, model: Model) -> 'Entity': + """Return an entity instance from an instance of its model.""" + fields = cls.model_to_orm_field_values(model) + return cls(**fields) + + def serialize(self) -> dict[str, Any]: + """Serialize the entity instance to JSON.""" + return self.to_model().model_dump() + + @classmethod + def from_serialized(cls, **kwargs: dict[str, Any]) -> 'Entity': + """Construct an entity instance from JSON serialized data.""" + return cls.from_model(cls.Model(**kwargs)) # type: ignore[arg-type] @classproperty def objects(cls: EntityType) -> CollectionType: # noqa: N805 @@ -236,6 +301,15 @@ def __init__(self, backend_entity: BackendEntityType) -> None: self._backend_entity = backend_entity call_with_super_check(self.initialize) + def __eq__(self, other) -> bool: + if not isinstance(other, self.__class__): + return False + + if hasattr(self, 'uuid'): + return self.uuid == other.uuid # type: ignore[attr-defined] + + return super().__eq__(other) + def __getstate__(self): """Prevent an ORM entity instance from being pickled.""" raise InvalidOperation('pickling of AiiDA ORM instances is not supported.') diff --git a/src/aiida/orm/fields.py b/src/aiida/orm/fields.py index 60d576a175..91839fa8ae 100644 --- a/src/aiida/orm/fields.py +++ b/src/aiida/orm/fields.py @@ -15,7 +15,10 @@ from functools import singledispatchmethod from pprint import pformat +from pydantic import BaseModel + from aiida.common.lang import isidentifier +from aiida.common.pydantic import get_metadata __all__ = ( 'QbField', @@ -111,11 +114,10 @@ def is_subscriptable(self) -> bool: return self._is_subscriptable def __repr__(self) -> str: - type_str = self._get_dtype_as_str() if self._dtype else '' return ( f'{self.__class__.__name__}({self.key!r}' + (f', {self._backend_key!r}' if self._backend_key != self.key else '') - + (f', dtype={type_str}' if self._dtype else '') + + (f', dtype={self._dtype or ""}') + (f', is_attribute={self.is_attribute}') + (f', is_subscriptable={self.is_subscriptable!r}' if self.is_subscriptable else '') + ')' @@ -124,8 +126,7 @@ def __repr__(self) -> str: def __str__(self) -> str: class_name = self.__class__.__name__ field_name = f'{self.backend_key}{".*" if self.is_subscriptable else ""}' - type_str = self._get_dtype_as_str() - return f'{class_name}({field_name}) -> {type_str}' + return f'{class_name}({field_name}) -> {self._dtype}' def __hash__(self): return hash((self.key, self.backend_key)) @@ -144,23 +145,6 @@ def in_(self, value: t.Iterable[t.Any]): raise TypeError('in_ must be iterable') return QbFieldFilters(((self, 'in', value),)) - def _get_dtype_as_str(self) -> str: - """Return field type as processed string. - - >>> None -> ? - >>> str -> str - >>> typing.Optional[str] -> Optional[str] - >>> typing.Dict[typing.List[str]] -> Dict[List[str]] - """ - if self._dtype: - if t.get_origin(self._dtype): - type_str = str(self._dtype).replace('typing.', '') - else: - type_str = self._dtype.__name__ - else: - type_str = '?' - return type_str - if t.TYPE_CHECKING: def __getitem__(self, key: str) -> 'QbField': ... @@ -420,29 +404,72 @@ def __init__(cls, name, bases, classdict): if current_fields is not None and not isinstance(current_fields, QbFields): raise ValueError(f"class '{cls}' already has a `fields` attribute set") - # Find all fields fields = {} - # Note: inspect.getmembers causes loading of AiiDA to fail - for key, attr in ((key, attr) for subcls in reversed(cls.__mro__) for key, attr in subcls.__dict__.items()): - # __qb_fields__ should be a list of QbField instances - if key == '__qb_fields__': - assert isinstance( - attr, t.Sequence - ), f"class '{cls}' has a '__qb_fields__' attribute, but it is not a sequence" - for field in attr: - if not isinstance(field, QbField): - raise ValueError(f"__qb_fields__ attribute of class '{cls}' must be list of QbField instances") - if field.key == 'value': - if dtype := getattr(cls, '_type', None): - value_field = add_field( - 'value', - dtype=dtype, - doc='The value of the data', - ) - - fields[field.key] = value_field - else: - fields[field.key] = field + + # If the class has an attribute ``Model`` that is a subclass of :class:`pydantic.BaseModel`, parse the model + # fields to build up the ``fields`` class attribute, which is used to allow specifying ``QueryBuilder`` filters + # programmatically. + if hasattr(cls, 'Model') and issubclass(cls.Model, BaseModel): + # If the class itself directly specifies the ``Model`` attribute, check that it is valid. Here, the check + # ``cls.__dict__`` is used instead of ``hasattr`` as the former only returns true if the class itself + # defines the attribute and does not just inherit it from a base class. In that case, this check will + # already have been performed for that subclass. + + # When a class defines a ``Model``, the following check ensures that the model inherits from the same bases + # as the class containing the attribute itself. For example, if ``cls`` inherits from ``ClassA`` and + # ``ClassB`` that each define a ``Model``, the ``cls.Model`` class should inherit from both ``ClassA.Model`` + # and ``ClassBModel`` or it will be losing the attributes of some of the models. + if 'Model' in cls.__dict__: + # Get all the base classes in the MRO of this class that define a class attribute ``Model`` that is a + # subclass of pydantic's ``BaseModel`` and not the class itself + cls_bases_with_model = [ + base + for base in cls.__mro__ + if base is not cls and 'Model' in base.__dict__ and issubclass(base.Model, BaseModel) # type: ignore[attr-defined] + ] + + # Now get the "leaf" bases, i.e., those base classes in the subclass list that themselves do not have a + # subclass in the tree. This set should be the base classes for the class' ``Model`` attribute. + cls_bases_with_model_leaves = { + base + for base in cls_bases_with_model + if all( + not issubclass(b.Model, base.Model) # type: ignore[attr-defined] + for b in cls_bases_with_model + if b is not base + ) + } + + cls_model_bases = {base.Model for base in cls_bases_with_model_leaves} # type: ignore[attr-defined] + + # If the base class does not have a base that defines a model, it means the ``Model`` should simply have + # ``pydantic.BaseModel`` as its sole base. + if not cls_model_bases: + cls_model_bases = { + BaseModel, + } + + # Get the set of bases of ``cls.Model`` that are a subclass of :class:`pydantic.BaseModel`. + model_bases = {base for base in cls.Model.__bases__ if issubclass(base, BaseModel)} + + # For ``cls.Model`` to be valid, the bases that contain a model, should equal to the leaf bases of the + # ``cls`` itself that also define a model. + if model_bases != cls_model_bases and not getattr(cls, '_SKIP_MODEL_INHERITANCE_CHECK', False): + bases = [f'{e.__module__}.{e.__name__}.Model' for e in cls_bases_with_model_leaves] + raise RuntimeError( + f'`{cls.__name__}.Model` does not subclass all necessary base classes. It should be: ' + f'`class Model({", ".join(sorted(bases))}):`' + ) + + for key, field in cls.Model.model_fields.items(): + fields[key] = add_field( + key, + alias=get_metadata(field, 'alias', None), + dtype=field.annotation, + doc=field.description, + is_attribute=get_metadata(field, 'is_attribute', False), + is_subscriptable=get_metadata(field, 'is_subscriptable', False), + ) cls.fields = QbFields({key: fields[key] for key in sorted(fields)}) diff --git a/src/aiida/orm/groups.py b/src/aiida/orm/groups.py index 38da3e616d..0d9a897625 100644 --- a/src/aiida/orm/groups.py +++ b/src/aiida/orm/groups.py @@ -8,17 +8,18 @@ ########################################################################### """AiiDA Group entites""" +import datetime import warnings from functools import cached_property from typing import TYPE_CHECKING, Any, ClassVar, Dict, Optional, Sequence, Tuple, Type, TypeVar, Union, cast from aiida.common import exceptions from aiida.common.lang import classproperty, type_check +from aiida.common.pydantic import MetadataField from aiida.common.warnings import warn_deprecation from aiida.manage import get_manager from . import convert, entities, extras, users -from .fields import add_field if TYPE_CHECKING: from importlib_metadata import EntryPoint @@ -108,51 +109,26 @@ class Group(entities.Entity['BackendGroup', GroupCollection]): __type_string: ClassVar[Optional[str]] - __qb_fields__ = [ - add_field( - 'uuid', - dtype=str, + class Model(entities.Entity.Model): + uuid: str = MetadataField(description='The UUID of the group', is_attribute=False, exclude_to_orm=True) + type_string: str = MetadataField(description='The type of the group', is_attribute=False, exclude_to_orm=True) + user: int = MetadataField( + description='The group owner', is_attribute=False, - doc='The UUID of the group', - ), - add_field( - 'type_string', - dtype=str, - is_attribute=False, - doc='The type of the group', - ), - add_field( - 'label', - dtype=str, - is_attribute=False, - doc='The group label', - ), - add_field( - 'description', - dtype=str, - is_attribute=False, - doc='The group description', - ), - add_field( - 'time', - dtype=str, - is_attribute=False, - doc='The time of the group creation', - ), - add_field( - 'extras', - dtype=Dict[str, Any], + orm_class='core.user', + orm_to_model=lambda group: group.user.pk, # type: ignore[attr-defined] + ) + time: Optional[datetime.datetime] = MetadataField( + description='The creation time of the node', is_attribute=False + ) + label: str = MetadataField(description='The group label', is_attribute=False) + description: Optional[str] = MetadataField(description='The group description', is_attribute=False) + extras: Optional[Dict[str, Any]] = MetadataField( + description='The group extras', is_attribute=False, is_subscriptable=True, - doc='The group extras', - ), - add_field( - 'user_pk', - dtype=int, - is_attribute=False, - doc='The PK for the creating user', - ), - ] + orm_to_model=lambda group: group.base.extras.all, # type: ignore[attr-defined] + ) _CLS_COLLECTION = GroupCollection @@ -162,6 +138,8 @@ def __init__( user: Optional['User'] = None, description: str = '', type_string: Optional[str] = None, + time: Optional[datetime.datetime] = None, + extras: Optional[Dict[str, Any]] = None, backend: Optional['StorageBackend'] = None, ): """Create a new group. Either pass a dbgroup parameter, to reload @@ -177,15 +155,19 @@ def __init__( if not label: raise ValueError('Group label must be provided') + if type_string: + warn_deprecation('Passing the `type_string` is deprecated, it is determined automatically', version=3) + backend = backend or get_manager().get_profile_storage() user = cast(users.User, user or backend.default_user) type_check(user, users.User) - type_string = self._type_string model = backend.groups.create( - label=label, user=user.backend_entity, description=description, type_string=type_string + label=label, user=user.backend_entity, description=description, type_string=self._type_string, time=time ) super().__init__(model) + if extras is not None: + self.base.extras.set_many(extras) @classproperty def _type_string(cls) -> Optional[str]: # noqa: N805 @@ -280,6 +262,11 @@ def type_string(self) -> str: """:return: the string defining the type of the group""" return self._backend_entity.type_string + @property + def time(self) -> datetime.datetime: + """:return: the creation time""" + return self._backend_entity.time + @property def user(self) -> 'User': """:return: the user associated with this group""" diff --git a/src/aiida/orm/implementation/groups.py b/src/aiida/orm/implementation/groups.py index 121271ca95..3be75c2050 100644 --- a/src/aiida/orm/implementation/groups.py +++ b/src/aiida/orm/implementation/groups.py @@ -9,6 +9,7 @@ """Backend group module""" import abc +import datetime from typing import TYPE_CHECKING, List, Optional, Protocol, Sequence, Union from .entities import BackendCollection, BackendEntity, BackendEntityExtrasMixin @@ -88,6 +89,11 @@ def user(self, user: 'BackendUser') -> None: def uuid(self) -> str: """Return the UUID of the group.""" + @property + @abc.abstractmethod + def time(self) -> datetime.datetime: + """Return the creation timestamp of the group.""" + @property @abc.abstractmethod def nodes(self) -> NodeIterator: diff --git a/src/aiida/orm/logs.py b/src/aiida/orm/logs.py index 25f9a594a5..134b98f845 100644 --- a/src/aiida/orm/logs.py +++ b/src/aiida/orm/logs.py @@ -13,10 +13,10 @@ from typing import TYPE_CHECKING, Any, Dict, List, Optional, Type from aiida.common import timezone +from aiida.common.pydantic import MetadataField from aiida.manage import get_manager from . import entities -from .fields import add_field if TYPE_CHECKING: from aiida.orm import Node @@ -129,50 +129,14 @@ class Log(entities.Entity['BackendLog', LogCollection]): _CLS_COLLECTION = LogCollection - __qb_fields__ = [ - add_field( - 'uuid', - dtype=str, - is_attribute=False, - doc='The UUID of the node', - ), - add_field( - 'loggername', - dtype=str, - is_attribute=False, - doc='The name of the logger', - ), - add_field( - 'levelname', - dtype=str, - is_attribute=False, - doc='The name of the log level', - ), - add_field( - 'message', - dtype=str, - is_attribute=False, - doc='The message of the log', - ), - add_field( - 'time', - dtype=datetime, - is_attribute=False, - doc='The time at which the log was created', - ), - add_field( - 'metadata', - dtype=Dict[str, Any], - is_attribute=False, - doc='The metadata of the log', - ), - add_field( - 'node_pk', - dtype=int, - is_attribute=False, - doc='The PK for the node', - ), - ] + class Model(entities.Entity.Model): + uuid: str = MetadataField(description='The UUID of the node', is_attribute=False, exclude_to_orm=True) + loggername: str = MetadataField(description='The name of the logger', is_attribute=False) + levelname: str = MetadataField(description='The name of the log level', is_attribute=False) + message: str = MetadataField(description='The message of the log', is_attribute=False) + time: datetime = MetadataField(description='The time at which the log was created', is_attribute=False) + metadata: Dict[str, Any] = MetadataField(description='The metadata of the log', is_attribute=False) + dbnode_id: int = MetadataField(description='Associated node', is_attribute=False) def __init__( self, diff --git a/src/aiida/orm/nodes/data/array/array.py b/src/aiida/orm/nodes/data/array/array.py index b77761acde..b3ccc019bd 100644 --- a/src/aiida/orm/nodes/data/array/array.py +++ b/src/aiida/orm/nodes/data/array/array.py @@ -10,9 +10,14 @@ from __future__ import annotations -from typing import Any, Iterator +import base64 +import io +from typing import Any, Iterator, Optional -from numpy import ndarray +import numpy as np +from pydantic import ConfigDict + +from aiida.common.pydantic import MetadataField from ..base import to_aiida_type from ..data import Data @@ -20,7 +25,7 @@ __all__ = ('ArrayData',) -@to_aiida_type.register(ndarray) +@to_aiida_type.register(np.ndarray) def _(value): return ArrayData(value) @@ -42,33 +47,67 @@ class ArrayData(Data): """ + class Model(Data.Model): + model_config = ConfigDict(arbitrary_types_allowed=True) + arrays: Optional[dict[str, bytes]] = MetadataField( + None, + description='The dictionary of numpy arrays.', + orm_to_model=lambda node: ArrayData.save_arrays(node.arrays), # type: ignore[attr-defined] + model_to_orm=lambda model: ArrayData.load_arrays(model.arrays), # type: ignore[attr-defined] + ) + array_prefix = 'array|' default_array_name = 'default' - def __init__(self, arrays: ndarray | dict[str, ndarray] | None = None, **kwargs): + def __init__(self, arrays: np.ndarray | dict[str, np.ndarray] | None = None, **kwargs): """Construct a new instance and set one or multiple numpy arrays. :param arrays: An optional single numpy array, or dictionary of numpy arrays to store. """ - import numpy - super().__init__(**kwargs) - self._cached_arrays: dict[str, ndarray] = {} + self._cached_arrays: dict[str, np.ndarray] = {} arrays = arrays if arrays is not None else {} - if isinstance(arrays, numpy.ndarray): + if isinstance(arrays, np.ndarray): arrays = {self.default_array_name: arrays} if ( not isinstance(arrays, dict) # type: ignore[redundant-expr] - or any(not isinstance(a, numpy.ndarray) for a in arrays.values()) + or any(not isinstance(a, np.ndarray) for a in arrays.values()) ): raise TypeError(f'`arrays` should be a single numpy array or dictionary of numpy arrays but got: {arrays}') for key, value in arrays.items(): self.set_array(key, value) + @staticmethod + def save_arrays(arrays: dict[str, np.ndarray]) -> dict[str, bytes]: + results = {} + + for key, array in arrays.items(): + stream = io.BytesIO() + np.save(stream, array) + stream.seek(0) + results[key] = base64.encodebytes(stream.read()) + + return results + + @staticmethod + def load_arrays(arrays: dict[str, bytes]) -> dict[str, np.ndarray]: + results = {} + + for key, encoded in arrays.items(): + stream = io.BytesIO(base64.decodebytes(encoded)) + stream.seek(0) + results[key] = np.load(stream) + + return results + + @property + def arrays(self) -> dict[str, np.ndarray]: + return {name: self.get_array(name) for name in self.get_arraynames()} + def initialize(self): super().initialize() self._cached_arrays = {} @@ -115,12 +154,12 @@ def get_shape(self, name: str) -> tuple[int, ...]: """ return tuple(self.base.attributes.get(f'{self.array_prefix}{name}')) - def get_iterarrays(self) -> Iterator[tuple[str, ndarray]]: + def get_iterarrays(self) -> Iterator[tuple[str, np.ndarray]]: """Iterator that returns tuples (name, array) for each array stored in the node.""" for name in self.get_arraynames(): yield (name, self.get_array(name)) - def get_array(self, name: str | None = None) -> ndarray: + def get_array(self, name: str | None = None) -> np.ndarray: """Return an array stored in the node :param name: The name of the array to return. The name can be omitted in case the node contains only a single @@ -141,7 +180,7 @@ def get_array(self, name: str | None = None) -> ndarray: name = names[0] - def get_array_from_file(self, name: str) -> ndarray: + def get_array_from_file(self, name: str) -> np.ndarray: """Return the array stored in a .npy file""" filename = f'{name}.npy' @@ -170,7 +209,7 @@ def clear_internal_cache(self) -> None: """ self._cached_arrays = {} - def set_array(self, name: str, array: ndarray) -> None: + def set_array(self, name: str, array: np.ndarray) -> None: """Store a new numpy array inside the node. Possibly overwrite the array if it already existed. @@ -182,9 +221,7 @@ def set_array(self, name: str, array: ndarray) -> None: import re import tempfile - import numpy - - if not isinstance(array, numpy.ndarray): + if not isinstance(array, np.ndarray): raise TypeError('ArrayData can only store numpy arrays. Convert the object to an array first') # Check if the name is valid @@ -196,7 +233,7 @@ def set_array(self, name: str, array: ndarray) -> None: # Write the array to a temporary file, and then add it to the repository of the node with tempfile.NamedTemporaryFile() as handle: - numpy.save(handle, array, allow_pickle=False) + np.save(handle, array, allow_pickle=False) # Flush and rewind the handle, otherwise the command to store it in the repo will write an empty file handle.flush() @@ -255,7 +292,7 @@ def _prepare_json(self, main_file_name='', comments=True) -> tuple[bytes, dict]: return json.dumps(json_dict).encode('utf-8'), {} -def clean_array(array: ndarray) -> list: +def clean_array(array: np.ndarray) -> list: """Replacing np.nan and np.inf/-np.inf for Nones. The function will also sanitize the array removing ``np.nan`` and ``np.inf`` diff --git a/src/aiida/orm/nodes/data/array/bands.py b/src/aiida/orm/nodes/data/array/bands.py index a33f104111..cbae36b90d 100644 --- a/src/aiida/orm/nodes/data/array/bands.py +++ b/src/aiida/orm/nodes/data/array/bands.py @@ -11,14 +11,14 @@ """ import json +import typing as t from string import Template -from typing import List, Optional import numpy from aiida.common.exceptions import ValidationError +from aiida.common.pydantic import MetadataField from aiida.common.utils import join_labels, prettify_labels -from aiida.orm.fields import add_field from .kpoints import KpointsData @@ -213,18 +213,9 @@ def nint(num): class BandsData(KpointsData): """Class to handle bands data""" - __qb_fields__ = [ - add_field( - 'array_labels', - dtype=Optional[List[str]], - doc='Labels associated with the band arrays', - ), - add_field( - 'units', - dtype=str, - doc='Units in which the data in bands were stored', - ), - ] + class Model(KpointsData.Model): + array_labels: t.Optional[t.List[str]] = MetadataField(description='Labels associated with the band arrays') + units: str = MetadataField(description='Units in which the data in bands were stored') def set_kpointsdata(self, kpointsdata): """Load the kpoints from a kpoint object. diff --git a/src/aiida/orm/nodes/data/array/kpoints.py b/src/aiida/orm/nodes/data/array/kpoints.py index ddf0cd6a96..e7958970a4 100644 --- a/src/aiida/orm/nodes/data/array/kpoints.py +++ b/src/aiida/orm/nodes/data/array/kpoints.py @@ -11,11 +11,11 @@ periodic crystal structure). """ -from typing import List +import typing as t import numpy -from aiida.orm.fields import add_field +from aiida.common.pydantic import MetadataField from .array import ArrayData @@ -38,48 +38,15 @@ class KpointsData(ArrayData): set_cell_from_structure methods. """ - __qb_fields__ = [ - add_field( - 'labels', - dtype=List[str], - doc='Labels associated with the list of kpoints', - ), - add_field( - 'label_numbers', - dtype=List[int], - doc='Index of the labels in the list of kpoints', - ), - add_field( - 'mesh', - dtype=List[int], - doc='Mesh of kpoints', - ), - add_field( - 'offset', - dtype=List[float], - doc='Offset of kpoints', - ), - add_field( - 'cell', - dtype=List[List[float]], - doc='Unit cell of the crystal, in Angstroms', - ), - add_field( - 'pbc1', - dtype=bool, - doc='True if the first lattice vector is periodic', - ), - add_field( - 'pbc2', - dtype=bool, - doc='True if the second lattice vector is periodic', - ), - add_field( - 'pbc3', - dtype=bool, - doc='True if the third lattice vector is periodic', - ), - ] + class Model(ArrayData.Model): + labels: t.List[str] = MetadataField(description='Labels associated with the list of kpoints') + label_numbers: t.List[int] = MetadataField(description='Index of the labels in the list of kpoints') + mesh: t.List[int] = MetadataField(description='Mesh of kpoints') + offset: t.List[float] = MetadataField(description='Offset of kpoints') + cell: t.List[t.List[float]] = MetadataField(description='Unit cell of the crystal, in Angstroms') + pbc1: bool = MetadataField(description='True if the first lattice vector is periodic') + pbc2: bool = MetadataField(description='True if the second lattice vector is periodic') + pbc3: bool = MetadataField(description='True if the third lattice vector is periodic') def get_description(self): """Returns a string with infos retrieved from kpoints node's properties. diff --git a/src/aiida/orm/nodes/data/array/trajectory.py b/src/aiida/orm/nodes/data/array/trajectory.py index 6381582b48..3d6356ebd2 100644 --- a/src/aiida/orm/nodes/data/array/trajectory.py +++ b/src/aiida/orm/nodes/data/array/trajectory.py @@ -11,7 +11,7 @@ import collections.abc from typing import List -from aiida.orm.fields import add_field +from aiida.common.pydantic import MetadataField from .array import ArrayData @@ -23,23 +23,10 @@ class TrajectoryData(ArrayData): possibly with velocities). """ - __qb_fields__ = [ - add_field( - 'units_positions', - 'units|positions', - dtype=str, - ), - add_field( - 'units_times', - 'units|times', - dtype=str, - ), - add_field( - 'symbols', - dtype=List[str], - doc='list of symbols', - ), - ] + class Model(ArrayData.Model): + units_positions: str = MetadataField(alias='units|positions', description='Unit of positions') + units_times: str = MetadataField(alias='units|times', description='Unit of time') + symbols: List[str] = MetadataField(description='List of symbols') def __init__(self, structurelist=None, **kwargs): super().__init__(**kwargs) diff --git a/src/aiida/orm/nodes/data/base.py b/src/aiida/orm/nodes/data/base.py index 265a7acd5f..adc0f3a98e 100644 --- a/src/aiida/orm/nodes/data/base.py +++ b/src/aiida/orm/nodes/data/base.py @@ -8,9 +8,10 @@ ########################################################################### """`Data` sub class to be used as a base for data containers that represent base python data types.""" +import typing as t from functools import singledispatch -from aiida.orm.fields import add_field +from aiida.common.pydantic import MetadataField from .data import Data @@ -26,12 +27,12 @@ def to_aiida_type(value): class BaseType(Data): """`Data` sub class to be used as a base for data containers that represent base python data types.""" - __qb_fields__ = [ - add_field( - 'value', - doc='The value of the data', - ), - ] + class Model(Data.Model): + value: t.Any = MetadataField( + ..., + title='Data value.', + description='The value of the data', + ) def __init__(self, value=None, **kwargs): try: diff --git a/src/aiida/orm/nodes/data/cif.py b/src/aiida/orm/nodes/data/cif.py index 9245d8d894..8421a617eb 100644 --- a/src/aiida/orm/nodes/data/cif.py +++ b/src/aiida/orm/nodes/data/cif.py @@ -9,10 +9,10 @@ """Tools for handling Crystallographic Information Files (CIF)""" import re -from typing import List +import typing as t +from aiida.common.pydantic import MetadataField from aiida.common.utils import Capturing -from aiida.orm.fields import add_field from .singlefile import SinglefileData @@ -250,20 +250,16 @@ class CifData(SinglefileData): _values = None _ase = None - __qb_fields__ = [ - add_field( - 'formulae', - dtype=List[str], - ), - add_field( - 'spacegroup_numbers', - dtype=List[str], - ), - add_field( - 'md5', - dtype=str, - ), - ] + class Model(SinglefileData.Model): + formulae: t.Optional[t.List[str]] = MetadataField( + None, description='List of formulae contained in the CIF file.', exclude_to_orm=True + ) + spacegroup_numbers: t.Optional[t.List[str]] = MetadataField( + None, description='List of space group numbers of the structure.', exclude_to_orm=True + ) + md5: t.Optional[str] = MetadataField( + None, description='MD5 checksum of the file contents.', exclude_to_orm=True + ) def __init__(self, ase=None, file=None, filename=None, values=None, scan_type=None, parse_policy=None, **kwargs): """Construct a new instance and set the contents to that of the file. @@ -383,6 +379,18 @@ def get_or_create(cls, filename, use_first=False, store_cif=True): return cifs[0], False + @property + def formulae(self): + return self.base.attributes.get('formulae') + + @property + def spacegroup_numbers(self): + return self.base.attributes.get('spacegroup_numbers') + + @property + def md5(self): + return self.base.attributes.get('md5') + @property def ase(self): """ASE object, representing the CIF. diff --git a/src/aiida/orm/nodes/data/code/abstract.py b/src/aiida/orm/nodes/data/code/abstract.py index b72a51e262..79fad0251f 100644 --- a/src/aiida/orm/nodes/data/code/abstract.py +++ b/src/aiida/orm/nodes/data/code/abstract.py @@ -15,13 +15,13 @@ import pathlib import typing as t -from pydantic import BaseModel, field_validator +from pydantic import field_validator from aiida.cmdline.params.options.interactive import TemplateInteractiveOption from aiida.common import exceptions from aiida.common.folders import Folder from aiida.common.lang import type_check -from aiida.common.pydantic import MetadataField +from aiida.common.pydantic import MetadataField, get_metadata from aiida.orm import Computer from aiida.plugins import CalculationFactory @@ -45,7 +45,7 @@ class AbstractCode(Data, metaclass=abc.ABCMeta): _KEY_ATTRIBUTE_WRAP_CMDLINE_PARAMS: str = 'wrap_cmdline_params' _KEY_EXTRA_IS_HIDDEN: str = 'hidden' # Should become ``is_hidden`` once ``Code`` is dropped - class Model(BaseModel, defer_build=True): + class Model(Data.Model, defer_build=True): """Model describing required information to create an instance.""" label: str = MetadataField( @@ -386,18 +386,13 @@ def _prepare_yaml(self, *args, **kwargs): """Export code to a YAML file.""" import yaml - code_data = {} - sort = kwargs.get('sort', False) + data = self.serialize() - for key in self.Model.model_fields.keys(): - value = getattr(self, key).label if key == 'computer' else getattr(self, key) + for key, field in self.Model.model_fields.items(): + if get_metadata(field, 'exclude_from_cli'): + data.pop(key) - # If the attribute is not set, for example ``with_mpi`` do not export it - # so that there are no null-values in the resulting YAML file - if value is not None: - code_data[key] = str(value) - - return yaml.dump(code_data, sort_keys=sort, encoding='utf-8'), {} + return yaml.dump(data, sort_keys=kwargs.get('sort', False), encoding='utf-8'), {} def _prepare_yml(self, *args, **kwargs): """Also allow for export as .yml""" diff --git a/src/aiida/orm/nodes/data/code/installed.py b/src/aiida/orm/nodes/data/code/installed.py index 7546c2acb8..a0c4245b3b 100644 --- a/src/aiida/orm/nodes/data/code/installed.py +++ b/src/aiida/orm/nodes/data/code/installed.py @@ -17,9 +17,8 @@ from __future__ import annotations import pathlib -import typing as t -from pydantic import ConfigDict, field_validator, model_validator +from pydantic import field_serializer, field_validator from aiida.common import exceptions from aiida.common.lang import type_check @@ -39,16 +38,16 @@ class InstalledCode(Code): _EMIT_CODE_DEPRECATION_WARNING: bool = False _KEY_ATTRIBUTE_FILEPATH_EXECUTABLE: str = 'filepath_executable' + _SKIP_MODEL_INHERITANCE_CHECK: bool = True class Model(AbstractCode.Model): """Model describing required information to create an instance.""" - model_config = ConfigDict(arbitrary_types_allowed=True) - - computer: t.Union[str, Computer] = MetadataField( + computer: str = MetadataField( # type: ignore[assignment] ..., title='Computer', description='The remote computer on which the executable resides.', + orm_to_model=lambda node: node.computer.label, short_name='-Y', priority=2, ) @@ -56,6 +55,7 @@ class Model(AbstractCode.Model): ..., title='Filepath executable', description='Filepath of the executable on the remote computer.', + orm_to_model=lambda node: str(node.filepath_executable), # type: ignore[attr-defined] short_name='-X', priority=1, ) @@ -77,21 +77,25 @@ def validate_computer(cls, value: str) -> Computer: except exceptions.NotExistent as exception: raise ValueError(exception) from exception - @model_validator(mode='after') # type: ignore[misc] - def validate_full_label_uniqueness(self) -> AbstractCode.Model: - """Validate that the full label does not already exist.""" - from aiida.orm import load_code - - full_label = f'{self.label}@{self.computer.label}' # type: ignore[union-attr] - - try: - load_code(full_label) - except exceptions.NotExistent: - return self - except exceptions.MultipleObjectsError as exception: - raise ValueError(f'Multiple codes with the label `{full_label}` already exist.') from exception - else: - raise ValueError(f'A code with the label `{full_label}` already exists.') + @field_serializer('computer') + def serialize_computer(self, computer: Computer, _info): + return computer.label + + # @model_validator(mode='after') # type: ignore[misc] + # def validate_full_label_uniqueness(self) -> AbstractCode.Model: + # """Validate that the full label does not already exist.""" + # from aiida.orm import load_code + + # full_label = f'{self.label}@{self.computer.label}' # type: ignore[attr-defined] + + # try: + # load_code(full_label) + # except exceptions.NotExistent: + # return self + # except exceptions.MultipleObjectsError as exception: + # raise ValueError(f'Multiple codes with the label `{full_label}` already exist.') from exception + # else: + # raise ValueError(f'A code with the label `{full_label}` already exists.') def __init__(self, computer: Computer, filepath_executable: str, **kwargs): """Construct a new instance. diff --git a/src/aiida/orm/nodes/data/code/legacy.py b/src/aiida/orm/nodes/data/code/legacy.py index 5f62b1cf97..a315acce05 100644 --- a/src/aiida/orm/nodes/data/code/legacy.py +++ b/src/aiida/orm/nodes/data/code/legacy.py @@ -10,13 +10,13 @@ import os import pathlib -from typing import Optional +import typing as t from aiida.common import exceptions from aiida.common.log import override_log_level +from aiida.common.pydantic import MetadataField from aiida.common.warnings import warn_deprecation from aiida.orm import Computer -from aiida.orm.fields import add_field from .abstract import AbstractCode @@ -39,38 +39,21 @@ class Code(AbstractCode): for the code to be run). """ - __qb_fields__ = [ - add_field( - 'prepend_text', - dtype=Optional[str], - doc='The code that will be put in the scheduler script before the execution of the code', - ), - add_field( - 'append_text', - dtype=Optional[str], - doc='The code that will be put in the scheduler script after the execution of the code', - ), - add_field( - 'input_plugin', - dtype=Optional[str], - doc='The name of the input plugin to be used for this code', - ), - add_field( - 'local_executable', - dtype=Optional[str], - doc='Path to a local executable', - ), - add_field( - 'remote_exec_path', - dtype=Optional[str], - doc='Remote path to executable', - ), - add_field( - 'is_local', - dtype=Optional[bool], - doc='Whether the code is local or remote', - ), - ] + class Model(AbstractCode.Model): + prepend_text: str = MetadataField( + '', + description='The code that will be put in the scheduler script before the execution of the code', + ) + append_text: str = MetadataField( + '', + description='The code that will be put in the scheduler script after the execution of the code', + ) + input_plugin: t.Optional[str] = MetadataField( + description='The name of the input plugin to be used for this code' + ) + local_executable: t.Optional[str] = MetadataField(description='Path to a local executable') + remote_exec_path: t.Optional[str] = MetadataField(description='Remote path to executable') + is_local: t.Optional[bool] = MetadataField(description='Whether the code is local or remote') def __init__(self, remote_computer_exec=None, local_executable=None, input_plugin_name=None, files=None, **kwargs): super().__init__(**kwargs) diff --git a/src/aiida/orm/nodes/data/code/portable.py b/src/aiida/orm/nodes/data/code/portable.py index 9db96c24f8..d4a19696b8 100644 --- a/src/aiida/orm/nodes/data/code/portable.py +++ b/src/aiida/orm/nodes/data/code/portable.py @@ -44,6 +44,7 @@ class PortableCode(Code): _EMIT_CODE_DEPRECATION_WARNING: bool = False _KEY_ATTRIBUTE_FILEPATH_EXECUTABLE: str = 'filepath_executable' + _SKIP_MODEL_INHERITANCE_CHECK: bool = True class Model(AbstractCode.Model): """Model describing required information to create an instance.""" diff --git a/src/aiida/orm/nodes/data/data.py b/src/aiida/orm/nodes/data/data.py index ec3118840a..56b3dcbdbb 100644 --- a/src/aiida/orm/nodes/data/data.py +++ b/src/aiida/orm/nodes/data/data.py @@ -13,8 +13,8 @@ from aiida.common import exceptions from aiida.common.lang import override from aiida.common.links import LinkType +from aiida.common.pydantic import MetadataField from aiida.orm.entities import from_backend_entity -from aiida.orm.fields import add_field from ..node import Node @@ -46,14 +46,10 @@ class Data(Node): _storable = True _unstorable_message = 'storing for this node has been disabled' - __qb_fields__ = [ - add_field( - 'source', - dtype=Optional[dict], - is_subscriptable=True, - doc='Source of the data', - ), - ] + class Model(Node.Model): + source: Optional[dict] = MetadataField( + None, description='Source of the data.', is_subscriptable=True, exclude_from_cli=True + ) def __init__(self, *args, source=None, **kwargs): """Construct a new instance, setting the ``source`` attribute if provided as a keyword argument.""" diff --git a/src/aiida/orm/nodes/data/dict.py b/src/aiida/orm/nodes/data/dict.py index f6e6cc87ca..99673de6fd 100644 --- a/src/aiida/orm/nodes/data/dict.py +++ b/src/aiida/orm/nodes/data/dict.py @@ -11,11 +11,10 @@ from __future__ import annotations import copy -from typing import Any -from typing import Dict as DictType +import typing as t from aiida.common import exceptions -from aiida.orm.fields import add_field +from aiida.common.pydantic import MetadataField from .base import to_aiida_type from .data import Data @@ -51,15 +50,12 @@ class Dict(Data): Finally, all dictionary mutations will be forbidden once the node is stored. """ - __qb_fields__ = [ - add_field( - 'dict', - dtype=DictType[str, Any], + class Model(Data.Model): + value: t.Dict[str, t.Any] = MetadataField( + description='Dictionary content.', is_attribute=False, is_subscriptable=True, - doc='Source of the data', - ), - ] + ) def __init__(self, value=None, **kwargs): """Initialise a ``Dict`` node instance. @@ -94,7 +90,7 @@ def __contains__(self, key: str) -> bool: """Return whether the node contains a key.""" return key in self.base.attributes - def get(self, key: str, default: Any | None = None, /): # type: ignore[override] + def get(self, key: str, default: t.Any | None = None, /): # type: ignore[override] """Return the value for key if key is in the dictionary, else default. :param key: The key whose value to return. @@ -153,6 +149,14 @@ def items(self): for key, value in self.base.attributes.items(): yield key, value + @property + def value(self) -> dict[str, t.Any]: + """Return the value of this node, which is the dictionary content. + + :return: The dictionary content. + """ + return self.base.attributes.all + @property def dict(self): """Return an instance of `AttributeManager` that transforms the dictionary into an attribute dict. diff --git a/src/aiida/orm/nodes/data/enum.py b/src/aiida/orm/nodes/data/enum.py index c7311a271c..1cb2c346fe 100644 --- a/src/aiida/orm/nodes/data/enum.py +++ b/src/aiida/orm/nodes/data/enum.py @@ -21,6 +21,7 @@ class Color(Enum): from plumpy.loaders import get_object_loader from aiida.common.lang import type_check +from aiida.common.pydantic import MetadataField from .base import to_aiida_type from .data import Data @@ -49,6 +50,12 @@ class of the enumeration) in the ``KEY_NAME``, ``KEY_VALUE`` and ``KEY_IDENTIFIE KEY_VALUE = 'value' KEY_IDENTIFIER = 'identifier' + class Model(Data.Model): + member: Enum = MetadataField( + description='The member name.', + orm_to_model=lambda node: node.get_member(), # type: ignore[attr-defined] + ) + def __init__(self, member: Enum, *args, **kwargs): """Construct the node for the to enum member that is to be wrapped.""" type_check(member, Enum) diff --git a/src/aiida/orm/nodes/data/jsonable.py b/src/aiida/orm/nodes/data/jsonable.py index 90387f6fa7..24309abd72 100644 --- a/src/aiida/orm/nodes/data/jsonable.py +++ b/src/aiida/orm/nodes/data/jsonable.py @@ -4,11 +4,16 @@ import json import typing +from pydantic import ConfigDict + +from aiida.common.pydantic import MetadataField + from .data import Data __all__ = ('JsonableData',) +@typing.runtime_checkable class JsonSerializableProtocol(typing.Protocol): def as_dict(self) -> typing.MutableMapping[typing.Any, typing.Any]: ... @@ -45,6 +50,10 @@ class JsonableData(Data): environment, or an ``ImportError`` will be raised. """ + class Model(Data.Model): + model_config = ConfigDict(arbitrary_types_allowed=True) + obj: JsonSerializableProtocol = MetadataField(description='The JSON-serializable object.') + def __init__(self, obj: JsonSerializableProtocol, *args, **kwargs): """Construct the node for the to be wrapped object.""" if obj is None: diff --git a/src/aiida/orm/nodes/data/list.py b/src/aiida/orm/nodes/data/list.py index d2c0857b35..f36dc70a8e 100644 --- a/src/aiida/orm/nodes/data/list.py +++ b/src/aiida/orm/nodes/data/list.py @@ -8,9 +8,12 @@ ########################################################################### """`Data` sub class to represent a list.""" +import typing as t from collections.abc import MutableSequence from typing import Any +from aiida.common.pydantic import MetadataField + from .base import to_aiida_type from .data import Data @@ -22,6 +25,11 @@ class List(Data, MutableSequence): _LIST_KEY = 'list' + class Model(Data.Model): + value: t.List[t.Any] = MetadataField( + description='Content of the data', + ) + def __init__(self, value=None, **kwargs): """Initialise a ``List`` node instance. @@ -110,6 +118,14 @@ def reverse(self): if not self._using_list_reference(): self.set_list(data) + @property + def value(self) -> list[t.Any]: + """Return the value of this node, which is the list content. + + :return: The list content. + """ + return self.get_list() + def get_list(self): """Return the contents of this node. diff --git a/src/aiida/orm/nodes/data/remote/base.py b/src/aiida/orm/nodes/data/remote/base.py index 1fc691d113..8631969a39 100644 --- a/src/aiida/orm/nodes/data/remote/base.py +++ b/src/aiida/orm/nodes/data/remote/base.py @@ -10,6 +10,7 @@ import os +from aiida.common.pydantic import MetadataField from aiida.orm import AuthInfo from aiida.orm.fields import add_field @@ -32,6 +33,9 @@ class RemoteData(Data): ), ] + class Model(Data.Model): + remote_path: str = MetadataField(description='Filepath on the remote computer.') + def __init__(self, remote_path=None, **kwargs): super().__init__(**kwargs) if remote_path is not None: diff --git a/src/aiida/orm/nodes/data/remote/stash/base.py b/src/aiida/orm/nodes/data/remote/stash/base.py index 27c8ddf245..7f9dfee200 100644 --- a/src/aiida/orm/nodes/data/remote/stash/base.py +++ b/src/aiida/orm/nodes/data/remote/stash/base.py @@ -2,7 +2,7 @@ from aiida.common.datastructures import StashMode from aiida.common.lang import type_check -from aiida.orm.fields import add_field +from aiida.common.pydantic import MetadataField from ...data import Data @@ -28,13 +28,8 @@ class RemoteStashData(Data): _storable = False - __qb_fields__ = [ - add_field( - 'stash_mode', - dtype=str, - doc='The mode with which the data was stashed', - ), - ] + class Model(Data.Model): + stash_mode: StashMode = MetadataField(description='The mode with which the data was stashed') def __init__(self, stash_mode: StashMode, **kwargs): """Construct a new instance diff --git a/src/aiida/orm/nodes/data/remote/stash/folder.py b/src/aiida/orm/nodes/data/remote/stash/folder.py index 2fe545af10..1c54c248ce 100644 --- a/src/aiida/orm/nodes/data/remote/stash/folder.py +++ b/src/aiida/orm/nodes/data/remote/stash/folder.py @@ -4,7 +4,7 @@ from aiida.common.datastructures import StashMode from aiida.common.lang import type_check -from aiida.orm.fields import add_field +from aiida.common.pydantic import MetadataField from .base import RemoteStashData @@ -19,18 +19,9 @@ class RemoteStashFolderData(RemoteStashData): _storable = True - __qb_fields__ = [ - add_field( - 'target_basepath', - dtype=str, - doc='The the target basepath', - ), - add_field( - 'source_list', - dtype=List[str], - doc='The list of source files that were stashed', - ), - ] + class Model(RemoteStashData.Model): + target_basepath: str = MetadataField(description='The the target basepath') + source_list: List[str] = MetadataField(description='The list of source files that were stashed') def __init__(self, stash_mode: StashMode, target_basepath: str, source_list: List, **kwargs): """Construct a new instance diff --git a/src/aiida/orm/nodes/data/singlefile.py b/src/aiida/orm/nodes/data/singlefile.py index 8faefc8cb4..c82e5d3cbc 100644 --- a/src/aiida/orm/nodes/data/singlefile.py +++ b/src/aiida/orm/nodes/data/singlefile.py @@ -17,6 +17,7 @@ import typing as t from aiida.common import exceptions +from aiida.common.pydantic import MetadataField from .data import Data @@ -30,6 +31,13 @@ class SinglefileData(Data): DEFAULT_FILENAME = 'file.txt' + class Model(Data.Model): + content: bytes = MetadataField( + description='The file content.', + model_to_orm=lambda model: io.BytesIO(model.content), # type: ignore[attr-defined] + ) + filename: t.Optional[str] = MetadataField(None, description='The filename. Defaults to `file.txt`.') + @classmethod def from_string(cls, content: str, filename: str | pathlib.Path | None = None, **kwargs: t.Any) -> 'SinglefileData': """Construct a new instance and set ``content`` as its contents. @@ -40,7 +48,11 @@ def from_string(cls, content: str, filename: str | pathlib.Path | None = None, * return cls(io.StringIO(content), filename, **kwargs) def __init__( - self, file: str | pathlib.Path | t.IO, filename: str | pathlib.Path | None = None, **kwargs: t.Any + self, + file: str | pathlib.Path | t.IO | None = None, + filename: str | pathlib.Path | None = None, + content: str | pathlib.Path | t.IO | None = None, + **kwargs: t.Any, ) -> None: """Construct a new instance and set the contents to that of the file. @@ -50,9 +62,19 @@ def __init__( """ super().__init__(**kwargs) + if file is not None and content is not None: + raise ValueError('cannot specify both `file` and `content`.') + + if content is not None: + file = content + if file is not None: self.set_file(file, filename=filename) + @property + def content(self) -> bytes: + return self.get_content(mode='rb') + @property def filename(self) -> str: """Return the name of the file stored. @@ -105,6 +127,12 @@ def as_path(self) -> t.Iterator[pathlib.Path]: with self.base.repository.as_path(self.filename) as filepath: yield filepath + @t.overload + def get_content(self, mode: t.Literal['rb']) -> bytes: ... + + @t.overload + def get_content(self, mode: t.Literal['r']) -> str: ... + def get_content(self, mode: str = 'r') -> str | bytes: """Return the content of the single file stored for this data node. diff --git a/src/aiida/orm/nodes/data/structure.py b/src/aiida/orm/nodes/data/structure.py index f046898b52..3f8534dd70 100644 --- a/src/aiida/orm/nodes/data/structure.py +++ b/src/aiida/orm/nodes/data/structure.py @@ -14,11 +14,11 @@ import functools import itertools import json -from typing import List, Optional +import typing as t from aiida.common.constants import elements from aiida.common.exceptions import UnsupportedSpeciesError -from aiida.orm.fields import add_field +from aiida.common.pydantic import MetadataField from .data import Data @@ -696,42 +696,32 @@ class StructureData(Data): _dimensionality_label = {0: '', 1: 'length', 2: 'surface', 3: 'volume'} _internal_kind_tags = None - __qb_fields__ = [ - add_field( - 'pbc1', - dtype=bool, - doc='Whether periodic in the a direction', - ), - add_field( - 'pbc2', - dtype=bool, - doc='Whether periodic in the b direction', - ), - add_field( - 'pbc3', - dtype=bool, - doc='Whether periodic in the c direction', - ), - add_field( - 'cell', - dtype=List[List[float]], - doc='The cell parameters', - ), - add_field( - 'kinds', - dtype=Optional[List[dict]], - doc='The kinds of atoms', - ), - add_field( - 'sites', - dtype=Optional[List[dict]], - doc='The atomic sites', - ), - ] + class Model(Data.Model): + pbc1: bool = MetadataField(description='Whether periodic in the a direction') + pbc2: bool = MetadataField(description='Whether periodic in the b direction') + pbc3: bool = MetadataField(description='Whether periodic in the c direction') + cell: t.List[t.List[float]] = MetadataField(description='The cell parameters') + kinds: t.Optional[t.List[dict]] = MetadataField(description='The kinds of atoms') + sites: t.Optional[t.List[dict]] = MetadataField(description='The atomic sites') def __init__( - self, cell=None, pbc=None, ase=None, pymatgen=None, pymatgen_structure=None, pymatgen_molecule=None, **kwargs + self, + cell=None, + pbc=None, + ase=None, + pymatgen=None, + pymatgen_structure=None, + pymatgen_molecule=None, + pbc1=None, + pbc2=None, + pbc3=None, + kinds=None, + sites=None, + **kwargs, ): + if pbc1 is not None and pbc2 is not None and pbc3 is not None: + pbc = [pbc1, pbc2, pbc3] + args = { 'cell': cell, 'pbc': pbc, @@ -769,6 +759,12 @@ def __init__( pbc = [True, True, True] self.set_pbc(pbc) + if kinds is not None: + self.base.attributes.set('kinds', kinds) + + if sites is not None: + self.base.attributes.set('sites', sites) + def get_dimensionality(self): """Return the dimensionality of the structure and its length/surface/volume. @@ -1532,7 +1528,7 @@ def get_kind_names(self): return [k.name for k in self.kinds] @property - def cell(self) -> List[List[float]]: + def cell(self) -> t.List[t.List[float]]: """Returns the cell shape. :return: a 3x3 list of lists. @@ -1617,6 +1613,18 @@ def reset_sites_positions(self, new_positions, conserve_particle=True): for this_new_site in new_sites: self.append_site(this_new_site) + @property + def pbc1(self): + return self.base.attributes.get('pbc1') + + @property + def pbc2(self): + return self.base.attributes.get('pbc2') + + @property + def pbc3(self): + return self.base.attributes.get('pbc3') + @property def pbc(self): """Get the periodic boundary conditions. diff --git a/src/aiida/orm/nodes/data/upf.py b/src/aiida/orm/nodes/data/upf.py index 6c0f945c22..c05b11f711 100644 --- a/src/aiida/orm/nodes/data/upf.py +++ b/src/aiida/orm/nodes/data/upf.py @@ -277,6 +277,8 @@ def parse_upf(fname, check_filename=True, encoding='utf-8'): class UpfData(SinglefileData): """`Data` sub class to represent a pseudopotential single file in UPF format.""" + CHECK_FILENAME = True + @classmethod def get_or_create(cls, filepath, use_first=False, store_upf=True, backend=None): """Get the `UpfData` with the same md5 of the given file, or create it if it does not yet exist. @@ -375,7 +377,7 @@ def set_file(self, file, filename=None): from aiida.common.exceptions import ParsingError from aiida.common.files import md5_file, md5_from_filelike - parsed_data = parse_upf(file) + parsed_data = parse_upf(file, check_filename=self.CHECK_FILENAME) try: md5sum = md5_file(file) diff --git a/src/aiida/orm/nodes/node.py b/src/aiida/orm/nodes/node.py index 442d3624e9..1c312cc87a 100644 --- a/src/aiida/orm/nodes/node.py +++ b/src/aiida/orm/nodes/node.py @@ -10,7 +10,8 @@ from __future__ import annotations -from datetime import datetime +import base64 +import datetime from functools import cached_property from logging import Logger from typing import TYPE_CHECKING, Any, ClassVar, Dict, Generic, Iterator, List, Optional, Tuple, Type, TypeVar @@ -19,6 +20,7 @@ from aiida.common import exceptions from aiida.common.lang import classproperty, type_check from aiida.common.links import LinkType +from aiida.common.pydantic import MetadataField from aiida.common.warnings import warn_deprecation from aiida.manage import get_manager from aiida.orm.utils.node import ( @@ -31,7 +33,6 @@ from ..entities import Collection as EntityCollection from ..entities import Entity, from_backend_entity from ..extras import EntityExtras -from ..fields import add_field from ..querybuilder import QueryBuilder from ..users import User from .attributes import NodeAttributes @@ -190,77 +191,101 @@ def _query_type_string(cls) -> str: # noqa: N805 _storable = False _unstorable_message = 'only Data, WorkflowNode, CalculationNode or their subclasses can be stored' - __qb_fields__ = [ - add_field( - 'uuid', - dtype=str, - is_attribute=False, - doc='The UUID of the node', - ), - add_field( - 'label', - dtype=str, - is_attribute=False, - doc='The node label', - ), - add_field( - 'description', - dtype=str, + class Model(Entity.Model): + uuid: Optional[str] = MetadataField( + None, description='The UUID of the node', is_attribute=False, exclude_to_orm=True, exclude_from_cli=True + ) + node_type: Optional[str] = MetadataField( + None, description='The type of the node', is_attribute=False, exclude_to_orm=True, exclude_from_cli=True + ) + process_type: Optional[str] = MetadataField( + None, + description='The process type of the node', is_attribute=False, - doc='The node description', - ), - add_field( - 'node_type', - dtype=str, + exclude_to_orm=True, + exclude_from_cli=True, + ) + repository_metadata: Optional[Dict[str, Any]] = MetadataField( + None, + description='Virtual hierarchy of the file repository.', is_attribute=False, - doc='The type of the node', - ), - add_field( - 'ctime', - dtype=datetime, + orm_to_model=lambda node: node.base.repository.metadata, # type: ignore[attr-defined] + exclude_to_orm=True, + exclude_from_cli=True, + ) + ctime: Optional[datetime.datetime] = MetadataField( + None, + description='The creation time of the node', is_attribute=False, - doc='The creation time of the node', - ), - add_field( - 'mtime', - dtype=datetime, + exclude_to_orm=True, + exclude_from_cli=True, + ) + mtime: Optional[datetime.datetime] = MetadataField( + None, + description='The modification time of the node', is_attribute=False, - doc='The modification time of the node', - ), - add_field( - 'repository_metadata', - dtype=Dict[str, Any], + exclude_to_orm=True, + exclude_from_cli=True, + ) + label: Optional[str] = MetadataField( + None, description='The node label', is_attribute=False, exclude_from_cli=True + ) + description: Optional[str] = MetadataField( + None, description='The node description', is_attribute=False, exclude_from_cli=True + ) + attributes: Optional[Dict[str, Any]] = MetadataField( + None, + description='The node attributes', is_attribute=False, - doc='The repository virtual file system', - ), - add_field( - 'extras', - dtype=Dict[str, Any], + orm_to_model=lambda node: node.base.attributes.all, # type: ignore[attr-defined] + is_subscriptable=True, + exclude_from_cli=True, + exclude_to_orm=True, + ) + extras: Optional[Dict[str, Any]] = MetadataField( + None, + description='The node extras', is_attribute=False, + orm_to_model=lambda node: node.base.extras.all, # type: ignore[attr-defined] is_subscriptable=True, - doc='The node extras', - ), - add_field( - 'user_pk', - dtype=int, + exclude_from_cli=True, + exclude_to_orm=True, + ) + computer: Optional[int] = MetadataField( + None, + description='The PK of the computer', + is_attribute=False, + orm_to_model=lambda node: node.computer.pk if node.computer else None, # type: ignore[attr-defined] + orm_class=Computer, + exclude_from_cli=True, + ) + user: Optional[int] = MetadataField( + None, + description='The PK of the user who owns the node', is_attribute=False, - doc='The PK of the user who owns the node', - ), - # Subclasses denote specific keys in the attributes dict - add_field( - 'attributes', - dtype=Dict[str, Any], + orm_to_model=lambda node: node.user.pk, # type: ignore[attr-defined] + orm_class=User, + exclude_from_cli=True, + ) + repository_content: Optional[dict[str, bytes]] = MetadataField( + None, + description='Dictionary of file repository content. Keys are relative filepaths and values are binary file ' + 'contents encoded as base64.', is_attribute=False, - is_subscriptable=True, - doc='The node attributes', - ), - ] + orm_to_model=lambda node: { + key: base64.encodebytes(content) + for key, content in node.base.repository.serialize_content().items() # type: ignore[attr-defined] + }, + exclude_from_cli=True, + exclude_to_orm=True, + ) def __init__( self, backend: Optional['StorageBackend'] = None, user: Optional[User] = None, computer: Optional[Computer] = None, + extras: Optional[Dict[str, Any]] = None, **kwargs: Any, ) -> None: backend = backend or get_manager().get_profile_storage() @@ -278,6 +303,21 @@ def __init__( node_type=self.class_node_type, user=user.backend_entity, computer=backend_computer, **kwargs ) super().__init__(backend_entity) + if extras is not None: + self.base.extras.set_many(extras) + + @classmethod + def from_model(cls, model: Model) -> 'Node': # type: ignore[override] + """Return an entity instance from an instance of its model.""" + fields = cls.model_to_orm_field_values(model) + + repository_content = fields.pop('repository_content', {}) + node = cls(**fields) + + for filepath, encoded in repository_content.items(): + node.base.repository.put_object_from_bytes(base64.decodebytes(encoded), filepath) + + return node @cached_property def base(self) -> NodeBase: @@ -477,7 +517,7 @@ def user(self, user: User) -> None: self.backend_entity.user = user.backend_entity @property - def ctime(self) -> datetime: + def ctime(self) -> datetime.datetime: """Return the node ctime. :return: the ctime @@ -485,7 +525,7 @@ def ctime(self) -> datetime: return self.backend_entity.ctime @property - def mtime(self) -> datetime: + def mtime(self) -> datetime.datetime: """Return the node mtime. :return: the mtime diff --git a/src/aiida/orm/nodes/process/calculation/calcjob.py b/src/aiida/orm/nodes/process/calculation/calcjob.py index a7cd20c88e..969d83b42a 100644 --- a/src/aiida/orm/nodes/process/calculation/calcjob.py +++ b/src/aiida/orm/nodes/process/calculation/calcjob.py @@ -14,7 +14,7 @@ from aiida.common import exceptions from aiida.common.datastructures import CalcJobState from aiida.common.lang import classproperty -from aiida.orm.fields import add_field +from aiida.common.pydantic import MetadataField from ..process import ProcessNodeCaching from .calculation import CalculationNode @@ -64,58 +64,43 @@ class CalcJobNode(CalculationNode): SCHEDULER_LAST_JOB_INFO_KEY = 'last_job_info' SCHEDULER_DETAILED_JOB_INFO_KEY = 'detailed_job_info' - __qb_fields__ = [ - add_field( - SCHEDULER_STATE_KEY, - dtype=Optional[str], - doc='The state of the scheduler', - ), - add_field( - CALC_JOB_STATE_KEY, - dtype=Optional[str], - doc='The active state of the calculation job', - ), - add_field( - REMOTE_WORKDIR_KEY, - dtype=Optional[str], - doc='The path to the remote (on cluster) scratch folder', - ), - add_field( - SCHEDULER_JOB_ID_KEY, - dtype=Optional[str], - doc='The scheduler job id', - ), - add_field( - SCHEDULER_LAST_CHECK_TIME_KEY, - dtype=Optional[str], - doc='The last time the scheduler was checked, in isoformat', - ), - add_field( - SCHEDULER_LAST_JOB_INFO_KEY, - dtype=Optional[str], - doc='The last job info returned by the scheduler', - ), - add_field( - SCHEDULER_DETAILED_JOB_INFO_KEY, - dtype=Optional[dict], - doc='The detailed job info returned by the scheduler', - ), - add_field( - RETRIEVE_LIST_KEY, - dtype=Optional[List[str]], - doc='The list of files to retrieve from the remote cluster', - ), - add_field( - RETRIEVE_TEMPORARY_LIST_KEY, - dtype=Optional[List[str]], - doc='The list of temporary files to retrieve from the remote cluster', - ), - add_field( - IMMIGRATED_KEY, - dtype=Optional[bool], - doc='Whether the node has been migrated', - ), - ] + class Model(CalculationNode.Model): + scheduler_state: Optional[str] = MetadataField( + description='The state of the scheduler', orm_to_model=lambda node: node.get_scheduler_state() + ) + state: Optional[str] = MetadataField( + description='The active state of the calculation job', orm_to_model=lambda node: node.get_state() + ) + remote_workdir: Optional[str] = MetadataField( + description='The path to the remote (on cluster) scratch folder', + orm_to_model=lambda node: node.get_remote_workdir(), + ) + job_id: Optional[str] = MetadataField( + description='The scheduler job id', orm_to_model=lambda node: node.get_job_id() + ) + scheduler_lastchecktime: Optional[datetime.datetime] = MetadataField( + description='The last time the scheduler was checked, in isoformat', + orm_to_model=lambda node: node.get_scheduler_lastchecktime(), + ) + last_job_info: Optional[dict] = MetadataField( + description='The last job info returned by the scheduler', + orm_to_model=lambda node: dict(node.get_last_job_info() or {}), + ) + detailed_job_info: Optional[dict] = MetadataField( + description='The detailed job info returned by the scheduler', + orm_to_model=lambda node: node.get_detailed_job_info(), + ) + retrieve_list: Optional[List[str]] = MetadataField( + description='The list of files to retrieve from the remote cluster', + orm_to_model=lambda node: node.get_retrieve_list(), + ) + retrieve_temporary_list: Optional[List[str]] = MetadataField( + description='The list of temporary files to retrieve from the remote cluster', + orm_to_model=lambda node: node.get_retrieve_temporary_list(), + ) + imported: Optional[bool] = MetadataField( + description='Whether the node has been migrated', orm_to_model=lambda node: node.is_imported + ) # An optional entry point for a CalculationTools instance _tools = None diff --git a/src/aiida/orm/nodes/process/process.py b/src/aiida/orm/nodes/process/process.py index 003aa231e4..da0433fee6 100644 --- a/src/aiida/orm/nodes/process/process.py +++ b/src/aiida/orm/nodes/process/process.py @@ -16,7 +16,7 @@ from aiida.common import exceptions from aiida.common.lang import classproperty from aiida.common.links import LinkType -from aiida.orm.fields import add_field +from aiida.common.pydantic import MetadataField from aiida.orm.utils.mixins import Sealable from ..caching import NodeCaching @@ -187,53 +187,14 @@ def _updatable_attributes(cls) -> Tuple[str, ...]: # noqa: N805 cls.PROCESS_STATUS_KEY, ) - __qb_fields__ = [ - add_field( - 'process_type', - dtype=Optional[str], - doc='The process type string', - ), - add_field( - 'computer_pk', - dtype=Optional[int], - doc='The computer PK', - ), - add_field( - PROCESS_LABEL_KEY, - dtype=Optional[str], - doc='The process label', - ), - add_field( - PROCESS_STATE_KEY, - dtype=Optional[str], - doc='The process state enum', - ), - add_field( - PROCESS_STATUS_KEY, - dtype=Optional[str], - doc='The process status is a generic status message', - ), - add_field( - EXIT_STATUS_KEY, - dtype=Optional[int], - doc='The process exit status', - ), - add_field( - EXIT_MESSAGE_KEY, - dtype=Optional[str], - doc='The process exit message', - ), - add_field( - EXCEPTION_KEY, - dtype=Optional[str], - doc='The process exception message', - ), - add_field( - PROCESS_PAUSED_KEY, - dtype=bool, - doc='Whether the process is paused', - ), - ] + class Model(Node.Model, Sealable.Model): + process_label: Optional[str] = MetadataField(description='The process label') + process_state: Optional[str] = MetadataField(description='The process state enum') + process_status: Optional[str] = MetadataField(description='The process status is a generic status message') + exit_status: Optional[int] = MetadataField(description='The process exit status') + exit_message: Optional[str] = MetadataField(description='The process exit message') + exception: Optional[str] = MetadataField(description='The process exception message') + paused: bool = MetadataField(description='Whether the process is paused') def set_metadata_inputs(self, value: Dict[str, Any]) -> None: """Set the mapping of inputs corresponding to ``metadata`` ports that were passed to the process.""" diff --git a/src/aiida/orm/nodes/repository.py b/src/aiida/orm/nodes/repository.py index bc24fe1377..c71de357af 100644 --- a/src/aiida/orm/nodes/repository.py +++ b/src/aiida/orm/nodes/repository.py @@ -134,6 +134,20 @@ def _clone(self, repo: 'NodeRepository') -> None: """ self._repository.clone(repo._repository) + def serialize_content(self) -> dict[str, bytes]: + """Serialize the content of the repository content into a JSON-serializable format. + + :return: dictionary with the content metadata. + """ + serialized = {} + + for dirpath, _, filenames in self.walk(): + for filename in filenames: + filepath = dirpath / filename + serialized[str(filepath)] = self.get_object_content(str(filepath), mode='rb') + + return serialized + def serialize(self) -> dict: """Serialize the metadata of the repository content into a JSON-serializable format. diff --git a/src/aiida/orm/users.py b/src/aiida/orm/users.py index a7d9095842..49564370ac 100644 --- a/src/aiida/orm/users.py +++ b/src/aiida/orm/users.py @@ -11,10 +11,10 @@ from typing import TYPE_CHECKING, Optional, Tuple, Type from aiida.common import exceptions +from aiida.common.pydantic import MetadataField from aiida.manage import get_manager from . import entities -from .fields import add_field if TYPE_CHECKING: from aiida.orm.implementation import StorageBackend @@ -53,32 +53,11 @@ class User(entities.Entity['BackendUser', UserCollection]): _CLS_COLLECTION = UserCollection - __qb_fields__ = [ - add_field( - 'email', - dtype=str, - is_attribute=False, - doc='The user email', - ), - add_field( - 'first_name', - dtype=str, - is_attribute=False, - doc='The user first name', - ), - add_field( - 'last_name', - dtype=str, - is_attribute=False, - doc='The user last name', - ), - add_field( - 'institution', - dtype=str, - is_attribute=False, - doc='The user institution', - ), - ] + class Model(entities.Entity.Model): + email: str = MetadataField(description='The user email', is_attribute=False) + first_name: str = MetadataField(description='The user first name', is_attribute=False) + last_name: str = MetadataField(description='The user last name', is_attribute=False) + institution: str = MetadataField(description='The user institution', is_attribute=False) def __init__( self, @@ -99,6 +78,12 @@ def __init__( def __str__(self) -> str: return self.email + def __eq__(self, other) -> bool: + if not isinstance(other, User): + return False + + return self.email == other.email + @staticmethod def normalize_email(email: str) -> str: """Normalize the address by lowercasing the domain part of the email address (taken from Django).""" diff --git a/src/aiida/orm/utils/mixins.py b/src/aiida/orm/utils/mixins.py index ac7d5baae0..fd022de2ce 100644 --- a/src/aiida/orm/utils/mixins.py +++ b/src/aiida/orm/utils/mixins.py @@ -12,10 +12,12 @@ import inspect +import pydantic + from aiida.common import exceptions from aiida.common.lang import classproperty, override, type_check +from aiida.common.pydantic import MetadataField from aiida.common.warnings import warn_deprecation -from aiida.orm.fields import add_field class FunctionCalculationMixin: @@ -181,22 +183,21 @@ class Sealable: SEALED_KEY = 'sealed' - __qb_fields__ = [ - add_field( - SEALED_KEY, - dtype=bool, - doc='Whether the node is sealed', - ), - ] + class Model(pydantic.BaseModel): + sealed: bool = MetadataField(description='Whether the node is sealed') @classproperty def _updatable_attributes(cls) -> tuple[str, ...]: # noqa: N805 return (cls.SEALED_KEY,) + @property + def sealed(self) -> bool: + return self.base.attributes.get(self.SEALED_KEY, False) # type: ignore[attr-defined] + @property def is_sealed(self) -> bool: """Returns whether the node is sealed, i.e. whether the sealed attribute has been set to True.""" - return self.base.attributes.get(self.SEALED_KEY, False) # type: ignore[attr-defined] + return self.sealed def seal(self) -> 'Sealable': """Seal the node by setting the sealed attribute to True.""" diff --git a/src/aiida/orm/utils/node.py b/src/aiida/orm/utils/node.py index 0848c72f3d..f5ff3f6592 100644 --- a/src/aiida/orm/utils/node.py +++ b/src/aiida/orm/utils/node.py @@ -95,7 +95,7 @@ def get_type_string_from_class(class_module, class_name): else: type_string = f'{class_module}.{class_name}.' - prefixes = ('aiida.orm.nodes.',) + prefixes = ('aiida.orm.nodes.', 'aiida.orm.core.') # Sequentially and **in order** strip the prefixes if present for prefix in prefixes: diff --git a/src/aiida/plugins/entry_point.py b/src/aiida/plugins/entry_point.py index e8c553e3c6..ee61b3cf42 100644 --- a/src/aiida/plugins/entry_point.py +++ b/src/aiida/plugins/entry_point.py @@ -89,6 +89,7 @@ class EntryPointFormat(enum.Enum): 'aiida.cmdline.data.structure.import': 'aiida.cmdline.data.structure.import', 'aiida.data': 'aiida.orm.nodes.data', 'aiida.groups': 'aiida.orm.groups', + 'aiida.orm': 'aiida.orm', 'aiida.node': 'aiida.orm.nodes', 'aiida.parsers': 'aiida.parsers.plugins', 'aiida.schedulers': 'aiida.schedulers.plugins', diff --git a/src/aiida/storage/psql_dos/orm/authinfos.py b/src/aiida/storage/psql_dos/orm/authinfos.py index 801fb64b4d..77a18e6023 100644 --- a/src/aiida/storage/psql_dos/orm/authinfos.py +++ b/src/aiida/storage/psql_dos/orm/authinfos.py @@ -23,7 +23,7 @@ class SqlaAuthInfo(entities.SqlaModelEntity[DbAuthInfo], BackendAuthInfo): USER_CLASS = users.SqlaUser COMPUTER_CLASS = computers.SqlaComputer - def __init__(self, backend, computer, user): + def __init__(self, backend, computer, user, enabled, auth_params, metadata): """Construct a new instance. :param computer: a :class:`aiida.orm.implementation.computers.BackendComputer` instance @@ -34,7 +34,14 @@ def __init__(self, backend, computer, user): type_check(user, self.USER_CLASS) type_check(computer, self.COMPUTER_CLASS) self._model = utils.ModelWrapper( - self.MODEL_CLASS(dbcomputer=computer.bare_model, aiidauser=user.bare_model), backend + self.MODEL_CLASS( + dbcomputer=computer.bare_model, + aiidauser=user.bare_model, + enabled=enabled, + auth_params=auth_params, + metadata=metadata, + ), + backend, ) @property diff --git a/src/aiida/storage/psql_dos/orm/groups.py b/src/aiida/storage/psql_dos/orm/groups.py index ee82dc24ec..afba12681b 100644 --- a/src/aiida/storage/psql_dos/orm/groups.py +++ b/src/aiida/storage/psql_dos/orm/groups.py @@ -32,7 +32,7 @@ class SqlaGroup(entities.SqlaModelEntity[DbGroup], ExtrasMixin, BackendGroup): NODE_CLASS = SqlaNode GROUP_NODE_CLASS = DbGroupNode - def __init__(self, backend, label, user, description='', type_string=''): + def __init__(self, backend, label, user, description='', type_string='', time=None): """Construct a new SQLA group :param backend: the backend to use @@ -44,7 +44,9 @@ def __init__(self, backend, label, user, description='', type_string=''): type_check(user, self.USER_CLASS) super().__init__(backend) - dbgroup = self.MODEL_CLASS(label=label, description=description, user=user.bare_model, type_string=type_string) + dbgroup = self.MODEL_CLASS( + label=label, description=description, user=user.bare_model, type_string=type_string, time=time + ) self._model = utils.ModelWrapper(dbgroup, backend) @property @@ -101,6 +103,10 @@ def pk(self): def uuid(self): return str(self.model.uuid) + @property + def time(self): + return self.model.time + @property def is_stored(self): return self.pk is not None diff --git a/src/aiida/storage/psql_dos/orm/querybuilder/main.py b/src/aiida/storage/psql_dos/orm/querybuilder/main.py index cf18134c0f..057cdeec99 100644 --- a/src/aiida/storage/psql_dos/orm/querybuilder/main.py +++ b/src/aiida/storage/psql_dos/orm/querybuilder/main.py @@ -48,7 +48,6 @@ }, 'db_dbnode': { 'pk': 'id', - 'dict': 'attributes', 'computer_pk': 'dbcomputer_id', 'user_pk': 'user_id', }, diff --git a/tests/cmdline/commands/test_code/test_code_export___no_sort_.yml b/tests/cmdline/commands/test_code/test_code_export___no_sort_.yml index 149df704b0..db9c8dc4d4 100644 --- a/tests/cmdline/commands/test_code/test_code_export___no_sort_.yml +++ b/tests/cmdline/commands/test_code/test_code_export___no_sort_.yml @@ -1,8 +1,9 @@ label: code description: '' +computer: localhost default_calc_job_plugin: core.arithmetic.add -use_double_quotes: 'False' +use_double_quotes: false +with_mpi: null prepend_text: "module load something\n some command" append_text: '' -computer: localhost filepath_executable: /bin/cat diff --git a/tests/cmdline/commands/test_code/test_code_export___sort_.yml b/tests/cmdline/commands/test_code/test_code_export___sort_.yml index 640717a1d2..3c0037409a 100644 --- a/tests/cmdline/commands/test_code/test_code_export___sort_.yml +++ b/tests/cmdline/commands/test_code/test_code_export___sort_.yml @@ -5,4 +5,5 @@ description: '' filepath_executable: /bin/cat label: code prepend_text: "module load something\n some command" -use_double_quotes: 'False' +use_double_quotes: false +with_mpi: null diff --git a/tests/orm/models/__init__.py b/tests/orm/models/__init__.py new file mode 100644 index 0000000000..40ed1e2958 --- /dev/null +++ b/tests/orm/models/__init__.py @@ -0,0 +1 @@ +"""Tests for the ``Model`` class attribute of ``Entity`` subclasses.""" diff --git a/tests/orm/models/test_models.py b/tests/orm/models/test_models.py new file mode 100644 index 0000000000..19a2e8b363 --- /dev/null +++ b/tests/orm/models/test_models.py @@ -0,0 +1,173 @@ +"""Tests for the ``Model`` class attribute of ``Entity`` subclasses.""" + +import datetime +import enum +import io + +import numpy as np +import pytest +from pydantic import BaseModel + +from aiida.orm import AuthInfo, Comment, Computer, Group, Log, User +from aiida.orm.nodes.data import ( + ArrayData, + Bool, + CifData, + Data, + Dict, + EnumData, + Float, + FolderData, + Int, + JsonableData, + List, + SinglefileData, + Str, + StructureData, +) + + +class DummyEnum(enum.Enum): + """Dummy enum for testing.""" + + OPTION_A = 'a' + OPTION_B = 'b' + + +class JsonableClass: + """Dummy class that implements the required interface.""" + + def __init__(self, data): + """Construct a new object.""" + self._data = data + + @property + def data(self): + """Return the data of this instance.""" + return self._data + + def as_dict(self): + """Represent the object as a JSON-serializable dictionary.""" + return { + 'data': self._data, + } + + @classmethod + def from_dict(cls, dictionary): + """Reconstruct an instance from a serialized version.""" + return cls(dictionary['data']) + + +@pytest.fixture +def required_arguments(request, default_user, aiida_localhost, tmp_path): + if request.param is AuthInfo: + return AuthInfo, {'user': default_user, 'computer': aiida_localhost} + if request.param is Comment: + return Comment, {'user': default_user, 'node': Data().store(), 'content': ''} + if request.param is Computer: + return Computer, {'label': 'localhost'} + if request.param is Group: + return Group, {'label': 'group'} + if request.param is Log: + return Log, { + 'time': datetime.datetime.now(), + 'loggername': 'logger', + 'levelname': 'REPORT', + 'message': 'message', + 'dbnode_id': Data().store().pk, + } + if request.param is User: + return User, {'email': 'test@localhost'} + if request.param is ArrayData: + return ArrayData, {'arrays': np.array([1, 0, 0])} + if request.param is Bool: + return Bool, {'value': True} + if request.param is CifData: + return CifData, {'content': io.BytesIO(b'some-content')} + if request.param is Data: + return Data, {'source': {'uri': 'http://127.0.0.1'}} + if request.param is Dict: + return Dict, {'value': {'a': 1}} + if request.param is EnumData: + return EnumData, {'member': DummyEnum.OPTION_A} + if request.param is Float: + return Float, {'value': 1.0} + if request.param is FolderData: + dirpath = tmp_path / 'folder_data' + dirpath.mkdir() + (dirpath / 'binary_file').write_bytes(b'byte content') + (dirpath / 'text_file').write_text('text content') + return FolderData, {'tree': dirpath} + if request.param is Int: + return Int, {'value': 1} + if request.param is JsonableData: + return JsonableData, {'obj': JsonableClass({'a': 1})} + if request.param is List: + return List, {'value': [1.0]} + if request.param is SinglefileData: + return SinglefileData, {'content': io.BytesIO(b'some-content')} + if request.param is Str: + return Str, {'value': 'string'} + if request.param is StructureData: + return StructureData, {'cell': [[1, 0, 0], [0, 1, 0], [0, 0, 1]]} + + raise NotImplementedError() + + +@pytest.mark.parametrize( + 'required_arguments', + ( + AuthInfo, + Comment, + Computer, + Group, + Log, + User, + SinglefileData, + ArrayData, + Bool, + CifData, + Data, + Dict, + EnumData, + Float, + FolderData, + Int, + JsonableData, + List, + SinglefileData, + Str, + StructureData, + ), + indirect=True, +) +def test_roundtrip(required_arguments): + cls, kwargs = required_arguments + + # Construct instance of the entity class + entity = cls(**kwargs) + assert isinstance(entity, cls) + + # Get the model instance from the entity instance + model = entity.to_model() + assert isinstance(model, BaseModel) + + # Reconstruct the entity instance from the model instance + roundtrip = cls.from_model(model) + assert isinstance(roundtrip, cls) + + # Get the model instance again from the reconstructed entity and check that the fields that would be passed to the + # ORM entity constructor are identical of the original model. The ``model_to_orm_field_values`` excludes values of + # fields that define ``exclude_to_orm=True`` because these can change during roundtrips. This because these + # typically correspond to entity fields that have defaults set on the database level, e.g., UUIDs. + roundtrip_model = roundtrip.to_model() + original_field_values = cls.model_to_orm_field_values(model) + + for key, value in cls.model_to_orm_field_values(roundtrip_model).items(): + if isinstance(value, io.BytesIO): + assert value.read() == original_field_values[key].read() + elif cls is ArrayData and key == 'arrays': + for array_name, array in value.items(): + assert np.array_equal(array, original_field_values[key][array_name]) + else: + assert value == original_field_values[key] diff --git a/tests/orm/test_fields.py b/tests/orm/test_fields.py index 0d5e934f8b..f22fdc3c73 100644 --- a/tests/orm/test_fields.py +++ b/tests/orm/test_fields.py @@ -12,6 +12,7 @@ from importlib_metadata import entry_points from aiida import orm +from aiida.common.pydantic import MetadataField from aiida.orm.fields import add_field from aiida.plugins import load_entry_point @@ -35,7 +36,7 @@ def node_and_data_entry_points() -> list[tuple[str, str]]: _eps: list[tuple[str, str]] = [] eps = entry_points() for group in ['aiida.node', 'aiida.data']: - _eps.extend((group, ep.name) for ep in eps.select(group=group)) + _eps.extend((group, ep.name) for ep in eps.select(group=group) if ep.name.startswith('core.')) return _eps @@ -53,13 +54,10 @@ def test_add_field(): """Test the `add_field` API.""" class NewNode(orm.Data): - __qb_fields__ = ( - add_field( - 'key1', - dtype=str, + class Model(orm.Data.Model): + key1: str = MetadataField( # type: ignore[annotation-unchecked] is_subscriptable=False, - ), - ) + ) node = NewNode() @@ -104,10 +102,9 @@ def _dummy(*args, **kwargs): ) class NewNode(orm.Data): - __qb_fields__ = [ - add_field('some_label', dtype=str), - add_field('some_value', dtype=int), - ] + class Model(orm.Data.Model): + some_label: str = MetadataField() # type: ignore[annotation-unchecked] + some_value: int = MetadataField() # type: ignore[annotation-unchecked] node = NewNode() node.base.attributes.set_many({'some_label': 'A', 'some_value': 1}) @@ -210,14 +207,14 @@ def test_query_filters(): @pytest.mark.usefixtures('aiida_profile_clean') def test_query_subscriptable(): """Test using subscriptable fields in a query.""" - node = orm.Dict(dict={'a': 1}).store() + node = orm.Dict({'a': 1}).store() node.base.extras.set('b', 2) result = ( orm.QueryBuilder() .append( orm.Dict, project=[ - orm.Dict.fields.dict['a'], + orm.Dict.fields.attributes['a'], orm.Dict.fields.extras['b'], ], ) diff --git a/tests/orm/test_fields/fields_AuthInfo.yml b/tests/orm/test_fields/fields_AuthInfo.yml index 7f7e4473ac..505c96da91 100644 --- a/tests/orm/test_fields/fields_AuthInfo.yml +++ b/tests/orm/test_fields/fields_AuthInfo.yml @@ -1,6 +1,6 @@ -auth_params: QbDictField('auth_params', dtype=Dict[str, Any], is_attribute=False) -computer_pk: QbNumericField('computer_pk', dtype=int, is_attribute=False) -enabled: QbField('enabled', dtype=bool, is_attribute=False) -metadata: QbDictField('metadata', dtype=Dict[str, Any], is_attribute=False) -pk: QbNumericField('pk', dtype=int, is_attribute=False) -user_pk: QbNumericField('user_pk', dtype=int, is_attribute=False) +auth_params: QbDictField('auth_params', dtype=typing.Dict[str, typing.Any], is_attribute=False) +computer: QbNumericField('computer', dtype=, is_attribute=False) +enabled: QbField('enabled', dtype=, is_attribute=False) +metadata: QbDictField('metadata', dtype=typing.Dict[str, typing.Any], is_attribute=False) +pk: QbNumericField('pk', dtype=typing.Optional[int], is_attribute=False) +user: QbNumericField('user', dtype=, is_attribute=False) diff --git a/tests/orm/test_fields/fields_Comment.yml b/tests/orm/test_fields/fields_Comment.yml index 727563a907..30aedcef79 100644 --- a/tests/orm/test_fields/fields_Comment.yml +++ b/tests/orm/test_fields/fields_Comment.yml @@ -1,7 +1,7 @@ -content: QbStrField('content', dtype=str, is_attribute=False) -ctime: QbNumericField('ctime', dtype=datetime, is_attribute=False) -mtime: QbNumericField('mtime', dtype=datetime, is_attribute=False) -node_pk: QbNumericField('node_pk', dtype=int, is_attribute=False) -pk: QbNumericField('pk', dtype=int, is_attribute=False) -user_pk: QbNumericField('user_pk', dtype=int, is_attribute=False) -uuid: QbStrField('uuid', dtype=str, is_attribute=False) +content: QbStrField('content', dtype=, is_attribute=False) +ctime: QbNumericField('ctime', dtype=typing.Optional[datetime.datetime], is_attribute=False) +mtime: QbNumericField('mtime', dtype=typing.Optional[datetime.datetime], is_attribute=False) +node: QbNumericField('node', dtype=, is_attribute=False) +pk: QbNumericField('pk', dtype=typing.Optional[int], is_attribute=False) +user: QbNumericField('user', dtype=, is_attribute=False) +uuid: QbStrField('uuid', dtype=typing.Optional[str], is_attribute=False) diff --git a/tests/orm/test_fields/fields_Computer.yml b/tests/orm/test_fields/fields_Computer.yml index bfc4d20ad5..7d4e37168b 100644 --- a/tests/orm/test_fields/fields_Computer.yml +++ b/tests/orm/test_fields/fields_Computer.yml @@ -1,8 +1,8 @@ -description: QbStrField('description', dtype=str, is_attribute=False) -hostname: QbStrField('hostname', dtype=str, is_attribute=False) -label: QbStrField('label', dtype=str, is_attribute=False) -metadata: QbDictField('metadata', dtype=Dict[str, Any], is_attribute=False) -pk: QbNumericField('pk', dtype=int, is_attribute=False) -scheduler_type: QbStrField('scheduler_type', dtype=str, is_attribute=False) -transport_type: QbStrField('transport_type', dtype=str, is_attribute=False) -uuid: QbStrField('uuid', dtype=str, is_attribute=False) +description: QbStrField('description', dtype=, is_attribute=False) +hostname: QbStrField('hostname', dtype=, is_attribute=False) +label: QbStrField('label', dtype=, is_attribute=False) +metadata: QbDictField('metadata', dtype=typing.Dict[str, typing.Any], is_attribute=False) +pk: QbNumericField('pk', dtype=typing.Optional[int], is_attribute=False) +scheduler_type: QbStrField('scheduler_type', dtype=, is_attribute=False) +transport_type: QbStrField('transport_type', dtype=, is_attribute=False) +uuid: QbStrField('uuid', dtype=, is_attribute=False) diff --git a/tests/orm/test_fields/fields_Group.yml b/tests/orm/test_fields/fields_Group.yml index 6e98912b6a..537c76a11d 100644 --- a/tests/orm/test_fields/fields_Group.yml +++ b/tests/orm/test_fields/fields_Group.yml @@ -1,8 +1,9 @@ -description: QbStrField('description', dtype=str, is_attribute=False) -extras: QbDictField('extras', dtype=Dict[str, Any], is_attribute=False, is_subscriptable=True) -label: QbStrField('label', dtype=str, is_attribute=False) -pk: QbNumericField('pk', dtype=int, is_attribute=False) -time: QbStrField('time', dtype=str, is_attribute=False) -type_string: QbStrField('type_string', dtype=str, is_attribute=False) -user_pk: QbNumericField('user_pk', dtype=int, is_attribute=False) -uuid: QbStrField('uuid', dtype=str, is_attribute=False) +description: QbStrField('description', dtype=typing.Optional[str], is_attribute=False) +extras: QbDictField('extras', dtype=typing.Optional[typing.Dict[str, typing.Any]], + is_attribute=False, is_subscriptable=True) +label: QbStrField('label', dtype=, is_attribute=False) +pk: QbNumericField('pk', dtype=typing.Optional[int], is_attribute=False) +time: QbNumericField('time', dtype=typing.Optional[datetime.datetime], is_attribute=False) +type_string: QbStrField('type_string', dtype=, is_attribute=False) +user: QbNumericField('user', dtype=, is_attribute=False) +uuid: QbStrField('uuid', dtype=, is_attribute=False) diff --git a/tests/orm/test_fields/fields_Log.yml b/tests/orm/test_fields/fields_Log.yml index 3e5153e0a0..90bf0a5b0b 100644 --- a/tests/orm/test_fields/fields_Log.yml +++ b/tests/orm/test_fields/fields_Log.yml @@ -1,8 +1,8 @@ -levelname: QbStrField('levelname', dtype=str, is_attribute=False) -loggername: QbStrField('loggername', dtype=str, is_attribute=False) -message: QbStrField('message', dtype=str, is_attribute=False) -metadata: QbDictField('metadata', dtype=Dict[str, Any], is_attribute=False) -node_pk: QbNumericField('node_pk', dtype=int, is_attribute=False) -pk: QbNumericField('pk', dtype=int, is_attribute=False) -time: QbNumericField('time', dtype=datetime, is_attribute=False) -uuid: QbStrField('uuid', dtype=str, is_attribute=False) +dbnode_id: QbNumericField('dbnode_id', dtype=, is_attribute=False) +levelname: QbStrField('levelname', dtype=, is_attribute=False) +loggername: QbStrField('loggername', dtype=, is_attribute=False) +message: QbStrField('message', dtype=, is_attribute=False) +metadata: QbDictField('metadata', dtype=typing.Dict[str, typing.Any], is_attribute=False) +pk: QbNumericField('pk', dtype=typing.Optional[int], is_attribute=False) +time: QbNumericField('time', dtype=, is_attribute=False) +uuid: QbStrField('uuid', dtype=, is_attribute=False) diff --git a/tests/orm/test_fields/fields_User.yml b/tests/orm/test_fields/fields_User.yml index 2eaf3af067..06fb9cd05c 100644 --- a/tests/orm/test_fields/fields_User.yml +++ b/tests/orm/test_fields/fields_User.yml @@ -1,5 +1,5 @@ -email: QbStrField('email', dtype=str, is_attribute=False) -first_name: QbStrField('first_name', dtype=str, is_attribute=False) -institution: QbStrField('institution', dtype=str, is_attribute=False) -last_name: QbStrField('last_name', dtype=str, is_attribute=False) -pk: QbNumericField('pk', dtype=int, is_attribute=False) +email: QbStrField('email', dtype=, is_attribute=False) +first_name: QbStrField('first_name', dtype=, is_attribute=False) +institution: QbStrField('institution', dtype=, is_attribute=False) +last_name: QbStrField('last_name', dtype=, is_attribute=False) +pk: QbNumericField('pk', dtype=typing.Optional[int], is_attribute=False) diff --git a/tests/orm/test_fields/fields_aiida.data.core.array.ArrayData.yml b/tests/orm/test_fields/fields_aiida.data.core.array.ArrayData.yml index eba6460b84..c31304e6f5 100644 --- a/tests/orm/test_fields/fields_aiida.data.core.array.ArrayData.yml +++ b/tests/orm/test_fields/fields_aiida.data.core.array.ArrayData.yml @@ -1,12 +1,20 @@ -attributes: QbDictField('attributes', dtype=Dict[str, Any], is_attribute=False, is_subscriptable=True) -ctime: QbNumericField('ctime', dtype=datetime, is_attribute=False) -description: QbStrField('description', dtype=str, is_attribute=False) -extras: QbDictField('extras', dtype=Dict[str, Any], is_attribute=False, is_subscriptable=True) -label: QbStrField('label', dtype=str, is_attribute=False) -mtime: QbNumericField('mtime', dtype=datetime, is_attribute=False) -node_type: QbStrField('node_type', dtype=str, is_attribute=False) -pk: QbNumericField('pk', dtype=int, is_attribute=False) -repository_metadata: QbDictField('repository_metadata', dtype=Dict[str, Any], is_attribute=False) -source: QbDictField('source', dtype=Optional[dict], is_attribute=True, is_subscriptable=True) -user_pk: QbNumericField('user_pk', dtype=int, is_attribute=False) -uuid: QbStrField('uuid', dtype=str, is_attribute=False) +arrays: QbDictField('arrays', dtype=typing.Optional[dict[str, bytes]], is_attribute=True) +attributes: QbDictField('attributes', dtype=typing.Optional[typing.Dict[str, typing.Any]], + is_attribute=False, is_subscriptable=True) +computer: QbNumericField('computer', dtype=typing.Optional[int], is_attribute=False) +ctime: QbNumericField('ctime', dtype=typing.Optional[datetime.datetime], is_attribute=False) +description: QbStrField('description', dtype=typing.Optional[str], is_attribute=False) +extras: QbDictField('extras', dtype=typing.Optional[typing.Dict[str, typing.Any]], + is_attribute=False, is_subscriptable=True) +label: QbStrField('label', dtype=typing.Optional[str], is_attribute=False) +mtime: QbNumericField('mtime', dtype=typing.Optional[datetime.datetime], is_attribute=False) +node_type: QbStrField('node_type', dtype=typing.Optional[str], is_attribute=False) +pk: QbNumericField('pk', dtype=typing.Optional[int], is_attribute=False) +process_type: QbStrField('process_type', dtype=typing.Optional[str], is_attribute=False) +repository_content: QbDictField('repository_content', dtype=typing.Optional[dict[str, + bytes]], is_attribute=False) +repository_metadata: QbDictField('repository_metadata', dtype=typing.Optional[typing.Dict[str, + typing.Any]], is_attribute=False) +source: QbDictField('source', dtype=typing.Optional[dict], is_attribute=True, is_subscriptable=True) +user: QbNumericField('user', dtype=typing.Optional[int], is_attribute=False) +uuid: QbStrField('uuid', dtype=typing.Optional[str], is_attribute=False) diff --git a/tests/orm/test_fields/fields_aiida.data.core.array.bands.BandsData.yml b/tests/orm/test_fields/fields_aiida.data.core.array.bands.BandsData.yml index 4be2827c92..f0bca48c81 100644 --- a/tests/orm/test_fields/fields_aiida.data.core.array.bands.BandsData.yml +++ b/tests/orm/test_fields/fields_aiida.data.core.array.bands.BandsData.yml @@ -1,22 +1,31 @@ -array_labels: QbArrayField('array_labels', dtype=Optional[List[str]], is_attribute=True) -attributes: QbDictField('attributes', dtype=Dict[str, Any], is_attribute=False, is_subscriptable=True) -cell: QbArrayField('cell', dtype=List[List[float]], is_attribute=True) -ctime: QbNumericField('ctime', dtype=datetime, is_attribute=False) -description: QbStrField('description', dtype=str, is_attribute=False) -extras: QbDictField('extras', dtype=Dict[str, Any], is_attribute=False, is_subscriptable=True) -label: QbStrField('label', dtype=str, is_attribute=False) -label_numbers: QbArrayField('label_numbers', dtype=List[int], is_attribute=True) -labels: QbArrayField('labels', dtype=List[str], is_attribute=True) -mesh: QbArrayField('mesh', dtype=List[int], is_attribute=True) -mtime: QbNumericField('mtime', dtype=datetime, is_attribute=False) -node_type: QbStrField('node_type', dtype=str, is_attribute=False) -offset: QbArrayField('offset', dtype=List[float], is_attribute=True) -pbc1: QbField('pbc1', dtype=bool, is_attribute=True) -pbc2: QbField('pbc2', dtype=bool, is_attribute=True) -pbc3: QbField('pbc3', dtype=bool, is_attribute=True) -pk: QbNumericField('pk', dtype=int, is_attribute=False) -repository_metadata: QbDictField('repository_metadata', dtype=Dict[str, Any], is_attribute=False) -source: QbDictField('source', dtype=Optional[dict], is_attribute=True, is_subscriptable=True) -units: QbStrField('units', dtype=str, is_attribute=True) -user_pk: QbNumericField('user_pk', dtype=int, is_attribute=False) -uuid: QbStrField('uuid', dtype=str, is_attribute=False) +array_labels: QbArrayField('array_labels', dtype=typing.Optional[typing.List[str]], + is_attribute=True) +arrays: QbDictField('arrays', dtype=typing.Optional[dict[str, bytes]], is_attribute=True) +attributes: QbDictField('attributes', dtype=typing.Optional[typing.Dict[str, typing.Any]], + is_attribute=False, is_subscriptable=True) +cell: QbArrayField('cell', dtype=typing.List[typing.List[float]], is_attribute=True) +computer: QbNumericField('computer', dtype=typing.Optional[int], is_attribute=False) +ctime: QbNumericField('ctime', dtype=typing.Optional[datetime.datetime], is_attribute=False) +description: QbStrField('description', dtype=typing.Optional[str], is_attribute=False) +extras: QbDictField('extras', dtype=typing.Optional[typing.Dict[str, typing.Any]], + is_attribute=False, is_subscriptable=True) +label: QbStrField('label', dtype=typing.Optional[str], is_attribute=False) +label_numbers: QbArrayField('label_numbers', dtype=typing.List[int], is_attribute=True) +labels: QbArrayField('labels', dtype=typing.List[str], is_attribute=True) +mesh: QbArrayField('mesh', dtype=typing.List[int], is_attribute=True) +mtime: QbNumericField('mtime', dtype=typing.Optional[datetime.datetime], is_attribute=False) +node_type: QbStrField('node_type', dtype=typing.Optional[str], is_attribute=False) +offset: QbArrayField('offset', dtype=typing.List[float], is_attribute=True) +pbc1: QbField('pbc1', dtype=, is_attribute=True) +pbc2: QbField('pbc2', dtype=, is_attribute=True) +pbc3: QbField('pbc3', dtype=, is_attribute=True) +pk: QbNumericField('pk', dtype=typing.Optional[int], is_attribute=False) +process_type: QbStrField('process_type', dtype=typing.Optional[str], is_attribute=False) +repository_content: QbDictField('repository_content', dtype=typing.Optional[dict[str, + bytes]], is_attribute=False) +repository_metadata: QbDictField('repository_metadata', dtype=typing.Optional[typing.Dict[str, + typing.Any]], is_attribute=False) +source: QbDictField('source', dtype=typing.Optional[dict], is_attribute=True, is_subscriptable=True) +units: QbStrField('units', dtype=, is_attribute=True) +user: QbNumericField('user', dtype=typing.Optional[int], is_attribute=False) +uuid: QbStrField('uuid', dtype=typing.Optional[str], is_attribute=False) diff --git a/tests/orm/test_fields/fields_aiida.data.core.array.kpoints.KpointsData.yml b/tests/orm/test_fields/fields_aiida.data.core.array.kpoints.KpointsData.yml index f95b7aa5e6..6d0aaa2b6f 100644 --- a/tests/orm/test_fields/fields_aiida.data.core.array.kpoints.KpointsData.yml +++ b/tests/orm/test_fields/fields_aiida.data.core.array.kpoints.KpointsData.yml @@ -1,20 +1,28 @@ -attributes: QbDictField('attributes', dtype=Dict[str, Any], is_attribute=False, is_subscriptable=True) -cell: QbArrayField('cell', dtype=List[List[float]], is_attribute=True) -ctime: QbNumericField('ctime', dtype=datetime, is_attribute=False) -description: QbStrField('description', dtype=str, is_attribute=False) -extras: QbDictField('extras', dtype=Dict[str, Any], is_attribute=False, is_subscriptable=True) -label: QbStrField('label', dtype=str, is_attribute=False) -label_numbers: QbArrayField('label_numbers', dtype=List[int], is_attribute=True) -labels: QbArrayField('labels', dtype=List[str], is_attribute=True) -mesh: QbArrayField('mesh', dtype=List[int], is_attribute=True) -mtime: QbNumericField('mtime', dtype=datetime, is_attribute=False) -node_type: QbStrField('node_type', dtype=str, is_attribute=False) -offset: QbArrayField('offset', dtype=List[float], is_attribute=True) -pbc1: QbField('pbc1', dtype=bool, is_attribute=True) -pbc2: QbField('pbc2', dtype=bool, is_attribute=True) -pbc3: QbField('pbc3', dtype=bool, is_attribute=True) -pk: QbNumericField('pk', dtype=int, is_attribute=False) -repository_metadata: QbDictField('repository_metadata', dtype=Dict[str, Any], is_attribute=False) -source: QbDictField('source', dtype=Optional[dict], is_attribute=True, is_subscriptable=True) -user_pk: QbNumericField('user_pk', dtype=int, is_attribute=False) -uuid: QbStrField('uuid', dtype=str, is_attribute=False) +arrays: QbDictField('arrays', dtype=typing.Optional[dict[str, bytes]], is_attribute=True) +attributes: QbDictField('attributes', dtype=typing.Optional[typing.Dict[str, typing.Any]], + is_attribute=False, is_subscriptable=True) +cell: QbArrayField('cell', dtype=typing.List[typing.List[float]], is_attribute=True) +computer: QbNumericField('computer', dtype=typing.Optional[int], is_attribute=False) +ctime: QbNumericField('ctime', dtype=typing.Optional[datetime.datetime], is_attribute=False) +description: QbStrField('description', dtype=typing.Optional[str], is_attribute=False) +extras: QbDictField('extras', dtype=typing.Optional[typing.Dict[str, typing.Any]], + is_attribute=False, is_subscriptable=True) +label: QbStrField('label', dtype=typing.Optional[str], is_attribute=False) +label_numbers: QbArrayField('label_numbers', dtype=typing.List[int], is_attribute=True) +labels: QbArrayField('labels', dtype=typing.List[str], is_attribute=True) +mesh: QbArrayField('mesh', dtype=typing.List[int], is_attribute=True) +mtime: QbNumericField('mtime', dtype=typing.Optional[datetime.datetime], is_attribute=False) +node_type: QbStrField('node_type', dtype=typing.Optional[str], is_attribute=False) +offset: QbArrayField('offset', dtype=typing.List[float], is_attribute=True) +pbc1: QbField('pbc1', dtype=, is_attribute=True) +pbc2: QbField('pbc2', dtype=, is_attribute=True) +pbc3: QbField('pbc3', dtype=, is_attribute=True) +pk: QbNumericField('pk', dtype=typing.Optional[int], is_attribute=False) +process_type: QbStrField('process_type', dtype=typing.Optional[str], is_attribute=False) +repository_content: QbDictField('repository_content', dtype=typing.Optional[dict[str, + bytes]], is_attribute=False) +repository_metadata: QbDictField('repository_metadata', dtype=typing.Optional[typing.Dict[str, + typing.Any]], is_attribute=False) +source: QbDictField('source', dtype=typing.Optional[dict], is_attribute=True, is_subscriptable=True) +user: QbNumericField('user', dtype=typing.Optional[int], is_attribute=False) +uuid: QbStrField('uuid', dtype=typing.Optional[str], is_attribute=False) diff --git a/tests/orm/test_fields/fields_aiida.data.core.array.projection.ProjectionData.yml b/tests/orm/test_fields/fields_aiida.data.core.array.projection.ProjectionData.yml index eba6460b84..c31304e6f5 100644 --- a/tests/orm/test_fields/fields_aiida.data.core.array.projection.ProjectionData.yml +++ b/tests/orm/test_fields/fields_aiida.data.core.array.projection.ProjectionData.yml @@ -1,12 +1,20 @@ -attributes: QbDictField('attributes', dtype=Dict[str, Any], is_attribute=False, is_subscriptable=True) -ctime: QbNumericField('ctime', dtype=datetime, is_attribute=False) -description: QbStrField('description', dtype=str, is_attribute=False) -extras: QbDictField('extras', dtype=Dict[str, Any], is_attribute=False, is_subscriptable=True) -label: QbStrField('label', dtype=str, is_attribute=False) -mtime: QbNumericField('mtime', dtype=datetime, is_attribute=False) -node_type: QbStrField('node_type', dtype=str, is_attribute=False) -pk: QbNumericField('pk', dtype=int, is_attribute=False) -repository_metadata: QbDictField('repository_metadata', dtype=Dict[str, Any], is_attribute=False) -source: QbDictField('source', dtype=Optional[dict], is_attribute=True, is_subscriptable=True) -user_pk: QbNumericField('user_pk', dtype=int, is_attribute=False) -uuid: QbStrField('uuid', dtype=str, is_attribute=False) +arrays: QbDictField('arrays', dtype=typing.Optional[dict[str, bytes]], is_attribute=True) +attributes: QbDictField('attributes', dtype=typing.Optional[typing.Dict[str, typing.Any]], + is_attribute=False, is_subscriptable=True) +computer: QbNumericField('computer', dtype=typing.Optional[int], is_attribute=False) +ctime: QbNumericField('ctime', dtype=typing.Optional[datetime.datetime], is_attribute=False) +description: QbStrField('description', dtype=typing.Optional[str], is_attribute=False) +extras: QbDictField('extras', dtype=typing.Optional[typing.Dict[str, typing.Any]], + is_attribute=False, is_subscriptable=True) +label: QbStrField('label', dtype=typing.Optional[str], is_attribute=False) +mtime: QbNumericField('mtime', dtype=typing.Optional[datetime.datetime], is_attribute=False) +node_type: QbStrField('node_type', dtype=typing.Optional[str], is_attribute=False) +pk: QbNumericField('pk', dtype=typing.Optional[int], is_attribute=False) +process_type: QbStrField('process_type', dtype=typing.Optional[str], is_attribute=False) +repository_content: QbDictField('repository_content', dtype=typing.Optional[dict[str, + bytes]], is_attribute=False) +repository_metadata: QbDictField('repository_metadata', dtype=typing.Optional[typing.Dict[str, + typing.Any]], is_attribute=False) +source: QbDictField('source', dtype=typing.Optional[dict], is_attribute=True, is_subscriptable=True) +user: QbNumericField('user', dtype=typing.Optional[int], is_attribute=False) +uuid: QbStrField('uuid', dtype=typing.Optional[str], is_attribute=False) diff --git a/tests/orm/test_fields/fields_aiida.data.core.array.trajectory.TrajectoryData.yml b/tests/orm/test_fields/fields_aiida.data.core.array.trajectory.TrajectoryData.yml index bb5110a013..87aaa30148 100644 --- a/tests/orm/test_fields/fields_aiida.data.core.array.trajectory.TrajectoryData.yml +++ b/tests/orm/test_fields/fields_aiida.data.core.array.trajectory.TrajectoryData.yml @@ -1,15 +1,23 @@ -attributes: QbDictField('attributes', dtype=Dict[str, Any], is_attribute=False, is_subscriptable=True) -ctime: QbNumericField('ctime', dtype=datetime, is_attribute=False) -description: QbStrField('description', dtype=str, is_attribute=False) -extras: QbDictField('extras', dtype=Dict[str, Any], is_attribute=False, is_subscriptable=True) -label: QbStrField('label', dtype=str, is_attribute=False) -mtime: QbNumericField('mtime', dtype=datetime, is_attribute=False) -node_type: QbStrField('node_type', dtype=str, is_attribute=False) -pk: QbNumericField('pk', dtype=int, is_attribute=False) -repository_metadata: QbDictField('repository_metadata', dtype=Dict[str, Any], is_attribute=False) -source: QbDictField('source', dtype=Optional[dict], is_attribute=True, is_subscriptable=True) -symbols: QbArrayField('symbols', dtype=List[str], is_attribute=True) -units_positions: QbStrField('units_positions', 'units|positions', dtype=str, is_attribute=True) -units_times: QbStrField('units_times', 'units|times', dtype=str, is_attribute=True) -user_pk: QbNumericField('user_pk', dtype=int, is_attribute=False) -uuid: QbStrField('uuid', dtype=str, is_attribute=False) +arrays: QbDictField('arrays', dtype=typing.Optional[dict[str, bytes]], is_attribute=True) +attributes: QbDictField('attributes', dtype=typing.Optional[typing.Dict[str, typing.Any]], + is_attribute=False, is_subscriptable=True) +computer: QbNumericField('computer', dtype=typing.Optional[int], is_attribute=False) +ctime: QbNumericField('ctime', dtype=typing.Optional[datetime.datetime], is_attribute=False) +description: QbStrField('description', dtype=typing.Optional[str], is_attribute=False) +extras: QbDictField('extras', dtype=typing.Optional[typing.Dict[str, typing.Any]], + is_attribute=False, is_subscriptable=True) +label: QbStrField('label', dtype=typing.Optional[str], is_attribute=False) +mtime: QbNumericField('mtime', dtype=typing.Optional[datetime.datetime], is_attribute=False) +node_type: QbStrField('node_type', dtype=typing.Optional[str], is_attribute=False) +pk: QbNumericField('pk', dtype=typing.Optional[int], is_attribute=False) +process_type: QbStrField('process_type', dtype=typing.Optional[str], is_attribute=False) +repository_content: QbDictField('repository_content', dtype=typing.Optional[dict[str, + bytes]], is_attribute=False) +repository_metadata: QbDictField('repository_metadata', dtype=typing.Optional[typing.Dict[str, + typing.Any]], is_attribute=False) +source: QbDictField('source', dtype=typing.Optional[dict], is_attribute=True, is_subscriptable=True) +symbols: QbArrayField('symbols', dtype=typing.List[str], is_attribute=True) +units_positions: QbStrField('units_positions', dtype=, is_attribute=True) +units_times: QbStrField('units_times', dtype=, is_attribute=True) +user: QbNumericField('user', dtype=typing.Optional[int], is_attribute=False) +uuid: QbStrField('uuid', dtype=typing.Optional[str], is_attribute=False) diff --git a/tests/orm/test_fields/fields_aiida.data.core.array.xy.XyData.yml b/tests/orm/test_fields/fields_aiida.data.core.array.xy.XyData.yml index eba6460b84..c31304e6f5 100644 --- a/tests/orm/test_fields/fields_aiida.data.core.array.xy.XyData.yml +++ b/tests/orm/test_fields/fields_aiida.data.core.array.xy.XyData.yml @@ -1,12 +1,20 @@ -attributes: QbDictField('attributes', dtype=Dict[str, Any], is_attribute=False, is_subscriptable=True) -ctime: QbNumericField('ctime', dtype=datetime, is_attribute=False) -description: QbStrField('description', dtype=str, is_attribute=False) -extras: QbDictField('extras', dtype=Dict[str, Any], is_attribute=False, is_subscriptable=True) -label: QbStrField('label', dtype=str, is_attribute=False) -mtime: QbNumericField('mtime', dtype=datetime, is_attribute=False) -node_type: QbStrField('node_type', dtype=str, is_attribute=False) -pk: QbNumericField('pk', dtype=int, is_attribute=False) -repository_metadata: QbDictField('repository_metadata', dtype=Dict[str, Any], is_attribute=False) -source: QbDictField('source', dtype=Optional[dict], is_attribute=True, is_subscriptable=True) -user_pk: QbNumericField('user_pk', dtype=int, is_attribute=False) -uuid: QbStrField('uuid', dtype=str, is_attribute=False) +arrays: QbDictField('arrays', dtype=typing.Optional[dict[str, bytes]], is_attribute=True) +attributes: QbDictField('attributes', dtype=typing.Optional[typing.Dict[str, typing.Any]], + is_attribute=False, is_subscriptable=True) +computer: QbNumericField('computer', dtype=typing.Optional[int], is_attribute=False) +ctime: QbNumericField('ctime', dtype=typing.Optional[datetime.datetime], is_attribute=False) +description: QbStrField('description', dtype=typing.Optional[str], is_attribute=False) +extras: QbDictField('extras', dtype=typing.Optional[typing.Dict[str, typing.Any]], + is_attribute=False, is_subscriptable=True) +label: QbStrField('label', dtype=typing.Optional[str], is_attribute=False) +mtime: QbNumericField('mtime', dtype=typing.Optional[datetime.datetime], is_attribute=False) +node_type: QbStrField('node_type', dtype=typing.Optional[str], is_attribute=False) +pk: QbNumericField('pk', dtype=typing.Optional[int], is_attribute=False) +process_type: QbStrField('process_type', dtype=typing.Optional[str], is_attribute=False) +repository_content: QbDictField('repository_content', dtype=typing.Optional[dict[str, + bytes]], is_attribute=False) +repository_metadata: QbDictField('repository_metadata', dtype=typing.Optional[typing.Dict[str, + typing.Any]], is_attribute=False) +source: QbDictField('source', dtype=typing.Optional[dict], is_attribute=True, is_subscriptable=True) +user: QbNumericField('user', dtype=typing.Optional[int], is_attribute=False) +uuid: QbStrField('uuid', dtype=typing.Optional[str], is_attribute=False) diff --git a/tests/orm/test_fields/fields_aiida.data.core.base.BaseType.yml b/tests/orm/test_fields/fields_aiida.data.core.base.BaseType.yml index eba6460b84..457621f596 100644 --- a/tests/orm/test_fields/fields_aiida.data.core.base.BaseType.yml +++ b/tests/orm/test_fields/fields_aiida.data.core.base.BaseType.yml @@ -1,12 +1,20 @@ -attributes: QbDictField('attributes', dtype=Dict[str, Any], is_attribute=False, is_subscriptable=True) -ctime: QbNumericField('ctime', dtype=datetime, is_attribute=False) -description: QbStrField('description', dtype=str, is_attribute=False) -extras: QbDictField('extras', dtype=Dict[str, Any], is_attribute=False, is_subscriptable=True) -label: QbStrField('label', dtype=str, is_attribute=False) -mtime: QbNumericField('mtime', dtype=datetime, is_attribute=False) -node_type: QbStrField('node_type', dtype=str, is_attribute=False) -pk: QbNumericField('pk', dtype=int, is_attribute=False) -repository_metadata: QbDictField('repository_metadata', dtype=Dict[str, Any], is_attribute=False) -source: QbDictField('source', dtype=Optional[dict], is_attribute=True, is_subscriptable=True) -user_pk: QbNumericField('user_pk', dtype=int, is_attribute=False) -uuid: QbStrField('uuid', dtype=str, is_attribute=False) +attributes: QbDictField('attributes', dtype=typing.Optional[typing.Dict[str, typing.Any]], + is_attribute=False, is_subscriptable=True) +computer: QbNumericField('computer', dtype=typing.Optional[int], is_attribute=False) +ctime: QbNumericField('ctime', dtype=typing.Optional[datetime.datetime], is_attribute=False) +description: QbStrField('description', dtype=typing.Optional[str], is_attribute=False) +extras: QbDictField('extras', dtype=typing.Optional[typing.Dict[str, typing.Any]], + is_attribute=False, is_subscriptable=True) +label: QbStrField('label', dtype=typing.Optional[str], is_attribute=False) +mtime: QbNumericField('mtime', dtype=typing.Optional[datetime.datetime], is_attribute=False) +node_type: QbStrField('node_type', dtype=typing.Optional[str], is_attribute=False) +pk: QbNumericField('pk', dtype=typing.Optional[int], is_attribute=False) +process_type: QbStrField('process_type', dtype=typing.Optional[str], is_attribute=False) +repository_content: QbDictField('repository_content', dtype=typing.Optional[dict[str, + bytes]], is_attribute=False) +repository_metadata: QbDictField('repository_metadata', dtype=typing.Optional[typing.Dict[str, + typing.Any]], is_attribute=False) +source: QbDictField('source', dtype=typing.Optional[dict], is_attribute=True, is_subscriptable=True) +user: QbNumericField('user', dtype=typing.Optional[int], is_attribute=False) +uuid: QbStrField('uuid', dtype=typing.Optional[str], is_attribute=False) +value: QbField('value', dtype=typing.Any, is_attribute=True) diff --git a/tests/orm/test_fields/fields_aiida.data.core.bool.Bool.yml b/tests/orm/test_fields/fields_aiida.data.core.bool.Bool.yml index dcffc342af..457621f596 100644 --- a/tests/orm/test_fields/fields_aiida.data.core.bool.Bool.yml +++ b/tests/orm/test_fields/fields_aiida.data.core.bool.Bool.yml @@ -1,13 +1,20 @@ -attributes: QbDictField('attributes', dtype=Dict[str, Any], is_attribute=False, is_subscriptable=True) -ctime: QbNumericField('ctime', dtype=datetime, is_attribute=False) -description: QbStrField('description', dtype=str, is_attribute=False) -extras: QbDictField('extras', dtype=Dict[str, Any], is_attribute=False, is_subscriptable=True) -label: QbStrField('label', dtype=str, is_attribute=False) -mtime: QbNumericField('mtime', dtype=datetime, is_attribute=False) -node_type: QbStrField('node_type', dtype=str, is_attribute=False) -pk: QbNumericField('pk', dtype=int, is_attribute=False) -repository_metadata: QbDictField('repository_metadata', dtype=Dict[str, Any], is_attribute=False) -source: QbDictField('source', dtype=Optional[dict], is_attribute=True, is_subscriptable=True) -user_pk: QbNumericField('user_pk', dtype=int, is_attribute=False) -uuid: QbStrField('uuid', dtype=str, is_attribute=False) -value: QbField('value', dtype=bool, is_attribute=True) +attributes: QbDictField('attributes', dtype=typing.Optional[typing.Dict[str, typing.Any]], + is_attribute=False, is_subscriptable=True) +computer: QbNumericField('computer', dtype=typing.Optional[int], is_attribute=False) +ctime: QbNumericField('ctime', dtype=typing.Optional[datetime.datetime], is_attribute=False) +description: QbStrField('description', dtype=typing.Optional[str], is_attribute=False) +extras: QbDictField('extras', dtype=typing.Optional[typing.Dict[str, typing.Any]], + is_attribute=False, is_subscriptable=True) +label: QbStrField('label', dtype=typing.Optional[str], is_attribute=False) +mtime: QbNumericField('mtime', dtype=typing.Optional[datetime.datetime], is_attribute=False) +node_type: QbStrField('node_type', dtype=typing.Optional[str], is_attribute=False) +pk: QbNumericField('pk', dtype=typing.Optional[int], is_attribute=False) +process_type: QbStrField('process_type', dtype=typing.Optional[str], is_attribute=False) +repository_content: QbDictField('repository_content', dtype=typing.Optional[dict[str, + bytes]], is_attribute=False) +repository_metadata: QbDictField('repository_metadata', dtype=typing.Optional[typing.Dict[str, + typing.Any]], is_attribute=False) +source: QbDictField('source', dtype=typing.Optional[dict], is_attribute=True, is_subscriptable=True) +user: QbNumericField('user', dtype=typing.Optional[int], is_attribute=False) +uuid: QbStrField('uuid', dtype=typing.Optional[str], is_attribute=False) +value: QbField('value', dtype=typing.Any, is_attribute=True) diff --git a/tests/orm/test_fields/fields_aiida.data.core.cif.CifData.yml b/tests/orm/test_fields/fields_aiida.data.core.cif.CifData.yml index ac27b1639e..da4e1d40d9 100644 --- a/tests/orm/test_fields/fields_aiida.data.core.cif.CifData.yml +++ b/tests/orm/test_fields/fields_aiida.data.core.cif.CifData.yml @@ -1,15 +1,25 @@ -attributes: QbDictField('attributes', dtype=Dict[str, Any], is_attribute=False, is_subscriptable=True) -ctime: QbNumericField('ctime', dtype=datetime, is_attribute=False) -description: QbStrField('description', dtype=str, is_attribute=False) -extras: QbDictField('extras', dtype=Dict[str, Any], is_attribute=False, is_subscriptable=True) -formulae: QbArrayField('formulae', dtype=List[str], is_attribute=True) -label: QbStrField('label', dtype=str, is_attribute=False) -md5: QbStrField('md5', dtype=str, is_attribute=True) -mtime: QbNumericField('mtime', dtype=datetime, is_attribute=False) -node_type: QbStrField('node_type', dtype=str, is_attribute=False) -pk: QbNumericField('pk', dtype=int, is_attribute=False) -repository_metadata: QbDictField('repository_metadata', dtype=Dict[str, Any], is_attribute=False) -source: QbDictField('source', dtype=Optional[dict], is_attribute=True, is_subscriptable=True) -spacegroup_numbers: QbArrayField('spacegroup_numbers', dtype=List[str], is_attribute=True) -user_pk: QbNumericField('user_pk', dtype=int, is_attribute=False) -uuid: QbStrField('uuid', dtype=str, is_attribute=False) +attributes: QbDictField('attributes', dtype=typing.Optional[typing.Dict[str, typing.Any]], + is_attribute=False, is_subscriptable=True) +computer: QbNumericField('computer', dtype=typing.Optional[int], is_attribute=False) +content: QbField('content', dtype=, is_attribute=True) +ctime: QbNumericField('ctime', dtype=typing.Optional[datetime.datetime], is_attribute=False) +description: QbStrField('description', dtype=typing.Optional[str], is_attribute=False) +extras: QbDictField('extras', dtype=typing.Optional[typing.Dict[str, typing.Any]], + is_attribute=False, is_subscriptable=True) +filename: QbStrField('filename', dtype=typing.Optional[str], is_attribute=True) +formulae: QbArrayField('formulae', dtype=typing.Optional[typing.List[str]], is_attribute=True) +label: QbStrField('label', dtype=typing.Optional[str], is_attribute=False) +md5: QbStrField('md5', dtype=typing.Optional[str], is_attribute=True) +mtime: QbNumericField('mtime', dtype=typing.Optional[datetime.datetime], is_attribute=False) +node_type: QbStrField('node_type', dtype=typing.Optional[str], is_attribute=False) +pk: QbNumericField('pk', dtype=typing.Optional[int], is_attribute=False) +process_type: QbStrField('process_type', dtype=typing.Optional[str], is_attribute=False) +repository_content: QbDictField('repository_content', dtype=typing.Optional[dict[str, + bytes]], is_attribute=False) +repository_metadata: QbDictField('repository_metadata', dtype=typing.Optional[typing.Dict[str, + typing.Any]], is_attribute=False) +source: QbDictField('source', dtype=typing.Optional[dict], is_attribute=True, is_subscriptable=True) +spacegroup_numbers: QbArrayField('spacegroup_numbers', dtype=typing.Optional[typing.List[str]], + is_attribute=True) +user: QbNumericField('user', dtype=typing.Optional[int], is_attribute=False) +uuid: QbStrField('uuid', dtype=typing.Optional[str], is_attribute=False) diff --git a/tests/orm/test_fields/fields_aiida.data.core.code.Code.yml b/tests/orm/test_fields/fields_aiida.data.core.code.Code.yml index c9aff4804d..8ebaa0804d 100644 --- a/tests/orm/test_fields/fields_aiida.data.core.code.Code.yml +++ b/tests/orm/test_fields/fields_aiida.data.core.code.Code.yml @@ -1,18 +1,29 @@ -append_text: QbStrField('append_text', dtype=Optional[str], is_attribute=True) -attributes: QbDictField('attributes', dtype=Dict[str, Any], is_attribute=False, is_subscriptable=True) -ctime: QbNumericField('ctime', dtype=datetime, is_attribute=False) -description: QbStrField('description', dtype=str, is_attribute=False) -extras: QbDictField('extras', dtype=Dict[str, Any], is_attribute=False, is_subscriptable=True) -input_plugin: QbStrField('input_plugin', dtype=Optional[str], is_attribute=True) -is_local: QbField('is_local', dtype=Optional[bool], is_attribute=True) -label: QbStrField('label', dtype=str, is_attribute=False) -local_executable: QbStrField('local_executable', dtype=Optional[str], is_attribute=True) -mtime: QbNumericField('mtime', dtype=datetime, is_attribute=False) -node_type: QbStrField('node_type', dtype=str, is_attribute=False) -pk: QbNumericField('pk', dtype=int, is_attribute=False) -prepend_text: QbStrField('prepend_text', dtype=Optional[str], is_attribute=True) -remote_exec_path: QbStrField('remote_exec_path', dtype=Optional[str], is_attribute=True) -repository_metadata: QbDictField('repository_metadata', dtype=Dict[str, Any], is_attribute=False) -source: QbDictField('source', dtype=Optional[dict], is_attribute=True, is_subscriptable=True) -user_pk: QbNumericField('user_pk', dtype=int, is_attribute=False) -uuid: QbStrField('uuid', dtype=str, is_attribute=False) +append_text: QbStrField('append_text', dtype=, is_attribute=True) +attributes: QbDictField('attributes', dtype=typing.Optional[typing.Dict[str, typing.Any]], + is_attribute=False, is_subscriptable=True) +computer: QbNumericField('computer', dtype=typing.Optional[int], is_attribute=False) +ctime: QbNumericField('ctime', dtype=typing.Optional[datetime.datetime], is_attribute=False) +default_calc_job_plugin: QbStrField('default_calc_job_plugin', dtype=typing.Optional[str], + is_attribute=True) +description: QbStrField('description', dtype=, is_attribute=True) +extras: QbDictField('extras', dtype=typing.Optional[typing.Dict[str, typing.Any]], + is_attribute=False, is_subscriptable=True) +input_plugin: QbStrField('input_plugin', dtype=typing.Optional[str], is_attribute=True) +is_local: QbField('is_local', dtype=typing.Optional[bool], is_attribute=True) +label: QbStrField('label', dtype=, is_attribute=True) +local_executable: QbStrField('local_executable', dtype=typing.Optional[str], is_attribute=True) +mtime: QbNumericField('mtime', dtype=typing.Optional[datetime.datetime], is_attribute=False) +node_type: QbStrField('node_type', dtype=typing.Optional[str], is_attribute=False) +pk: QbNumericField('pk', dtype=typing.Optional[int], is_attribute=False) +prepend_text: QbStrField('prepend_text', dtype=, is_attribute=True) +process_type: QbStrField('process_type', dtype=typing.Optional[str], is_attribute=False) +remote_exec_path: QbStrField('remote_exec_path', dtype=typing.Optional[str], is_attribute=True) +repository_content: QbDictField('repository_content', dtype=typing.Optional[dict[str, + bytes]], is_attribute=False) +repository_metadata: QbDictField('repository_metadata', dtype=typing.Optional[typing.Dict[str, + typing.Any]], is_attribute=False) +source: QbDictField('source', dtype=typing.Optional[dict], is_attribute=True, is_subscriptable=True) +use_double_quotes: QbField('use_double_quotes', dtype=, is_attribute=True) +user: QbNumericField('user', dtype=typing.Optional[int], is_attribute=False) +uuid: QbStrField('uuid', dtype=typing.Optional[str], is_attribute=False) +with_mpi: QbField('with_mpi', dtype=typing.Optional[bool], is_attribute=True) diff --git a/tests/orm/test_fields/fields_aiida.data.core.code.containerized.ContainerizedCode.yml b/tests/orm/test_fields/fields_aiida.data.core.code.containerized.ContainerizedCode.yml index c9aff4804d..e7f12a1a94 100644 --- a/tests/orm/test_fields/fields_aiida.data.core.code.containerized.ContainerizedCode.yml +++ b/tests/orm/test_fields/fields_aiida.data.core.code.containerized.ContainerizedCode.yml @@ -1,18 +1,29 @@ -append_text: QbStrField('append_text', dtype=Optional[str], is_attribute=True) -attributes: QbDictField('attributes', dtype=Dict[str, Any], is_attribute=False, is_subscriptable=True) -ctime: QbNumericField('ctime', dtype=datetime, is_attribute=False) -description: QbStrField('description', dtype=str, is_attribute=False) -extras: QbDictField('extras', dtype=Dict[str, Any], is_attribute=False, is_subscriptable=True) -input_plugin: QbStrField('input_plugin', dtype=Optional[str], is_attribute=True) -is_local: QbField('is_local', dtype=Optional[bool], is_attribute=True) -label: QbStrField('label', dtype=str, is_attribute=False) -local_executable: QbStrField('local_executable', dtype=Optional[str], is_attribute=True) -mtime: QbNumericField('mtime', dtype=datetime, is_attribute=False) -node_type: QbStrField('node_type', dtype=str, is_attribute=False) -pk: QbNumericField('pk', dtype=int, is_attribute=False) -prepend_text: QbStrField('prepend_text', dtype=Optional[str], is_attribute=True) -remote_exec_path: QbStrField('remote_exec_path', dtype=Optional[str], is_attribute=True) -repository_metadata: QbDictField('repository_metadata', dtype=Dict[str, Any], is_attribute=False) -source: QbDictField('source', dtype=Optional[dict], is_attribute=True, is_subscriptable=True) -user_pk: QbNumericField('user_pk', dtype=int, is_attribute=False) -uuid: QbStrField('uuid', dtype=str, is_attribute=False) +append_text: QbStrField('append_text', dtype=, is_attribute=True) +attributes: QbDictField('attributes', dtype=typing.Optional[typing.Dict[str, typing.Any]], + is_attribute=False, is_subscriptable=True) +computer: QbStrField('computer', dtype=, is_attribute=True) +ctime: QbNumericField('ctime', dtype=typing.Optional[datetime.datetime], is_attribute=False) +default_calc_job_plugin: QbStrField('default_calc_job_plugin', dtype=typing.Optional[str], + is_attribute=True) +description: QbStrField('description', dtype=, is_attribute=True) +engine_command: QbStrField('engine_command', dtype=, is_attribute=True) +extras: QbDictField('extras', dtype=typing.Optional[typing.Dict[str, typing.Any]], + is_attribute=False, is_subscriptable=True) +filepath_executable: QbStrField('filepath_executable', dtype=, is_attribute=True) +image_name: QbStrField('image_name', dtype=, is_attribute=True) +label: QbStrField('label', dtype=, is_attribute=True) +mtime: QbNumericField('mtime', dtype=typing.Optional[datetime.datetime], is_attribute=False) +node_type: QbStrField('node_type', dtype=typing.Optional[str], is_attribute=False) +pk: QbNumericField('pk', dtype=typing.Optional[int], is_attribute=False) +prepend_text: QbStrField('prepend_text', dtype=, is_attribute=True) +process_type: QbStrField('process_type', dtype=typing.Optional[str], is_attribute=False) +repository_content: QbDictField('repository_content', dtype=typing.Optional[dict[str, + bytes]], is_attribute=False) +repository_metadata: QbDictField('repository_metadata', dtype=typing.Optional[typing.Dict[str, + typing.Any]], is_attribute=False) +source: QbDictField('source', dtype=typing.Optional[dict], is_attribute=True, is_subscriptable=True) +use_double_quotes: QbField('use_double_quotes', dtype=, is_attribute=True) +user: QbNumericField('user', dtype=typing.Optional[int], is_attribute=False) +uuid: QbStrField('uuid', dtype=typing.Optional[str], is_attribute=False) +with_mpi: QbField('with_mpi', dtype=typing.Optional[bool], is_attribute=True) +wrap_cmdline_params: QbField('wrap_cmdline_params', dtype=, is_attribute=True) diff --git a/tests/orm/test_fields/fields_aiida.data.core.code.installed.InstalledCode.yml b/tests/orm/test_fields/fields_aiida.data.core.code.installed.InstalledCode.yml index c9aff4804d..15089b4a3d 100644 --- a/tests/orm/test_fields/fields_aiida.data.core.code.installed.InstalledCode.yml +++ b/tests/orm/test_fields/fields_aiida.data.core.code.installed.InstalledCode.yml @@ -1,18 +1,26 @@ -append_text: QbStrField('append_text', dtype=Optional[str], is_attribute=True) -attributes: QbDictField('attributes', dtype=Dict[str, Any], is_attribute=False, is_subscriptable=True) -ctime: QbNumericField('ctime', dtype=datetime, is_attribute=False) -description: QbStrField('description', dtype=str, is_attribute=False) -extras: QbDictField('extras', dtype=Dict[str, Any], is_attribute=False, is_subscriptable=True) -input_plugin: QbStrField('input_plugin', dtype=Optional[str], is_attribute=True) -is_local: QbField('is_local', dtype=Optional[bool], is_attribute=True) -label: QbStrField('label', dtype=str, is_attribute=False) -local_executable: QbStrField('local_executable', dtype=Optional[str], is_attribute=True) -mtime: QbNumericField('mtime', dtype=datetime, is_attribute=False) -node_type: QbStrField('node_type', dtype=str, is_attribute=False) -pk: QbNumericField('pk', dtype=int, is_attribute=False) -prepend_text: QbStrField('prepend_text', dtype=Optional[str], is_attribute=True) -remote_exec_path: QbStrField('remote_exec_path', dtype=Optional[str], is_attribute=True) -repository_metadata: QbDictField('repository_metadata', dtype=Dict[str, Any], is_attribute=False) -source: QbDictField('source', dtype=Optional[dict], is_attribute=True, is_subscriptable=True) -user_pk: QbNumericField('user_pk', dtype=int, is_attribute=False) -uuid: QbStrField('uuid', dtype=str, is_attribute=False) +append_text: QbStrField('append_text', dtype=, is_attribute=True) +attributes: QbDictField('attributes', dtype=typing.Optional[typing.Dict[str, typing.Any]], + is_attribute=False, is_subscriptable=True) +computer: QbStrField('computer', dtype=, is_attribute=True) +ctime: QbNumericField('ctime', dtype=typing.Optional[datetime.datetime], is_attribute=False) +default_calc_job_plugin: QbStrField('default_calc_job_plugin', dtype=typing.Optional[str], + is_attribute=True) +description: QbStrField('description', dtype=, is_attribute=True) +extras: QbDictField('extras', dtype=typing.Optional[typing.Dict[str, typing.Any]], + is_attribute=False, is_subscriptable=True) +filepath_executable: QbStrField('filepath_executable', dtype=, is_attribute=True) +label: QbStrField('label', dtype=, is_attribute=True) +mtime: QbNumericField('mtime', dtype=typing.Optional[datetime.datetime], is_attribute=False) +node_type: QbStrField('node_type', dtype=typing.Optional[str], is_attribute=False) +pk: QbNumericField('pk', dtype=typing.Optional[int], is_attribute=False) +prepend_text: QbStrField('prepend_text', dtype=, is_attribute=True) +process_type: QbStrField('process_type', dtype=typing.Optional[str], is_attribute=False) +repository_content: QbDictField('repository_content', dtype=typing.Optional[dict[str, + bytes]], is_attribute=False) +repository_metadata: QbDictField('repository_metadata', dtype=typing.Optional[typing.Dict[str, + typing.Any]], is_attribute=False) +source: QbDictField('source', dtype=typing.Optional[dict], is_attribute=True, is_subscriptable=True) +use_double_quotes: QbField('use_double_quotes', dtype=, is_attribute=True) +user: QbNumericField('user', dtype=typing.Optional[int], is_attribute=False) +uuid: QbStrField('uuid', dtype=typing.Optional[str], is_attribute=False) +with_mpi: QbField('with_mpi', dtype=typing.Optional[bool], is_attribute=True) diff --git a/tests/orm/test_fields/fields_aiida.data.core.code.portable.PortableCode.yml b/tests/orm/test_fields/fields_aiida.data.core.code.portable.PortableCode.yml index c9aff4804d..2b006682cc 100644 --- a/tests/orm/test_fields/fields_aiida.data.core.code.portable.PortableCode.yml +++ b/tests/orm/test_fields/fields_aiida.data.core.code.portable.PortableCode.yml @@ -1,18 +1,28 @@ -append_text: QbStrField('append_text', dtype=Optional[str], is_attribute=True) -attributes: QbDictField('attributes', dtype=Dict[str, Any], is_attribute=False, is_subscriptable=True) -ctime: QbNumericField('ctime', dtype=datetime, is_attribute=False) -description: QbStrField('description', dtype=str, is_attribute=False) -extras: QbDictField('extras', dtype=Dict[str, Any], is_attribute=False, is_subscriptable=True) -input_plugin: QbStrField('input_plugin', dtype=Optional[str], is_attribute=True) -is_local: QbField('is_local', dtype=Optional[bool], is_attribute=True) -label: QbStrField('label', dtype=str, is_attribute=False) -local_executable: QbStrField('local_executable', dtype=Optional[str], is_attribute=True) -mtime: QbNumericField('mtime', dtype=datetime, is_attribute=False) -node_type: QbStrField('node_type', dtype=str, is_attribute=False) -pk: QbNumericField('pk', dtype=int, is_attribute=False) -prepend_text: QbStrField('prepend_text', dtype=Optional[str], is_attribute=True) -remote_exec_path: QbStrField('remote_exec_path', dtype=Optional[str], is_attribute=True) -repository_metadata: QbDictField('repository_metadata', dtype=Dict[str, Any], is_attribute=False) -source: QbDictField('source', dtype=Optional[dict], is_attribute=True, is_subscriptable=True) -user_pk: QbNumericField('user_pk', dtype=int, is_attribute=False) -uuid: QbStrField('uuid', dtype=str, is_attribute=False) +append_text: QbStrField('append_text', dtype=, is_attribute=True) +attributes: QbDictField('attributes', dtype=typing.Optional[typing.Dict[str, typing.Any]], + is_attribute=False, is_subscriptable=True) +computer: QbNumericField('computer', dtype=typing.Optional[int], is_attribute=False) +ctime: QbNumericField('ctime', dtype=typing.Optional[datetime.datetime], is_attribute=False) +default_calc_job_plugin: QbStrField('default_calc_job_plugin', dtype=typing.Optional[str], + is_attribute=True) +description: QbStrField('description', dtype=, is_attribute=True) +extras: QbDictField('extras', dtype=typing.Optional[typing.Dict[str, typing.Any]], + is_attribute=False, is_subscriptable=True) +filepath_executable: QbStrField('filepath_executable', dtype=, is_attribute=True) +filepath_files: QbStrField('filepath_files', dtype=typing.Union[str, pathlib.Path], + is_attribute=True) +label: QbStrField('label', dtype=, is_attribute=True) +mtime: QbNumericField('mtime', dtype=typing.Optional[datetime.datetime], is_attribute=False) +node_type: QbStrField('node_type', dtype=typing.Optional[str], is_attribute=False) +pk: QbNumericField('pk', dtype=typing.Optional[int], is_attribute=False) +prepend_text: QbStrField('prepend_text', dtype=, is_attribute=True) +process_type: QbStrField('process_type', dtype=typing.Optional[str], is_attribute=False) +repository_content: QbDictField('repository_content', dtype=typing.Optional[dict[str, + bytes]], is_attribute=False) +repository_metadata: QbDictField('repository_metadata', dtype=typing.Optional[typing.Dict[str, + typing.Any]], is_attribute=False) +source: QbDictField('source', dtype=typing.Optional[dict], is_attribute=True, is_subscriptable=True) +use_double_quotes: QbField('use_double_quotes', dtype=, is_attribute=True) +user: QbNumericField('user', dtype=typing.Optional[int], is_attribute=False) +uuid: QbStrField('uuid', dtype=typing.Optional[str], is_attribute=False) +with_mpi: QbField('with_mpi', dtype=typing.Optional[bool], is_attribute=True) diff --git a/tests/orm/test_fields/fields_aiida.data.core.dict.Dict.yml b/tests/orm/test_fields/fields_aiida.data.core.dict.Dict.yml index 6a053a6989..710d253b4d 100644 --- a/tests/orm/test_fields/fields_aiida.data.core.dict.Dict.yml +++ b/tests/orm/test_fields/fields_aiida.data.core.dict.Dict.yml @@ -1,13 +1,21 @@ -attributes: QbDictField('attributes', dtype=Dict[str, Any], is_attribute=False, is_subscriptable=True) -ctime: QbNumericField('ctime', dtype=datetime, is_attribute=False) -description: QbStrField('description', dtype=str, is_attribute=False) -dict: QbDictField('dict', dtype=Dict[str, Any], is_attribute=False, is_subscriptable=True) -extras: QbDictField('extras', dtype=Dict[str, Any], is_attribute=False, is_subscriptable=True) -label: QbStrField('label', dtype=str, is_attribute=False) -mtime: QbNumericField('mtime', dtype=datetime, is_attribute=False) -node_type: QbStrField('node_type', dtype=str, is_attribute=False) -pk: QbNumericField('pk', dtype=int, is_attribute=False) -repository_metadata: QbDictField('repository_metadata', dtype=Dict[str, Any], is_attribute=False) -source: QbDictField('source', dtype=Optional[dict], is_attribute=True, is_subscriptable=True) -user_pk: QbNumericField('user_pk', dtype=int, is_attribute=False) -uuid: QbStrField('uuid', dtype=str, is_attribute=False) +attributes: QbDictField('attributes', dtype=typing.Optional[typing.Dict[str, typing.Any]], + is_attribute=False, is_subscriptable=True) +computer: QbNumericField('computer', dtype=typing.Optional[int], is_attribute=False) +ctime: QbNumericField('ctime', dtype=typing.Optional[datetime.datetime], is_attribute=False) +description: QbStrField('description', dtype=typing.Optional[str], is_attribute=False) +extras: QbDictField('extras', dtype=typing.Optional[typing.Dict[str, typing.Any]], + is_attribute=False, is_subscriptable=True) +label: QbStrField('label', dtype=typing.Optional[str], is_attribute=False) +mtime: QbNumericField('mtime', dtype=typing.Optional[datetime.datetime], is_attribute=False) +node_type: QbStrField('node_type', dtype=typing.Optional[str], is_attribute=False) +pk: QbNumericField('pk', dtype=typing.Optional[int], is_attribute=False) +process_type: QbStrField('process_type', dtype=typing.Optional[str], is_attribute=False) +repository_content: QbDictField('repository_content', dtype=typing.Optional[dict[str, + bytes]], is_attribute=False) +repository_metadata: QbDictField('repository_metadata', dtype=typing.Optional[typing.Dict[str, + typing.Any]], is_attribute=False) +source: QbDictField('source', dtype=typing.Optional[dict], is_attribute=True, is_subscriptable=True) +user: QbNumericField('user', dtype=typing.Optional[int], is_attribute=False) +uuid: QbStrField('uuid', dtype=typing.Optional[str], is_attribute=False) +value: QbDictField('value', dtype=typing.Dict[str, typing.Any], is_attribute=False, + is_subscriptable=True) diff --git a/tests/orm/test_fields/fields_aiida.data.core.enum.EnumData.yml b/tests/orm/test_fields/fields_aiida.data.core.enum.EnumData.yml index eba6460b84..cfc3976079 100644 --- a/tests/orm/test_fields/fields_aiida.data.core.enum.EnumData.yml +++ b/tests/orm/test_fields/fields_aiida.data.core.enum.EnumData.yml @@ -1,12 +1,20 @@ -attributes: QbDictField('attributes', dtype=Dict[str, Any], is_attribute=False, is_subscriptable=True) -ctime: QbNumericField('ctime', dtype=datetime, is_attribute=False) -description: QbStrField('description', dtype=str, is_attribute=False) -extras: QbDictField('extras', dtype=Dict[str, Any], is_attribute=False, is_subscriptable=True) -label: QbStrField('label', dtype=str, is_attribute=False) -mtime: QbNumericField('mtime', dtype=datetime, is_attribute=False) -node_type: QbStrField('node_type', dtype=str, is_attribute=False) -pk: QbNumericField('pk', dtype=int, is_attribute=False) -repository_metadata: QbDictField('repository_metadata', dtype=Dict[str, Any], is_attribute=False) -source: QbDictField('source', dtype=Optional[dict], is_attribute=True, is_subscriptable=True) -user_pk: QbNumericField('user_pk', dtype=int, is_attribute=False) -uuid: QbStrField('uuid', dtype=str, is_attribute=False) +attributes: QbDictField('attributes', dtype=typing.Optional[typing.Dict[str, typing.Any]], + is_attribute=False, is_subscriptable=True) +computer: QbNumericField('computer', dtype=typing.Optional[int], is_attribute=False) +ctime: QbNumericField('ctime', dtype=typing.Optional[datetime.datetime], is_attribute=False) +description: QbStrField('description', dtype=typing.Optional[str], is_attribute=False) +extras: QbDictField('extras', dtype=typing.Optional[typing.Dict[str, typing.Any]], + is_attribute=False, is_subscriptable=True) +label: QbStrField('label', dtype=typing.Optional[str], is_attribute=False) +member: QbField('member', dtype=, is_attribute=True) +mtime: QbNumericField('mtime', dtype=typing.Optional[datetime.datetime], is_attribute=False) +node_type: QbStrField('node_type', dtype=typing.Optional[str], is_attribute=False) +pk: QbNumericField('pk', dtype=typing.Optional[int], is_attribute=False) +process_type: QbStrField('process_type', dtype=typing.Optional[str], is_attribute=False) +repository_content: QbDictField('repository_content', dtype=typing.Optional[dict[str, + bytes]], is_attribute=False) +repository_metadata: QbDictField('repository_metadata', dtype=typing.Optional[typing.Dict[str, + typing.Any]], is_attribute=False) +source: QbDictField('source', dtype=typing.Optional[dict], is_attribute=True, is_subscriptable=True) +user: QbNumericField('user', dtype=typing.Optional[int], is_attribute=False) +uuid: QbStrField('uuid', dtype=typing.Optional[str], is_attribute=False) diff --git a/tests/orm/test_fields/fields_aiida.data.core.float.Float.yml b/tests/orm/test_fields/fields_aiida.data.core.float.Float.yml index 5abc6a38b9..457621f596 100644 --- a/tests/orm/test_fields/fields_aiida.data.core.float.Float.yml +++ b/tests/orm/test_fields/fields_aiida.data.core.float.Float.yml @@ -1,13 +1,20 @@ -attributes: QbDictField('attributes', dtype=Dict[str, Any], is_attribute=False, is_subscriptable=True) -ctime: QbNumericField('ctime', dtype=datetime, is_attribute=False) -description: QbStrField('description', dtype=str, is_attribute=False) -extras: QbDictField('extras', dtype=Dict[str, Any], is_attribute=False, is_subscriptable=True) -label: QbStrField('label', dtype=str, is_attribute=False) -mtime: QbNumericField('mtime', dtype=datetime, is_attribute=False) -node_type: QbStrField('node_type', dtype=str, is_attribute=False) -pk: QbNumericField('pk', dtype=int, is_attribute=False) -repository_metadata: QbDictField('repository_metadata', dtype=Dict[str, Any], is_attribute=False) -source: QbDictField('source', dtype=Optional[dict], is_attribute=True, is_subscriptable=True) -user_pk: QbNumericField('user_pk', dtype=int, is_attribute=False) -uuid: QbStrField('uuid', dtype=str, is_attribute=False) -value: QbNumericField('value', dtype=float, is_attribute=True) +attributes: QbDictField('attributes', dtype=typing.Optional[typing.Dict[str, typing.Any]], + is_attribute=False, is_subscriptable=True) +computer: QbNumericField('computer', dtype=typing.Optional[int], is_attribute=False) +ctime: QbNumericField('ctime', dtype=typing.Optional[datetime.datetime], is_attribute=False) +description: QbStrField('description', dtype=typing.Optional[str], is_attribute=False) +extras: QbDictField('extras', dtype=typing.Optional[typing.Dict[str, typing.Any]], + is_attribute=False, is_subscriptable=True) +label: QbStrField('label', dtype=typing.Optional[str], is_attribute=False) +mtime: QbNumericField('mtime', dtype=typing.Optional[datetime.datetime], is_attribute=False) +node_type: QbStrField('node_type', dtype=typing.Optional[str], is_attribute=False) +pk: QbNumericField('pk', dtype=typing.Optional[int], is_attribute=False) +process_type: QbStrField('process_type', dtype=typing.Optional[str], is_attribute=False) +repository_content: QbDictField('repository_content', dtype=typing.Optional[dict[str, + bytes]], is_attribute=False) +repository_metadata: QbDictField('repository_metadata', dtype=typing.Optional[typing.Dict[str, + typing.Any]], is_attribute=False) +source: QbDictField('source', dtype=typing.Optional[dict], is_attribute=True, is_subscriptable=True) +user: QbNumericField('user', dtype=typing.Optional[int], is_attribute=False) +uuid: QbStrField('uuid', dtype=typing.Optional[str], is_attribute=False) +value: QbField('value', dtype=typing.Any, is_attribute=True) diff --git a/tests/orm/test_fields/fields_aiida.data.core.folder.FolderData.yml b/tests/orm/test_fields/fields_aiida.data.core.folder.FolderData.yml index eba6460b84..5bee2ef441 100644 --- a/tests/orm/test_fields/fields_aiida.data.core.folder.FolderData.yml +++ b/tests/orm/test_fields/fields_aiida.data.core.folder.FolderData.yml @@ -1,12 +1,19 @@ -attributes: QbDictField('attributes', dtype=Dict[str, Any], is_attribute=False, is_subscriptable=True) -ctime: QbNumericField('ctime', dtype=datetime, is_attribute=False) -description: QbStrField('description', dtype=str, is_attribute=False) -extras: QbDictField('extras', dtype=Dict[str, Any], is_attribute=False, is_subscriptable=True) -label: QbStrField('label', dtype=str, is_attribute=False) -mtime: QbNumericField('mtime', dtype=datetime, is_attribute=False) -node_type: QbStrField('node_type', dtype=str, is_attribute=False) -pk: QbNumericField('pk', dtype=int, is_attribute=False) -repository_metadata: QbDictField('repository_metadata', dtype=Dict[str, Any], is_attribute=False) -source: QbDictField('source', dtype=Optional[dict], is_attribute=True, is_subscriptable=True) -user_pk: QbNumericField('user_pk', dtype=int, is_attribute=False) -uuid: QbStrField('uuid', dtype=str, is_attribute=False) +attributes: QbDictField('attributes', dtype=typing.Optional[typing.Dict[str, typing.Any]], + is_attribute=False, is_subscriptable=True) +computer: QbNumericField('computer', dtype=typing.Optional[int], is_attribute=False) +ctime: QbNumericField('ctime', dtype=typing.Optional[datetime.datetime], is_attribute=False) +description: QbStrField('description', dtype=typing.Optional[str], is_attribute=False) +extras: QbDictField('extras', dtype=typing.Optional[typing.Dict[str, typing.Any]], + is_attribute=False, is_subscriptable=True) +label: QbStrField('label', dtype=typing.Optional[str], is_attribute=False) +mtime: QbNumericField('mtime', dtype=typing.Optional[datetime.datetime], is_attribute=False) +node_type: QbStrField('node_type', dtype=typing.Optional[str], is_attribute=False) +pk: QbNumericField('pk', dtype=typing.Optional[int], is_attribute=False) +process_type: QbStrField('process_type', dtype=typing.Optional[str], is_attribute=False) +repository_content: QbDictField('repository_content', dtype=typing.Optional[dict[str, + bytes]], is_attribute=False) +repository_metadata: QbDictField('repository_metadata', dtype=typing.Optional[typing.Dict[str, + typing.Any]], is_attribute=False) +source: QbDictField('source', dtype=typing.Optional[dict], is_attribute=True, is_subscriptable=True) +user: QbNumericField('user', dtype=typing.Optional[int], is_attribute=False) +uuid: QbStrField('uuid', dtype=typing.Optional[str], is_attribute=False) diff --git a/tests/orm/test_fields/fields_aiida.data.core.int.Int.yml b/tests/orm/test_fields/fields_aiida.data.core.int.Int.yml index b8216dc3b7..457621f596 100644 --- a/tests/orm/test_fields/fields_aiida.data.core.int.Int.yml +++ b/tests/orm/test_fields/fields_aiida.data.core.int.Int.yml @@ -1,13 +1,20 @@ -attributes: QbDictField('attributes', dtype=Dict[str, Any], is_attribute=False, is_subscriptable=True) -ctime: QbNumericField('ctime', dtype=datetime, is_attribute=False) -description: QbStrField('description', dtype=str, is_attribute=False) -extras: QbDictField('extras', dtype=Dict[str, Any], is_attribute=False, is_subscriptable=True) -label: QbStrField('label', dtype=str, is_attribute=False) -mtime: QbNumericField('mtime', dtype=datetime, is_attribute=False) -node_type: QbStrField('node_type', dtype=str, is_attribute=False) -pk: QbNumericField('pk', dtype=int, is_attribute=False) -repository_metadata: QbDictField('repository_metadata', dtype=Dict[str, Any], is_attribute=False) -source: QbDictField('source', dtype=Optional[dict], is_attribute=True, is_subscriptable=True) -user_pk: QbNumericField('user_pk', dtype=int, is_attribute=False) -uuid: QbStrField('uuid', dtype=str, is_attribute=False) -value: QbNumericField('value', dtype=int, is_attribute=True) +attributes: QbDictField('attributes', dtype=typing.Optional[typing.Dict[str, typing.Any]], + is_attribute=False, is_subscriptable=True) +computer: QbNumericField('computer', dtype=typing.Optional[int], is_attribute=False) +ctime: QbNumericField('ctime', dtype=typing.Optional[datetime.datetime], is_attribute=False) +description: QbStrField('description', dtype=typing.Optional[str], is_attribute=False) +extras: QbDictField('extras', dtype=typing.Optional[typing.Dict[str, typing.Any]], + is_attribute=False, is_subscriptable=True) +label: QbStrField('label', dtype=typing.Optional[str], is_attribute=False) +mtime: QbNumericField('mtime', dtype=typing.Optional[datetime.datetime], is_attribute=False) +node_type: QbStrField('node_type', dtype=typing.Optional[str], is_attribute=False) +pk: QbNumericField('pk', dtype=typing.Optional[int], is_attribute=False) +process_type: QbStrField('process_type', dtype=typing.Optional[str], is_attribute=False) +repository_content: QbDictField('repository_content', dtype=typing.Optional[dict[str, + bytes]], is_attribute=False) +repository_metadata: QbDictField('repository_metadata', dtype=typing.Optional[typing.Dict[str, + typing.Any]], is_attribute=False) +source: QbDictField('source', dtype=typing.Optional[dict], is_attribute=True, is_subscriptable=True) +user: QbNumericField('user', dtype=typing.Optional[int], is_attribute=False) +uuid: QbStrField('uuid', dtype=typing.Optional[str], is_attribute=False) +value: QbField('value', dtype=typing.Any, is_attribute=True) diff --git a/tests/orm/test_fields/fields_aiida.data.core.jsonable.JsonableData.yml b/tests/orm/test_fields/fields_aiida.data.core.jsonable.JsonableData.yml index eba6460b84..1166fbc570 100644 --- a/tests/orm/test_fields/fields_aiida.data.core.jsonable.JsonableData.yml +++ b/tests/orm/test_fields/fields_aiida.data.core.jsonable.JsonableData.yml @@ -1,12 +1,21 @@ -attributes: QbDictField('attributes', dtype=Dict[str, Any], is_attribute=False, is_subscriptable=True) -ctime: QbNumericField('ctime', dtype=datetime, is_attribute=False) -description: QbStrField('description', dtype=str, is_attribute=False) -extras: QbDictField('extras', dtype=Dict[str, Any], is_attribute=False, is_subscriptable=True) -label: QbStrField('label', dtype=str, is_attribute=False) -mtime: QbNumericField('mtime', dtype=datetime, is_attribute=False) -node_type: QbStrField('node_type', dtype=str, is_attribute=False) -pk: QbNumericField('pk', dtype=int, is_attribute=False) -repository_metadata: QbDictField('repository_metadata', dtype=Dict[str, Any], is_attribute=False) -source: QbDictField('source', dtype=Optional[dict], is_attribute=True, is_subscriptable=True) -user_pk: QbNumericField('user_pk', dtype=int, is_attribute=False) -uuid: QbStrField('uuid', dtype=str, is_attribute=False) +attributes: QbDictField('attributes', dtype=typing.Optional[typing.Dict[str, typing.Any]], + is_attribute=False, is_subscriptable=True) +computer: QbNumericField('computer', dtype=typing.Optional[int], is_attribute=False) +ctime: QbNumericField('ctime', dtype=typing.Optional[datetime.datetime], is_attribute=False) +description: QbStrField('description', dtype=typing.Optional[str], is_attribute=False) +extras: QbDictField('extras', dtype=typing.Optional[typing.Dict[str, typing.Any]], + is_attribute=False, is_subscriptable=True) +label: QbStrField('label', dtype=typing.Optional[str], is_attribute=False) +mtime: QbNumericField('mtime', dtype=typing.Optional[datetime.datetime], is_attribute=False) +node_type: QbStrField('node_type', dtype=typing.Optional[str], is_attribute=False) +obj: QbField('obj', dtype=, + is_attribute=True) +pk: QbNumericField('pk', dtype=typing.Optional[int], is_attribute=False) +process_type: QbStrField('process_type', dtype=typing.Optional[str], is_attribute=False) +repository_content: QbDictField('repository_content', dtype=typing.Optional[dict[str, + bytes]], is_attribute=False) +repository_metadata: QbDictField('repository_metadata', dtype=typing.Optional[typing.Dict[str, + typing.Any]], is_attribute=False) +source: QbDictField('source', dtype=typing.Optional[dict], is_attribute=True, is_subscriptable=True) +user: QbNumericField('user', dtype=typing.Optional[int], is_attribute=False) +uuid: QbStrField('uuid', dtype=typing.Optional[str], is_attribute=False) diff --git a/tests/orm/test_fields/fields_aiida.data.core.list.List.yml b/tests/orm/test_fields/fields_aiida.data.core.list.List.yml index eba6460b84..4edd6d3380 100644 --- a/tests/orm/test_fields/fields_aiida.data.core.list.List.yml +++ b/tests/orm/test_fields/fields_aiida.data.core.list.List.yml @@ -1,12 +1,20 @@ -attributes: QbDictField('attributes', dtype=Dict[str, Any], is_attribute=False, is_subscriptable=True) -ctime: QbNumericField('ctime', dtype=datetime, is_attribute=False) -description: QbStrField('description', dtype=str, is_attribute=False) -extras: QbDictField('extras', dtype=Dict[str, Any], is_attribute=False, is_subscriptable=True) -label: QbStrField('label', dtype=str, is_attribute=False) -mtime: QbNumericField('mtime', dtype=datetime, is_attribute=False) -node_type: QbStrField('node_type', dtype=str, is_attribute=False) -pk: QbNumericField('pk', dtype=int, is_attribute=False) -repository_metadata: QbDictField('repository_metadata', dtype=Dict[str, Any], is_attribute=False) -source: QbDictField('source', dtype=Optional[dict], is_attribute=True, is_subscriptable=True) -user_pk: QbNumericField('user_pk', dtype=int, is_attribute=False) -uuid: QbStrField('uuid', dtype=str, is_attribute=False) +attributes: QbDictField('attributes', dtype=typing.Optional[typing.Dict[str, typing.Any]], + is_attribute=False, is_subscriptable=True) +computer: QbNumericField('computer', dtype=typing.Optional[int], is_attribute=False) +ctime: QbNumericField('ctime', dtype=typing.Optional[datetime.datetime], is_attribute=False) +description: QbStrField('description', dtype=typing.Optional[str], is_attribute=False) +extras: QbDictField('extras', dtype=typing.Optional[typing.Dict[str, typing.Any]], + is_attribute=False, is_subscriptable=True) +label: QbStrField('label', dtype=typing.Optional[str], is_attribute=False) +mtime: QbNumericField('mtime', dtype=typing.Optional[datetime.datetime], is_attribute=False) +node_type: QbStrField('node_type', dtype=typing.Optional[str], is_attribute=False) +pk: QbNumericField('pk', dtype=typing.Optional[int], is_attribute=False) +process_type: QbStrField('process_type', dtype=typing.Optional[str], is_attribute=False) +repository_content: QbDictField('repository_content', dtype=typing.Optional[dict[str, + bytes]], is_attribute=False) +repository_metadata: QbDictField('repository_metadata', dtype=typing.Optional[typing.Dict[str, + typing.Any]], is_attribute=False) +source: QbDictField('source', dtype=typing.Optional[dict], is_attribute=True, is_subscriptable=True) +user: QbNumericField('user', dtype=typing.Optional[int], is_attribute=False) +uuid: QbStrField('uuid', dtype=typing.Optional[str], is_attribute=False) +value: QbArrayField('value', dtype=typing.List[typing.Any], is_attribute=True) diff --git a/tests/orm/test_fields/fields_aiida.data.core.numeric.NumericType.yml b/tests/orm/test_fields/fields_aiida.data.core.numeric.NumericType.yml index eba6460b84..457621f596 100644 --- a/tests/orm/test_fields/fields_aiida.data.core.numeric.NumericType.yml +++ b/tests/orm/test_fields/fields_aiida.data.core.numeric.NumericType.yml @@ -1,12 +1,20 @@ -attributes: QbDictField('attributes', dtype=Dict[str, Any], is_attribute=False, is_subscriptable=True) -ctime: QbNumericField('ctime', dtype=datetime, is_attribute=False) -description: QbStrField('description', dtype=str, is_attribute=False) -extras: QbDictField('extras', dtype=Dict[str, Any], is_attribute=False, is_subscriptable=True) -label: QbStrField('label', dtype=str, is_attribute=False) -mtime: QbNumericField('mtime', dtype=datetime, is_attribute=False) -node_type: QbStrField('node_type', dtype=str, is_attribute=False) -pk: QbNumericField('pk', dtype=int, is_attribute=False) -repository_metadata: QbDictField('repository_metadata', dtype=Dict[str, Any], is_attribute=False) -source: QbDictField('source', dtype=Optional[dict], is_attribute=True, is_subscriptable=True) -user_pk: QbNumericField('user_pk', dtype=int, is_attribute=False) -uuid: QbStrField('uuid', dtype=str, is_attribute=False) +attributes: QbDictField('attributes', dtype=typing.Optional[typing.Dict[str, typing.Any]], + is_attribute=False, is_subscriptable=True) +computer: QbNumericField('computer', dtype=typing.Optional[int], is_attribute=False) +ctime: QbNumericField('ctime', dtype=typing.Optional[datetime.datetime], is_attribute=False) +description: QbStrField('description', dtype=typing.Optional[str], is_attribute=False) +extras: QbDictField('extras', dtype=typing.Optional[typing.Dict[str, typing.Any]], + is_attribute=False, is_subscriptable=True) +label: QbStrField('label', dtype=typing.Optional[str], is_attribute=False) +mtime: QbNumericField('mtime', dtype=typing.Optional[datetime.datetime], is_attribute=False) +node_type: QbStrField('node_type', dtype=typing.Optional[str], is_attribute=False) +pk: QbNumericField('pk', dtype=typing.Optional[int], is_attribute=False) +process_type: QbStrField('process_type', dtype=typing.Optional[str], is_attribute=False) +repository_content: QbDictField('repository_content', dtype=typing.Optional[dict[str, + bytes]], is_attribute=False) +repository_metadata: QbDictField('repository_metadata', dtype=typing.Optional[typing.Dict[str, + typing.Any]], is_attribute=False) +source: QbDictField('source', dtype=typing.Optional[dict], is_attribute=True, is_subscriptable=True) +user: QbNumericField('user', dtype=typing.Optional[int], is_attribute=False) +uuid: QbStrField('uuid', dtype=typing.Optional[str], is_attribute=False) +value: QbField('value', dtype=typing.Any, is_attribute=True) diff --git a/tests/orm/test_fields/fields_aiida.data.core.orbital.OrbitalData.yml b/tests/orm/test_fields/fields_aiida.data.core.orbital.OrbitalData.yml index eba6460b84..5bee2ef441 100644 --- a/tests/orm/test_fields/fields_aiida.data.core.orbital.OrbitalData.yml +++ b/tests/orm/test_fields/fields_aiida.data.core.orbital.OrbitalData.yml @@ -1,12 +1,19 @@ -attributes: QbDictField('attributes', dtype=Dict[str, Any], is_attribute=False, is_subscriptable=True) -ctime: QbNumericField('ctime', dtype=datetime, is_attribute=False) -description: QbStrField('description', dtype=str, is_attribute=False) -extras: QbDictField('extras', dtype=Dict[str, Any], is_attribute=False, is_subscriptable=True) -label: QbStrField('label', dtype=str, is_attribute=False) -mtime: QbNumericField('mtime', dtype=datetime, is_attribute=False) -node_type: QbStrField('node_type', dtype=str, is_attribute=False) -pk: QbNumericField('pk', dtype=int, is_attribute=False) -repository_metadata: QbDictField('repository_metadata', dtype=Dict[str, Any], is_attribute=False) -source: QbDictField('source', dtype=Optional[dict], is_attribute=True, is_subscriptable=True) -user_pk: QbNumericField('user_pk', dtype=int, is_attribute=False) -uuid: QbStrField('uuid', dtype=str, is_attribute=False) +attributes: QbDictField('attributes', dtype=typing.Optional[typing.Dict[str, typing.Any]], + is_attribute=False, is_subscriptable=True) +computer: QbNumericField('computer', dtype=typing.Optional[int], is_attribute=False) +ctime: QbNumericField('ctime', dtype=typing.Optional[datetime.datetime], is_attribute=False) +description: QbStrField('description', dtype=typing.Optional[str], is_attribute=False) +extras: QbDictField('extras', dtype=typing.Optional[typing.Dict[str, typing.Any]], + is_attribute=False, is_subscriptable=True) +label: QbStrField('label', dtype=typing.Optional[str], is_attribute=False) +mtime: QbNumericField('mtime', dtype=typing.Optional[datetime.datetime], is_attribute=False) +node_type: QbStrField('node_type', dtype=typing.Optional[str], is_attribute=False) +pk: QbNumericField('pk', dtype=typing.Optional[int], is_attribute=False) +process_type: QbStrField('process_type', dtype=typing.Optional[str], is_attribute=False) +repository_content: QbDictField('repository_content', dtype=typing.Optional[dict[str, + bytes]], is_attribute=False) +repository_metadata: QbDictField('repository_metadata', dtype=typing.Optional[typing.Dict[str, + typing.Any]], is_attribute=False) +source: QbDictField('source', dtype=typing.Optional[dict], is_attribute=True, is_subscriptable=True) +user: QbNumericField('user', dtype=typing.Optional[int], is_attribute=False) +uuid: QbStrField('uuid', dtype=typing.Optional[str], is_attribute=False) diff --git a/tests/orm/test_fields/fields_aiida.data.core.remote.RemoteData.yml b/tests/orm/test_fields/fields_aiida.data.core.remote.RemoteData.yml index 0eece2a5c3..046b3a6aab 100644 --- a/tests/orm/test_fields/fields_aiida.data.core.remote.RemoteData.yml +++ b/tests/orm/test_fields/fields_aiida.data.core.remote.RemoteData.yml @@ -1,13 +1,20 @@ -attributes: QbDictField('attributes', dtype=Dict[str, Any], is_attribute=False, is_subscriptable=True) -ctime: QbNumericField('ctime', dtype=datetime, is_attribute=False) -description: QbStrField('description', dtype=str, is_attribute=False) -extras: QbDictField('extras', dtype=Dict[str, Any], is_attribute=False, is_subscriptable=True) -label: QbStrField('label', dtype=str, is_attribute=False) -mtime: QbNumericField('mtime', dtype=datetime, is_attribute=False) -node_type: QbStrField('node_type', dtype=str, is_attribute=False) -pk: QbNumericField('pk', dtype=int, is_attribute=False) -remote_path: QbStrField('remote_path', dtype=str, is_attribute=True) -repository_metadata: QbDictField('repository_metadata', dtype=Dict[str, Any], is_attribute=False) -source: QbDictField('source', dtype=Optional[dict], is_attribute=True, is_subscriptable=True) -user_pk: QbNumericField('user_pk', dtype=int, is_attribute=False) -uuid: QbStrField('uuid', dtype=str, is_attribute=False) +attributes: QbDictField('attributes', dtype=typing.Optional[typing.Dict[str, typing.Any]], + is_attribute=False, is_subscriptable=True) +computer: QbNumericField('computer', dtype=typing.Optional[int], is_attribute=False) +ctime: QbNumericField('ctime', dtype=typing.Optional[datetime.datetime], is_attribute=False) +description: QbStrField('description', dtype=typing.Optional[str], is_attribute=False) +extras: QbDictField('extras', dtype=typing.Optional[typing.Dict[str, typing.Any]], + is_attribute=False, is_subscriptable=True) +label: QbStrField('label', dtype=typing.Optional[str], is_attribute=False) +mtime: QbNumericField('mtime', dtype=typing.Optional[datetime.datetime], is_attribute=False) +node_type: QbStrField('node_type', dtype=typing.Optional[str], is_attribute=False) +pk: QbNumericField('pk', dtype=typing.Optional[int], is_attribute=False) +process_type: QbStrField('process_type', dtype=typing.Optional[str], is_attribute=False) +remote_path: QbStrField('remote_path', dtype=, is_attribute=True) +repository_content: QbDictField('repository_content', dtype=typing.Optional[dict[str, + bytes]], is_attribute=False) +repository_metadata: QbDictField('repository_metadata', dtype=typing.Optional[typing.Dict[str, + typing.Any]], is_attribute=False) +source: QbDictField('source', dtype=typing.Optional[dict], is_attribute=True, is_subscriptable=True) +user: QbNumericField('user', dtype=typing.Optional[int], is_attribute=False) +uuid: QbStrField('uuid', dtype=typing.Optional[str], is_attribute=False) diff --git a/tests/orm/test_fields/fields_aiida.data.core.remote.stash.RemoteStashData.yml b/tests/orm/test_fields/fields_aiida.data.core.remote.stash.RemoteStashData.yml index 2d148dd68b..35e6e4188e 100644 --- a/tests/orm/test_fields/fields_aiida.data.core.remote.stash.RemoteStashData.yml +++ b/tests/orm/test_fields/fields_aiida.data.core.remote.stash.RemoteStashData.yml @@ -1,13 +1,20 @@ -attributes: QbDictField('attributes', dtype=Dict[str, Any], is_attribute=False, is_subscriptable=True) -ctime: QbNumericField('ctime', dtype=datetime, is_attribute=False) -description: QbStrField('description', dtype=str, is_attribute=False) -extras: QbDictField('extras', dtype=Dict[str, Any], is_attribute=False, is_subscriptable=True) -label: QbStrField('label', dtype=str, is_attribute=False) -mtime: QbNumericField('mtime', dtype=datetime, is_attribute=False) -node_type: QbStrField('node_type', dtype=str, is_attribute=False) -pk: QbNumericField('pk', dtype=int, is_attribute=False) -repository_metadata: QbDictField('repository_metadata', dtype=Dict[str, Any], is_attribute=False) -source: QbDictField('source', dtype=Optional[dict], is_attribute=True, is_subscriptable=True) -stash_mode: QbStrField('stash_mode', dtype=str, is_attribute=True) -user_pk: QbNumericField('user_pk', dtype=int, is_attribute=False) -uuid: QbStrField('uuid', dtype=str, is_attribute=False) +attributes: QbDictField('attributes', dtype=typing.Optional[typing.Dict[str, typing.Any]], + is_attribute=False, is_subscriptable=True) +computer: QbNumericField('computer', dtype=typing.Optional[int], is_attribute=False) +ctime: QbNumericField('ctime', dtype=typing.Optional[datetime.datetime], is_attribute=False) +description: QbStrField('description', dtype=typing.Optional[str], is_attribute=False) +extras: QbDictField('extras', dtype=typing.Optional[typing.Dict[str, typing.Any]], + is_attribute=False, is_subscriptable=True) +label: QbStrField('label', dtype=typing.Optional[str], is_attribute=False) +mtime: QbNumericField('mtime', dtype=typing.Optional[datetime.datetime], is_attribute=False) +node_type: QbStrField('node_type', dtype=typing.Optional[str], is_attribute=False) +pk: QbNumericField('pk', dtype=typing.Optional[int], is_attribute=False) +process_type: QbStrField('process_type', dtype=typing.Optional[str], is_attribute=False) +repository_content: QbDictField('repository_content', dtype=typing.Optional[dict[str, + bytes]], is_attribute=False) +repository_metadata: QbDictField('repository_metadata', dtype=typing.Optional[typing.Dict[str, + typing.Any]], is_attribute=False) +source: QbDictField('source', dtype=typing.Optional[dict], is_attribute=True, is_subscriptable=True) +stash_mode: QbField('stash_mode', dtype=, is_attribute=True) +user: QbNumericField('user', dtype=typing.Optional[int], is_attribute=False) +uuid: QbStrField('uuid', dtype=typing.Optional[str], is_attribute=False) diff --git a/tests/orm/test_fields/fields_aiida.data.core.remote.stash.folder.RemoteStashFolderData.yml b/tests/orm/test_fields/fields_aiida.data.core.remote.stash.folder.RemoteStashFolderData.yml index c4969fbd4d..82e177e738 100644 --- a/tests/orm/test_fields/fields_aiida.data.core.remote.stash.folder.RemoteStashFolderData.yml +++ b/tests/orm/test_fields/fields_aiida.data.core.remote.stash.folder.RemoteStashFolderData.yml @@ -1,15 +1,22 @@ -attributes: QbDictField('attributes', dtype=Dict[str, Any], is_attribute=False, is_subscriptable=True) -ctime: QbNumericField('ctime', dtype=datetime, is_attribute=False) -description: QbStrField('description', dtype=str, is_attribute=False) -extras: QbDictField('extras', dtype=Dict[str, Any], is_attribute=False, is_subscriptable=True) -label: QbStrField('label', dtype=str, is_attribute=False) -mtime: QbNumericField('mtime', dtype=datetime, is_attribute=False) -node_type: QbStrField('node_type', dtype=str, is_attribute=False) -pk: QbNumericField('pk', dtype=int, is_attribute=False) -repository_metadata: QbDictField('repository_metadata', dtype=Dict[str, Any], is_attribute=False) -source: QbDictField('source', dtype=Optional[dict], is_attribute=True, is_subscriptable=True) -source_list: QbArrayField('source_list', dtype=List[str], is_attribute=True) -stash_mode: QbStrField('stash_mode', dtype=str, is_attribute=True) -target_basepath: QbStrField('target_basepath', dtype=str, is_attribute=True) -user_pk: QbNumericField('user_pk', dtype=int, is_attribute=False) -uuid: QbStrField('uuid', dtype=str, is_attribute=False) +attributes: QbDictField('attributes', dtype=typing.Optional[typing.Dict[str, typing.Any]], + is_attribute=False, is_subscriptable=True) +computer: QbNumericField('computer', dtype=typing.Optional[int], is_attribute=False) +ctime: QbNumericField('ctime', dtype=typing.Optional[datetime.datetime], is_attribute=False) +description: QbStrField('description', dtype=typing.Optional[str], is_attribute=False) +extras: QbDictField('extras', dtype=typing.Optional[typing.Dict[str, typing.Any]], + is_attribute=False, is_subscriptable=True) +label: QbStrField('label', dtype=typing.Optional[str], is_attribute=False) +mtime: QbNumericField('mtime', dtype=typing.Optional[datetime.datetime], is_attribute=False) +node_type: QbStrField('node_type', dtype=typing.Optional[str], is_attribute=False) +pk: QbNumericField('pk', dtype=typing.Optional[int], is_attribute=False) +process_type: QbStrField('process_type', dtype=typing.Optional[str], is_attribute=False) +repository_content: QbDictField('repository_content', dtype=typing.Optional[dict[str, + bytes]], is_attribute=False) +repository_metadata: QbDictField('repository_metadata', dtype=typing.Optional[typing.Dict[str, + typing.Any]], is_attribute=False) +source: QbDictField('source', dtype=typing.Optional[dict], is_attribute=True, is_subscriptable=True) +source_list: QbArrayField('source_list', dtype=typing.List[str], is_attribute=True) +stash_mode: QbField('stash_mode', dtype=, is_attribute=True) +target_basepath: QbStrField('target_basepath', dtype=, is_attribute=True) +user: QbNumericField('user', dtype=typing.Optional[int], is_attribute=False) +uuid: QbStrField('uuid', dtype=typing.Optional[str], is_attribute=False) diff --git a/tests/orm/test_fields/fields_aiida.data.core.singlefile.SinglefileData.yml b/tests/orm/test_fields/fields_aiida.data.core.singlefile.SinglefileData.yml index eba6460b84..71f35c46f7 100644 --- a/tests/orm/test_fields/fields_aiida.data.core.singlefile.SinglefileData.yml +++ b/tests/orm/test_fields/fields_aiida.data.core.singlefile.SinglefileData.yml @@ -1,12 +1,21 @@ -attributes: QbDictField('attributes', dtype=Dict[str, Any], is_attribute=False, is_subscriptable=True) -ctime: QbNumericField('ctime', dtype=datetime, is_attribute=False) -description: QbStrField('description', dtype=str, is_attribute=False) -extras: QbDictField('extras', dtype=Dict[str, Any], is_attribute=False, is_subscriptable=True) -label: QbStrField('label', dtype=str, is_attribute=False) -mtime: QbNumericField('mtime', dtype=datetime, is_attribute=False) -node_type: QbStrField('node_type', dtype=str, is_attribute=False) -pk: QbNumericField('pk', dtype=int, is_attribute=False) -repository_metadata: QbDictField('repository_metadata', dtype=Dict[str, Any], is_attribute=False) -source: QbDictField('source', dtype=Optional[dict], is_attribute=True, is_subscriptable=True) -user_pk: QbNumericField('user_pk', dtype=int, is_attribute=False) -uuid: QbStrField('uuid', dtype=str, is_attribute=False) +attributes: QbDictField('attributes', dtype=typing.Optional[typing.Dict[str, typing.Any]], + is_attribute=False, is_subscriptable=True) +computer: QbNumericField('computer', dtype=typing.Optional[int], is_attribute=False) +content: QbField('content', dtype=, is_attribute=True) +ctime: QbNumericField('ctime', dtype=typing.Optional[datetime.datetime], is_attribute=False) +description: QbStrField('description', dtype=typing.Optional[str], is_attribute=False) +extras: QbDictField('extras', dtype=typing.Optional[typing.Dict[str, typing.Any]], + is_attribute=False, is_subscriptable=True) +filename: QbStrField('filename', dtype=typing.Optional[str], is_attribute=True) +label: QbStrField('label', dtype=typing.Optional[str], is_attribute=False) +mtime: QbNumericField('mtime', dtype=typing.Optional[datetime.datetime], is_attribute=False) +node_type: QbStrField('node_type', dtype=typing.Optional[str], is_attribute=False) +pk: QbNumericField('pk', dtype=typing.Optional[int], is_attribute=False) +process_type: QbStrField('process_type', dtype=typing.Optional[str], is_attribute=False) +repository_content: QbDictField('repository_content', dtype=typing.Optional[dict[str, + bytes]], is_attribute=False) +repository_metadata: QbDictField('repository_metadata', dtype=typing.Optional[typing.Dict[str, + typing.Any]], is_attribute=False) +source: QbDictField('source', dtype=typing.Optional[dict], is_attribute=True, is_subscriptable=True) +user: QbNumericField('user', dtype=typing.Optional[int], is_attribute=False) +uuid: QbStrField('uuid', dtype=typing.Optional[str], is_attribute=False) diff --git a/tests/orm/test_fields/fields_aiida.data.core.str.Str.yml b/tests/orm/test_fields/fields_aiida.data.core.str.Str.yml index b6d51f91a6..457621f596 100644 --- a/tests/orm/test_fields/fields_aiida.data.core.str.Str.yml +++ b/tests/orm/test_fields/fields_aiida.data.core.str.Str.yml @@ -1,13 +1,20 @@ -attributes: QbDictField('attributes', dtype=Dict[str, Any], is_attribute=False, is_subscriptable=True) -ctime: QbNumericField('ctime', dtype=datetime, is_attribute=False) -description: QbStrField('description', dtype=str, is_attribute=False) -extras: QbDictField('extras', dtype=Dict[str, Any], is_attribute=False, is_subscriptable=True) -label: QbStrField('label', dtype=str, is_attribute=False) -mtime: QbNumericField('mtime', dtype=datetime, is_attribute=False) -node_type: QbStrField('node_type', dtype=str, is_attribute=False) -pk: QbNumericField('pk', dtype=int, is_attribute=False) -repository_metadata: QbDictField('repository_metadata', dtype=Dict[str, Any], is_attribute=False) -source: QbDictField('source', dtype=Optional[dict], is_attribute=True, is_subscriptable=True) -user_pk: QbNumericField('user_pk', dtype=int, is_attribute=False) -uuid: QbStrField('uuid', dtype=str, is_attribute=False) -value: QbStrField('value', dtype=str, is_attribute=True) +attributes: QbDictField('attributes', dtype=typing.Optional[typing.Dict[str, typing.Any]], + is_attribute=False, is_subscriptable=True) +computer: QbNumericField('computer', dtype=typing.Optional[int], is_attribute=False) +ctime: QbNumericField('ctime', dtype=typing.Optional[datetime.datetime], is_attribute=False) +description: QbStrField('description', dtype=typing.Optional[str], is_attribute=False) +extras: QbDictField('extras', dtype=typing.Optional[typing.Dict[str, typing.Any]], + is_attribute=False, is_subscriptable=True) +label: QbStrField('label', dtype=typing.Optional[str], is_attribute=False) +mtime: QbNumericField('mtime', dtype=typing.Optional[datetime.datetime], is_attribute=False) +node_type: QbStrField('node_type', dtype=typing.Optional[str], is_attribute=False) +pk: QbNumericField('pk', dtype=typing.Optional[int], is_attribute=False) +process_type: QbStrField('process_type', dtype=typing.Optional[str], is_attribute=False) +repository_content: QbDictField('repository_content', dtype=typing.Optional[dict[str, + bytes]], is_attribute=False) +repository_metadata: QbDictField('repository_metadata', dtype=typing.Optional[typing.Dict[str, + typing.Any]], is_attribute=False) +source: QbDictField('source', dtype=typing.Optional[dict], is_attribute=True, is_subscriptable=True) +user: QbNumericField('user', dtype=typing.Optional[int], is_attribute=False) +uuid: QbStrField('uuid', dtype=typing.Optional[str], is_attribute=False) +value: QbField('value', dtype=typing.Any, is_attribute=True) diff --git a/tests/orm/test_fields/fields_aiida.data.core.structure.StructureData.yml b/tests/orm/test_fields/fields_aiida.data.core.structure.StructureData.yml index 6b68e61ee1..8e94962d01 100644 --- a/tests/orm/test_fields/fields_aiida.data.core.structure.StructureData.yml +++ b/tests/orm/test_fields/fields_aiida.data.core.structure.StructureData.yml @@ -1,18 +1,25 @@ -attributes: QbDictField('attributes', dtype=Dict[str, Any], is_attribute=False, is_subscriptable=True) -cell: QbArrayField('cell', dtype=List[List[float]], is_attribute=True) -ctime: QbNumericField('ctime', dtype=datetime, is_attribute=False) -description: QbStrField('description', dtype=str, is_attribute=False) -extras: QbDictField('extras', dtype=Dict[str, Any], is_attribute=False, is_subscriptable=True) -kinds: QbArrayField('kinds', dtype=Optional[List[dict]], is_attribute=True) -label: QbStrField('label', dtype=str, is_attribute=False) -mtime: QbNumericField('mtime', dtype=datetime, is_attribute=False) -node_type: QbStrField('node_type', dtype=str, is_attribute=False) -pbc1: QbField('pbc1', dtype=bool, is_attribute=True) -pbc2: QbField('pbc2', dtype=bool, is_attribute=True) -pbc3: QbField('pbc3', dtype=bool, is_attribute=True) -pk: QbNumericField('pk', dtype=int, is_attribute=False) -repository_metadata: QbDictField('repository_metadata', dtype=Dict[str, Any], is_attribute=False) -sites: QbArrayField('sites', dtype=Optional[List[dict]], is_attribute=True) -source: QbDictField('source', dtype=Optional[dict], is_attribute=True, is_subscriptable=True) -user_pk: QbNumericField('user_pk', dtype=int, is_attribute=False) -uuid: QbStrField('uuid', dtype=str, is_attribute=False) +attributes: QbDictField('attributes', dtype=typing.Optional[typing.Dict[str, typing.Any]], + is_attribute=False, is_subscriptable=True) +cell: QbArrayField('cell', dtype=typing.List[typing.List[float]], is_attribute=True) +computer: QbNumericField('computer', dtype=typing.Optional[int], is_attribute=False) +ctime: QbNumericField('ctime', dtype=typing.Optional[datetime.datetime], is_attribute=False) +description: QbStrField('description', dtype=typing.Optional[str], is_attribute=False) +extras: QbDictField('extras', dtype=typing.Optional[typing.Dict[str, typing.Any]], + is_attribute=False, is_subscriptable=True) +kinds: QbArrayField('kinds', dtype=typing.Optional[typing.List[dict]], is_attribute=True) +label: QbStrField('label', dtype=typing.Optional[str], is_attribute=False) +mtime: QbNumericField('mtime', dtype=typing.Optional[datetime.datetime], is_attribute=False) +node_type: QbStrField('node_type', dtype=typing.Optional[str], is_attribute=False) +pbc1: QbField('pbc1', dtype=, is_attribute=True) +pbc2: QbField('pbc2', dtype=, is_attribute=True) +pbc3: QbField('pbc3', dtype=, is_attribute=True) +pk: QbNumericField('pk', dtype=typing.Optional[int], is_attribute=False) +process_type: QbStrField('process_type', dtype=typing.Optional[str], is_attribute=False) +repository_content: QbDictField('repository_content', dtype=typing.Optional[dict[str, + bytes]], is_attribute=False) +repository_metadata: QbDictField('repository_metadata', dtype=typing.Optional[typing.Dict[str, + typing.Any]], is_attribute=False) +sites: QbArrayField('sites', dtype=typing.Optional[typing.List[dict]], is_attribute=True) +source: QbDictField('source', dtype=typing.Optional[dict], is_attribute=True, is_subscriptable=True) +user: QbNumericField('user', dtype=typing.Optional[int], is_attribute=False) +uuid: QbStrField('uuid', dtype=typing.Optional[str], is_attribute=False) diff --git a/tests/orm/test_fields/fields_aiida.data.core.upf.UpfData.yml b/tests/orm/test_fields/fields_aiida.data.core.upf.UpfData.yml index eba6460b84..71f35c46f7 100644 --- a/tests/orm/test_fields/fields_aiida.data.core.upf.UpfData.yml +++ b/tests/orm/test_fields/fields_aiida.data.core.upf.UpfData.yml @@ -1,12 +1,21 @@ -attributes: QbDictField('attributes', dtype=Dict[str, Any], is_attribute=False, is_subscriptable=True) -ctime: QbNumericField('ctime', dtype=datetime, is_attribute=False) -description: QbStrField('description', dtype=str, is_attribute=False) -extras: QbDictField('extras', dtype=Dict[str, Any], is_attribute=False, is_subscriptable=True) -label: QbStrField('label', dtype=str, is_attribute=False) -mtime: QbNumericField('mtime', dtype=datetime, is_attribute=False) -node_type: QbStrField('node_type', dtype=str, is_attribute=False) -pk: QbNumericField('pk', dtype=int, is_attribute=False) -repository_metadata: QbDictField('repository_metadata', dtype=Dict[str, Any], is_attribute=False) -source: QbDictField('source', dtype=Optional[dict], is_attribute=True, is_subscriptable=True) -user_pk: QbNumericField('user_pk', dtype=int, is_attribute=False) -uuid: QbStrField('uuid', dtype=str, is_attribute=False) +attributes: QbDictField('attributes', dtype=typing.Optional[typing.Dict[str, typing.Any]], + is_attribute=False, is_subscriptable=True) +computer: QbNumericField('computer', dtype=typing.Optional[int], is_attribute=False) +content: QbField('content', dtype=, is_attribute=True) +ctime: QbNumericField('ctime', dtype=typing.Optional[datetime.datetime], is_attribute=False) +description: QbStrField('description', dtype=typing.Optional[str], is_attribute=False) +extras: QbDictField('extras', dtype=typing.Optional[typing.Dict[str, typing.Any]], + is_attribute=False, is_subscriptable=True) +filename: QbStrField('filename', dtype=typing.Optional[str], is_attribute=True) +label: QbStrField('label', dtype=typing.Optional[str], is_attribute=False) +mtime: QbNumericField('mtime', dtype=typing.Optional[datetime.datetime], is_attribute=False) +node_type: QbStrField('node_type', dtype=typing.Optional[str], is_attribute=False) +pk: QbNumericField('pk', dtype=typing.Optional[int], is_attribute=False) +process_type: QbStrField('process_type', dtype=typing.Optional[str], is_attribute=False) +repository_content: QbDictField('repository_content', dtype=typing.Optional[dict[str, + bytes]], is_attribute=False) +repository_metadata: QbDictField('repository_metadata', dtype=typing.Optional[typing.Dict[str, + typing.Any]], is_attribute=False) +source: QbDictField('source', dtype=typing.Optional[dict], is_attribute=True, is_subscriptable=True) +user: QbNumericField('user', dtype=typing.Optional[int], is_attribute=False) +uuid: QbStrField('uuid', dtype=typing.Optional[str], is_attribute=False) diff --git a/tests/orm/test_fields/fields_aiida.node.data.Data.yml b/tests/orm/test_fields/fields_aiida.node.data.Data.yml index eba6460b84..5bee2ef441 100644 --- a/tests/orm/test_fields/fields_aiida.node.data.Data.yml +++ b/tests/orm/test_fields/fields_aiida.node.data.Data.yml @@ -1,12 +1,19 @@ -attributes: QbDictField('attributes', dtype=Dict[str, Any], is_attribute=False, is_subscriptable=True) -ctime: QbNumericField('ctime', dtype=datetime, is_attribute=False) -description: QbStrField('description', dtype=str, is_attribute=False) -extras: QbDictField('extras', dtype=Dict[str, Any], is_attribute=False, is_subscriptable=True) -label: QbStrField('label', dtype=str, is_attribute=False) -mtime: QbNumericField('mtime', dtype=datetime, is_attribute=False) -node_type: QbStrField('node_type', dtype=str, is_attribute=False) -pk: QbNumericField('pk', dtype=int, is_attribute=False) -repository_metadata: QbDictField('repository_metadata', dtype=Dict[str, Any], is_attribute=False) -source: QbDictField('source', dtype=Optional[dict], is_attribute=True, is_subscriptable=True) -user_pk: QbNumericField('user_pk', dtype=int, is_attribute=False) -uuid: QbStrField('uuid', dtype=str, is_attribute=False) +attributes: QbDictField('attributes', dtype=typing.Optional[typing.Dict[str, typing.Any]], + is_attribute=False, is_subscriptable=True) +computer: QbNumericField('computer', dtype=typing.Optional[int], is_attribute=False) +ctime: QbNumericField('ctime', dtype=typing.Optional[datetime.datetime], is_attribute=False) +description: QbStrField('description', dtype=typing.Optional[str], is_attribute=False) +extras: QbDictField('extras', dtype=typing.Optional[typing.Dict[str, typing.Any]], + is_attribute=False, is_subscriptable=True) +label: QbStrField('label', dtype=typing.Optional[str], is_attribute=False) +mtime: QbNumericField('mtime', dtype=typing.Optional[datetime.datetime], is_attribute=False) +node_type: QbStrField('node_type', dtype=typing.Optional[str], is_attribute=False) +pk: QbNumericField('pk', dtype=typing.Optional[int], is_attribute=False) +process_type: QbStrField('process_type', dtype=typing.Optional[str], is_attribute=False) +repository_content: QbDictField('repository_content', dtype=typing.Optional[dict[str, + bytes]], is_attribute=False) +repository_metadata: QbDictField('repository_metadata', dtype=typing.Optional[typing.Dict[str, + typing.Any]], is_attribute=False) +source: QbDictField('source', dtype=typing.Optional[dict], is_attribute=True, is_subscriptable=True) +user: QbNumericField('user', dtype=typing.Optional[int], is_attribute=False) +uuid: QbStrField('uuid', dtype=typing.Optional[str], is_attribute=False) diff --git a/tests/orm/test_fields/fields_aiida.node.process.ProcessNode.yml b/tests/orm/test_fields/fields_aiida.node.process.ProcessNode.yml index 772a62237d..d8928ee1a4 100644 --- a/tests/orm/test_fields/fields_aiida.node.process.ProcessNode.yml +++ b/tests/orm/test_fields/fields_aiida.node.process.ProcessNode.yml @@ -1,21 +1,26 @@ -attributes: QbDictField('attributes', dtype=Dict[str, Any], is_attribute=False, is_subscriptable=True) -computer_pk: QbNumericField('computer_pk', dtype=Optional[int], is_attribute=True) -ctime: QbNumericField('ctime', dtype=datetime, is_attribute=False) -description: QbStrField('description', dtype=str, is_attribute=False) -exception: QbStrField('exception', dtype=Optional[str], is_attribute=True) -exit_message: QbStrField('exit_message', dtype=Optional[str], is_attribute=True) -exit_status: QbNumericField('exit_status', dtype=Optional[int], is_attribute=True) -extras: QbDictField('extras', dtype=Dict[str, Any], is_attribute=False, is_subscriptable=True) -label: QbStrField('label', dtype=str, is_attribute=False) -mtime: QbNumericField('mtime', dtype=datetime, is_attribute=False) -node_type: QbStrField('node_type', dtype=str, is_attribute=False) -paused: QbField('paused', dtype=bool, is_attribute=True) -pk: QbNumericField('pk', dtype=int, is_attribute=False) -process_label: QbStrField('process_label', dtype=Optional[str], is_attribute=True) -process_state: QbStrField('process_state', dtype=Optional[str], is_attribute=True) -process_status: QbStrField('process_status', dtype=Optional[str], is_attribute=True) -process_type: QbStrField('process_type', dtype=Optional[str], is_attribute=True) -repository_metadata: QbDictField('repository_metadata', dtype=Dict[str, Any], is_attribute=False) -sealed: QbField('sealed', dtype=bool, is_attribute=True) -user_pk: QbNumericField('user_pk', dtype=int, is_attribute=False) -uuid: QbStrField('uuid', dtype=str, is_attribute=False) +attributes: QbDictField('attributes', dtype=typing.Optional[typing.Dict[str, typing.Any]], + is_attribute=False, is_subscriptable=True) +computer: QbNumericField('computer', dtype=typing.Optional[int], is_attribute=False) +ctime: QbNumericField('ctime', dtype=typing.Optional[datetime.datetime], is_attribute=False) +description: QbStrField('description', dtype=typing.Optional[str], is_attribute=False) +exception: QbStrField('exception', dtype=typing.Optional[str], is_attribute=True) +exit_message: QbStrField('exit_message', dtype=typing.Optional[str], is_attribute=True) +exit_status: QbNumericField('exit_status', dtype=typing.Optional[int], is_attribute=True) +extras: QbDictField('extras', dtype=typing.Optional[typing.Dict[str, typing.Any]], + is_attribute=False, is_subscriptable=True) +label: QbStrField('label', dtype=typing.Optional[str], is_attribute=False) +mtime: QbNumericField('mtime', dtype=typing.Optional[datetime.datetime], is_attribute=False) +node_type: QbStrField('node_type', dtype=typing.Optional[str], is_attribute=False) +paused: QbField('paused', dtype=, is_attribute=True) +pk: QbNumericField('pk', dtype=typing.Optional[int], is_attribute=False) +process_label: QbStrField('process_label', dtype=typing.Optional[str], is_attribute=True) +process_state: QbStrField('process_state', dtype=typing.Optional[str], is_attribute=True) +process_status: QbStrField('process_status', dtype=typing.Optional[str], is_attribute=True) +process_type: QbStrField('process_type', dtype=typing.Optional[str], is_attribute=False) +repository_content: QbDictField('repository_content', dtype=typing.Optional[dict[str, + bytes]], is_attribute=False) +repository_metadata: QbDictField('repository_metadata', dtype=typing.Optional[typing.Dict[str, + typing.Any]], is_attribute=False) +sealed: QbField('sealed', dtype=, is_attribute=True) +user: QbNumericField('user', dtype=typing.Optional[int], is_attribute=False) +uuid: QbStrField('uuid', dtype=typing.Optional[str], is_attribute=False) diff --git a/tests/orm/test_fields/fields_aiida.node.process.calculation.CalculationNode.yml b/tests/orm/test_fields/fields_aiida.node.process.calculation.CalculationNode.yml index 772a62237d..d8928ee1a4 100644 --- a/tests/orm/test_fields/fields_aiida.node.process.calculation.CalculationNode.yml +++ b/tests/orm/test_fields/fields_aiida.node.process.calculation.CalculationNode.yml @@ -1,21 +1,26 @@ -attributes: QbDictField('attributes', dtype=Dict[str, Any], is_attribute=False, is_subscriptable=True) -computer_pk: QbNumericField('computer_pk', dtype=Optional[int], is_attribute=True) -ctime: QbNumericField('ctime', dtype=datetime, is_attribute=False) -description: QbStrField('description', dtype=str, is_attribute=False) -exception: QbStrField('exception', dtype=Optional[str], is_attribute=True) -exit_message: QbStrField('exit_message', dtype=Optional[str], is_attribute=True) -exit_status: QbNumericField('exit_status', dtype=Optional[int], is_attribute=True) -extras: QbDictField('extras', dtype=Dict[str, Any], is_attribute=False, is_subscriptable=True) -label: QbStrField('label', dtype=str, is_attribute=False) -mtime: QbNumericField('mtime', dtype=datetime, is_attribute=False) -node_type: QbStrField('node_type', dtype=str, is_attribute=False) -paused: QbField('paused', dtype=bool, is_attribute=True) -pk: QbNumericField('pk', dtype=int, is_attribute=False) -process_label: QbStrField('process_label', dtype=Optional[str], is_attribute=True) -process_state: QbStrField('process_state', dtype=Optional[str], is_attribute=True) -process_status: QbStrField('process_status', dtype=Optional[str], is_attribute=True) -process_type: QbStrField('process_type', dtype=Optional[str], is_attribute=True) -repository_metadata: QbDictField('repository_metadata', dtype=Dict[str, Any], is_attribute=False) -sealed: QbField('sealed', dtype=bool, is_attribute=True) -user_pk: QbNumericField('user_pk', dtype=int, is_attribute=False) -uuid: QbStrField('uuid', dtype=str, is_attribute=False) +attributes: QbDictField('attributes', dtype=typing.Optional[typing.Dict[str, typing.Any]], + is_attribute=False, is_subscriptable=True) +computer: QbNumericField('computer', dtype=typing.Optional[int], is_attribute=False) +ctime: QbNumericField('ctime', dtype=typing.Optional[datetime.datetime], is_attribute=False) +description: QbStrField('description', dtype=typing.Optional[str], is_attribute=False) +exception: QbStrField('exception', dtype=typing.Optional[str], is_attribute=True) +exit_message: QbStrField('exit_message', dtype=typing.Optional[str], is_attribute=True) +exit_status: QbNumericField('exit_status', dtype=typing.Optional[int], is_attribute=True) +extras: QbDictField('extras', dtype=typing.Optional[typing.Dict[str, typing.Any]], + is_attribute=False, is_subscriptable=True) +label: QbStrField('label', dtype=typing.Optional[str], is_attribute=False) +mtime: QbNumericField('mtime', dtype=typing.Optional[datetime.datetime], is_attribute=False) +node_type: QbStrField('node_type', dtype=typing.Optional[str], is_attribute=False) +paused: QbField('paused', dtype=, is_attribute=True) +pk: QbNumericField('pk', dtype=typing.Optional[int], is_attribute=False) +process_label: QbStrField('process_label', dtype=typing.Optional[str], is_attribute=True) +process_state: QbStrField('process_state', dtype=typing.Optional[str], is_attribute=True) +process_status: QbStrField('process_status', dtype=typing.Optional[str], is_attribute=True) +process_type: QbStrField('process_type', dtype=typing.Optional[str], is_attribute=False) +repository_content: QbDictField('repository_content', dtype=typing.Optional[dict[str, + bytes]], is_attribute=False) +repository_metadata: QbDictField('repository_metadata', dtype=typing.Optional[typing.Dict[str, + typing.Any]], is_attribute=False) +sealed: QbField('sealed', dtype=, is_attribute=True) +user: QbNumericField('user', dtype=typing.Optional[int], is_attribute=False) +uuid: QbStrField('uuid', dtype=typing.Optional[str], is_attribute=False) diff --git a/tests/orm/test_fields/fields_aiida.node.process.calculation.calcfunction.CalcFunctionNode.yml b/tests/orm/test_fields/fields_aiida.node.process.calculation.calcfunction.CalcFunctionNode.yml index 772a62237d..d8928ee1a4 100644 --- a/tests/orm/test_fields/fields_aiida.node.process.calculation.calcfunction.CalcFunctionNode.yml +++ b/tests/orm/test_fields/fields_aiida.node.process.calculation.calcfunction.CalcFunctionNode.yml @@ -1,21 +1,26 @@ -attributes: QbDictField('attributes', dtype=Dict[str, Any], is_attribute=False, is_subscriptable=True) -computer_pk: QbNumericField('computer_pk', dtype=Optional[int], is_attribute=True) -ctime: QbNumericField('ctime', dtype=datetime, is_attribute=False) -description: QbStrField('description', dtype=str, is_attribute=False) -exception: QbStrField('exception', dtype=Optional[str], is_attribute=True) -exit_message: QbStrField('exit_message', dtype=Optional[str], is_attribute=True) -exit_status: QbNumericField('exit_status', dtype=Optional[int], is_attribute=True) -extras: QbDictField('extras', dtype=Dict[str, Any], is_attribute=False, is_subscriptable=True) -label: QbStrField('label', dtype=str, is_attribute=False) -mtime: QbNumericField('mtime', dtype=datetime, is_attribute=False) -node_type: QbStrField('node_type', dtype=str, is_attribute=False) -paused: QbField('paused', dtype=bool, is_attribute=True) -pk: QbNumericField('pk', dtype=int, is_attribute=False) -process_label: QbStrField('process_label', dtype=Optional[str], is_attribute=True) -process_state: QbStrField('process_state', dtype=Optional[str], is_attribute=True) -process_status: QbStrField('process_status', dtype=Optional[str], is_attribute=True) -process_type: QbStrField('process_type', dtype=Optional[str], is_attribute=True) -repository_metadata: QbDictField('repository_metadata', dtype=Dict[str, Any], is_attribute=False) -sealed: QbField('sealed', dtype=bool, is_attribute=True) -user_pk: QbNumericField('user_pk', dtype=int, is_attribute=False) -uuid: QbStrField('uuid', dtype=str, is_attribute=False) +attributes: QbDictField('attributes', dtype=typing.Optional[typing.Dict[str, typing.Any]], + is_attribute=False, is_subscriptable=True) +computer: QbNumericField('computer', dtype=typing.Optional[int], is_attribute=False) +ctime: QbNumericField('ctime', dtype=typing.Optional[datetime.datetime], is_attribute=False) +description: QbStrField('description', dtype=typing.Optional[str], is_attribute=False) +exception: QbStrField('exception', dtype=typing.Optional[str], is_attribute=True) +exit_message: QbStrField('exit_message', dtype=typing.Optional[str], is_attribute=True) +exit_status: QbNumericField('exit_status', dtype=typing.Optional[int], is_attribute=True) +extras: QbDictField('extras', dtype=typing.Optional[typing.Dict[str, typing.Any]], + is_attribute=False, is_subscriptable=True) +label: QbStrField('label', dtype=typing.Optional[str], is_attribute=False) +mtime: QbNumericField('mtime', dtype=typing.Optional[datetime.datetime], is_attribute=False) +node_type: QbStrField('node_type', dtype=typing.Optional[str], is_attribute=False) +paused: QbField('paused', dtype=, is_attribute=True) +pk: QbNumericField('pk', dtype=typing.Optional[int], is_attribute=False) +process_label: QbStrField('process_label', dtype=typing.Optional[str], is_attribute=True) +process_state: QbStrField('process_state', dtype=typing.Optional[str], is_attribute=True) +process_status: QbStrField('process_status', dtype=typing.Optional[str], is_attribute=True) +process_type: QbStrField('process_type', dtype=typing.Optional[str], is_attribute=False) +repository_content: QbDictField('repository_content', dtype=typing.Optional[dict[str, + bytes]], is_attribute=False) +repository_metadata: QbDictField('repository_metadata', dtype=typing.Optional[typing.Dict[str, + typing.Any]], is_attribute=False) +sealed: QbField('sealed', dtype=, is_attribute=True) +user: QbNumericField('user', dtype=typing.Optional[int], is_attribute=False) +uuid: QbStrField('uuid', dtype=typing.Optional[str], is_attribute=False) diff --git a/tests/orm/test_fields/fields_aiida.node.process.calculation.calcjob.CalcJobNode.yml b/tests/orm/test_fields/fields_aiida.node.process.calculation.calcjob.CalcJobNode.yml index ec30d47fe0..8da4b34cb8 100644 --- a/tests/orm/test_fields/fields_aiida.node.process.calculation.calcjob.CalcJobNode.yml +++ b/tests/orm/test_fields/fields_aiida.node.process.calculation.calcjob.CalcJobNode.yml @@ -1,33 +1,39 @@ -attributes: QbDictField('attributes', dtype=Dict[str, Any], is_attribute=False, is_subscriptable=True) -computer_pk: QbNumericField('computer_pk', dtype=Optional[int], is_attribute=True) -ctime: QbNumericField('ctime', dtype=datetime, is_attribute=False) -description: QbStrField('description', dtype=str, is_attribute=False) -detailed_job_info: QbDictField('detailed_job_info', dtype=Optional[dict], is_attribute=True) -exception: QbStrField('exception', dtype=Optional[str], is_attribute=True) -exit_message: QbStrField('exit_message', dtype=Optional[str], is_attribute=True) -exit_status: QbNumericField('exit_status', dtype=Optional[int], is_attribute=True) -extras: QbDictField('extras', dtype=Dict[str, Any], is_attribute=False, is_subscriptable=True) -imported: QbField('imported', dtype=Optional[bool], is_attribute=True) -job_id: QbStrField('job_id', dtype=Optional[str], is_attribute=True) -label: QbStrField('label', dtype=str, is_attribute=False) -last_job_info: QbStrField('last_job_info', dtype=Optional[str], is_attribute=True) -mtime: QbNumericField('mtime', dtype=datetime, is_attribute=False) -node_type: QbStrField('node_type', dtype=str, is_attribute=False) -paused: QbField('paused', dtype=bool, is_attribute=True) -pk: QbNumericField('pk', dtype=int, is_attribute=False) -process_label: QbStrField('process_label', dtype=Optional[str], is_attribute=True) -process_state: QbStrField('process_state', dtype=Optional[str], is_attribute=True) -process_status: QbStrField('process_status', dtype=Optional[str], is_attribute=True) -process_type: QbStrField('process_type', dtype=Optional[str], is_attribute=True) -remote_workdir: QbStrField('remote_workdir', dtype=Optional[str], is_attribute=True) -repository_metadata: QbDictField('repository_metadata', dtype=Dict[str, Any], is_attribute=False) -retrieve_list: QbArrayField('retrieve_list', dtype=Optional[List[str]], is_attribute=True) -retrieve_temporary_list: QbArrayField('retrieve_temporary_list', dtype=Optional[List[str]], +attributes: QbDictField('attributes', dtype=typing.Optional[typing.Dict[str, typing.Any]], + is_attribute=False, is_subscriptable=True) +computer: QbNumericField('computer', dtype=typing.Optional[int], is_attribute=False) +ctime: QbNumericField('ctime', dtype=typing.Optional[datetime.datetime], is_attribute=False) +description: QbStrField('description', dtype=typing.Optional[str], is_attribute=False) +detailed_job_info: QbDictField('detailed_job_info', dtype=typing.Optional[dict], is_attribute=True) +exception: QbStrField('exception', dtype=typing.Optional[str], is_attribute=True) +exit_message: QbStrField('exit_message', dtype=typing.Optional[str], is_attribute=True) +exit_status: QbNumericField('exit_status', dtype=typing.Optional[int], is_attribute=True) +extras: QbDictField('extras', dtype=typing.Optional[typing.Dict[str, typing.Any]], + is_attribute=False, is_subscriptable=True) +imported: QbField('imported', dtype=typing.Optional[bool], is_attribute=True) +job_id: QbStrField('job_id', dtype=typing.Optional[str], is_attribute=True) +label: QbStrField('label', dtype=typing.Optional[str], is_attribute=False) +last_job_info: QbStrField('last_job_info', dtype=typing.Optional[str], is_attribute=True) +mtime: QbNumericField('mtime', dtype=typing.Optional[datetime.datetime], is_attribute=False) +node_type: QbStrField('node_type', dtype=typing.Optional[str], is_attribute=False) +paused: QbField('paused', dtype=, is_attribute=True) +pk: QbNumericField('pk', dtype=typing.Optional[int], is_attribute=False) +process_label: QbStrField('process_label', dtype=typing.Optional[str], is_attribute=True) +process_state: QbStrField('process_state', dtype=typing.Optional[str], is_attribute=True) +process_status: QbStrField('process_status', dtype=typing.Optional[str], is_attribute=True) +process_type: QbStrField('process_type', dtype=typing.Optional[str], is_attribute=False) +remote_workdir: QbStrField('remote_workdir', dtype=typing.Optional[str], is_attribute=True) +repository_content: QbDictField('repository_content', dtype=typing.Optional[dict[str, + bytes]], is_attribute=False) +repository_metadata: QbDictField('repository_metadata', dtype=typing.Optional[typing.Dict[str, + typing.Any]], is_attribute=False) +retrieve_list: QbArrayField('retrieve_list', dtype=typing.Optional[typing.List[str]], is_attribute=True) -scheduler_lastchecktime: QbStrField('scheduler_lastchecktime', dtype=Optional[str], +retrieve_temporary_list: QbArrayField('retrieve_temporary_list', dtype=typing.Optional[typing.List[str]], is_attribute=True) -scheduler_state: QbStrField('scheduler_state', dtype=Optional[str], is_attribute=True) -sealed: QbField('sealed', dtype=bool, is_attribute=True) -state: QbStrField('state', dtype=Optional[str], is_attribute=True) -user_pk: QbNumericField('user_pk', dtype=int, is_attribute=False) -uuid: QbStrField('uuid', dtype=str, is_attribute=False) +scheduler_lastchecktime: QbStrField('scheduler_lastchecktime', dtype=typing.Optional[str], + is_attribute=True) +scheduler_state: QbStrField('scheduler_state', dtype=typing.Optional[str], is_attribute=True) +sealed: QbField('sealed', dtype=, is_attribute=True) +state: QbStrField('state', dtype=typing.Optional[str], is_attribute=True) +user: QbNumericField('user', dtype=typing.Optional[int], is_attribute=False) +uuid: QbStrField('uuid', dtype=typing.Optional[str], is_attribute=False) diff --git a/tests/orm/test_fields/fields_aiida.node.process.workflow.WorkflowNode.yml b/tests/orm/test_fields/fields_aiida.node.process.workflow.WorkflowNode.yml index 772a62237d..d8928ee1a4 100644 --- a/tests/orm/test_fields/fields_aiida.node.process.workflow.WorkflowNode.yml +++ b/tests/orm/test_fields/fields_aiida.node.process.workflow.WorkflowNode.yml @@ -1,21 +1,26 @@ -attributes: QbDictField('attributes', dtype=Dict[str, Any], is_attribute=False, is_subscriptable=True) -computer_pk: QbNumericField('computer_pk', dtype=Optional[int], is_attribute=True) -ctime: QbNumericField('ctime', dtype=datetime, is_attribute=False) -description: QbStrField('description', dtype=str, is_attribute=False) -exception: QbStrField('exception', dtype=Optional[str], is_attribute=True) -exit_message: QbStrField('exit_message', dtype=Optional[str], is_attribute=True) -exit_status: QbNumericField('exit_status', dtype=Optional[int], is_attribute=True) -extras: QbDictField('extras', dtype=Dict[str, Any], is_attribute=False, is_subscriptable=True) -label: QbStrField('label', dtype=str, is_attribute=False) -mtime: QbNumericField('mtime', dtype=datetime, is_attribute=False) -node_type: QbStrField('node_type', dtype=str, is_attribute=False) -paused: QbField('paused', dtype=bool, is_attribute=True) -pk: QbNumericField('pk', dtype=int, is_attribute=False) -process_label: QbStrField('process_label', dtype=Optional[str], is_attribute=True) -process_state: QbStrField('process_state', dtype=Optional[str], is_attribute=True) -process_status: QbStrField('process_status', dtype=Optional[str], is_attribute=True) -process_type: QbStrField('process_type', dtype=Optional[str], is_attribute=True) -repository_metadata: QbDictField('repository_metadata', dtype=Dict[str, Any], is_attribute=False) -sealed: QbField('sealed', dtype=bool, is_attribute=True) -user_pk: QbNumericField('user_pk', dtype=int, is_attribute=False) -uuid: QbStrField('uuid', dtype=str, is_attribute=False) +attributes: QbDictField('attributes', dtype=typing.Optional[typing.Dict[str, typing.Any]], + is_attribute=False, is_subscriptable=True) +computer: QbNumericField('computer', dtype=typing.Optional[int], is_attribute=False) +ctime: QbNumericField('ctime', dtype=typing.Optional[datetime.datetime], is_attribute=False) +description: QbStrField('description', dtype=typing.Optional[str], is_attribute=False) +exception: QbStrField('exception', dtype=typing.Optional[str], is_attribute=True) +exit_message: QbStrField('exit_message', dtype=typing.Optional[str], is_attribute=True) +exit_status: QbNumericField('exit_status', dtype=typing.Optional[int], is_attribute=True) +extras: QbDictField('extras', dtype=typing.Optional[typing.Dict[str, typing.Any]], + is_attribute=False, is_subscriptable=True) +label: QbStrField('label', dtype=typing.Optional[str], is_attribute=False) +mtime: QbNumericField('mtime', dtype=typing.Optional[datetime.datetime], is_attribute=False) +node_type: QbStrField('node_type', dtype=typing.Optional[str], is_attribute=False) +paused: QbField('paused', dtype=, is_attribute=True) +pk: QbNumericField('pk', dtype=typing.Optional[int], is_attribute=False) +process_label: QbStrField('process_label', dtype=typing.Optional[str], is_attribute=True) +process_state: QbStrField('process_state', dtype=typing.Optional[str], is_attribute=True) +process_status: QbStrField('process_status', dtype=typing.Optional[str], is_attribute=True) +process_type: QbStrField('process_type', dtype=typing.Optional[str], is_attribute=False) +repository_content: QbDictField('repository_content', dtype=typing.Optional[dict[str, + bytes]], is_attribute=False) +repository_metadata: QbDictField('repository_metadata', dtype=typing.Optional[typing.Dict[str, + typing.Any]], is_attribute=False) +sealed: QbField('sealed', dtype=, is_attribute=True) +user: QbNumericField('user', dtype=typing.Optional[int], is_attribute=False) +uuid: QbStrField('uuid', dtype=typing.Optional[str], is_attribute=False) diff --git a/tests/orm/test_fields/fields_aiida.node.process.workflow.workchain.WorkChainNode.yml b/tests/orm/test_fields/fields_aiida.node.process.workflow.workchain.WorkChainNode.yml index 772a62237d..d8928ee1a4 100644 --- a/tests/orm/test_fields/fields_aiida.node.process.workflow.workchain.WorkChainNode.yml +++ b/tests/orm/test_fields/fields_aiida.node.process.workflow.workchain.WorkChainNode.yml @@ -1,21 +1,26 @@ -attributes: QbDictField('attributes', dtype=Dict[str, Any], is_attribute=False, is_subscriptable=True) -computer_pk: QbNumericField('computer_pk', dtype=Optional[int], is_attribute=True) -ctime: QbNumericField('ctime', dtype=datetime, is_attribute=False) -description: QbStrField('description', dtype=str, is_attribute=False) -exception: QbStrField('exception', dtype=Optional[str], is_attribute=True) -exit_message: QbStrField('exit_message', dtype=Optional[str], is_attribute=True) -exit_status: QbNumericField('exit_status', dtype=Optional[int], is_attribute=True) -extras: QbDictField('extras', dtype=Dict[str, Any], is_attribute=False, is_subscriptable=True) -label: QbStrField('label', dtype=str, is_attribute=False) -mtime: QbNumericField('mtime', dtype=datetime, is_attribute=False) -node_type: QbStrField('node_type', dtype=str, is_attribute=False) -paused: QbField('paused', dtype=bool, is_attribute=True) -pk: QbNumericField('pk', dtype=int, is_attribute=False) -process_label: QbStrField('process_label', dtype=Optional[str], is_attribute=True) -process_state: QbStrField('process_state', dtype=Optional[str], is_attribute=True) -process_status: QbStrField('process_status', dtype=Optional[str], is_attribute=True) -process_type: QbStrField('process_type', dtype=Optional[str], is_attribute=True) -repository_metadata: QbDictField('repository_metadata', dtype=Dict[str, Any], is_attribute=False) -sealed: QbField('sealed', dtype=bool, is_attribute=True) -user_pk: QbNumericField('user_pk', dtype=int, is_attribute=False) -uuid: QbStrField('uuid', dtype=str, is_attribute=False) +attributes: QbDictField('attributes', dtype=typing.Optional[typing.Dict[str, typing.Any]], + is_attribute=False, is_subscriptable=True) +computer: QbNumericField('computer', dtype=typing.Optional[int], is_attribute=False) +ctime: QbNumericField('ctime', dtype=typing.Optional[datetime.datetime], is_attribute=False) +description: QbStrField('description', dtype=typing.Optional[str], is_attribute=False) +exception: QbStrField('exception', dtype=typing.Optional[str], is_attribute=True) +exit_message: QbStrField('exit_message', dtype=typing.Optional[str], is_attribute=True) +exit_status: QbNumericField('exit_status', dtype=typing.Optional[int], is_attribute=True) +extras: QbDictField('extras', dtype=typing.Optional[typing.Dict[str, typing.Any]], + is_attribute=False, is_subscriptable=True) +label: QbStrField('label', dtype=typing.Optional[str], is_attribute=False) +mtime: QbNumericField('mtime', dtype=typing.Optional[datetime.datetime], is_attribute=False) +node_type: QbStrField('node_type', dtype=typing.Optional[str], is_attribute=False) +paused: QbField('paused', dtype=, is_attribute=True) +pk: QbNumericField('pk', dtype=typing.Optional[int], is_attribute=False) +process_label: QbStrField('process_label', dtype=typing.Optional[str], is_attribute=True) +process_state: QbStrField('process_state', dtype=typing.Optional[str], is_attribute=True) +process_status: QbStrField('process_status', dtype=typing.Optional[str], is_attribute=True) +process_type: QbStrField('process_type', dtype=typing.Optional[str], is_attribute=False) +repository_content: QbDictField('repository_content', dtype=typing.Optional[dict[str, + bytes]], is_attribute=False) +repository_metadata: QbDictField('repository_metadata', dtype=typing.Optional[typing.Dict[str, + typing.Any]], is_attribute=False) +sealed: QbField('sealed', dtype=, is_attribute=True) +user: QbNumericField('user', dtype=typing.Optional[int], is_attribute=False) +uuid: QbStrField('uuid', dtype=typing.Optional[str], is_attribute=False) diff --git a/tests/orm/test_fields/fields_aiida.node.process.workflow.workfunction.WorkFunctionNode.yml b/tests/orm/test_fields/fields_aiida.node.process.workflow.workfunction.WorkFunctionNode.yml index 772a62237d..d8928ee1a4 100644 --- a/tests/orm/test_fields/fields_aiida.node.process.workflow.workfunction.WorkFunctionNode.yml +++ b/tests/orm/test_fields/fields_aiida.node.process.workflow.workfunction.WorkFunctionNode.yml @@ -1,21 +1,26 @@ -attributes: QbDictField('attributes', dtype=Dict[str, Any], is_attribute=False, is_subscriptable=True) -computer_pk: QbNumericField('computer_pk', dtype=Optional[int], is_attribute=True) -ctime: QbNumericField('ctime', dtype=datetime, is_attribute=False) -description: QbStrField('description', dtype=str, is_attribute=False) -exception: QbStrField('exception', dtype=Optional[str], is_attribute=True) -exit_message: QbStrField('exit_message', dtype=Optional[str], is_attribute=True) -exit_status: QbNumericField('exit_status', dtype=Optional[int], is_attribute=True) -extras: QbDictField('extras', dtype=Dict[str, Any], is_attribute=False, is_subscriptable=True) -label: QbStrField('label', dtype=str, is_attribute=False) -mtime: QbNumericField('mtime', dtype=datetime, is_attribute=False) -node_type: QbStrField('node_type', dtype=str, is_attribute=False) -paused: QbField('paused', dtype=bool, is_attribute=True) -pk: QbNumericField('pk', dtype=int, is_attribute=False) -process_label: QbStrField('process_label', dtype=Optional[str], is_attribute=True) -process_state: QbStrField('process_state', dtype=Optional[str], is_attribute=True) -process_status: QbStrField('process_status', dtype=Optional[str], is_attribute=True) -process_type: QbStrField('process_type', dtype=Optional[str], is_attribute=True) -repository_metadata: QbDictField('repository_metadata', dtype=Dict[str, Any], is_attribute=False) -sealed: QbField('sealed', dtype=bool, is_attribute=True) -user_pk: QbNumericField('user_pk', dtype=int, is_attribute=False) -uuid: QbStrField('uuid', dtype=str, is_attribute=False) +attributes: QbDictField('attributes', dtype=typing.Optional[typing.Dict[str, typing.Any]], + is_attribute=False, is_subscriptable=True) +computer: QbNumericField('computer', dtype=typing.Optional[int], is_attribute=False) +ctime: QbNumericField('ctime', dtype=typing.Optional[datetime.datetime], is_attribute=False) +description: QbStrField('description', dtype=typing.Optional[str], is_attribute=False) +exception: QbStrField('exception', dtype=typing.Optional[str], is_attribute=True) +exit_message: QbStrField('exit_message', dtype=typing.Optional[str], is_attribute=True) +exit_status: QbNumericField('exit_status', dtype=typing.Optional[int], is_attribute=True) +extras: QbDictField('extras', dtype=typing.Optional[typing.Dict[str, typing.Any]], + is_attribute=False, is_subscriptable=True) +label: QbStrField('label', dtype=typing.Optional[str], is_attribute=False) +mtime: QbNumericField('mtime', dtype=typing.Optional[datetime.datetime], is_attribute=False) +node_type: QbStrField('node_type', dtype=typing.Optional[str], is_attribute=False) +paused: QbField('paused', dtype=, is_attribute=True) +pk: QbNumericField('pk', dtype=typing.Optional[int], is_attribute=False) +process_label: QbStrField('process_label', dtype=typing.Optional[str], is_attribute=True) +process_state: QbStrField('process_state', dtype=typing.Optional[str], is_attribute=True) +process_status: QbStrField('process_status', dtype=typing.Optional[str], is_attribute=True) +process_type: QbStrField('process_type', dtype=typing.Optional[str], is_attribute=False) +repository_content: QbDictField('repository_content', dtype=typing.Optional[dict[str, + bytes]], is_attribute=False) +repository_metadata: QbDictField('repository_metadata', dtype=typing.Optional[typing.Dict[str, + typing.Any]], is_attribute=False) +sealed: QbField('sealed', dtype=, is_attribute=True) +user: QbNumericField('user', dtype=typing.Optional[int], is_attribute=False) +uuid: QbStrField('uuid', dtype=typing.Optional[str], is_attribute=False)