Ejemplo n.º 1
0
    async def test_listens_for_related_deletes(self):
        # the model connecting the two
        connection_model = self.model()
        setattr(connection_model, model_service_name(self.service1), 1)
        setattr(connection_model, model_service_name(self.service2), 1)
        connection_model.save()

        # make sure the connection model can be found
        assert self.model.get(self.service1_value == 1), (
            "Test record could not be created before deleting."
        )

        # the action data for a related delete
        action_type = conventions.get_crud_action(
            'delete',
            self.service1,
            status='success'
        )
        payload = dict(id=1)

        # instantiate an action handler to test
        handler = self.service.action_handler()
        # fire the action
        await handler.handle_action(
            action_type=action_type,
            payload=payload,
            props={},
            notify=False
        )

        # make sure the model can't be found
        self.assertRaises(Exception, self.model.get, self.service1_value == 1)
Ejemplo n.º 2
0
    def test_connection_model(self):
        # the fields of the underlying service model
        model_fields = {field.name for field in self.service.model.fields()}

        # the target field names
        target_fields = {
            'id',
            model_service_name(self.service1),
            model_service_name(self.service2)
        }
        # for each model managed by this service
        assert model_fields == target_fields, (
            "Connection model did not have the correct fields"
        )
Ejemplo n.º 3
0
    def setUp(self):
        # point the database to a in-memory sqlite database
        nautilus.database.init_db('sqlite:///test.db')

        # create a spy we can check for later
        self.spy = Mock()

        # save the names of the connected services to the suite
        self.service1 = 'TestService1'
        self.service2 = 'TestService2'

        class TestConnectionService(nautilus.ConnectionService):
            from_service = (self.service1,)
            to_service = (self.service2,)

        self.services = [self.service1, self.service2]

        self.service = TestConnectionService()
        self.model = self.service.model

        # create the test table
        self.model.create_table(True)

        # save the attribute we'll use to test against
        self.service1_value = getattr(self.model, model_service_name(self.service1))
Ejemplo n.º 4
0
    def __init__(self, model=None, **kwargs):
        # avoid circular depdencies
        from ..api.util import create_model_schema

        # if we were given a model for the service
        if model:
            # use the given model
            self.model = model

        # if there is no model associated with this service
        if not self.model:
            # yell loudly
            raise ValueError("Please provide a model for the model service.")

        # pull the name of the service from kwargs if it was given
        name = kwargs.pop('name', None) or model_service_name(self.model)

        # create the service
        super().__init__(
            schema=create_model_schema(self.model),
            name=name,
            **kwargs
        )
        # initialize the database
        self.init_db()
Ejemplo n.º 5
0
    def __init__(self, model, additonal_action_handler = noop_handler, **kwargs):
        # save a reference to the model this service is managing
        self.model = model

        # the schema to add to the service
        schema = create_model_schema(model)

        # the action handler is a combination
        action_handler = combine_action_handlers(
            # of the given one
            additonal_action_handler,
            # and a crud handler
            CRUDHandler(model)
        )

        # pull the name of the service from kwargs if it was given
        name = kwargs.pop('name', None) or model_service_name(model)

        # create the service
        super().__init__(
            schema=schema,
            action_handler=action_handler,
            name=name,
            **kwargs
        )
Ejemplo n.º 6
0
 def summarize(self, **extra_fields):
     # start with the default summary
     try:
         return {
             **super().summarize(), 'connection': {
                 'from': {
                     'service': model_service_name(self.from_service[0]),
                 },
                 'to': {
                     'service': model_service_name(self.to_service[0]),
                 }
             },
             **extra_fields
         }
     except Exception as e:
         print(e)
Ejemplo n.º 7
0
 def summarize(self, **extra_fields):
     # start with the default summary
     try:
         return {
             **super().summarize(),
             'connection': {
                 'from': {
                     'service': model_service_name(self.from_service[0]),
                 },
                 'to': {
                     'service': model_service_name(self.to_service[0]),
                 }
             },
             **extra_fields
         }
     except Exception as e:
         print(e)
Ejemplo n.º 8
0
 async def _verify_action_handler_create(self):
     action_type = conventions.get_crud_action('create', self.service.model)
     payload = {
         model_service_name(self.service1): 'foo',
         model_service_name(self.service2): 'bar'
     }
     # create an instance of the action handler
     handler = self.service.action_handler()
     # fire a create action
     await handler.handle_action(
         action_type=action_type,
         payload=payload,
         props={},
         notify=False
     )
     # the query to find a matching model
     matching_model = self.service1_value == 'foo'
     # make sure the created record was found and save the id
     self.model_id = self.model_id = self.model.get(matching_model).id
Ejemplo n.º 9
0
 def test_model_service_name(self):
     # a model to test with
     class TestModel(nautilus.models.BaseModel):
         name = nautilus.models.fields.CharField()
     TestModel = MockModel()
     # generate a service from the model
     class TestService(nautilus.ModelService):
         model = TestModel
     # make sure we could generate a name for it
     assert isinstance(conventions.model_service_name(TestService), str), (
         "Could not generate name for model service"
     )
Ejemplo n.º 10
0
def create_connection_model(service):
    """ Create an SQL Alchemy table that connects the provides services """
    # the services connected
    services = service._services

    # the mixins / base for the model
    bases = (BaseModel,)
    # the fields of the derived
    attributes = {model_service_name(service): fields.CharField() for service in services}

    # create an instance of base model with the right attributes
    return type(BaseModel)(connection_service_name(service), bases, attributes)
Ejemplo n.º 11
0
 async def _verify_action_handler_update(self):
     payload = {'id':self.model_id, model_service_name(self.service1): 'bars'}
     # create an instance of the action handler
     handler = self.service.action_handler()
     # call the service action handler
     await handler.handle_action(
         action_type=conventions.get_crud_action('update', self.model),
         props={},
         payload=payload,
         notify=False
     )
     # check that a model matches
     self.model.get(self.service1_value == 'bars')
Ejemplo n.º 12
0
    def test_model_service_name(self):
        # a model to test with
        class TestModel(nautilus.models.BaseModel):
            name = nautilus.models.fields.CharField()

        TestModel = MockModel()

        # generate a service from the model
        class TestService(nautilus.ModelService):
            model = TestModel

        # make sure we could generate a name for it
        assert isinstance(conventions.model_service_name(TestService),
                          str), ("Could not generate name for model service")
Ejemplo n.º 13
0
    def test_can_create_connection_model(self):
        import nautilus

        # models to test
        Model1 = model_service_name('Model1')
        Model2 = model_service_name('Model2')

        class TestConnectionService(nautilus.ConnectionService):
            to_service = (Model1, )
            from_service = (Model2, )

        # create the connection model
        connection_model = nautilus.models.create_connection_model(
            TestConnectionService())

        assert issubclass(connection_model, models.BaseModel), (
            "Generated connection model is not an instance of BaseModel")

        # grab the name of the fields
        connect_fields = {field.name for field in connection_model.fields()}

        assert connect_fields == {
            Model1, Model2, 'id'
        }, ("Connection model did not have the correct fields.")
Ejemplo n.º 14
0
    def test_model_service_name_accepts_numbers(self):
        # a model to test with
        class TestModel(nautilus.models.BaseModel):
            name = nautilus.models.fields.CharField()

        # generate a service from the model
        class TestService1(nautilus.ModelService):
            model = TestModel

        # figure out the conventional name for the service
        service_name = conventions.model_service_name(TestService1)

        # make sure we could generate a name for it
        assert (isinstance(service_name, str) and '1' in service_name), (
            "Could not generate name for model service when it has a number.")
Ejemplo n.º 15
0
    def test_can_create_connection_model(self):
        import nautilus

        # models to test
        Model1 = model_service_name('Model1')
        Model2 = model_service_name('Model2')

        class TestConnectionService(nautilus.ConnectionService):
            to_service = (Model1,)
            from_service = (Model2,)

        # create the connection model
        connection_model = nautilus.models.create_connection_model(TestConnectionService())

        assert issubclass(connection_model, models.BaseModel), (
            "Generated connection model is not an instance of BaseModel"
        )

        # grab the name of the fields
        connect_fields = {field.name for field in connection_model.fields()}

        assert connect_fields == {Model1, Model2, 'id'}, (
            "Connection model did not have the correct fields."
        )
Ejemplo n.º 16
0
    def test_model_service_name_accepts_numbers(self):
        # a model to test with
        class TestModel(nautilus.models.BaseModel):
            name = nautilus.models.fields.CharField()
        # generate a service from the model
        class TestService1(nautilus.ModelService):
            model = TestModel

        # figure out the conventional name for the service
        service_name = conventions.model_service_name(TestService1)

        # make sure we could generate a name for it
        assert (
            isinstance(service_name, str) and
            '1' in service_name
        ), (
            "Could not generate name for model service when it has a number."
        )
Ejemplo n.º 17
0
        async def action_handler(action_type, payload, notify=True, **kwds):
            """
                an action handler to remove related entries in the
                connection db.
            """
            # if the action designates a successful delete of the model
            if action_type == related_action_type:
                # the id of the deleted model
                related_id = payload['id']
                # the query for matching fields
                matching_records = getattr(self.model, model_service_name(model)) == related_id
                ids = [model.id for model in self.model.filter(matching_records)]
                # find the matching records
                self.model.delete().where(matching_records).execute()

                # if we are supposed to notify
                if notify:
                    # notify of the related delete
                    await self.event_broker.send(
                        action_type=get_crud_action('delete', self.model, status=success_status()),
                        payload=ids
                    )
Ejemplo n.º 18
0
    def test_has_valid_schema(self):
        assert hasattr(self.service, 'schema') and self.service.schema, (
            "Model Service did not have a schema."
        )
        # the field to query
        field_name = service_conventions.model_service_name(self.service1)
        # the query to test the schema
        query = """
            query {
                all_models {
                    %s
                }
            }
        """ % field_name

        parsed_query = self.service.schema.execute(query)
        # make sure there are no errors
        assert parsed_query.errors == [], (
            "Model service schema is invalid: " + str(parsed_query.errors)
        )
        assert len(parsed_query.data) > 0, (
            "Model could not be retrieved with schema."
        )
Ejemplo n.º 19
0
        async def action_handler(action_type, payload, notify=True, **kwds):
            """
                an action handler to remove related entries in the
                connection db.
            """
            # if the action designates a successful delete of the model
            if action_type == related_action_type:
                # the id of the deleted model
                related_id = payload['id']
                # the query for matching fields
                matching_records = getattr(
                    self.model, model_service_name(model)) == related_id
                ids = [
                    model.id for model in self.model.filter(matching_records)
                ]
                # find the matching records
                self.model.delete().where(matching_records).execute()

                # if we are supposed to notify
                if notify:
                    # notify of the related delete
                    await self.event_broker.send(action_type=get_crud_action(
                        'delete', self.model, status=success_status()),
                                                 payload=ids)
Ejemplo n.º 20
0
 def __new__(cls, *args, **kwds):
     # make sure the service has the right name
     cls.name = model_service_name(cls.model) if cls.model else ''
     # bubble up
     return super().__new__(cls, *args)
Ejemplo n.º 21
0
 def test_has_conventional_name(self):
     assert self.service_record.name == \
                 service_conventions.model_service_name(self.model), (
         "Model service did not have the correct name."
     )