kopia lustrzana https://gitlab.com/jaywink/federation
rodzic
cd8304fcdb
commit
62380a5d77
|
@ -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"
|
||||
|
|
|
@ -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 ""
|
|
@ -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
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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))"
|
||||
|
|
|
@ -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>
|
||||
"""
|
||||
|
|
Ładowanie…
Reference in New Issue