Skip to content

Commit

Permalink
Add exclude_from_cli field metadata key
Browse files Browse the repository at this point in the history
  • Loading branch information
sphuber committed Mar 20, 2024
1 parent 56c258d commit aec4a35
Show file tree
Hide file tree
Showing 44 changed files with 86 additions and 61 deletions.
4 changes: 2 additions & 2 deletions src/aiida/cmdline/commands/cmd_code.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,10 +26,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}')

Expand Down
4 changes: 1 addition & 3 deletions src/aiida/cmdline/commands/cmd_profile.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,7 @@ def verdi_profile():
"""Inspect and manage the configured profiles."""


def command_create_profile(
ctx: click.Context, storage_cls, non_interactive: bool, profile: Profile, set_as_default: bool = True, **kwargs
):
def command_create_profile(ctx: click.Context, storage_cls, profile: Profile, set_as_default: bool = True, **kwargs):
"""Create a new profile, initialise its storage and create a default user.
:param ctx: The context of the CLI command.
Expand Down
17 changes: 9 additions & 8 deletions src/aiida/cmdline/groups/dynamic.py
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down Expand Up @@ -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'):
Expand All @@ -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
Expand Down
4 changes: 4 additions & 0 deletions src/aiida/common/pydantic.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ def MetadataField( # noqa: N802
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,
Expand Down Expand Up @@ -72,6 +73,8 @@ class Model(BaseModel):
: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.
"""
Expand All @@ -85,6 +88,7 @@ class Model(BaseModel):
('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),
):
Expand Down
1 change: 1 addition & 0 deletions src/aiida/orm/entities.py
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,7 @@ class Model(BaseModel):
description='The primary key of the entity. Can be `None` if the entity is not yet stored.',
is_attribute=False,
exclude_to_orm=True,
exclude_from_cli=True,
)

@classmethod
Expand Down
4 changes: 1 addition & 3 deletions src/aiida/orm/nodes/data/data.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,9 +47,7 @@ class Data(Node):

class Model(Node.Model):
source: Optional[dict] = MetadataField(
None,
description='Source of the data.',
is_subscriptable=True,
None, description='Source of the data.', is_subscriptable=True, exclude_from_cli=True
)

def __init__(self, *args, source=None, **kwargs):
Expand Down
39 changes: 31 additions & 8 deletions src/aiida/orm/nodes/node.py
Original file line number Diff line number Diff line change
Expand Up @@ -188,55 +188,77 @@ def _query_type_string(cls) -> str: # noqa: N805

class Model(Entity.Model):
uuid: Optional[str] = MetadataField(
None, description='The UUID of the node', is_attribute=False, exclude_to_orm=True
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
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, exclude_to_orm=True
None,
description='The process type of the node',
is_attribute=False,
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,
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, exclude_to_orm=True
None,
description='The creation time of the node',
is_attribute=False,
exclude_to_orm=True,
exclude_from_cli=True,
)
mtime: Optional[datetime.datetime] = MetadataField(
None, description='The modification time of the node', is_attribute=False, exclude_to_orm=True
None,
description='The modification time of the node',
is_attribute=False,
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
)
label: Optional[str] = MetadataField(None, description='The node label', is_attribute=False)
description: Optional[str] = MetadataField(None, description='The node description', is_attribute=False)
attributes: Optional[Dict[str, Any]] = MetadataField(
None,
description='The node attributes',
is_attribute=False,
orm_to_model=lambda node: node.base.attributes.all, # type: ignore[attr-defined]
is_subscriptable=True,
exclude_from_cli=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,
exclude_from_cli=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: int = MetadataField(
user: Optional[int] = MetadataField(
None,
description='The PK of the user who owns the node',
is_attribute=False,
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,
Expand All @@ -247,6 +269,7 @@ class Model(Entity.Model):
key: base64.encodebytes(content)
for key, content in node.base.repository.serialize_content().items() # type: ignore[attr-defined]
},
exclude_from_cli=True,
)

def __init__(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,5 +16,5 @@ repository_content: QbDictField('repository_content', dtype=Optional[dict[str, b
repository_metadata: QbDictField('repository_metadata', dtype=Optional[Dict[str, Any]],
is_attribute=False)
source: QbDictField('source', dtype=Optional[dict], is_attribute=True, is_subscriptable=True)
user: QbNumericField('user', dtype=int, is_attribute=False)
user: QbNumericField('user', dtype=Optional[int], is_attribute=False)
uuid: QbStrField('uuid', dtype=Optional[str], is_attribute=False)
Original file line number Diff line number Diff line change
Expand Up @@ -26,5 +26,5 @@ repository_metadata: QbDictField('repository_metadata', dtype=Optional[Dict[str,
is_attribute=False)
source: QbDictField('source', dtype=Optional[dict], is_attribute=True, is_subscriptable=True)
units: QbStrField('units', dtype=str, is_attribute=True)
user: QbNumericField('user', dtype=int, is_attribute=False)
user: QbNumericField('user', dtype=Optional[int], is_attribute=False)
uuid: QbStrField('uuid', dtype=Optional[str], is_attribute=False)
Original file line number Diff line number Diff line change
Expand Up @@ -24,5 +24,5 @@ repository_content: QbDictField('repository_content', dtype=Optional[dict[str, b
repository_metadata: QbDictField('repository_metadata', dtype=Optional[Dict[str, Any]],
is_attribute=False)
source: QbDictField('source', dtype=Optional[dict], is_attribute=True, is_subscriptable=True)
user: QbNumericField('user', dtype=int, is_attribute=False)
user: QbNumericField('user', dtype=Optional[int], is_attribute=False)
uuid: QbStrField('uuid', dtype=Optional[str], is_attribute=False)
Original file line number Diff line number Diff line change
Expand Up @@ -14,5 +14,5 @@ process_type: QbStrField('process_type', dtype=Optional[str], is_attribute=False
repository_metadata: QbDictField('repository_metadata', dtype=Optional[Dict[str, Any]],
is_attribute=False)
source: QbDictField('source', dtype=Optional[dict], is_attribute=True, is_subscriptable=True)
user: QbNumericField('user', dtype=int, is_attribute=False)
user: QbNumericField('user', dtype=Optional[int], is_attribute=False)
uuid: QbStrField('uuid', dtype=Optional[str], is_attribute=False)
Original file line number Diff line number Diff line change
Expand Up @@ -19,5 +19,5 @@ source: QbDictField('source', dtype=Optional[dict], is_attribute=True, is_subscr
symbols: QbArrayField('symbols', dtype=List[str], is_attribute=True)
units_positions: QbStrField('units_positions', dtype=str, is_attribute=True)
units_times: QbStrField('units_times', dtype=str, is_attribute=True)
user: QbNumericField('user', dtype=int, is_attribute=False)
user: QbNumericField('user', dtype=Optional[int], is_attribute=False)
uuid: QbStrField('uuid', dtype=Optional[str], is_attribute=False)
Original file line number Diff line number Diff line change
Expand Up @@ -14,5 +14,5 @@ process_type: QbStrField('process_type', dtype=Optional[str], is_attribute=False
repository_metadata: QbDictField('repository_metadata', dtype=Optional[Dict[str, Any]],
is_attribute=False)
source: QbDictField('source', dtype=Optional[dict], is_attribute=True, is_subscriptable=True)
user: QbNumericField('user', dtype=int, is_attribute=False)
user: QbNumericField('user', dtype=Optional[int], is_attribute=False)
uuid: QbStrField('uuid', dtype=Optional[str], is_attribute=False)
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,6 @@ repository_content: QbDictField('repository_content', dtype=Optional[dict[str, b
repository_metadata: QbDictField('repository_metadata', dtype=Optional[Dict[str, Any]],
is_attribute=False)
source: QbDictField('source', dtype=Optional[dict], is_attribute=True, is_subscriptable=True)
user: QbNumericField('user', dtype=int, is_attribute=False)
user: QbNumericField('user', dtype=Optional[int], is_attribute=False)
uuid: QbStrField('uuid', dtype=Optional[str], is_attribute=False)
value: QbField('value', dtype=Any, is_attribute=True)
2 changes: 1 addition & 1 deletion tests/orm/test_fields/fields_aiida.data.core.bool.Bool.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,6 @@ repository_content: QbDictField('repository_content', dtype=Optional[dict[str, b
repository_metadata: QbDictField('repository_metadata', dtype=Optional[Dict[str, Any]],
is_attribute=False)
source: QbDictField('source', dtype=Optional[dict], is_attribute=True, is_subscriptable=True)
user: QbNumericField('user', dtype=int, is_attribute=False)
user: QbNumericField('user', dtype=Optional[int], is_attribute=False)
uuid: QbStrField('uuid', dtype=Optional[str], is_attribute=False)
value: QbField('value', dtype=Any, is_attribute=True)
Original file line number Diff line number Diff line change
Expand Up @@ -21,5 +21,5 @@ repository_metadata: QbDictField('repository_metadata', dtype=Optional[Dict[str,
source: QbDictField('source', dtype=Optional[dict], is_attribute=True, is_subscriptable=True)
spacegroup_numbers: QbArrayField('spacegroup_numbers', dtype=Optional[List[str]],
is_attribute=True)
user: QbNumericField('user', dtype=int, is_attribute=False)
user: QbNumericField('user', dtype=Optional[int], is_attribute=False)
uuid: QbStrField('uuid', dtype=Optional[str], is_attribute=False)
2 changes: 1 addition & 1 deletion tests/orm/test_fields/fields_aiida.data.core.code.Code.yml
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,6 @@ repository_metadata: QbDictField('repository_metadata', dtype=Optional[Dict[str,
is_attribute=False)
source: QbDictField('source', dtype=Optional[dict], is_attribute=True, is_subscriptable=True)
use_double_quotes: QbField('use_double_quotes', dtype=bool, is_attribute=True)
user: QbNumericField('user', dtype=int, is_attribute=False)
user: QbNumericField('user', dtype=Optional[int], is_attribute=False)
uuid: QbStrField('uuid', dtype=Optional[str], is_attribute=False)
with_mpi: QbField('with_mpi', dtype=Optional[bool], is_attribute=True)
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ repository_metadata: QbDictField('repository_metadata', dtype=Optional[Dict[str,
is_attribute=False)
source: QbDictField('source', dtype=Optional[dict], is_attribute=True, is_subscriptable=True)
use_double_quotes: QbField('use_double_quotes', dtype=bool, is_attribute=True)
user: QbNumericField('user', dtype=int, is_attribute=False)
user: QbNumericField('user', dtype=Optional[int], is_attribute=False)
uuid: QbStrField('uuid', dtype=Optional[str], is_attribute=False)
with_mpi: QbField('with_mpi', dtype=Optional[bool], is_attribute=True)
wrap_cmdline_params: QbField('wrap_cmdline_params', dtype=bool, is_attribute=True)
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,6 @@ repository_metadata: QbDictField('repository_metadata', dtype=Optional[Dict[str,
is_attribute=False)
source: QbDictField('source', dtype=Optional[dict], is_attribute=True, is_subscriptable=True)
use_double_quotes: QbField('use_double_quotes', dtype=bool, is_attribute=True)
user: QbNumericField('user', dtype=int, is_attribute=False)
user: QbNumericField('user', dtype=Optional[int], is_attribute=False)
uuid: QbStrField('uuid', dtype=Optional[str], is_attribute=False)
with_mpi: QbField('with_mpi', dtype=Optional[bool], is_attribute=True)
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,6 @@ repository_metadata: QbDictField('repository_metadata', dtype=Optional[Dict[str,
is_attribute=False)
source: QbDictField('source', dtype=Optional[dict], is_attribute=True, is_subscriptable=True)
use_double_quotes: QbField('use_double_quotes', dtype=bool, is_attribute=True)
user: QbNumericField('user', dtype=int, is_attribute=False)
user: QbNumericField('user', dtype=Optional[int], is_attribute=False)
uuid: QbStrField('uuid', dtype=Optional[str], is_attribute=False)
with_mpi: QbField('with_mpi', dtype=Optional[bool], is_attribute=True)
2 changes: 1 addition & 1 deletion tests/orm/test_fields/fields_aiida.data.core.dict.Dict.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,6 @@ repository_content: QbDictField('repository_content', dtype=Optional[dict[str, b
repository_metadata: QbDictField('repository_metadata', dtype=Optional[Dict[str, Any]],
is_attribute=False)
source: QbDictField('source', dtype=Optional[dict], is_attribute=True, is_subscriptable=True)
user: QbNumericField('user', dtype=int, is_attribute=False)
user: QbNumericField('user', dtype=Optional[int], is_attribute=False)
uuid: QbStrField('uuid', dtype=Optional[str], is_attribute=False)
value: QbDictField('value', dtype=Dict[str, Any], is_attribute=False, is_subscriptable=True)
Original file line number Diff line number Diff line change
Expand Up @@ -16,5 +16,5 @@ repository_content: QbDictField('repository_content', dtype=Optional[dict[str, b
repository_metadata: QbDictField('repository_metadata', dtype=Optional[Dict[str, Any]],
is_attribute=False)
source: QbDictField('source', dtype=Optional[dict], is_attribute=True, is_subscriptable=True)
user: QbNumericField('user', dtype=int, is_attribute=False)
user: QbNumericField('user', dtype=Optional[int], is_attribute=False)
uuid: QbStrField('uuid', dtype=Optional[str], is_attribute=False)
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,6 @@ repository_content: QbDictField('repository_content', dtype=Optional[dict[str, b
repository_metadata: QbDictField('repository_metadata', dtype=Optional[Dict[str, Any]],
is_attribute=False)
source: QbDictField('source', dtype=Optional[dict], is_attribute=True, is_subscriptable=True)
user: QbNumericField('user', dtype=int, is_attribute=False)
user: QbNumericField('user', dtype=Optional[int], is_attribute=False)
uuid: QbStrField('uuid', dtype=Optional[str], is_attribute=False)
value: QbField('value', dtype=Any, is_attribute=True)
Original file line number Diff line number Diff line change
Expand Up @@ -15,5 +15,5 @@ repository_content: QbDictField('repository_content', dtype=Optional[dict[str, b
repository_metadata: QbDictField('repository_metadata', dtype=Optional[Dict[str, Any]],
is_attribute=False)
source: QbDictField('source', dtype=Optional[dict], is_attribute=True, is_subscriptable=True)
user: QbNumericField('user', dtype=int, is_attribute=False)
user: QbNumericField('user', dtype=Optional[int], is_attribute=False)
uuid: QbStrField('uuid', dtype=Optional[str], is_attribute=False)
2 changes: 1 addition & 1 deletion tests/orm/test_fields/fields_aiida.data.core.int.Int.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,6 @@ repository_content: QbDictField('repository_content', dtype=Optional[dict[str, b
repository_metadata: QbDictField('repository_metadata', dtype=Optional[Dict[str, Any]],
is_attribute=False)
source: QbDictField('source', dtype=Optional[dict], is_attribute=True, is_subscriptable=True)
user: QbNumericField('user', dtype=int, is_attribute=False)
user: QbNumericField('user', dtype=Optional[int], is_attribute=False)
uuid: QbStrField('uuid', dtype=Optional[str], is_attribute=False)
value: QbField('value', dtype=Any, is_attribute=True)
Original file line number Diff line number Diff line change
Expand Up @@ -16,5 +16,5 @@ repository_content: QbDictField('repository_content', dtype=Optional[dict[str, b
repository_metadata: QbDictField('repository_metadata', dtype=Optional[Dict[str, Any]],
is_attribute=False)
source: QbDictField('source', dtype=Optional[dict], is_attribute=True, is_subscriptable=True)
user: QbNumericField('user', dtype=int, is_attribute=False)
user: QbNumericField('user', dtype=Optional[int], is_attribute=False)
uuid: QbStrField('uuid', dtype=Optional[str], is_attribute=False)
Loading

0 comments on commit aec4a35

Please sign in to comment.