Refactor expand/parse; WIP fetch

master
Douglas Blank 2018-07-19 23:03:37 -04:00
rodzic 7a140e26c5
commit 88e1881cda
3 zmienionych plików z 87 dodań i 46 usunięć

Wyświetl plik

@ -33,7 +33,7 @@ class ActivityPubBase():
if attr_name.startswith("ap_"):
attr = getattr(self, attr_name)
if isinstance(attr, str) and "$" in attr:
dependencies[attr_name[3:]] = {x[1:] for x in self.parse(attr)
dependencies[attr_name[3:]] = {x[1:] for x in self.manager.parse(attr)
if x.startswith("$") and x[1:] != attr_name[3:]}
## Now, replace them in order:
for attr_name in self.topological_sort(dependencies):
@ -46,7 +46,7 @@ class ActivityPubBase():
if attr is None:
raise Exception("variable depends on field that is empty: %s" % attr_name)
if isinstance(attr, str) and "$" in attr:
setattr(self, attr_name, self.expand_defaults(attr))
setattr(self, attr_name, self.manager.expand_defaults(attr))
def topological_sort(self, data):
"""
@ -71,49 +71,6 @@ class ActivityPubBase():
for item, dep in data.items()
if item not in ordered}
def parse(self, string):
"""
Parse a string delimited by non-alpha, non-$ symbols.
>>> from activitypub import Manager
>>> m = Manager()
>>> p = m.Person()
>>> p.parse("apple/banana/$variable")
['apple', 'banana', '$variable']
"""
retval = []
current = []
for s in string:
if s.isalpha() or (s in ["$"] and len(current) == 0):
current.append(s)
else:
if current:
retval.append("".join(current))
if s == "$":
current = ["$"]
else:
current = []
if current:
retval.append("".join(current))
return retval
def expand_defaults(self, string):
"""
Expand a string with defaults.
"""
for key in self.manager.defaults:
if key.startswith("$"):
if callable(self.manager.defaults[key]):
string = string.replace(key, self.manager.defaults[key]())
else:
string = string.replace(key, self.manager.defaults[key])
for key in self.parse(string):
if key.startswith("$"):
if getattr(self, "ap_" + key[1:]) is None:
raise Exception("expansion requires %s" % key[1:])
string = string.replace(key, getattr(self, "ap_" + key[1:]))
return string
def to_dict(self):
"""
Convert object to JSON format.

Wyświetl plik

@ -194,9 +194,10 @@ class DummyTable(Table):
>>> table.find({"c": 1, "d": 2}).count()
2
"""
row = copy.deepcopy(row) # expensive, but prevents errors
if row.get("_id", None) is None:
row["_id"] = ObjectId()
self.data.append(copy.deepcopy(row))
self.data.append(row)
def find(self, query=None, limit=None):
"""

Wyświetl plik

@ -11,6 +11,8 @@ class Manager():
>>> manager = Manager(database=db)
>>>
"""
app_name = "activitypub"
version = "1.0.0"
def __init__(self, context=None, defaults=None, database=None):
from .classes import ActivityPubBase
self.callback = lambda box, activity_id: None
@ -53,6 +55,54 @@ class Manager():
"Note.id": "$attributedTo/note/$id",
}
def user_agent(self):
return "%s (%s/%s; +%s)" % (requests.utils.default_user_agent(),
self.app_name,
self.version,
self.expand_defaults("$SCHEME/$HOST"))
def expand_defaults(self, obj, string):
"""
Expand a string with defaults.
"""
for key in self.defaults:
if key.startswith("$"):
if callable(self.defaults[key]):
string = string.replace(key, self.defaults[key]())
else:
string = string.replace(key, self.defaults[key])
for key in self.parse(string):
if key.startswith("$"):
if getattr(obj, "ap_" + key[1:]) is None:
raise Exception("expansion requires %s" % key[1:])
string = string.replace(key, getattr(obj, "ap_" + key[1:]))
return string
def parse(self, string):
"""
Parse a string delimited by non-alpha, non-$ symbols.
>>> from activitypub import Manager
>>> m = Manager()
>>> m.parse("apple/banana/$variable")
['apple', 'banana', '$variable']
"""
retval = []
current = []
for s in string:
if s.isalpha() or (s in ["$"] and len(current) == 0):
current.append(s)
else:
if current:
retval.append("".join(current))
if s == "$":
current = ["$"]
else:
current = []
if current:
retval.append("".join(current))
return retval
def from_dict(self, data):
from .classes import ActivityPubBase
return ActivityPubBase.from_dict(data)
@ -65,6 +115,8 @@ class Manager():
def on_post_to_box(self, box, activity):
"""
manager.on_post_to_box("inbox", activity)
manager.on_post_to_box("outbox", activity)
manager.on_post_to_box("replies", reply)
"""
self.database.activities.insert_one(
{
@ -110,3 +162,34 @@ class Manager():
return [doc["activity"]["object"]
for doc in self.database.activities.find(q)]
def get_iri(self, iri):
if iri.startswith(self.expand_defaults("$SCHEME/$HOST")):
## get from table
## self.database.activity.find()
## TODO: WIP
pass
else:
try:
response = requests.get(
iri,
headers={
"User-Agent": self.user_agent(),
"Accept": "application/activity+json",
},
timeout=10,
allow_redirects=False,
**kwargs)
except:
raise Exception("unable to fetch uri")
return self.handle(response)
def handle_response(self, response):
if response.status_code == 404:
raise Exception("iri is not found")
elif response.status_code == 410:
raise Exception("iri is gone")
elif response.status_code in [500, 502, 503]:
raise Exception("unable to fetch; server error")
response.raise_for_status()
return response.json()