Skip to content

Commit 8f70996

Browse files
committed
Merge remote-tracking branch 'upstream/main' into feat/support-aiida-resource-registry
2 parents 18af087 + c91007e commit 8f70996

13 files changed

Lines changed: 321 additions & 141 deletions

File tree

.github/workflows/nightly.yml

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,10 @@ jobs:
114114
matrix:
115115
# Currently supported RMQ versions per:
116116
# https://www.rabbitmq.com/docs/which-erlang#compatibility-matrix
117-
rabbitmq-version: ['3.11', '3.12', '3.13', '4.0']
117+
# Version 3.10 is currently used by AiiDAlab.
118+
# Version 4.3 broke aiida-core, so the latest supported is 4.2:
119+
# https://github.com/aiidateam/aiida-core/issues/7375
120+
rabbitmq-version: ['3.10', '4.2']
118121

119122
services:
120123
rabbitmq:

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -245,7 +245,7 @@ notebook = [
245245
# https://github.com/python/typeshed?tab=readme-ov-file#package-versioning-for-third-party-stubs
246246
pre-commit = [
247247
'aiida-core[tests]',
248-
'mypy~=1.19.0',
248+
'mypy~=2.1.0',
249249
'packaging~=23.0',
250250
'pre-commit~=3.5',
251251
'sqlalchemy[mypy]~=2.0',

src/aiida/orm/nodes/data/array/trajectory.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -830,7 +830,7 @@ def collapse_into_unit_cell(point, cell):
830830
xmin, ymin, zmin = _x.min(), _y.min(), _z.min()
831831
xmax, ymax, zmax = _x.max(), _y.max(), _z.max()
832832

833-
_xi, _yi, _zi = np.mgrid[xmin:xmax:60j, ymin:ymax:30j, zmin:zmax:30j] # type: ignore[misc]
833+
_xi, _yi, _zi = np.mgrid[xmin:xmax:60j, ymin:ymax:30j, zmin:zmax:30j]
834834
coords = np.vstack([item.ravel() for item in [_xi, _yi, _zi]])
835835
density = kde(coords).reshape(_xi.shape)
836836

src/aiida/orm/nodes/data/data.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -354,3 +354,13 @@ def _get_converters(self):
354354
valid_format_names = [i[len(exporter_prefix) :] for i in method_names if i.startswith(exporter_prefix)]
355355
valid_formats = {k: getattr(self, exporter_prefix + k) for k in valid_format_names}
356356
return valid_formats
357+
358+
@classmethod
359+
def _get_patched_node_type_field(cls):
360+
node_type_field = super()._get_patched_node_type_field()
361+
if cls.__name__ == 'Data':
362+
# `Data` is not to be used directly! It is only ever used when a subclass
363+
# from an uninstalled plugin regresses to `Data`, in which case, the node
364+
# type should not be validated against a `Literal`, only as a `str`.
365+
return (str, node_type_field[1])
366+
return node_type_field

src/aiida/orm/nodes/node.py

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1074,6 +1074,12 @@ def _patch_attributes_model(cls):
10741074
cls.AttributesModel = AttributesModel # type: ignore[misc]
10751075
cls.AttributesModel.model_rebuild(force=True)
10761076

1077+
@classmethod
1078+
def _get_patched_node_type_field(cls):
1079+
"""Return a copy of the `node_type` field cast as the literal type for this class."""
1080+
node_type_field = deepcopy(cls.BaseNodeModel.model_fields['node_type'])
1081+
return (Literal[cls.class_node_type], node_type_field)
1082+
10771083
@classmethod
10781084
def _patch_read_model(cls):
10791085
"""Patch `ReadModel` by wiring the subclass-specific `attributes` model.
@@ -1107,9 +1113,8 @@ def _patch_read_model(cls):
11071113
}
11081114

11091115
attributes_field = deepcopy(cls.ReadModel.model_fields['attributes'])
1110-
node_type_field = deepcopy(cls.BaseNodeModel.model_fields['node_type'])
1111-
model_fields['node_type'] = (Literal[cls.class_node_type], node_type_field)
11121116
model_fields['attributes'] = (cls.AttributesModel, attributes_field)
1117+
model_fields['node_type'] = cls._get_patched_node_type_field()
11131118

11141119
ReadModel = cast( # noqa: N806
11151120
type[Node.ReadModel],
@@ -1130,23 +1135,28 @@ def _patch_constructor_model(cls):
11301135
"""Patch `ConstructorModel` by synthesizing it from `BaseNodeModel` and `ConstructorArgsModel`."""
11311136
if not cls.supports_constructor_model:
11321137
return
1133-
node_type_field = deepcopy(cls.BaseNodeModel.model_fields['node_type'])
1138+
11341139
args_field = OrmMetadataField(
11351140
description='The constructor arguments.',
11361141
write_only=True,
11371142
)
1143+
model_fields: dict[str, Any] = {
1144+
'args': (cls.ConstructorArgsModel, args_field),
1145+
'node_type': cls._get_patched_node_type_field(),
1146+
}
1147+
11381148
ConstructorModel = cast( # noqa: N806
11391149
type[Node.BaseNodeModel],
11401150
pdt.create_model(
11411151
'ConstructorModel',
11421152
__base__=cls.BaseNodeModel,
11431153
__module__=cls.__module__,
1144-
node_type=(Literal[cls.class_node_type], node_type_field),
1145-
args=(cls.ConstructorArgsModel, args_field),
1154+
**model_fields,
11461155
),
11471156
)
11481157
ConstructorModel.__qualname__ = f'{cls.__name__}.ConstructorModel'
11491158
ConstructorModel.model_rebuild(force=True)
1159+
11501160
cls._ConstructorModel = ConstructorModel
11511161

11521162
@classmethod

src/aiida/orm/utils/links.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -176,10 +176,10 @@ def validate_link(
176176

177177
type_source, type_target, outdegree, indegree = link_mapping[link_type]
178178

179-
if not isinstance(source, type_source) or not isinstance(target, type_target):
179+
if not isinstance(source, type_source) or not isinstance(target, type_target): # type: ignore[unreachable]
180180
raise ValueError(f'cannot add a {link_type} link from {type(source)} to {type(target)}')
181181

182-
if outdegree == 'unique_triple' or indegree == 'unique_triple':
182+
if outdegree == 'unique_triple' or indegree == 'unique_triple': # type: ignore[unreachable]
183183
# For a `unique_triple` degree we just have to check if an identical triple already exist, either in the cache
184184
# or stored, in which case, the new proposed link is a duplicate and thus illegal
185185
duplicate_link_triple = link_triple_exists(source, target, link_type, link_label, backend)

src/aiida/orm/utils/node.py

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ def load_node_class(type_string):
2828
:param type_string: the `type` string of the node
2929
:return: a sub class of `Node`
3030
"""
31-
from aiida.orm import Data, Node
31+
from aiida.orm import Data, Node, ProcessNode
3232
from aiida.plugins.entry_point import load_entry_point
3333

3434
if type_string == '':
@@ -47,17 +47,20 @@ def load_node_class(type_string):
4747
if base_path.startswith('node.'):
4848
base_path = base_path.removeprefix('node.')
4949

50-
# Data nodes are the only ones with sub classes that are still external, so if the plugin is not available
51-
# we fall back on the base node type
50+
# If the Data plugin is not available we fall back on the base Data class
5251
if base_path.startswith('data.'):
5352
entry_point_name = base_path.removeprefix('data.')
5453
try:
5554
return load_entry_point('aiida.data', entry_point_name)
5655
except exceptions.MissingEntryPointError:
5756
return Data
5857

58+
# If the Process plugin is not available we fall back on the base ProcessNode class
5959
if base_path.startswith('process'):
60-
return load_entry_point('aiida.node', base_path)
60+
try:
61+
return load_entry_point('aiida.node', base_path)
62+
except exceptions.MissingEntryPointError:
63+
return ProcessNode
6164

6265
# At this point we really have an anomalous type string. At some point, storing nodes with unresolvable type strings
6366
# was allowed, for example by creating a sub class in a shell and then storing an instance. Attempting to load the

src/aiida/orm/utils/remote.py

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515

1616
from aiida import orm
1717
from aiida.cmdline.utils import echo
18+
from aiida.common.exceptions import NotExistent
1819
from aiida.orm.nodes.data.remote.base import RemoteData
1920

2021
if t.TYPE_CHECKING:
@@ -52,7 +53,7 @@ def clean_mapping_remote_paths(path_mapping, silent=False):
5253
:param path_mapping: a dictionary where the keys are the computer UUIDs and the values are lists of remote folders
5354
It's designed to accept the output of `get_calcjob_remote_paths`
5455
:param transport: the transport to use to clean the remote folders
55-
:param silent: if True, the `echo` output will be suppressed
56+
:param silent: if True, the success message output will be suppressed
5657
"""
5758

5859
user = orm.User.collection.get_default()
@@ -63,7 +64,16 @@ def clean_mapping_remote_paths(path_mapping, silent=False):
6364
for computer_uuid, paths in path_mapping.items():
6465
counter = 0
6566
computer = orm.load_computer(uuid=computer_uuid)
66-
transport = orm.AuthInfo.collection.get(dbcomputer_id=computer.pk, aiidauser_id=user.pk).get_transport()
67+
try:
68+
authinfo = orm.AuthInfo.collection.get(dbcomputer_id=computer.pk, aiidauser_id=user.pk)
69+
except NotExistent:
70+
echo.echo_warning(
71+
f'Skipping {len(paths)} remote folders on `{computer.label}`: '
72+
f'computer is not configured for user `{user.email}`'
73+
)
74+
continue
75+
76+
transport = authinfo.get_transport()
6777

6878
with transport:
6979
for remote_folder in paths:

src/aiida/tools/archive/create.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -239,7 +239,7 @@ def querybuilder():
239239
elif isinstance(entry, orm.Computer):
240240
starting_uuids[EntityTypes.COMPUTER].add(entry.uuid)
241241
entity_ids[EntityTypes.COMPUTER].add(entry.pk)
242-
elif isinstance(entry, orm.User):
242+
elif isinstance(entry, orm.User): # type: ignore[unreachable]
243243
starting_uuids[EntityTypes.USER].add(entry.email)
244244
entity_ids[EntityTypes.USER].add(entry.pk)
245245
else:

src/aiida/tools/graph/age_entities.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -200,7 +200,7 @@ def _check_self_and_other(self, other: Self) -> None:
200200
if self._identifier_type != other.identifier_type:
201201
raise TypeError('The two instances do not have the same identifier type!')
202202

203-
def _check_input_for_set(self, input_for_set: _NodeOrGroupCls | int) -> Any:
203+
def _check_input_for_set(self, input_for_set: orm.Node | orm.Group | int) -> Any:
204204
if isinstance(input_for_set, self._aiida_cls):
205205
return getattr(input_for_set, self._identifier)
206206

0 commit comments

Comments
 (0)