Skip to content
This repository has been archived by the owner on Feb 21, 2020. It is now read-only.

Injector.alias() #13

Open
groner opened this issue Sep 24, 2015 · 2 comments
Open

Injector.alias() #13

groner opened this issue Sep 24, 2015 · 2 comments

Comments

@groner
Copy link
Collaborator

groner commented Sep 24, 2015

Instead of writing:

@Injector.factory('send_mail')
def send_mail_factory(send_mail: annotate.partial(send_mail)):
    return send_mail

What if you could just write:

Injector.alias('send_mail', annotate.partial(send_mail))

Another possible use:

# In a web application
Injector.alias('user', 'session:user')
# In tests
Injector.alias('user', 'fixture:user')
@groner
Copy link
Collaborator Author

groner commented Jan 11, 2016

Here is a quick implementation of Injector.alias().

import functools

from jeni import Injector, Provider, FactoryProvider, annotate


class AliasProvider(Provider):
    @classmethod
    def bind(cls, note):
        basenote, name = note
        if name is not None:
            @annotate
            def alias(v: note):
                return FactoryProvider(lambda: v)
            return alias
        return lambda: cls(basenote)

    def __init__(self, basenote):
        self.basenote = basenote

    @annotate
    def get(self, *, name=None, injector: 'injector'):
        return injector.get((self.basenote, name))


class AliasingInjector(Injector):
    alias_provider = AliasProvider

    def __init__(self, provide_self=True):
        if provide_self is not True:
            raise ValueError('provide_self can only be True')
        # Work around #14.
        #super().__init__(True)
        super().__init__(False)
        self.values['injector'] = self

    @classmethod
    def alias(cls, note, other_note=None, *, partial=None):
        if other_note is None:
            return functools.partial(cls.alias, note, partial=partial)

        if partial:
            other_note = annotate.partial(other_note)
        else:
            other_note = cls.parse_note(other_note)
        provider = cls.alias_provider.bind(other_note)
        cls.register(note, provider)


if __name__ == "__main__":
    import unittest

    class TestAliasingInjector(unittest.TestCase):
        def setUp(self):
            class TestInjector(AliasingInjector): pass
            self.TestInjector = TestInjector

            @TestInjector.provider('named', name=True)
            def named_provider():
                name = None
                while True:
                    if name is None:
                        name = yield 'named'
                    else:
                        name = yield 'named[{}]'.format(name)

        def test_alias_basenote(self):
            self.TestInjector.alias('borrower', 'named')

            with self.TestInjector() as inj:
                self.assertEqual(inj.get('borrower'), 'named')
                self.assertEqual(inj.get('borrower:bar'), 'named[bar]')

        def test_alias_namednote(self):
            self.TestInjector.alias('borrower', 'named:foo')

            with self.TestInjector() as inj:
                self.assertEqual(inj.get('borrower'), 'named[foo]')
                with self.assertRaises(TypeError):
                    inj.get('borrower:bar')

        def test_alias_partial(self):
            class QuuxificationError(Exception): pass

            @self.TestInjector.alias('quuxify', partial=True)
            @annotate
            def quuxify(x: 'named:x'):
                raise QuuxificationError()

            with self.TestInjector() as inj:
                with self.assertRaises(QuuxificationError):
                    inj.get('quuxify')()

    unittest.main()

@groner
Copy link
Collaborator Author

groner commented Jan 20, 2016

I just realized that this makes it easier to register annotated functions than plain functions. If Injector.value(note) worked as a decorator, that would fix it.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant