Skip to content

Commit

Permalink
Simplified the API and added the documentation for Decorator API and …
Browse files Browse the repository at this point in the history
…the standalone mode
  • Loading branch information
shiroyuki committed Jun 11, 2020
1 parent 2fde007 commit e18707f
Show file tree
Hide file tree
Showing 5 changed files with 98 additions and 14 deletions.
95 changes: 84 additions & 11 deletions docs/source/getting-started/10-standalone_mode.rst
Original file line number Diff line number Diff line change
@@ -1,14 +1,7 @@
Standalone Mode
###############
Standalone Mode and Component Decorators
########################################

.. versionadded:: Imagination 3.0.0a1
This is a testing feature which is designed to be used with the coming
companion feature to `allow service declarations with decorators <https://github.com/shiroyuki/Imagination/issues/33>`_.

Please note that a testing feature is relative stable but may not be suitable
for production use.

This is made to allow developers to quickly use the Imagination container with
The standalone mode is designed to allow developers to quickly use the Imagination container with
any programming frameworks.

To use this, instead of using :class:`imagination.assembler.core.Assembler` in
Expand All @@ -26,5 +19,85 @@ configuration files from the configuration file from (this the listed order):
* Wherever you define in the system environment variable ``IMAGINATION_CONF_FILEPATH``
* ``imagination.xml`` (from the current working directory)
* ``services.xml`` (from the current working directory)
* service decorators (see the next section)

.. note::
You can also load more configuration files later by calling :method:`imagination.standalone.load_config_file`.

Decorator API
*************

With the feedback from the community, in version 3.3, you can use decorators to configure services without the need to
learn how to write XML. This feature is now generally available for testing based on `the rolling feature ticket <https://github.com/shiroyuki/Imagination/issues/33>`_.

.. note:: It currently only supports entity-type service declarations.

How to use the API
==================

The decorator API will use a different set of terminologies, but similar to Angular's.

The decorator ``imagination.decorator.Component`` is to declare an entity-type service where the constructor's arguments
(AKA parameters) can be defined with the following object of these classes.

* ``imagination.decorator.Primitive`` is a primitive-type argument.
* It is equivalent to ``<param/>`` for primitive-type arguments but without ``type`` attribute as the type is inferred from the value.
* ``imagination.decorator.Injectable`` is an injectable argument for components.
* If you have an argument with type hint to a class, which is declared as a component, you can leave this blank as the container will automatically figure out which component to use by type hint.
* ``imagination.decorator.EnvironmentVariable`` is an argument whose value is derived from an environment variable.


Example
=======

Suppose we have ``Service1`` with no parameters.

.. code-block:: python
from imagination.decorator import Component
@Component()
class Service1:
...
Instead of registering in an XML file, we now can use ``@service.registered()`` to declare this as a (singleton) service.

Let's say we also have ``Service2`` that requires ``Service1``.

.. code-block:: python
from imagination.decorator import Component, Primitive, Injectable
from app.service import Service1
@Component([
Primitive('Panda'),
Injectable(Service1),
])
class Service2:
def __init__(self, name: str, s1: Service1):
...
But this is still mouthful to declare a service. You can simplify this by leaving ``Injectable`` alone.

.. code-block:: python
from imagination.decorator import Component, Primitive
from app.service.s1 import Service1
@Component([Primitive('Panda')])
class Service2:
def __init__(self, name: str, s1: Service1):
...
To call components, you can simply use ``imagination.standalone.container``.

.. code-block:: python
from imagination.standalone import container
from app.service.s1 import Service1
from app.service.s2 import Service2
You can also load more configuration files later by calling :method:`imagination.standalone.load_config_file`.
s1 : Service1 = container.get(Service1) # --> Service1
s2 : Service2 = container.get(Service2) # --> Service2
2 changes: 2 additions & 0 deletions imagination/decorator/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
from .config import EnvironmentVariable, Parameter as Primitive, Service as Injectable
from .service import registered as Component
11 changes: 9 additions & 2 deletions imagination/decorator/service.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,14 @@
from .helper import set_parameter


def registered(id: Optional[str] = None, params: Optional[List[Any]] = None, is_primary: Optional[bool] = False,
def registered(params: Optional[List[Any]] = None, id: Optional[str] = None, is_primary: Optional[bool] = False,
auto_wired: Optional[bool] = True, wiring_optional: Optional[bool] = False,
id_naming_strategy: Optional[Callable] = None):
"""
Define the class as a service.
:param str id: Service ID. By default, it will turn the FQCN (module + class name) into the default service ID.
:param list params: Parameters for the class constructor.
:param str id: Service ID. By default, it will turn the FQCN (module + class name) into the default service ID.
:param bool is_primary: Flag to determine whether or not this is the primary service of this type
:param bool auto_wired: Flag to tell Imagination to automatically wire all required dependencies without explicitly
specifying them in :param:`params`.
Expand Down Expand Up @@ -47,6 +47,13 @@ def inner_decorator(cls):
return inner_decorator


Service = registered
""" Service
.. versionadded:: 3.3
"""


def __define_defintion(definition, params):
for param in (params or []):
set_parameter(definition, param)
2 changes: 2 additions & 0 deletions requirements.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
kotoba
sphinx
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

setup(
name = 'imagination',
version = '3.2.0',
version = '3.3.0',
description = 'Reusable Component Framework',
author = 'Juti Noppornpitak',
author_email = 'juti_n@yahoo.co.jp',
Expand Down

0 comments on commit e18707f

Please sign in to comment.