From bc39251426a50e6d362b83b863c9b8bd5de74340 Mon Sep 17 00:00:00 2001 From: Roman Mogilatov Date: Tue, 28 Jul 2015 01:29:31 +0300 Subject: [PATCH] Adding docs about writing custom providers --- docs/images/providers/custom_provider.png | Bin 0 -> 30351 bytes docs/providers/custom.rst | 73 ++++++++++++++++++++++ examples/providers/custom_factory.py | 38 +++++++++++ 3 files changed, 111 insertions(+) create mode 100644 docs/images/providers/custom_provider.png create mode 100644 docs/providers/custom.rst create mode 100644 examples/providers/custom_factory.py diff --git a/docs/images/providers/custom_provider.png b/docs/images/providers/custom_provider.png new file mode 100644 index 0000000000000000000000000000000000000000..a64b0b37c2a1d0f590268e03a69e4bcf29f2793d GIT binary patch literal 30351 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 J)o479_;0itU912A literal 0 HcmV?d00001 diff --git a/docs/providers/custom.rst b/docs/providers/custom.rst new file mode 100644 index 00000000..e1c43698 --- /dev/null +++ b/docs/providers/custom.rst @@ -0,0 +1,73 @@ +Writing custom providers +------------------------ + +List of *Objects* providers could be widened with custom providers. + +Below are some tips and recommendations that have to be met: + + 1. Every custom provider has to extend base provider class - + ``objects.providers.Provider``. + 2. Cusom provider's ``__init__()`` could be overriden with only condition: + parent initializer (``objects.providers.Provider.__init__()``) has + to be called. + 3. Providing strategy has to be implemented in custom provider's + ``_provide()`` method. All ``*args`` & ``**kwargs`` that will be + recieved by ``objects.providers.Provider.__call__()`` will be transefed + to custom provider's ``_provide()``. + 4. If custom provider is based on some standard providers, it is better to + use delegation of standard providers, then extending of them. + 5. If custom provider defines any attributes, it is good to list them in + ``__slots__`` attribute (as *Objects* does). It can save some memory. + 6. If custom provider deals with injections (e.g. ``Factory``, + ``Singleton`` providers), it is strongly recommended to use + ``objects.injections.Injection`` and its subclasses: + ``objects.injections.KwArg``, ``objects.injections.Attribute`` and + ``objects.injections.Method``. + +Example: + +.. image:: /images/providers/custom_provider.png + :width: 100% + :align: center + +.. code-block:: python + + """Custom `Factory` example.""" + + from objects.providers import Provider + from objects.providers import Factory + + + class User(object): + + """Example class User.""" + + + class UsersFactory(Provider): + + """Example users factory.""" + + __slots__ = ('_factory',) + + def __init__(self): + """Initializer.""" + self._factory = Factory(User) + super(UsersFactory, self).__init__() + + def _provide(self, *args, **kwargs): + """Return provided instance.""" + return self._factory(*args, **kwargs) + + + # Users factory: + users_factory = UsersFactory() + + # Creating several User objects: + user1 = users_factory() + user2 = users_factory() + + # Making some asserts: + assert isinstance(user1, User) + assert isinstance(user2, User) + assert user1 is not user2 + diff --git a/examples/providers/custom_factory.py b/examples/providers/custom_factory.py new file mode 100644 index 00000000..82dae96f --- /dev/null +++ b/examples/providers/custom_factory.py @@ -0,0 +1,38 @@ +"""Custom `Factory` example.""" + +from objects.providers import Provider +from objects.providers import Factory + + +class User(object): + + """Example class User.""" + + +class UsersFactory(Provider): + + """Example users factory.""" + + __slots__ = ('_factory',) + + def __init__(self): + """Initializer.""" + self._factory = Factory(User) + super(UsersFactory, self).__init__() + + def _provide(self, *args, **kwargs): + """Return provided instance.""" + return self._factory(*args, **kwargs) + + +# Users factory: +users_factory = UsersFactory() + +# Creating several User objects: +user1 = users_factory() +user2 = users_factory() + +# Making some asserts: +assert isinstance(user1, User) +assert isinstance(user2, User) +assert user1 is not user2