Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Move the Comment class to the new backend interface #2225

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 0 additions & 3 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -234,15 +234,13 @@
aiida/orm/implementation/django/authinfo.py|
aiida/orm/implementation/django/backend.py|
aiida/orm/implementation/django/code.py|
aiida/orm/implementation/django/comment.py|
aiida/orm/implementation/django/computer.py|
aiida/orm/implementation/django/group.py|
aiida/orm/implementation/django/__init__.py|
aiida/orm/implementation/django/node.py|
aiida/orm/implementation/django/user.py|
aiida/orm/implementation/django/utils.py|
aiida/orm/implementation/django/workflow.py|
aiida/orm/implementation/general/comment.py|
aiida/orm/implementation/general/group.py|
aiida/orm/implementation/general/__init__.py|
aiida/orm/implementation/general/node.py|
Expand All @@ -251,7 +249,6 @@
aiida/orm/implementation/sqlalchemy/authinfo.py|
aiida/orm/implementation/sqlalchemy/backend.py|
aiida/orm/implementation/sqlalchemy/code.py|
aiida/orm/implementation/sqlalchemy/comment.py|
aiida/orm/implementation/sqlalchemy/computer.py|
aiida/orm/implementation/sqlalchemy/group.py|
aiida/orm/implementation/sqlalchemy/__init__.py|
Expand Down
1 change: 0 additions & 1 deletion aiida/backends/djsite/db/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -1456,7 +1456,6 @@ def get_aiida_class(self):
return DjangoAuthInfo.from_dbmodel(self, construct_backend())



@python_2_unicode_compatible
class DbComment(m.Model):
uuid = m.UUIDField(default=get_new_uuid, unique=True)
Expand Down
2 changes: 1 addition & 1 deletion aiida/backends/sqlalchemy/models/comment.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ class DbComment(Base):
)

ctime = Column(DateTime(timezone=True), default=timezone.now)
mtime = Column(DateTime(timezone=True), default=timezone.now)
mtime = Column(DateTime(timezone=True), default=timezone.now, onupdate=timezone.now)

user_id = Column(
Integer,
Expand Down
2 changes: 1 addition & 1 deletion aiida/backends/sqlalchemy/models/node.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ class DbNode(Base):
default="") # Does it make sense to be nullable and have a default?
description = Column(Text(), nullable=True, default="")
ctime = Column(DateTime(timezone=True), default=timezone.now)
mtime = Column(DateTime(timezone=True), default=timezone.now)
mtime = Column(DateTime(timezone=True), default=timezone.now, onupdate=timezone.now)
nodeversion = Column(Integer, default=1)
public = Column(Boolean, default=False)
attributes = Column(JSONB)
Expand Down
2 changes: 1 addition & 1 deletion aiida/backends/sqlalchemy/models/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ class DbSetting(Base):

# I also add a description field for the variables
description = Column(String(255), default='', nullable=False)
time = Column(DateTime(timezone=True), default=timezone.utc)
time = Column(DateTime(timezone=True), default=timezone.utc, onupdate=timezone.now)

def __str__(self):
return "'{}'={}".format(self.key, self.getvalue())
Expand Down
2 changes: 1 addition & 1 deletion aiida/backends/sqlalchemy/models/workflow.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ class DbWorkflow(Base):
uuid = Column(UUID(as_uuid=True), default=uuid_func)

ctime = Column(DateTime(timezone=True), default=timezone.now)
mtime = Column(DateTime(timezone=True), default=timezone.now)
mtime = Column(DateTime(timezone=True), default=timezone.now, onupdate=timezone.now)

user_id = Column(Integer, ForeignKey('db_dbuser.id'))
user = relationship('DbUser')
Expand Down
3 changes: 2 additions & 1 deletion aiida/backends/tests/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -86,8 +86,9 @@
'common.archive': ['aiida.backends.tests.common.test_archive'],
'common.datastructures': ['aiida.backends.tests.common.test_datastructures'],
'daemon.client': ['aiida.backends.tests.daemon.test_client'],
'orm.computer': ['aiida.backends.tests.computer'],
'orm.authinfo': ['aiida.backends.tests.orm.authinfo'],
'orm.comment': ['aiida.backends.tests.orm.comment'],
'orm.computer': ['aiida.backends.tests.computer'],
'orm.data.frozendict': ['aiida.backends.tests.orm.data.frozendict'],
'orm.data.remote': ['aiida.backends.tests.orm.data.remote'],
'orm.log': ['aiida.backends.tests.orm.log'],
Expand Down
70 changes: 21 additions & 49 deletions aiida/backends/tests/cmdline/commands/test_comment.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,10 @@
from __future__ import print_function
from __future__ import absolute_import

from six.moves import range
from click.testing import CliRunner

from aiida.backends.testbase import AiidaTestCase
from aiida.cmdline.commands import cmd_comment
from aiida import orm

COMMENT = u'Well I never...'
Expand All @@ -24,68 +24,40 @@ class TestVerdiUserCommand(AiidaTestCase):

def setUp(self):
self.cli_runner = CliRunner()
self.node = orm.Node().store()

def test_comment_show_simple(self):
""" test simply calling the show command (without data to show) """
from aiida.cmdline.commands.cmd_comment import show

result = CliRunner().invoke(show, [], catch_exceptions=False)
self.assertEqual(result.output, "")
"""Test simply calling the show command (without data to show)."""
result = self.cli_runner.invoke(cmd_comment.show, [], catch_exceptions=False)
self.assertEqual(result.output, '')
self.assertEqual(result.exit_code, 0)

def test_comment_show(self):
""" Test showing an existing comment """
from aiida.cmdline.commands.cmd_comment import show

node = orm.Node()
node.store()
node.add_comment(COMMENT)
"""Test showing an existing comment."""
self.node.add_comment(COMMENT)

result = CliRunner().invoke(show, [str(node.pk)], catch_exceptions=False)
options = [str(self.node.pk)]
result = self.cli_runner.invoke(cmd_comment.show, options, catch_exceptions=False)
self.assertNotEqual(result.output.find(COMMENT), -1)
self.assertEqual(result.exit_code, 0)

def test_comment_add(self):
""" Test adding a comment """
from aiida.cmdline.commands.cmd_comment import add

node = orm.Node()
node.store()

result = CliRunner().invoke(add, ['-c{}'.format(COMMENT), str(node.pk)], catch_exceptions=False)
"""Test adding a comment."""
options = ['-N', str(self.node.pk), '--', '{}'.format(COMMENT)]
result = self.cli_runner.invoke(cmd_comment.add, options, catch_exceptions=False)
self.assertEqual(result.exit_code, 0)

comment = node.get_comments()
comment = self.node.get_comments()
self.assertEquals(len(comment), 1)
self.assertEqual(comment[0]['content'], COMMENT)
self.assertEqual(comment[0].content, COMMENT)

def test_comment_remove(self):
""" Test removing a comment """
from aiida.cmdline.commands.cmd_comment import remove
"""Test removing a comment."""
comment = self.node.add_comment(COMMENT)

node = orm.Node()
node.store()
comment_id = node.add_comment(COMMENT)

self.assertEquals(len(node.get_comments()), 1)

result = CliRunner().invoke(remove, [str(node.pk), str(comment_id), '--force'], catch_exceptions=False)
self.assertEqual(result.exit_code, 0)

self.assertEquals(len(node.get_comments()), 0)

def test_comment_remove_all(self):
""" Test removing all comments from a node """
from aiida.cmdline.commands.cmd_comment import remove

node = orm.Node()
node.store()
for _ in range(10):
node.add_comment(COMMENT)

self.assertEqual(len(node.get_comments()), 10)

result = CliRunner().invoke(remove, [str(node.pk), '--all', '--force'], catch_exceptions=False)
self.assertEqual(result.exit_code, 0)
self.assertEquals(len(self.node.get_comments()), 1)

self.assertEqual(len(node.get_comments()), 0)
options = [str(comment.pk), '--force']
result = self.cli_runner.invoke(cmd_comment.remove, options, catch_exceptions=False)
self.assertEqual(result.exit_code, 0, result.output)
self.assertEquals(len(self.node.get_comments()), 0)
14 changes: 8 additions & 6 deletions aiida/backends/tests/nodes.py
Original file line number Diff line number Diff line change
Expand Up @@ -1207,31 +1207,33 @@ def test_comments(self):
# of directly loading datetime.datetime.now(), or you can get a
# "can't compare offset-naive and offset-aware datetimes" error
from aiida.utils import timezone
from aiida.orm.backends import construct_backend
import time
from time import sleep

user = User.objects(self.backend).get_default()

a = Node()
with self.assertRaises(ModificationNotAllowed):
a.add_comment('text', user=user)

a.store()
self.assertEquals(a.get_comments(), [])

before = timezone.now()
time.sleep(1) # I wait 1 second because MySql time precision is 1 sec
sleep(1) # I wait 1 second because MySql time precision is 1 sec
a.add_comment('text', user=user)
a.add_comment('text2', user=user)
time.sleep(1)
sleep(1)
after = timezone.now()

comments = a.get_comments()

times = [i['mtime'] for i in comments]
times = [i.ctime for i in comments]

for time in times:
self.assertTrue(time > before)
self.assertTrue(time < after)

self.assertEquals([(i['user__email'], i['content']) for i in comments], [
self.assertEquals([(i.user.email, i.content) for i in comments], [
(self.user_email, 'text'),
(self.user_email, 'text2'),
])
Expand Down
102 changes: 102 additions & 0 deletions aiida/backends/tests/orm/comment.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
# -*- coding: utf-8 -*-
###########################################################################
# Copyright (c), The AiiDA team. All rights reserved. #
# This file is part of the AiiDA code. #
# #
# The code is hosted on GitHub at https://github.com/aiidateam/aiida_core #
# For further information on the license, see the LICENSE.txt file #
# For further information please visit http://www.aiida.net #
###########################################################################
"""Unit tests for the Comment ORM class."""
from __future__ import division
from __future__ import print_function
from __future__ import absolute_import

from aiida import orm
from aiida.orm.comments import Comment
from aiida.backends.testbase import AiidaTestCase
from aiida.common import exceptions


class TestComment(AiidaTestCase):
"""Unit tests for the Comment ORM class."""

def setUp(self):
super(TestComment, self).setUp()
self.node = orm.Node().store()
self.user = orm.User.objects.get_default()
self.content = 'Sometimes when I am freestyling, I lose confidence'
self.comment = Comment(self.node, self.user, self.content).store()

def tearDown(self):
super(TestComment, self).tearDown()
comments = Comment.objects.all()
for comment in comments:
Comment.objects.delete(comment.id)

def test_comment_content(self):
"""Test getting and setting content of a Comment."""
content = 'Be more constructive with your feedback'
self.comment.set_content(content)
self.assertEqual(self.comment.content, content)

def test_comment_mtime(self):
"""Test getting and setting mtime of a Comment."""
mtime = self.comment.mtime
self.comment.set_content('Changing an attribute should automatically change the mtime')
self.assertEqual(self.comment.content, 'Changing an attribute should automatically change the mtime')
self.assertNotEqual(self.comment.mtime, mtime)

def test_comment_node(self):
"""Test getting the node of a Comment."""
self.assertEqual(self.comment.node.uuid, self.node.uuid)

def test_comment_user(self):
"""Test getting the user of a Comment."""
self.assertEqual(self.comment.user.uuid, self.user.uuid)

def test_comment_collection_get(self):
"""Test retrieving a Comment through the collection."""
comment = Comment.objects.get(comment=self.comment.pk)
self.assertEqual(self.comment.uuid, comment.uuid)

def test_comment_collection_delete(self):
"""Test deleting a Comment through the collection."""
comment = Comment(self.node, self.user, 'I will perish').store()
comment_pk = comment.pk

Comment.objects.delete(comment=comment.pk)

with self.assertRaises(exceptions.NotExistent):
Comment.objects.get(comment=comment_pk)

def test_comment_querybuilder(self):
"""Test querying for comments by joining on nodes in the QueryBuilder."""
node_one = orm.Node().store()
comment_one = Comment(node_one, self.user, 'comment_one').store()

node_two = orm.Node().store()
comment_three = Comment(node_two, self.user, 'comment_three').store()
comment_four = Comment(node_two, self.user, 'comment_four').store()

# Retrieve a node by joining on a specific comment
nodes = orm.QueryBuilder().append(
Comment, tag='comment', filters={
'id': comment_one.id
}).append(
orm.Node, with_comment='comment', project=['uuid']).all()

self.assertEqual(len(nodes), 1)
for node in nodes:
self.assertIn(str(node[0]), [node_one.uuid])

# Retrieve a comment by joining on a specific node
comments = orm.QueryBuilder().append(
orm.Node, tag='node', filters={
'id': node_two.id
}).append(
Comment, with_node='node', project=['uuid']).all()

self.assertEqual(len(comments), 2)
for comment in comments:
self.assertIn(str(comment[0]), [comment_three.uuid, comment_four.uuid])
Loading