Exemplo n.º 1
0
    async def test_add_person(self, dbsession, root_component):
        # Simulate adding a row to the "people" table in the application
        async with Context() as root_ctx:
            await root_component.start(root_ctx)
            async with Context() as ctx:
                session = ctx.require_resource(Session)
                session.add(Person(name="Another person"))

        # The testing code should see both rows now
        assert dbsession.scalar(func.count(Person.id)) == 2
Exemplo n.º 2
0
    async def test_delete_person(self, dbsession, root_component):
        # Simulate removing the test person in the application
        async with Context() as root_ctx:
            await root_component.start(root_ctx)
            async with Context() as ctx:
                session = ctx.require_resource(Session)
                session.execute(delete(Person))

        # The testing code should not see any rows now
        assert dbsession.scalar(func.count(Person.id)) == 0
async def test_multiple_clients(caplog):
    """Test that a multiple connection configuration works as intended."""
    async with Context() as context:
        await MongoDBComponent(
            clients={
                'db1': {
                    'host': 'localhost:27018'
                },
                'db2': {
                    'host': '/tmp/mongodb.sock',
                    'ssl': True
                }
            }).start(context)
        assert isinstance(context.db1, AsyncIOMotorClient)
        assert isinstance(context.db2, AsyncIOMotorClient)

    records = [
        record for record in caplog.records
        if record.name == 'asphalt.mongodb.component'
    ]
    records.sort(key=lambda r: r.message)
    assert len(records) == 4
    assert records[0].message == ("Configured MongoDB client (db1 / ctx.db1; "
                                  "hosts={'localhost:27018'})")
    assert records[1].message == ("Configured MongoDB client (db2 / ctx.db2; "
                                  "hosts={'/tmp/mongodb.sock'})")
    assert records[2].message == 'MongoDB client (db1) shut down'
    assert records[3].message == 'MongoDB client (db2) shut down'
Exemplo n.º 4
0
    async def start(self, ip: str = "127.0.0.1", port: int = 4444, *,
                    component=None, base_context: Context = None):
        """
        Runs the Kyoukai component asynchronously.

        This will bypass Asphalt's default runner, and allow you to run your app easily inside 
        something else, for example.

        :param ip: The IP of the built-in server.
        :param port: The port of the built-in server.
        :param component: The component to start the app with. This should be an instance of \
            :class:`~.KyoukaiComponent`.
                    
        :param base_context: The base context that the HTTPRequestContext should be started with.
        """
        if not base_context:
            base_context = Context()

        if not component:
            from kyoukai.asphalt import KyoukaiComponent
            self.component = KyoukaiComponent(self, ip, port)
        else:
            self.component = component

        # Start the app.
        await self.component.start(base_context)
async def test_multiple_clients(caplog):
    """Test that a multiple client configuration works as expected."""
    async with Context() as context:
        await InfluxDBComponent(
            clients={
                'db1': {
                    'base_urls': 'http://localhost:9999'
                },
                'db2': {
                    'base_urls': 'https://remotehost.example.org:443/influx'
                }
            }).start(context)
        assert isinstance(context.db1, InfluxDBClient)
        assert isinstance(context.db2, InfluxDBClient)

    records = [
        record for record in caplog.records
        if record.name == 'asphalt.influxdb.component'
    ]
    records.sort(key=lambda r: r.message)
    assert len(records) == 4
    assert records[0].message == ("Configured InfluxDB client (db1 / ctx.db1; "
                                  "base_urls=['http://localhost:9999'])")
    assert records[1].message == (
        "Configured InfluxDB client (db2 / ctx.db2; "
        "base_urls=['https://remotehost.example.org:443/influx'])")
    assert records[2].message == 'InfluxDB client (db1) shut down'
    assert records[3].message == 'InfluxDB client (db2) shut down'
async def test_multiple_connections(caplog):
    """Test that a multiple connection configuration works as intended."""
    async with Context() as context:
        await MemcachedComponent(
            clients={
                'mc1': {
                    'host': '1.2.3.4',
                    'port': 11212
                },
                'mc2': {
                    'host': '127.0.0.2'
                }
            }).start(context)
        assert isinstance(context.mc1, Client)
        assert isinstance(context.mc2, Client)

    records = [
        record for record in caplog.records
        if record.name == 'asphalt.memcached.component'
    ]
    records.sort(key=lambda r: r.message)
    assert len(records) == 4
    assert records[0].message == 'Configured Memcached client (mc1 / ctx.mc1)'
    assert records[1].message == 'Configured Memcached client (mc2 / ctx.mc2)'
    assert records[2].message == 'Memcached client (mc1) shut down'
    assert records[3].message == 'Memcached client (mc2) shut down'
Exemplo n.º 7
0
    def test_getattr_parent(self, context):
        """
        Test that accessing a nonexistent attribute on a context retrieves the value from parent.

        """
        child_context = Context(context)
        context.a = 2
        assert child_context.a == 2
Exemplo n.º 8
0
    async def test_missing_yield(self):
        @context_teardown
        async def start(ctx: Context):
            pass

        with pytest.raises(RuntimeError) as exc_info:
            await start(Context())

        exc_info.match(' did not do "await yield_\(\)"$')
Exemplo n.º 9
0
    async def test_rollback(self, dbsession, root_component):
        # Simulate a rollback happening in a subcontext
        async with Context() as root_ctx:
            await root_component.start(root_ctx)
            async with Context() as ctx:
                session = ctx.require_resource(Session)
                try:
                    # No value for a non-nullable column => IntegrityError!
                    session.add(Person())
                    session.flush()
                except IntegrityError:
                    # Without the session listener, this row would now be inserted
                    # outside a SAVEPOINT, breaking test isolation
                    session.rollback()
                    session.add(Person(name="Works now!"))
                    session.flush()

        # The context is gone, but the extra Person should still be around
        assert dbsession.scalar(func.count(Person.id)) == 2
Exemplo n.º 10
0
    async def test_add_resource_factory_no_inherit(self, context):
        """
        Test that a subcontext gets its own version of a factory-generated resource even if a
        parent context has one already.

        """
        context.add_resource_factory(id, int, context_attr='foo')
        subcontext = Context(context)
        assert context.foo == id(context)
        assert subcontext.foo == id(subcontext)
Exemplo n.º 11
0
    async def test_exception(self):
        @context_teardown
        async def start(ctx):
            raise Exception('dummy error')

        context = Context()
        with pytest.raises(Exception) as exc_info:
            await start(context)

        exc_info.match('dummy error')
Exemplo n.º 12
0
    async def test_request_resource_parent_add(self, context, event_loop):
        """
        Test that adding a resource to the parent context will satisfy a resource request in a
        child context.

        """
        child_context = Context(context)
        task = event_loop.create_task(child_context.request_resource(int))
        event_loop.call_soon(context.add_resource, 6)
        resource = await task
        assert resource == 6
Exemplo n.º 13
0
    def __init__(self, app: Kyoukai, base_context: Context = None):
        """
        :param app: The current application to run.
        :param base_context: The base context which is used as the parent to the \ 
            HTTPRequestContext created.
        """
        self.app = app

        self._base_context = base_context
        if not self._base_context:
            # Create an empty context as the default base context.
            self._base_context = Context()
Exemplo n.º 14
0
    async def test_generate_value(self, thread, context_attr):
        container = ResourceContainer(lambda ctx: 'foo', (str,), 'default', context_attr, True)
        context = Context()
        if thread:
            value = await context.call_in_executor(container.generate_value, context)
        else:
            value = container.generate_value(context)

        assert value == 'foo'
        assert context.get_resource(str) == 'foo'
        if context_attr:
            assert getattr(context, context_attr) == 'foo'
Exemplo n.º 15
0
    async def start(self, ctx: Context):
        # Remove the db file if it exists
        db_path = self.csv_path.with_name('people.db')
        if db_path.exists():
            db_path.unlink()

        self.add_component('sqlalchemy', url='sqlite:///{}'.format(db_path))
        await super().start(ctx)

        # Create the table in a subcontext – never use connections or sessions from a long lived
        # context!
        async with Context(ctx):
            Base.metadata.create_all(ctx.sql.bind)
async def test_create_remove_document():
    """Test the client against a real MongoDB server."""
    async with Context() as context:
        await MongoDBComponent(host=MONGODB_HOSTNAME).start(context)
        collection = context.mongo['testdb']['testcollection']
        document = {'somekey': 'somevalue'}
        document2 = {'otherkey': 7}
        try:
            await collection.insert(document)
            await collection.insert(document2)
            documents = await collection.find().to_list(None)
            assert documents == [document, document2]
        finally:
            await context.mongo.drop_database('testdb')
async def test_default_connection(caplog):
    """Test that the default connection is started and is available on the context."""
    async with Context() as context:
        await MemcachedComponent().start(context)
        assert isinstance(context.memcached, Client)

    records = [
        record for record in caplog.records
        if record.name == 'asphalt.memcached.component'
    ]
    records.sort(key=lambda r: r.message)
    assert len(records) == 2
    assert records[
        0].message == "Configured Memcached client (default / ctx.memcached)"
    assert records[1].message == 'Memcached client (default) shut down'
async def test_default_client(caplog):
    """Test that the default connection is started and is available on the context."""
    async with Context() as context:
        await MongoDBComponent().start(context)
        assert isinstance(context.mongo, AsyncIOMotorClient)

    records = [
        record for record in caplog.records
        if record.name == 'asphalt.mongodb.component'
    ]
    records.sort(key=lambda r: r.message)
    assert len(records) == 2
    assert records[0].message == (
        "Configured MongoDB client (default / ctx.mongo; "
        "hosts={'localhost:27017'})")
    assert records[1].message == 'MongoDB client (default) shut down'
async def test_default_client(caplog):
    """Test that the default client configuration works as expected."""
    async with Context() as context:
        await InfluxDBComponent().start(context)
        assert isinstance(context.influxdb, InfluxDBClient)

    records = [
        record for record in caplog.records
        if record.name == 'asphalt.influxdb.component'
    ]
    records.sort(key=lambda r: r.message)
    assert len(records) == 2
    assert records[0].message == (
        "Configured InfluxDB client (default / ctx.influxdb; "
        "base_urls=['http://localhost:8086'])")
    assert records[1].message == 'InfluxDB client (default) shut down'
Exemplo n.º 20
0
    async def test_function(self, expected_exc):
        @context_teardown
        async def start(ctx: Context):
            nonlocal phase, received_exception
            phase = 'started'
            exc = await yield_()
            phase = 'finished'
            received_exception = exc

        phase = received_exception = None
        context = Context()
        await start(context)
        assert phase == 'started'

        await context.close(expected_exc)
        assert phase == 'finished'
        assert received_exception == expected_exc
Exemplo n.º 21
0
    async def test_method(self, expected_exc):
        class SomeComponent:
            @context_teardown
            async def start(self, ctx: Context):
                nonlocal phase, received_exception
                phase = 'started'
                exc = await yield_()
                phase = 'finished'
                received_exception = exc

        phase = received_exception = None
        context = Context()
        await SomeComponent().start(context)
        assert phase == 'started'

        await context.close(expected_exc)
        assert phase == 'finished'
        assert received_exception == expected_exc
async def test_clustered_client(caplog):
    """Test that a clustered client configuration works as expected."""
    async with Context() as context:
        base_urls = [
            'http://influx1.example.org:8086',
            'http://influx2.example.org:8087/prefix'
        ]
        await InfluxDBComponent(base_urls=base_urls).start(context)
        assert isinstance(context.influxdb, InfluxDBClient)

    records = [
        record for record in caplog.records
        if record.name == 'asphalt.influxdb.component'
    ]
    records.sort(key=lambda r: r.message)
    assert len(records) == 2
    assert records[0].message == (
        "Configured InfluxDB client (default / ctx.influxdb; "
        "base_urls=['http://influx1.example.org:8086', 'http://influx2.example.org:8087/prefix'])"
    )
    assert records[1].message == 'InfluxDB client (default) shut down'
Exemplo n.º 23
0
    async def start(self,
                    ip="0.0.0.0",
                    port=4444,
                    component=None):  # pragma: no cover
        """
        Run the Kyoukai component asynchronously.

        This bypasses Asphalt's runner completely and starts Kyoukai as it's own context.

        :param ip: The IP address to bind to.
        :param port: The port to bind to.
        :param component: The component to set on the application.
            If this is not passed in, it will create an empty one.
        """
        self.logger.warning(
            "Kyoukai is bypassing Asphalt - contexts will not work.")
        ctx = Context()
        if not component:
            from kyoukai.asphalt import KyoukaiComponent
            self.component = KyoukaiComponent(self, ip, port)
        await self.component.start(ctx)
Exemplo n.º 24
0
    def from_asphalt_config(cls, filename: str) -> 'GunicornAdapter':
        """
        Creates a new :class:`GunicornAdapter` from an Asphalt component config file.
        """
        from ruamel import yaml
        with open(filename):
            config_data = yaml.load(filename)

        # Instantiate the root component
        try:
            component_config = config_data.pop('component')
        except KeyError:
            raise LookupError('missing configuration key: component') from None
        else:
            component = component_types.create_object(
                **component_config)  # type: ContainerComponent

        # Create a new Context.
        context = Context()

        # Run `start()` on the app.
        loop = asyncio.get_event_loop()
        # You best hope this doesn't block.
        loop.run_until_complete(component.start(context))

        # Find the KyoukaiComponent.
        for c in component.child_components:
            if isinstance(c, KyoukaiBaseComponent):
                break
        else:
            raise TypeError(
                "Could not find KyoukaiComponent in component list")

        del component

        # Create a new adapter.
        klass = cls(c.app, context)
        return klass
Exemplo n.º 25
0
 def test_getattr_attribute_error(self, context):
     child_context = Context(context)
     pytest.raises(AttributeError, getattr, child_context, 'foo').\
         match('no such context variable: foo')
Exemplo n.º 26
0
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)

        self._testing_protocol = TestProtocol(self, Context())

        self._responses = asyncio.Queue()
Exemplo n.º 27
0
def context(event_loop):
    ctx = Context()
    yield ctx
    event_loop.run_until_complete(ctx.close())
Exemplo n.º 28
0
 def test_parent(self):
     """Test that the parent property points to the parent context instance, if any."""
     parent = Context()
     child = Context(parent)
     assert parent.parent is None
     assert child.parent is parent
Exemplo n.º 29
0
def context(event_loop):
    ctx = Context()
    yield ctx
    event_loop.run_until_complete(
        ctx.finished.dispatch(None, return_future=True))
Exemplo n.º 30
0
def context(event_loop):
    return Context()