Add support for Comment entity

Refs: #4
merge-requests/130/head
Jason Robinson 2016-04-03 22:25:12 +03:00
rodzic cd8304fcdb
commit 62380a5d77
7 zmienionych plików z 111 dodań i 20 usunięć

Wyświetl plik

@ -1,8 +1,12 @@
# -*- coding: utf-8 -*-
from datetime import datetime
import datetime
from dirty_validators.basic import Email
__all__ = ("Post", "Image", "Comment")
class BaseEntity(object):
_required = []
@ -62,22 +66,18 @@ class PublicMixin(BaseEntity):
class CreatedAtMixin(BaseEntity):
created_at = datetime.now()
created_at = datetime.datetime.now()
def __init__(self, *args, **kwargs):
super(CreatedAtMixin, self).__init__(*args, **kwargs)
self._required += ["created_at"]
class Post(GUIDMixin, HandleMixin, PublicMixin, CreatedAtMixin, BaseEntity):
"""Reflects a post, status message, etc, which will be composed from the message or to the message."""
class RawContentMixin(BaseEntity):
raw_content = ""
provider_display_name = ""
location = ""
photos = []
def __init__(self, *args, **kwargs):
super(Post, self).__init__(*args, **kwargs)
super(RawContentMixin, self).__init__(*args, **kwargs)
self._required += ["raw_content"]
@property
@ -86,6 +86,13 @@ class Post(GUIDMixin, HandleMixin, PublicMixin, CreatedAtMixin, BaseEntity):
return set({word.strip("#") for word in self.raw_content.split() if word.startswith("#")})
class Post(RawContentMixin, GUIDMixin, HandleMixin, PublicMixin, CreatedAtMixin, BaseEntity):
"""Reflects a post, status message, etc, which will be composed from the message or to the message."""
provider_display_name = ""
location = ""
photos = []
class Image(GUIDMixin, HandleMixin, PublicMixin, CreatedAtMixin, BaseEntity):
"""Reflects a single image, possibly linked to another object."""
remote_path = ""
@ -99,3 +106,23 @@ class Image(GUIDMixin, HandleMixin, PublicMixin, CreatedAtMixin, BaseEntity):
def __init__(self, *args, **kwargs):
super(Image, self).__init__(*args, **kwargs)
self._required += ["remote_path", "remote_name"]
class ParticipationMixin(BaseEntity):
"""Reflects a participation to something."""
target_guid = ""
participation = ""
def __init__(self, *args, **kwargs):
super(ParticipationMixin, self).__init__(*args, **kwargs)
self._required += ["target_guid", "participation"]
def validate_participation(self):
"""Ensure participation is of a certain type."""
if self.participation not in ["like", "subscription", "comment"]:
raise ValueError("participation should be one of: like, subscription, comment")
class Comment(RawContentMixin, GUIDMixin, ParticipationMixin, CreatedAtMixin, HandleMixin):
"""Represents a comment, linked to another object."""
participation = "comment"

Wyświetl plik

@ -0,0 +1,10 @@
# -*- coding: utf-8 -*-
from ..base import Comment
class DiasporaComment(Comment):
"""Diaspora comments additionally have an author_signature."""
@property
def author_signature(self):
#TODO: implement at later stage when outbound payloads are to be used
return ""

Wyświetl plik

@ -1,3 +1,4 @@
# -*- coding: utf-8 -*-
from dateutil.tz import tzlocal, tzutc
from lxml import etree
@ -30,6 +31,7 @@ class EntityConverter(object):
etree.SubElement(node, k).text = v
def convert_to_xml(self):
#TODO: move these to entities themselves as `to_xml` methods
if hasattr(self, "%s_to_xml" % self.entity_type):
method_name = "%s_to_xml" % self.entity_type
return getattr(self, method_name)()
@ -52,3 +54,14 @@ class EntityConverter(object):
{'created_at': self.format_dt(self.entity.created_at)}
])
return req
def diasporacomment_to_xml(self):
req = etree.Element("comment")
self.struct_to_xml(req, [
{'guid': self.entity.guid},
{'parent_guid': self.entity.target_guid},
{'author_signature': self.entity.author_signature},
{'text': self.entity.raw_content},
{'diaspora_handle': self.entity.handle},
])
return req

Wyświetl plik

@ -1,12 +1,15 @@
# -*- coding: utf-8 -*-
from datetime import datetime
from lxml import etree
from federation.entities.base import Post, Image
from federation.entities.base import Post, Image, Comment
MAPPINGS = {
"status_message": Post,
"photo": Image,
"comment": Comment,
}
BOOLEAN_KEYS = [
@ -35,7 +38,8 @@ def message_to_objects(message):
if cls:
attrs = xml_children_as_dict(element)
transformed = transform_attributes(cls, attrs)
entities.append(cls(**transformed))
entity = cls(**transformed)
entities.append(entity)
return entities
@ -43,10 +47,12 @@ def transform_attributes(cls, attrs):
"""Transform some attribute keys."""
transformed = {}
for key, value in attrs.items():
if key == "raw_message":
if key in ["raw_message", "text"]:
transformed["raw_content"] = value
elif key == "diaspora_handle":
transformed["handle"] = value
elif key == "parent_guid":
transformed["target_guid"] = value
elif key in BOOLEAN_KEYS:
transformed[key] = True if value == "true" else False
elif key in DATETIME_KEYS:

Wyświetl plik

@ -1,9 +1,10 @@
# -*- coding: utf-8 -*-
from datetime import datetime
from lxml import etree
from unittest.mock import patch
from lxml import etree
from federation.entities.base import Post
from federation.entities.diaspora.entities import DiasporaComment
from federation.entities.diaspora.generators import EntityConverter
@ -19,13 +20,23 @@ class TestEntityConverterCallsToXML(object):
assert mock_to_xml.called
def test_entity_converter_converts_a_post(self):
entity = Post(raw_content="raw_content", guid="guid", handle="handle", public=True, created_at=datetime.today())
entity = Post(raw_content="raw_content", guid="guid", handle="handle", public=True)
entity_converter = EntityConverter(entity)
result = entity_converter.convert_to_xml()
assert result.tag == "status_message"
assert len(result.find("created_at").text) > 0
result.find("created_at").text = "" # timestamp makes testing painful
post_converted = b"<status_message><raw_message>raw_content</raw_message><guid>guid</guid>" \
b"<diaspora_handle>handle</diaspora_handle><public>true</public><created_at>" \
b"</created_at></status_message>"
assert etree.tostring(result) == post_converted
converted = b"<status_message><raw_message>raw_content</raw_message><guid>guid</guid>" \
b"<diaspora_handle>handle</diaspora_handle><public>true</public><created_at>" \
b"</created_at></status_message>"
assert etree.tostring(result) == converted
def test_entity_converter_converts_a_comment(self):
entity = DiasporaComment(raw_content="raw_content", guid="guid", target_guid="target_guid", handle="handle")
entity_converter = EntityConverter(entity)
result = entity_converter.convert_to_xml()
assert result.tag == "comment"
converted = b"<comment><guid>guid</guid><parent_guid>target_guid</parent_guid>" \
b"<author_signature></author_signature><text>raw_content</text>" \
b"<diaspora_handle>handle</diaspora_handle></comment>"
assert etree.tostring(result) == converted

Wyświetl plik

@ -1,9 +1,9 @@
# -*- coding: utf-8 -*-
from datetime import datetime
from federation.entities.base import Post
from federation.entities.base import Post, Comment
from federation.entities.diaspora.mappers import message_to_objects
from federation.tests.fixtures.payloads import DIASPORA_POST_SIMPLE
from federation.tests.fixtures.payloads import DIASPORA_POST_SIMPLE, DIASPORA_POST_COMMENT
class TestDiasporaEntityMappersReceive(object):
@ -18,3 +18,14 @@ class TestDiasporaEntityMappersReceive(object):
assert post.handle == "alice@alice.diaspora.example.org"
assert post.public == False
assert post.created_at == datetime(2011, 7, 20, 1, 36, 7)
def test_message_to_objects_comment(self):
entities = message_to_objects(DIASPORA_POST_COMMENT)
assert len(entities) == 1
comment = entities[0]
assert isinstance(comment, Comment)
assert comment.target_guid == "((parent_guid))"
assert comment.guid == "((guid))"
assert comment.handle == "alice@alice.diaspora.example.org"
assert comment.participation == "comment"
assert comment.raw_content == "((text))"

Wyświetl plik

@ -35,3 +35,16 @@ DIASPORA_POST_SIMPLE = """<XML>
</post>
</XML>
"""
DIASPORA_POST_COMMENT = """<XML>
<post>
<comment>
<guid>((guid))</guid>
<parent_guid>((parent_guid))</parent_guid>
<author_signature>((base64-encoded data))</author_signature>
<text>((text))</text>
<diaspora_handle>alice@alice.diaspora.example.org</diaspora_handle>
</comment>
</post>
</XML>
"""