Skip to content

Commit

Permalink
Move the Comment class to the new backend interface
Browse files Browse the repository at this point in the history
  • Loading branch information
sphuber committed Nov 22, 2018
1 parent eaee1cc commit 84a5756
Show file tree
Hide file tree
Showing 26 changed files with 619 additions and 396 deletions.
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
65 changes: 25 additions & 40 deletions aiida/backends/tests/cmdline/commands/test_comment.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
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 +25,52 @@ 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 = ['-c{}'.format(COMMENT), str(self.node.pk)]
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)

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

node = orm.Node()
node.store()
comment_id = node.add_comment(COMMENT)
self.assertEquals(len(self.node.get_comments()), 1)

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

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

self.assertEquals(len(node.get_comments()), 0)
self.assertEquals(len(self.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()
"""Test removing all comments from a self.node."""
for _ in range(10):
node.add_comment(COMMENT)
self.node.add_comment(COMMENT)

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

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

self.assertEqual(len(node.get_comments()), 0)
self.assertEqual(len(self.node.get_comments()), 0)
65 changes: 65 additions & 0 deletions aiida/backends/tests/orm/comment.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
# -*- 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 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)
12 changes: 6 additions & 6 deletions aiida/orm/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,16 +18,16 @@
from aiida.orm.workflow import Workflow

from .authinfos import *
from .backends import *
from .calculation import *
from .computers import *
from .entities import *
from .groups import *
from .logs import *
from .node import *
from .backends import *
from .querybuilder import *
from .users import *
from .utils import *
from .querybuilder import *

# For legacy reasons support the singulars as well
authinfo = authinfos
Expand All @@ -41,12 +41,12 @@

__all__ = (_local +
authinfos.__all__ +
backends.__all__ +
calculation.__all__ +
computers.__all__ +
entities.__all__ +
groups.__all__ +
logs.__all__ +
utils.__all__ +
users.__all__ +
backends.__all__ +
querybuilder.__all__ +
groups.__all__)
users.__all__ +
utils.__all__)
91 changes: 91 additions & 0 deletions aiida/orm/comments.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
# -*- 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 #
###########################################################################
"""Comment objects and functions"""
from __future__ import division
from __future__ import print_function
from __future__ import absolute_import

from . import backends
from . import entities
from . import users

__all__ = ('Comment',)


class Comment(entities.Entity):
"""Base class to map a DbComment that represents a comment attached to a certain Node."""

class Collection(entities.Collection):
"""The collection of Comment entries."""

def delete(self, comment):
"""
Remove a Comment from the collection with the given id
:param comment: the id of the comment to delete
"""
self._backend.comments.delete(comment)

def get(self, comment):
"""
Return a Comment given its id
:param comment: the id of the comment to retrieve
:return: the comment
:raise NotExistent: if the comment with the given id does not exist
:raise MultipleObjectsError: if the id cannot be uniquely resolved to a comment
"""
return self._backend.comments.get(comment)

def __init__(self, node, user, content=None, backend=None):
"""
Create a Comment for a given node and user
:param node: a Node instance
:param user: a User instance
:param content: the comment content
:return: a Comment object associated to the given node and user
"""
backend = backend or backends.construct_backend()
model = backend.comments.create(node=node, user=user.backend_entity, content=content)
super(Comment, self).__init__(model)

def __str__(self):
arguments = [self.uuid, self.node.pk, self.user.email, self.content]
return 'Comment<{}> for node<{}> and user<{}>: {}'.format(*arguments)

@property
def ctime(self):
return self._backend_entity.ctime

@property
def mtime(self):
return self._backend_entity.mtime

def set_mtime(self, value):
return self._backend_entity.set_mtime(value)

@property
def node(self):
return self._backend_entity.node

@property
def user(self):
return users.User.from_backend_entity(self._backend_entity.user)

def set_user(self, value):
self._backend_entity.set_user(value.backend_entity)

@property
def content(self):
return self._backend_entity.content

def set_content(self, value):
return self._backend_entity.set_content(value)
Loading

0 comments on commit 84a5756

Please sign in to comment.