Exemple #1
0
def test_value_error_is_raised_if_source_decorator_was_used_without_argument():
    async def source(*_):
        yield "test"  # pragma: no cover

    subscription = SubscriptionType()
    with pytest.raises(ValueError):
        subscription.source(source)
Exemple #2
0
def test_attempt_bind_subscription_to_undefined_field_raises_error(schema):
    async def source(*_):
        yield "test"  # pragma: no cover

    subscription = SubscriptionType()
    subscription.set_source("fake", source)
    with pytest.raises(ValueError):
        subscription.bind_to_schema(schema)
Exemple #3
0
def test_field_source_can_be_set_using_decorator(schema):
    async def source(*_):
        yield "test"  # pragma: no cover

    subscription = SubscriptionType()
    subscription.source("message")(source)
    subscription.bind_to_schema(schema)
    field = schema.type_map.get("Subscription").fields["message"]
    assert field.subscribe is source
Exemple #4
0
    def start(self):
        query = QueryType()
        query.set_field('echo', self._echo_resolver())

        mutation = MutationType()
        mutation.set_field('createTable', self._create_table_resolver())
        mutation.set_field('addPlayer', self._add_player_resolver())
        mutation.set_field('takeAction', self._take_action_resolver())
        mutation.set_field('startGame', self._start_game_resolver())
        mutation.set_field('stopGame', self._stop_game_resolver())
        mutation.set_field('reset', self._reset_resolver())

        subscription = SubscriptionType()
        subscription.set_field('subscribe', self._subscribe_resolver())
        subscription.set_source('subscribe', self._subscribe_generator())

        resolvers = [query, mutation, subscription]

        executable_schema = make_executable_schema(self._schema_str, resolvers)
        self._app = GraphQL(executable_schema, debug=True)
Exemple #5
0
import os
import os.path
import pathlib
import asyncio

from graphql import parse
from ariadne import MutationType, SubscriptionType, load_schema_from_path

from nomine.models import Namer
from nomine.models.folder_entry import FolderEntry, FILE_TYPE, DIRECTORY_TYPE

mutation = MutationType()
subscription = SubscriptionType()
bindables = [mutation, subscription]
schema_file = load_schema_from_path(
    pathlib.Path(__file__).parent.joinpath("schema.graphql").absolute())
schema = parse(schema_file)
queue = asyncio.Queue()


def get_or_create_entry(session, folder_id, dir_entry):
    if dir_entry.is_file():
        entry_type = FILE_TYPE
    elif dir_entry.is_dir():
        entry_type = DIRECTORY_TYPE
    else:
        return

    existing = (session.query(FolderEntry).filter(
        FolderEntry.path == dir_entry.path).first())
    if existing:
Exemple #6
0
def subscriptions():
    subscription = SubscriptionType()
    subscription.set_source("ping", ping_generator)
    subscription.set_source("resolverError", ping_generator)
    subscription.set_field("resolverError", resolve_error)
    subscription.set_source("sourceError", error_generator)
    subscription.set_source("testContext", test_context_generator)
    subscription.set_source("testRoot", test_root_generator)
    return subscription
Exemple #7
0
    pathlib.Path(__file__).parent.absolute().joinpath("graphql", "schema.graphql")
)
type_defs = load_schema_from_path("saltapi/graphql/schema.graphql")

datetime_scalar = ScalarType("Datetime")
datetime_scalar.set_serializer(scalars.serialize_datetime)
datetime_scalar.set_value_parser(scalars.parse_datetime)

proposal_code_scalar = ScalarType("ProposalCode")
proposal_code_scalar.set_serializer(scalars.serialize_proposal_code)
proposal_code_scalar.set_value_parser(scalars.parse_proposal_code)

mutation = MutationType()
mutation.set_field("submitProposal", resolvers.resolve_submit_proposal)

subscription = SubscriptionType()
subscription.set_field("submissionProgress", resolvers.resolve_submission_progress)
subscription.set_source("submissionProgress", resolvers.submission_progress_generator)

schema = make_executable_schema(
    type_defs,
    datetime_scalar,
    proposal_code_scalar,
    mutation,
    subscription,
    directives={"permittedFor": PermittedForDirective},
)


# non-GraphQL routes
Exemple #8
0
def subscriptions():
    subs = SubscriptionType()
    subs.source("ping")(ping)
    return subs
Exemple #9
0
class GraphAPI:
    query: QueryType = QueryType()
    subscription = SubscriptionType()
    mutations = MutationType()

    def __init__(self, core: "Core"):
        self.core = core
        self.type_defs = load_schema_from_path(f"{core.location}/api/schema/")
        # self.add_query("spotifyProgress: String!", self.type_defs)

        self.query.set_field(CORE_VERSION, lambda *_: core.version)
        self.query.set_field(PLUGIN_VERSION, lambda *_: VERSION)
        self.query.set_field(PLUGINS, lambda *_: list(core.plugins.keys()))
        self.query.set_field(VALUE, self.get_value)
        self.query.set_field(AVAILABLE_COMPONENTS,
                             lambda *_: list(core.registry.components.keys()))
        self.query.set_field(
            AVAILABLE_FORMATTER,
            lambda *_: list(map(lambda x: x.gql(), core.io.formatter)),
        )
        self.query.set_field(COMMIT_ID,
                             lambda *_: os.getenv("COMMIT", "unknown"))

        self.query.set_field(ENTITY, self.get_entity)
        self.query.set_field(ENTITIES, self.get_entities)

        self.subscription.set_field(ENTITY, self.entity_subscription)
        self.subscription.set_source(ENTITY, self.entity_subscription_source)

        self.subscription.set_field(VALUE, self.value_subscription)
        self.subscription.set_source(VALUE, self.value_subscription_source)

        self.subscription.set_field(EVENT, self.event_subscription)
        self.subscription.set_source(EVENT, self.event_subscription_source)

        self.mutations.set_field(SET_COMPONENT, self.set_mutation)
        self.mutations.set_field(ACTIVATE_SCENE, self.activate_scene)

    def add_query(self, query_def: str, resolver: Callable):
        query_definition: str = re.findall("(?=type Query)([\s\S]*?)(?<=})",
                                           self.type_defs)[0]
        self.type_defs = self.type_defs.replace(query_definition, "")

        lines = query_definition.split("\n")
        lines.insert(1, query_def)
        query_definition = "\n".join(lines)

        name = query_def.split("(")[0].split(":")[0].strip()

        self.query.set_field(name, resolver)

        self.type_defs += f"\n{query_definition}"

    def add_mutation(self, mutation_def: str, handler: Callable):
        mutations: str = re.findall("(?=type Mutation)([\s\S]*?)(?<=})",
                                    self.type_defs)[0]
        self.type_defs = self.type_defs.replace(mutations, "")

        lines = mutations.split("\n")
        lines.insert(1, mutation_def)
        mutations = "\n".join(lines)

        name = mutation_def.split("(")[0].split(":")[0].strip()
        self.mutations.set_field(name, handler)

        self.type_defs += f"\n{mutations}"

    async def setup(self):
        schema = make_executable_schema(self.type_defs, self.query,
                                        self.subscription, self.mutations)
        app = CORSMiddleware(
            GraphQL(schema),
            allow_origins=["*"],
            allow_methods=("GET", "POST", "OPTIONS"),
        )
        conf = Config()
        conf.bind = ["0.0.0.0:8006"]
        conf.loglevel = "fatal"  # to suppress lifespan error
        LOGGER.info("starting GQL API")
        try:  # also to suppress lifespan error
            await serve(app, conf)
        except Exception as e:
            print(e)

    # ----------- QUERIES -----------

    def get_entity(self, _, __, name: str):
        entity = self.core.registry.get_entities()[name]
        return entity.gql()

    def get_entities(self, *_):
        entities = self.core.registry.get_entities()
        return map(lambda e: e.gql(), entities.values())

    def get_value(self, *_, key=""):
        v = self.core.storage.get_value(key)
        return v if v in BASE_TYPES else default_encoder(v)

    # ----------- SUBSCRIPTIONS -----------

    async def entity_subscription_source(self, *_, name=""):
        async for entity in self.core.registry.state_queue.subscribe():
            if entity.name != name:
                continue
            yield entity.gql()

    @staticmethod
    def entity_subscription(entity, *_, name=""):
        return entity

    async def value_subscription_source(self, *_, key=""):
        value = self.core.storage.get_value(key)
        if type(value) not in BASE_TYPES:
            value = default_encoder(value)
        yield value
        async for value in self.core.storage.subscribe(key):
            if type(value) not in BASE_TYPES:
                value = default_encoder(value)
            yield value

    @staticmethod
    def value_subscription(value, *_, key=""):
        return value

    @staticmethod
    def event_subscription(value, *_):
        return value

    async def event_subscription_source(self, *_):
        async for event in self.core.bus.event_stream.subscribe(
        ):  # type: Event
            yield event.gql()

    # ----------- MUTATIONS -----------

    def set_mutation(self, _, info, entity, component, target):
        self.core.registry.call_method(entity,
                                       component,
                                       "set",
                                       target,
                                       context=Context.admin(external=True))
        return True

    def activate_scene(self, _, info, scene):
        self.core.registry.activate_scene(scene)
        return True
Exemple #10
0
from ariadne.executable_schema import make_executable_schema
from graphql.pyutils import EventEmitter, EventEmitterAsyncIterator
from starlette.applications import Starlette
from tortoise.exceptions import DoesNotExist

from .models import Post, User, close_connections, init_db

APP = Starlette()

SCHEMA = load_schema_from_path(os.path.join("example_site", "schema.graphql"))

MUTATION = ObjectType("Mutation")
PUBSUB = EventEmitter()
QUERY = ObjectType("Query")
POST = ObjectType("Post")
SUBSCRIPTION = SubscriptionType()


@QUERY.field("users")
async def get_all_users(_root, _info):
    """return list of all users"""
    results = await User.all()
    return results


@QUERY.field("posts")
async def get_all_posts(_root, _info):
    """return a list of all posts"""
    results = await Post.all()
    return results
Exemple #11
0
from ariadne import SubscriptionType
from aiostream import stream
import rpc_pb2 as ln
from context import LND, PUBSUB
from models import Invoice
from classes.user import User
from helpers.mixins import LoggerMixin

_sub_logger = LoggerMixin()


INVOICE = SubscriptionType()


@INVOICE.source("invoice")
async def r_invoice_gen(user: User, *_):
    # create new new pub sub client for streaming locally paid invoices
    local_stream = PUBSUB.add_client(user.username)

    # create stream for remotely paid invoices
    remote_stream = await LND.stub.SubscribeInvoices(ln.InvoiceSubscription())
    global_stream = stream.merge(local_stream, remote_stream)

    async with global_stream.stream() as streamer:
        async for response in streamer:
            try:
                # check if response if from lnd
                # external payment or pubsub - local payment
                if isinstance(response, Invoice):
                    # invoice model received from pubsub client
                    # yield and default resolver will retrieve requested fields