pull/1/head
Thomas Sileo 2018-06-16 14:19:47 +02:00
rodzic 479000d418
commit 4ff4b3a85c
3 zmienionych plików z 127 dodań i 9 usunięć

Wyświetl plik

@ -1,11 +1,28 @@
import abc import abc
import typing import typing
from typing import Any
from typing import Dict
import requests
from .__version__ import __version__
if typing.TYPE_CHECKING: if typing.TYPE_CHECKING:
from little_boxes import activitypub as ap # noqa: type checking from little_boxes import activitypub as ap # noqa: type checking
class Backend(abc.ABC): class Backend(abc.ABC):
def user_agent(self) -> str:
return f"Little Boxes {__version__} (+http://github.com/tsileo/little-boxes)"
def fetch_json(self, url: str) -> Dict[str, Any]:
resp = requests.get(
url, headers={"User-Agent": self.user_agent(), "Accept": "application/json"}
)
resp.raise_for_status()
return resp.json()
@abc.abstractmethod @abc.abstractmethod
def base_url(self) -> str: def base_url(self) -> str:
pass pass

Wyświetl plik

@ -1,4 +1,4 @@
"""Contains some ActivityPub related utils.""" """Collection releated utils."""
from typing import Any from typing import Any
from typing import Callable from typing import Callable
from typing import Dict from typing import Dict
@ -9,7 +9,7 @@ from .errors import RecursionLimitExceededError
from .errors import UnexpectedActivityTypeError from .errors import UnexpectedActivityTypeError
def parse_collection( def parse_collection( # noqa: C901
payload: Optional[Dict[str, Any]] = None, payload: Optional[Dict[str, Any]] = None,
url: Optional[str] = None, url: Optional[str] = None,
level: int = 0, level: int = 0,
@ -34,13 +34,22 @@ def parse_collection(
if "items" in payload: if "items" in payload:
return payload["items"] return payload["items"]
if "first" in payload: if "first" in payload:
if "orderedItems" in payload["first"]: if isinstance(payload["first"], str):
out.extend(payload["first"]["orderedItems"]) out.extend(
if "items" in payload["first"]: parse_collection(
out.extend(payload["first"]["items"]) url=payload["first"], level=level + 1, fetcher=fetcher
n = payload["first"].get("next") )
if n: )
out.extend(parse_collection(url=n, level=level + 1, fetcher=fetcher)) else:
if "orderedItems" in payload["first"]:
out.extend(payload["first"]["orderedItems"])
if "items" in payload["first"]:
out.extend(payload["first"]["items"])
n = payload["first"].get("next")
if n:
out.extend(
parse_collection(url=n, level=level + 1, fetcher=fetcher)
)
return out return out
while payload: while payload:

Wyświetl plik

@ -0,0 +1,92 @@
import logging
import pytest
from little_boxes import activitypub as ap
from little_boxes.collection import parse_collection
from little_boxes.errors import RecursionLimitExceededError
from little_boxes.errors import UnexpectedActivityTypeError
from test_backend import InMemBackend
logging.basicConfig(level=logging.DEBUG)
def test_empty_collection():
back = InMemBackend()
ap.use_backend(back)
back.FETCH_MOCK["https://lol.com"] = {
"type": "Collection",
"items": [],
"id": "https://lol.com",
}
out = parse_collection(url="https://lol.com", fetcher=back.fetch_iri)
assert out == []
def test_recursive_collection_limit():
back = InMemBackend()
ap.use_backend(back)
back.FETCH_MOCK["https://lol.com"] = {
"type": "Collection",
"first": "https://lol.com",
"id": "https://lol.com",
}
with pytest.raises(RecursionLimitExceededError):
parse_collection(url="https://lol.com", fetcher=back.fetch_iri)
def test_unexpected_activity_type():
back = InMemBackend()
ap.use_backend(back)
back.FETCH_MOCK["https://lol.com"] = {"type": "Actor", "id": "https://lol.com"}
with pytest.raises(UnexpectedActivityTypeError):
parse_collection(url="https://lol.com", fetcher=back.fetch_iri)
def test_collection():
back = InMemBackend()
ap.use_backend(back)
back.FETCH_MOCK["https://lol.com"] = {
"type": "Collection",
"first": "https://lol.com/page1",
"id": "https://lol.com",
}
back.FETCH_MOCK["https://lol.com/page1"] = {
"type": "CollectionPage",
"id": "https://lol.com/page1",
"items": [1, 2, 3],
}
out = parse_collection(url="https://lol.com", fetcher=back.fetch_iri)
assert out == [1, 2, 3]
def test_ordered_collection():
back = InMemBackend()
ap.use_backend(back)
back.FETCH_MOCK["https://lol.com"] = {
"type": "OrderedCollection",
"first": {
"type": "OrderedCollectionPage",
"id": "https://lol.com/page1",
"orderedItems": [1, 2, 3],
"next": "https://lol.com/page2",
},
"id": "https://lol.com",
}
back.FETCH_MOCK["https://lol.com/page2"] = {
"type": "OrderedCollectionPage",
"id": "https://lol.com/page2",
"orderedItems": [4, 5, 6],
}
out = parse_collection(url="https://lol.com", fetcher=back.fetch_iri)
assert out == [1, 2, 3, 4, 5, 6]