Skip to content

Commit 2be5681

Browse files
Switch from pk to uuid for entity identifier (except users)
1 parent 3bcf4f0 commit 2be5681

File tree

11 files changed

+240
-192
lines changed

11 files changed

+240
-192
lines changed

aiida_restapi/repository/entity.py

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,9 @@ class EntityRepository(t.Generic[EntityType, EntityModelType]):
1717
:ivar entity_cls: The AiiDA ORM entity class associated with this utility, e.g. `orm.User`, `orm.Node`, etc.
1818
"""
1919

20-
def __init__(self, entity_class: type[EntityType]) -> None:
21-
self.entity_class: type[EntityType] = entity_class
20+
def __init__(self, entity_class: type[EntityType], identifier: t.Literal['pk', 'uuid']) -> None:
21+
self.entity_class = entity_class
22+
self.identifier = identifier
2223

2324
def get_entity_schema(self, which: t.Literal['get', 'post'] | None = None) -> dict:
2425
"""Get JSON schema for the AiiDA entity.
@@ -65,25 +66,25 @@ def get_entities(self, queries: QueryParams) -> PaginatedResults:
6566
results=[self.to_model(result) for result in results],
6667
)
6768

68-
def get_entity_by_id(self, entity_id: int) -> EntityModelType:
69+
def get_entity_by_id(self, identifier: str | int) -> EntityModelType:
6970
"""Get an AiiDA entity by id.
7071
71-
:param entity_id: The id of the entity to retrieve.
72+
:param identifier: The id of the entity to retrieve.
7273
:return: The AiiDA entity model, e.g. `orm.User.Model`, `orm.Node.Model`, etc.
7374
"""
74-
entity = self.entity_class.collection.get(pk=entity_id)
75+
entity = self.entity_class.collection.get(**{self.identifier: identifier})
7576
return self.to_model(entity)
7677

77-
def get_entity_extras(self, entity_id: int) -> dict[str, t.Any]:
78+
def get_entity_extras(self, identifier: str | int) -> dict[str, t.Any]:
7879
"""Get the extras of an entity.
7980
80-
:param entity_id: The id of the entity to retrieve the extras for.
81+
:param identifier: The id of the entity to retrieve the extras for.
8182
:return: A dictionary with the entity extras.
8283
"""
8384
return t.cast(
8485
dict,
8586
self.entity_class.collection.query(
86-
filters={'pk': entity_id},
87+
filters={self.identifier: identifier},
8788
project=['extras'],
8889
).first()[0],
8990
)

aiida_restapi/repository/node.py

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -74,13 +74,13 @@ def get_all_download_formats(self, full_type: str | None = None) -> dict:
7474

7575
return all_formats
7676

77-
def get_node_repository_metadata(self, node_id: int) -> dict[str, dict]:
77+
def get_node_repository_metadata(self, uuid: str) -> dict[str, dict]:
7878
"""Get the repository metadata of a node.
7979
80-
:param node_id: The id of the node to retrieve the repository metadata for.
80+
:param uuid: The uuid of the node to retrieve the repository metadata for.
8181
:return: A dictionary with the repository file metadata.
8282
"""
83-
node = self.entity_class.collection.get(pk=node_id)
83+
node = self.entity_class.collection.get(uuid=uuid)
8484
total_size = 0
8585

8686
def get_metadata(objects: list[File], path: str | None = None) -> dict[str, dict]:
@@ -113,7 +113,7 @@ def get_metadata(objects: list[File], path: str | None = None) -> dict[str, dict
113113
'type': 'FILE',
114114
'binary': binary,
115115
'size': size,
116-
'download': f'/nodes/{node_id}/repo/contents?filename={obj_name}',
116+
'download': f'/nodes/{uuid}/repo/contents?filename={obj_name}',
117117
}
118118
total_size += size
119119

@@ -126,39 +126,39 @@ def get_metadata(objects: list[File], path: str | None = None) -> dict[str, dict
126126
'type': 'FILE',
127127
'binary': True,
128128
'size': total_size,
129-
'download': f'/nodes/{node_id}/repo/contents',
129+
'download': f'/nodes/{uuid}/repo/contents',
130130
}
131131

132132
return metadata
133133

134-
def get_node_attributes(self, node_id: int) -> dict[str, t.Any]:
134+
def get_node_attributes(self, uuid: str) -> dict[str, t.Any]:
135135
"""Get the attributes of a node.
136136
137-
:param node_id: The id of the node to retrieve the attributes for.
137+
:param uuid: The uuid of the node to retrieve the attributes for.
138138
:return: A dictionary with the node attributes.
139139
"""
140140
return t.cast(
141141
dict,
142142
self.entity_class.collection.query(
143-
filters={'pk': node_id},
143+
filters={'uuid': uuid},
144144
project=['attributes'],
145145
).first()[0],
146146
)
147147

148148
def get_node_links(
149149
self,
150-
node_id: int,
150+
uuid: str,
151151
queries: QueryParams,
152152
direction: t.Literal['incoming', 'outgoing'],
153153
) -> PaginatedResults[NodeLinks]:
154154
"""Get the incoming links of a node.
155155
156-
:param node_id: The id of the node to retrieve the incoming links for.
156+
:param uuid: The uuid of the node to retrieve the incoming links for.
157157
:param queries: The query parameters, including filters, order_by, page_size, and page.
158158
:param direction: Specify whether to retrieve incoming or outgoing links.
159159
:return: The paginated requested linked nodes.
160160
"""
161-
node = self.entity_class.collection.get(pk=node_id)
161+
node = self.entity_class.collection.get(uuid=uuid)
162162

163163
start, end = (
164164
queries.page_size * (queries.page - 1),

aiida_restapi/routers/computers.py

Lines changed: 34 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,10 @@
1818
read_router = APIRouter()
1919
write_router = APIRouter()
2020

21-
repository = EntityRepository[orm.Computer, orm.Computer.Model](orm.Computer)
21+
repository = EntityRepository[orm.Computer, orm.Computer.Model](
22+
entity_class=orm.Computer,
23+
identifier='pk',
24+
)
2225

2326

2427
@read_router.get('/computers/schema')
@@ -32,12 +35,15 @@ async def get_computers_schema(
3235
3336
:param which: The type of schema to retrieve: 'get' or 'post'.
3437
:return: A dictionary with 'get' and 'post' keys containing the respective JSON schemas.
35-
:raises HTTPException: 422 if the 'which' parameter is not 'get' or 'post'.
38+
:raises HTTPException: 422 if the 'which' parameter is not 'get' or 'post',
39+
500 for any other failures.
3640
"""
3741
try:
3842
return repository.get_entity_schema(which=which)
39-
except ValueError as err:
40-
raise HTTPException(status_code=422, detail=str(err)) from err
43+
except ValueError as exception:
44+
raise HTTPException(status_code=422, detail=str(exception)) from exception
45+
except Exception as exception:
46+
raise HTTPException(status_code=500, detail=str(exception)) from exception
4147

4248

4349
@read_router.get('/computers/projectable_properties', response_model=list[str])
@@ -68,39 +74,45 @@ async def get_computers(
6874

6975

7076
@read_router.get(
71-
'/computers/{computer_id}',
77+
'/computers/{pk}',
7278
response_model=orm.Computer.Model,
7379
response_model_exclude_none=True,
7480
response_model_exclude_unset=True,
7581
)
7682
@with_dbenv()
77-
async def get_computer(computer_id: int) -> orm.Computer.Model:
78-
"""Get AiiDA computer by id.
83+
async def get_computer(pk: str) -> orm.Computer.Model:
84+
"""Get AiiDA computer by pk.
7985
80-
:param computer_id: The id of the AiiDA computer.
86+
:param pk: The pk of the AiiDA computer.
8187
:return: The computer model.
82-
:raises HTTPException: 404 if the computer with the given id does not exist.
88+
:raises HTTPException: 404 if the computer with the given pk does not exist,
89+
500 for any other failures.
8390
"""
8491
try:
85-
return repository.get_entity_by_id(computer_id)
86-
except NotExistent:
87-
raise HTTPException(status_code=404, detail=f'Could not find a Computer with id {computer_id}')
92+
return repository.get_entity_by_id(pk)
93+
except NotExistent as exception:
94+
raise HTTPException(status_code=404, detail=str(exception)) from exception
95+
except Exception as exception:
96+
raise HTTPException(status_code=500, detail=str(exception)) from exception
8897

8998

90-
@read_router.get('/computers/{computer_id}/metadata', response_model=dict[str, t.Any])
99+
@read_router.get('/computers/{pk}/metadata', response_model=dict[str, t.Any])
91100
@with_dbenv()
92-
async def get_computer_metadata(computer_id: int) -> dict[str, t.Any]:
93-
"""Get metadata of an AiiDA computer by id.
101+
async def get_computer_metadata(pk: str) -> dict[str, t.Any]:
102+
"""Get metadata of an AiiDA computer by pk.
94103
95-
:param computer_id: The id of the AiiDA computer.
104+
:param pk: The pk of the AiiDA computer.
96105
:return: The metadata dictionary of the computer.
97-
:raises HTTPException: 404 if the computer with the given id does not exist.
106+
:raises HTTPException: 404 if the computer with the given pk does not exist,
107+
500 for any other failures.
98108
"""
99109
try:
100-
computer = repository.get_entity_by_id(computer_id)
110+
computer = repository.get_entity_by_id(pk)
101111
return computer.metadata
102-
except NotExistent:
103-
raise HTTPException(status_code=404, detail=f'Could not find a Computer with id {computer_id}')
112+
except NotExistent as exception:
113+
raise HTTPException(status_code=404, detail=str(exception)) from exception
114+
except Exception as exception:
115+
raise HTTPException(status_code=500, detail=str(exception)) from exception
104116

105117

106118
@write_router.post(
@@ -123,5 +135,5 @@ async def create_computer(
123135
"""
124136
try:
125137
return repository.create_entity(computer_model)
126-
except Exception as err:
127-
raise HTTPException(status_code=500, detail=str(err))
138+
except Exception as exception:
139+
raise HTTPException(status_code=500, detail=str(exception))

aiida_restapi/routers/groups.py

Lines changed: 31 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,10 @@
1818
read_router = APIRouter()
1919
write_router = APIRouter()
2020

21-
repository = EntityRepository[orm.Group, orm.Group.Model](orm.Group)
21+
repository = EntityRepository[orm.Group, orm.Group.Model](
22+
entity_class=orm.Group,
23+
identifier='uuid',
24+
)
2225

2326

2427
@read_router.get('/groups/schema')
@@ -32,12 +35,15 @@ async def get_groups_schema(
3235
3336
:param which: The type of schema to retrieve: 'get' or 'post'.
3437
:return: A dictionary with 'get' and 'post' keys containing the respective JSON schemas.
35-
:raises HTTPException: 422 if the 'which' parameter is not 'get' or 'post'.
38+
:raises HTTPException: 422 if the 'which' parameter is not 'get' or 'post',
39+
500 for any other failures.
3640
"""
3741
try:
3842
return repository.get_entity_schema(which=which)
39-
except ValueError as err:
40-
raise HTTPException(status_code=422, detail=str(err)) from err
43+
except ValueError as exception:
44+
raise HTTPException(status_code=422, detail=str(exception)) from exception
45+
except Exception as exception:
46+
raise HTTPException(status_code=500, detail=str(exception)) from exception
4147

4248

4349
@read_router.get('/groups/projectable_properties', response_model=list[str])
@@ -68,47 +74,47 @@ async def get_groups(
6874

6975

7076
@read_router.get(
71-
'/groups/{group_id}',
77+
'/groups/{uuid}',
7278
response_model=orm.Group.Model,
7379
response_model_exclude_none=True,
7480
response_model_exclude_unset=True,
7581
)
7682
@with_dbenv()
77-
async def get_group(group_id: int) -> orm.Group.Model:
78-
"""Get AiiDA group by id.
83+
async def get_group(uuid: str) -> orm.Group.Model:
84+
"""Get AiiDA group by uuid.
7985
80-
:param group_id: The id of the group to retrieve.
86+
:param uuid: The uuid of the group to retrieve.
8187
:return: The AiiDA group model.
82-
:raises HTTPException: 404 if a group with the given id does not exist,
88+
:raises HTTPException: 404 if a group with the given uuid does not exist,
8389
500 for any other server error.
8490
"""
8591
try:
86-
return repository.get_entity_by_id(group_id)
87-
except NotExistent:
88-
raise HTTPException(status_code=404, detail=f'Could not find a Group with id {group_id}')
89-
except Exception as err:
90-
raise HTTPException(status_code=500, detail=str(err))
92+
return repository.get_entity_by_id(uuid)
93+
except NotExistent as exception:
94+
raise HTTPException(status_code=404, detail=str(exception)) from exception
95+
except Exception as exception:
96+
raise HTTPException(status_code=500, detail=str(exception)) from exception
9197

9298

9399
@read_router.get(
94-
'/groups/{group_id}/extras',
100+
'/groups/{uuid}/extras',
95101
response_model=dict[str, t.Any],
96102
)
97103
@with_dbenv()
98-
async def get_group_extras(group_id: int) -> dict[str, t.Any]:
104+
async def get_group_extras(uuid: str) -> dict[str, t.Any]:
99105
"""Get the extras of a group.
100106
101-
:param group_id: The id of the group to retrieve the extras for.
107+
:param uuid: The uuid of the group to retrieve the extras for.
102108
:return: A dictionary with the group extras.
103-
:raises HTTPException: 404 if the group with the given id does not exist,
109+
:raises HTTPException: 404 if the group with the given uuid does not exist,
104110
500 for other failures during retrieval.
105111
"""
106112
try:
107-
return repository.get_entity_extras(group_id)
108-
except NotExistent:
109-
raise HTTPException(status_code=404, detail=f'Could not find any group with id {group_id}')
110-
except Exception as err:
111-
raise HTTPException(status_code=500, detail=str(err)) from err
113+
return repository.get_entity_extras(uuid)
114+
except NotExistent as exception:
115+
raise HTTPException(status_code=404, detail=str(exception)) from exception
116+
except Exception as exception:
117+
raise HTTPException(status_code=500, detail=str(exception)) from exception
112118

113119

114120
@write_router.post(
@@ -131,5 +137,5 @@ async def create_group(
131137
"""
132138
try:
133139
return repository.create_entity(group_model)
134-
except Exception as err:
135-
raise HTTPException(status_code=500, detail=str(err))
140+
except Exception as exception:
141+
raise HTTPException(status_code=500, detail=str(exception)) from exception

0 commit comments

Comments
 (0)