Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 23 additions & 10 deletions activate/activate_manager.py
Original file line number Diff line number Diff line change
@@ -1,29 +1,42 @@
import functools
from typing import Callable

from fastapi import HTTPException

from activate.types.activity_streams.core_types import Activity

activate_manager: "ActivateManager"


def get_activate_manager():
return ActivateManager()
global activate_manager
if not activate_manager:
activate_manager = ActivateManager()
return activate_manager


class ActivateManager:
schema: dict[Activity, Callable]
schema: dict[str, Callable] = {}

def resolve(self, activity: Activity):
async def resolve(self, activity: str):
"""
Called by the web adapter to resolve activities
"""
# TODO: check the schema for a registered activity that matches the requested one
# TODO: if so, call it
if self.schema[Activity]:
return await self.schema[Activity](activity)
else:
raise HTTPException(status_code=404, detail="Activity can NOT be handled")

def resolver(self):
def resolver(self, resolver_function):
"""
A decorator used by the package user to register custom resolvers for activities
"""
def wrapper(resolver_function):
# TODO: check that the first argument to the function is an activity
# TODO: if so, register the resolver function in schema
return resolver_function
@functools.wraps(resolver_function)
async def wrapper(activity: Activity):
self.schema[Activity] = resolver_function
return resolver_function(activity)

return wrapper


activate_manager = ActivateManager()
77 changes: 39 additions & 38 deletions activate/types/activity_streams/activity_types.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,12 @@

from pydantic import AnyUrl


from activate.types.activity_streams.core_types import (
Activity,
IntransitiveActivity,
Object,
Link
Link,
)


Expand All @@ -26,7 +27,11 @@ class Arrive(Activity):
type: AnyUrl = "Arrive"


class Block("Ignore"):
class Ignore(Activity):
type: AnyUrl = "Ignore"


class Block(Ignore):
type: AnyUrl = "Block"


Expand All @@ -50,11 +55,11 @@ class Follow(Activity):
type: AnyUrl = "Follow"


class Ignore(Activity):
type: AnyUrl = "Ignore"
class Offer(Activity):
type: AnyUrl = "Offer"


class Invite("Offer"):
class Invite(Offer):
type: AnyUrl = "Invite"


Expand All @@ -68,63 +73,59 @@ class Leave(Activity):

class Like(Activity):
type: AnyUrl = "Like"


class Listen(Activity):
type: AnyUrl = "Listen"


class Move(Activity):
type: AnyUrl = "Move"


class Offer(Activity):
type: AnyUrl = "Offer"




class Question(IntransitiveActivity):
type: AnyUrl = "Question"

# oneOf and anyOf must NOT exist together
#FIXME: how to validate this?
oneOf: list[Object | Link] | Object | Link
anyOf: list[Object | Link] | Object | Link
# FIXME: how to validate this?
# oneOf: list[Object | Link] | Object | Link
# anyOf: list[Object | Link] | Object | Link

# closed can also be a generic object as per the vocabulary. HOW?
closed: datetime | bool
# closed: datetime | bool


class Reject(Activity):
type: AnyUrl = "Reject"


class Read(Activity):
type: AnyUrl = "Read"


class Remove(Activity):
type: AnyUrl = "Remove"


class TentativeReject(Reject):
type: AnyUrl = "TentativeReject"


class TentativeAccept(Accept):
type: AnyUrl = "TentativeAccept"


class Travel(IntransitiveActivity):
type: AnyUrl = "Travel"
type: AnyUrl = "Travel"


class Undo(Activity):
type: AnyUrl = "Undo"


class Update(Activity):
type: AnyUrl = "Update"


class View(Activity):
type: AnyUrl = "View"
75 changes: 37 additions & 38 deletions activate/types/activity_streams/core_types.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
from datetime import datetime, timedelta

from typing import Union

from pydantic import BaseModel, AnyUrl
from pydantic import Field


class Link(BaseModel):
# Type is NOT explicitly defined in the standard vocabulary as functional.
# It is assumed to be functional (a single value) here
Expand All @@ -17,7 +20,7 @@ class Link(BaseModel):
# In the [HTML5], any string NOT containing the
# "space" U+0020, "tab" (U+0009), "LF" (U+000A), "FF" (U+000C), "CR" (U+000D) or "," (U+002C) characters
# can be used as a valid link relation.
rel: list[str] | str
# rel: list[str] | str

# should be a MIME media type (how to validate this? Is there a specific set of MIME types?)
mediaType: str
Expand All @@ -37,7 +40,7 @@ class Link(BaseModel):
height: int = Field(ge=0)
width: int = Field(ge=0)

preview: list["Object" | "Link"] | "Object" | "Link"
preview: Union[list["Object"], list["Link"], "Object", "Link"]


class Object(BaseModel):
Expand All @@ -47,9 +50,9 @@ class Object(BaseModel):

id: AnyUrl | None

attachment: list["Object" | Link] | "Object" | Link
attributedTo: list["Object" | Link] | "Object" | Link
audience: list["Object" | Link] | "Object" | Link
# attachment: Union[list["Object"], Link, "Object", Link]
# attributedTo: Union[list["Object"], Link, "Object", Link]
# audience: Union[list["Object" | Link], "Object", Link]

# By default, content is an HTML string.
# Otherwise, use the mediatype property to declare the type of string. How to enforce this?
Expand All @@ -60,7 +63,7 @@ class Object(BaseModel):

# content is NOT explicitly defined in the standard vocabulary as functional.
# It is assumed to be functional (a single value) here
context: "Object" | Link
# context: Union["Object", Link]

# name must NOT include HTML markup (how to enforce this?).
# It can be a map of the name in different languages (maybe a map would be supported later)
Expand All @@ -72,16 +75,16 @@ class Object(BaseModel):

# content is NOT explicitly defined in the standard vocabulary as functional.
# It is assumed to be functional (a single value) here
generator: "Object" | Link
# generator: Union["Object", Link]

# Icons should be of 1:1 aspect ratio and should be suitable for presentation at a small size
icon: list["Image" | Link] | "Image" | Link
# icon: Union[list["Image", Link], "Image", Link]
# Images don't have the limitations assumed in icons
image: list["Image" | Link] | "Image" | Link
# image: list["Image" | Link] | "Image" | Link

inReplyTo: list["Object" | Link] | "Object" | Link
location: list["Object" | Link] | "Object" | Link
preview: list["Object" | Link] | "Object" | Link
# inReplyTo: list["Object" | Link] | "Object" | Link
# location: list["Object" | Link] | "Object" | Link
# preview: list["Object" | Link] | "Object" | Link
published: datetime

# replies is a collection, but it is a functional property (a single collection)
Expand All @@ -90,17 +93,17 @@ class Object(BaseModel):
startTime: datetime

# Like the content property
summary: list[str] | str
# summary: list[str] | str

# Attachments imply association by inclusion. Tags imply association by reference.
tag: list["Object" | Link] | "Object" | Link
# tag: list["Object" | Link] | "Object" | Link

updated: datetime
url: list["AnyUrl" | Link] | "AnyUrl" | Link
to: list["Object" | Link] | "Object" | Link
bto: list["Object" | Link] | "Object" | Link
cc: list["Object" | Link] | "Object" | Link
bcc: list["Object" | Link] | "Object" | Link
# url: list["AnyUrl" | Link] | "AnyUrl" | Link
# to: list["Object" | Link] | "Object" | Link
# bto: list["Object" | Link] | "Object" | Link
# cc: list["Object" | Link] | "Object" | Link
# bcc: list["Object" | Link] | "Object" | Link

# should be a MIME media type (how to validate this? Is there a specific set of MIME types?)
mediaType: str
Expand All @@ -112,16 +115,17 @@ class Object(BaseModel):


class BaseActivity(Object):
...
# Abstract class for the activity and IntransitiveActivity Types

# Subproperty of "attributedTO"
#TODO: what are the complications of this?
actor: list["Object" | Link] | "Object" | Link
# TODO: what are the complications of this?
# actor: list["Object" | Link] | "Object" | Link

target: list["Object" | Link] | "Object" | Link
result: list["Object" | Link] | "Object" | Link
origin: list["Object" | Link] | "Object" | Link
instrument: list["Object" | Link] | "Object" | Link
# target: list["Object" | Link] | "Object" | Link
# result: list["Object" | Link] | "Object" | Link
# origin: list["Object" | Link] | "Object" | Link
# instrument: list["Object" | Link] | "Object" | Link


class IntransitiveActivity(BaseActivity):
Expand All @@ -131,7 +135,7 @@ class IntransitiveActivity(BaseActivity):
class Activity(BaseActivity):
type: AnyUrl = "Activity"

object: list["Object" | Link] | "Object" | Link
# object: list["Object" | Link] | "Object" | Link


class Collection(Object):
Expand All @@ -141,10 +145,10 @@ class Collection(Object):
# serialized within the Collection object instance
totalItems: int = Field(ge=0)

current: "CollectionPage" | Link
first: "CollectionPage" | Link
last: "CollectionPage" | Link
items: list[Object | Link] | Object | Link
# current: "CollectionPage" | Link
# first: "CollectionPage" | Link
# last: "CollectionPage" | Link
# items: list[Object | Link] | Object | Link


class OrderedCollection(Collection):
Expand All @@ -154,17 +158,12 @@ class OrderedCollection(Collection):
class CollectionPage(Collection):
type: AnyUrl = "CollectionPage"

partOf: Collection | Link
next: "CollectionPage" | Link
prev: "CollectionPage" | Link
# partOf: Collection | Link
# next: "CollectionPage" | Link
# prev: "CollectionPage" | Link


class OrderedCollectionPage(OrderedCollection, CollectionPage):
type: AnyUrl = "OrderedCollectionPage"

startIndex: int = Field(ge=0)





Loading