Metadata-Version: 2.1
Name: touchstone
Version: 2.0.1
Summary: IoC framework driven by annotations and type hints
Home-page: https://github.com/gmaybrun/touchstone
Maintainer: gmaybrun@gmail.com
Maintainer-email: gmaybrun@gmail.com
License: UNKNOWN
Description: Touchstone
        ==========
        
        .. contents::
           :depth: 2
           :backlinks: none
        
        What is Touchstone?
        -------------------
        
        Touchstone is an annotations-driven Inversion of Control container for
        Python 3.6 and above.
        
        Links:
        
        * `GitHub <https://github.com/gmaybrun/touchstone>`__
        
        
        Learn by Example
        ----------------
        
        Auto Wiring
        ~~~~~~~~~~~
        
        .. code:: python
        
            from touchstone import Container
        
            class Child:
                pass
        
            class Parent:
                def __init__(self, child: Child) -> None:
                    self.child = child
        
        
            container = Container()
            parent = container.make(Parent)
        
            assert isinstance(parent.child, Child)
        
        Interface Binding
        ~~~~~~~~~~~~~~~~~
        
        .. code:: python
        
            from touchstone import Container
        
            class AbstractChild:
                pass
        
            class Child(AbstractChild):
                pass
        
            class Parent:
                def __init__(self, child: AbstractChild) -> None:
                    self.child = child
        
        
            container = Container()
            container.bind(AbstractChild, Child)
            parent = container.make(Parent)
        
            assert isinstance(parent.child, Child)
        
        Binding with Factory Methods
        ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
        
        .. code:: python
        
            from touchstone import Container
        
            class Child:
                def __init__(self, name: str) -> None:
                    self.name = name
        
            class Parent:
                def __init__(self, child: Child) -> None:
                    self.child = child
        
        
            container = Container()
            container.bind(Child, lambda: Child('them'))
            parent = container.make(Parent)
        
            assert isinstance(parent.child, Child)
            assert parent.child.name == 'them'
        
        Binding Singletons
        ~~~~~~~~~~~~~~~~~~
        
        .. code:: python
        
            from touchstone import Container, SINGLETON
        
            class Child:
                def __init__(self, name: str) -> None:
                    self.name = name
        
            class Parent:
                def __init__(self, child: Child) -> None:
                    self.child = child
        
        
            container = Container()
            them_child = Child('them')
            container.bind_instance(Child, them_child)
            # Or...
            container.bind(Child, lambda: them_child, lifetime_strategy=SINGLETON)
            parent = container.make(Parent)
        
            assert isinstance(parent.child, Child)
            assert parent.child is them_child
        
        Contextual Binding
        ~~~~~~~~~~~~~~~~~~
        
        .. code:: python
        
            from touchstone import Container
        
            class Child:
                def __init__(self, name: str) -> None:
                    self.name = name
        
            class Parent:
                def __init__(self, child1: Child, child2: Child) -> None:
                    self.child1 = child1
                    self.child2 = child2
        
        
            container = Container()
            container.bind_contextual(when=Parent, wants=Child, wants_name='child1', give=lambda: Child('her'))
            container.bind_contextual(when=Parent, wants=Child, wants_name='child2', give=lambda: Child('him'))
            parent = container.make(Parent)
        
            assert isinstance(parent.child1, Child)
            assert isinstance(parent.child2, Child)
            assert parent.child1.name == 'her'
            assert parent.child2.name == 'him'
        
        Django Support
        --------------
        
        Now featuring Django support! New in v0.3.0
        
        * Configure your instance of ``touchstone.Container`` however you see fit.
        * In your main ``settings.py``, set ``TOUCHSTONE_CONTAINER_GETTER`` to
          the path to a callable that will return the singleton instance of
          ``touchstone.Container`` your app uses.
        
          * Note that your ``getter`` should build the ``Container`` precisely once, and
            then return that same ``Container`` on all subsequent calls. Build it as a
            singleton.
        
        To get injected properties in your class-based views:
        
        * In your main ``settings.py``, add ``touchstone.django.InjectViewsMiddleware``
          to your ``MIDDLEWARE`` list.
        * Use class annotations on your class-based views. Cached Properties will be
          added to your view classes so that they automatically resolve using your
          configured touchstone container. For example:
        
        .. code:: python
        
            class MyView(View):
                something: MyObject
                def get(self, request):
                    # You can now access self.something!
        
        To get injected properties in your middleware, you'll need to do a
        little more work because we haven't found a good way to hook into
        Django's middleware instantiation logic.
        
        .. code:: python
        
            from touchstone.django import inject_magic_properties
        
            @inject_magic_properties
            class MyMixin:
                something: MyObject
                # define your mixin here...
                # You'll be able to use `self.something` from within every instance method.
        
        Celery Tasks
        ~~~~~~~~~~~~
        
        Celery tasks called can be applied to any callable with a decorator. For example:
        
        .. code:: python
        
            class MyLogger:
                def __init__(self, another_logger: AnotherLogger):
                    self.another_logger = another_logger
        
                def log(self, msg):
                    print(msg)
                    self.another_logger.log(msg)
        
            @app.task
            def log_messages(msg):
                another_logger = AnotherLogger()
                my_logger = MyLogger(another_logger)
        
                my_logger.log(msg)
        
            log_messages.apply_async(args=['hello world'])
        
        However, if we want to refactor this code to make use of touchstone as a service locator:
        
        .. code:: python
        
            class MyLogger:
                def __init__(self, another_logger: AnotherLogger):
                    self.another_logger = another_logger
        
                def log(self, msg):
                    print(msg)
                    self.another_logger.log(msg)
        
            @app.task
            def log_messages(msg):
                container = get_container()
                my_logger = container.make(MyLogger)
        
                my_logger.log(msg)
        
            log_messages.apply_async(args=['hello world'])
        
        Each task would then have quite a bit of repeated code to create the container for each task and then
        make class instance we need.
        
        .. code:: python
        
            class MyLogger:
                def __init__(self, another_logger: AnotherLogger):
                    self.another_logger = another_logger
        
                def log(self, msg):
                    print(msg)
                    self.another_logger.log(msg)
        
            @touchstone_task
            class LogMessagesTask:
                my_logger: MyLogger
        
                def run(self, msg):
                    self.my_logger.log(msg)
        
            LogMessagesTask.apply_async(args=['hello world'])
        
Platform: UNKNOWN
Classifier: Development Status :: 5 - Production/Stable
Classifier: Intended Audience :: Developers
Classifier: Natural Language :: English
Classifier: Operating System :: OS Independent
Classifier: License :: OSI Approved :: GNU General Public License v3 (GPLv3)
Classifier: Programming Language :: Python :: 3.6
Classifier: Programming Language :: Python :: 3.7
Classifier: Programming Language :: Python :: 3.8
Classifier: Topic :: Software Development :: Libraries :: Application Frameworks
Classifier: Topic :: Software Development :: Object Brokering
Classifier: Topic :: Utilities
Classifier: Typing :: Typed
Provides-Extra: dist
Provides-Extra: tests
Provides-Extra: django
Provides-Extra: djangorestframework
Provides-Extra: django_celery
