Skip to content

Commit

Permalink
🐛 FIX: Node comments API (#4760)
Browse files Browse the repository at this point in the history
  • Loading branch information
chrisjsewell authored Feb 17, 2021
1 parent 8dfe6e7 commit d63c9c1
Show file tree
Hide file tree
Showing 2 changed files with 55 additions and 9 deletions.
17 changes: 9 additions & 8 deletions aiida/orm/nodes/node.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
import importlib
import warnings
import traceback
from typing import List, Optional

from aiida.common import exceptions
from aiida.common.escaping import sql_string_match
Expand Down Expand Up @@ -671,7 +672,7 @@ def delete_object(self, path=None, force=False, key=None):

self._repository.delete_object(path, force)

def add_comment(self, content, user=None):
def add_comment(self, content: str, user: Optional[User] = None) -> Comment:
"""Add a new comment.
:param content: string with comment
Expand All @@ -681,40 +682,40 @@ def add_comment(self, content, user=None):
user = user or User.objects.get_default()
return Comment(node=self, user=user, content=content).store()

def get_comment(self, identifier):
def get_comment(self, identifier: int) -> Comment:
"""Return a comment corresponding to the given identifier.
:param identifier: the comment pk
:raise aiida.common.NotExistent: if the comment with the given id does not exist
:raise aiida.common.MultipleObjectsError: if the id cannot be uniquely resolved to a comment
:return: the comment
"""
return Comment.objects.get(dbnode_id=self.pk, pk=identifier)
return Comment.objects.get(dbnode_id=self.pk, id=identifier)

def get_comments(self):
def get_comments(self) -> List[Comment]:
"""Return a sorted list of comments for this node.
:return: the list of comments, sorted by pk
"""
return Comment.objects.find(filters={'dbnode_id': self.pk}, order_by=[{'id': 'asc'}])

def update_comment(self, identifier, content):
def update_comment(self, identifier: int, content: str) -> None:
"""Update the content of an existing comment.
:param identifier: the comment pk
:param content: the new comment content
:raise aiida.common.NotExistent: if the comment with the given id does not exist
:raise aiida.common.MultipleObjectsError: if the id cannot be uniquely resolved to a comment
"""
comment = Comment.objects.get(dbnode_id=self.pk, pk=identifier)
comment = Comment.objects.get(dbnode_id=self.pk, id=identifier)
comment.set_content(content)

def remove_comment(self, identifier):
def remove_comment(self, identifier: int) -> None: # pylint: disable=no-self-use
"""Delete an existing comment.
:param identifier: the comment pk
"""
Comment.objects.delete(dbnode_id=self.pk, comment=identifier)
Comment.objects.delete(identifier)

def add_incoming(self, source, link_type, link_label):
"""Add a link of the given type from a given node to ourself.
Expand Down
47 changes: 46 additions & 1 deletion tests/orm/node/test_node.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
# For further information on the license, see the LICENSE.txt file #
# For further information please visit http://www.aiida.net #
###########################################################################
# pylint: disable=too-many-public-methods
# pylint: disable=too-many-public-methods,no-self-use
"""Tests for the Node ORM class."""
import io
import os
Expand Down Expand Up @@ -824,6 +824,51 @@ def test_delete_collection_outgoing_link(self):
Node.objects.delete(calculation.pk)


@pytest.mark.usefixtures('clear_database_before_test')
class TestNodeComments:
"""Tests for creating comments on nodes."""

def test_add_comment(self):
"""Test comment addition."""
data = Data().store()
content = 'whatever Trevor'
comment = data.add_comment(content)
assert comment.content == content
assert comment.node.pk == data.pk

def test_get_comment(self):
"""Test retrieve single comment."""
data = Data().store()
content = 'something something dark side'
add_comment = data.add_comment(content)
get_comment = data.get_comment(add_comment.pk)
assert get_comment.content == content
assert get_comment.pk == add_comment.pk

def test_get_comments(self):
"""Test retrieve multiple comments."""
data = Data().store()
data.add_comment('one')
data.add_comment('two')
comments = data.get_comments()
assert {c.content for c in comments} == {'one', 'two'}

def test_update_comment(self):
"""Test update a comment."""
data = Data().store()
comment = data.add_comment('original')
data.update_comment(comment.pk, 'new')
assert comment.content == 'new'

def test_remove_comment(self):
"""Test remove a comment."""
data = Data().store()
comment = data.add_comment('original')
assert len(data.get_comments()) == 1
data.remove_comment(comment.pk)
assert len(data.get_comments()) == 0


@pytest.mark.usefixtures('clear_database_before_test')
def test_store_from_cache():
"""Regression test for storing a Node with (nested) repository content with caching."""
Expand Down

0 comments on commit d63c9c1

Please sign in to comment.