New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More
Socket
Sign inDemoInstall
Socket

touchstone

Package Overview
Dependencies
Maintainers
1
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

touchstone

IoC framework driven by annotations and type hints

  • 2.0.3
  • PyPI
  • Socket score

Maintainers
1

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'])


FAQs


Did you know?

Socket

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Install

Related posts

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc