Extension — IoC 0.0.4 documentation

### Navigation

- index
- next |
- previous |
- IoC 0.0.4 documentation »

# Extension

An extension is a class used to configure services. A vendor might want to expose a configuration file to automatically generated valid services.

Here a flask extension, `ioc.extra.flask.di.Extension`

    import ioc.loader, ioc.component
    import os

    class Extension(ioc.component.Extension):
        def load(self, config, container_builder):

            path = os.path.dirname(os.path.abspath(__file__))

            # load an external file defining services
            loader = ioc.loader.YamlLoader()
            loader.load("%s/resources/config/flask.yml" % path, container_builder)

            # set default parameters into the container to be reuse by the container builder
            # or by external services
            container_builder.parameters.set('ioc.extra.flask.app.name', config.get('name', ''))
            container_builder.parameters.set('ioc.extra.flask.app.static_path', config.get('static_path', ''))
            container_builder.parameters.set('ioc.extra.flask.app.static_url_path', config.get('static_url_path', 'static'))
            container_builder.parameters.set('ioc.extra.flask.app.instance_path', config.get('instance_path', 'templates'))
            container_builder.parameters.set('ioc.extra.flask.app.template_folder', config.get('template_folder', ''))
            container_builder.parameters.set('ioc.extra.flask.app.instance_relative_config', config.get('instance_relative_config', False))
            container_builder.parameters.set('ioc.extra.flask.app.port', config.get('port', 8080))

## How to use an extensions

An extension is declared in the top yaml file by using its module name (`di.Extension` is added by the `ioc`), so in order to generate a flask instance just do:

    ioc.extra.flask:
        port:               8080
        name:               ''
        static_path:        ''
        static_url_path:    ''
        static_folder:      'static'
        template_folder:    'templates'
        instance_path:      ''
        instance_relative_config: false

and to use it:

    import ioc

    container = ioc.build(['config.yml'])

    app = container.get('ioc.extra.flask.app')

    __name__ == ’__main__’:
        app.run()

## Going further

The previous example is a bit overkill as Flask itself required a minimun amount of code to run. However the previous code allows to configure the default port which can be usefull for running different configurations.

Now, the `ioc.extra.flask.app` is available inside the container, so other services can use it.

The `shirka` project exposes some `flask` actions as service:

    shirka.flask.view.shirka_proc_list:
        class: [shirka.control.proc, ProcListView.as_view]
        arguments:
            - shirka_proc_list
            - "%shirka.data.dir%/proc"

    shirka.flask.view.shirka_proc_view:
        class: [shirka.control.proc, ProcView.as_view]
        arguments:
            - shirka_proc_view
            - "%shirka.data.dir%/proc"

So there are 2 actions as a service defined here : `shirka.flask.view.shirka_proc_view` and `shirka.flask.view.shirka_proc_list`. As you can note, we are injected custom parameters into each service, these parameters can be configured by the user in an external file.

The `shirka` project also provide a custom extension `shirka.di.Extension`, this extension will register theses services as methods call to the `ioc.extra.flask` service.

    import ioc
    import os

    class Extension(ioc.component.Extension):

        def pre_build(self, container_builder, container):

            # if the service does not exist, then avoid registering services
            if not container_builder.has('ioc.extra.flask.app'):
                return

            definition = container_builder.get('ioc.extra.flask.app')

            base_url = container_builder.parameters.get('shirka.web.api.base_url')
            definition.method_calls.append([
                'add_url_rule',
                ['%s/process' % base_url],
                {'view_func': ioc.component.Reference('shirka.flask.view.shirka_proc_list')}
            ])

            definition.method_calls.append([
                'add_url_rule',
                ['%s/process/<id>' % base_url],
                {'view_func': ioc.component.Reference('shirka.flask.view.shirka_proc_view')}
            ])

The `pre_build` method is called after all extensions are loaded, this allow extensions to alter service definitions.

shirka configuration defined inside the `config.yml` file:

    shirka:
        # public_dir:
        api:
            base_url: '/shirka/api'
        data_dir: '%base_dir%/data'

So through some configuration, the user can configure how the Flask action will be expose `/shirka/api`.

### Navigation

- index
- next |
- previous |
- IoC 0.0.4 documentation »