# Path: snakeguice/injector.py
# class Injector(object):
# 
#     def __init__(self, modules=None, binder=None, stage=None):
#         if modules is None:
#             modules = []
#         elif not hasattr(modules, '__iter__'):
#             modules = [modules]
# 
#         if binder:
#             self._binder = binder.create_child()
#         else:
#             self._binder = Binder()
# 
#         self._stage = stage
# 
#         self.add_modules(modules)
# 
#     def add_modules(self, modules):
#         provides_helper = ProvidesBinderHelper()
#         for module in modules:
#             ModuleAdapter(module, self).configure(self._binder)
#             provides_helper.bind_providers(module, self._binder)
# 
#     def get_provider(self, cls, annotation=None):
#         injector = self
# 
#         class DynamicProvider(object):
# 
#             def get(self):
#                 return injector.get_instance(cls, annotation)
# 
#         return DynamicProvider()
# 
#     def get_instance(self, cls, annotation=None):
#         if cls is IInjector: # TODO: i don't like this, but it works for now
#             return self
# 
#         key = Key(cls, annotation)
#         binding = self._binder.get_binding(key)
#         if binding:
#             if isinstance(binding.provider, type):
#                 binding.provider = self.get_instance(binding.provider)
#             provider = binding.scope.scope(key, binding.provider)
#             if isinstance(provider, type):
#                 provider = self.get_instance(provider)
#             return provider.get()
#         else:
#             instance = self.create_object(cls)
#             return self.inject_members(instance)
# 
#     def create_child(self, modules):
#         """Create a new injector that inherits the state from this injector.
# 
#         All bindings are inherited. In the future this may become closer to
#         child injectors on google-guice.
#         """
#         binder = self._binder.create_child()
#         return Injector(modules, binder=binder, stage=self._stage)
# 
#     def create_object(self, cls):
#         if not hasattr(cls, '__mro__'):
#             warnings.warn("can't create an instance of %r - no __mro__; "
#                          "this legacy behavior will be removed in a future "
#                           "version")
#             return cls
# 
#         guice_data = _GuiceData.composite_from_class(cls)
# 
#         if not guice_data.init:
#             instance = cls()
#         else:
#             kwargs = {}
#             for name, guicearg in guice_data.init.items():
#                 kwargs[name] = self.get_instance(guicearg.datatype,
#                                                  guicearg.annotation)
#             instance = cls(**kwargs)
# 
#         return instance
# 
#     def inject_members(self, instance):
#         # this may be a little slow; done twice
#         guice_data = _GuiceData.composite_from_class(instance.__class__)
# 
#         for name, gm in guice_data.methods.items():
#             kwargs = {}
#             for param, guicearg in gm.items():
#                 kwargs[param] = self.get_instance(guicearg.datatype,
#                                                   guicearg.annotation)
#             getattr(instance, name)(**kwargs)
#         return instance
# 
# Path: snakeguice/decorators.py
# def inject(**kwargs):
# 
#     scope = kwargs.get('scope')
#     if 'scope' in kwargs:
#         del kwargs['scope']
# 
#     def _inject(func):
#         class_locals = enclosing_frame().f_locals
# 
#         guice_data = GuiceData.from_class_dict(class_locals)
# 
#         annotations = getattr(func, '__guice_annotations__', {})
# 
#         gmethod = dict((k, GuiceArg(v, annotations.get(k)))
#                        for k, v in kwargs.items())
# 
#         _validate_func_args(func, kwargs)
#         if func.__name__ == '__init__':
#             guice_data.init = gmethod
#         else:
#             guice_data.methods[func.__name__] = gmethod
# 
#         return func
# 
#     return _inject
# 
# class annotate(object):
# 
#     def __init__(self, **kwargs):
#         self.kwargs = kwargs
# 
#     def __call__(self, method):
#         class_locals = enclosing_frame().f_locals
#         if '__guice__' in class_locals:
#             if method.__name__ in class_locals['__guice__'].methods:
#                 raise Exception('annotate must be applied before inject')
#         method.__guice_annotations__ = self.kwargs
#         return method


from snakeguice import Injector, inject, annotate


def describe_a_child_inheriting_an_injected_init():
    class Parent(object):
        @inject(value=OldData)
        def __init__(self, value):
            self.value = value

    class Child(Parent):
        pass

    instance = Injector(Module()).get_instance(Child)

    def child_should_have_value_set():
        assert isinstance(instance.value, OldData)


def describe_a_child_inheriting_an_injected_method():
    class Parent(object):
        @inject(value=Data)
        @annotate(value='old')
        def set_parent_value(self, value):
            self.parent_value = value

    class Child(Parent):
        @inject(value=Data)
        @annotate(value='new')
        def set_child_value(self, value):
            self.child_value = value


# Path: snakeguice/injector.py
# class Injector(object):
# 
#     def __init__(self, modules=None, binder=None, stage=None):
#         if modules is None:
#             modules = []
#         elif not hasattr(modules, '__iter__'):
#             modules = [modules]
# 
#         if binder:
#             self._binder = binder.create_child()
#         else:
#             self._binder = Binder()
# 
#         self._stage = stage
# 
#         self.add_modules(modules)
# 
#     def add_modules(self, modules):
#         provides_helper = ProvidesBinderHelper()
#         for module in modules:
#             ModuleAdapter(module, self).configure(self._binder)
#             provides_helper.bind_providers(module, self._binder)
# 
#     def get_provider(self, cls, annotation=None):
#         injector = self
# 
#         class DynamicProvider(object):
# 
#             def get(self):
#                 return injector.get_instance(cls, annotation)
# 
#         return DynamicProvider()
# 
#     def get_instance(self, cls, annotation=None):
#         if cls is IInjector: # TODO: i don't like this, but it works for now
#             return self
# 
#         key = Key(cls, annotation)
#         binding = self._binder.get_binding(key)
#         if binding:
#             if isinstance(binding.provider, type):
#                 binding.provider = self.get_instance(binding.provider)
#             provider = binding.scope.scope(key, binding.provider)
#             if isinstance(provider, type):
#                 provider = self.get_instance(provider)
#             return provider.get()
#         else:
#             instance = self.create_object(cls)
#             return self.inject_members(instance)
# 
#     def create_child(self, modules):
#         """Create a new injector that inherits the state from this injector.
# 
#         All bindings are inherited. In the future this may become closer to
#         child injectors on google-guice.
#         """
#         binder = self._binder.create_child()
#         return Injector(modules, binder=binder, stage=self._stage)
# 
#     def create_object(self, cls):
#         if not hasattr(cls, '__mro__'):
#             warnings.warn("can't create an instance of %r - no __mro__; "
#                          "this legacy behavior will be removed in a future "
#                           "version")
#             return cls
# 
#         guice_data = _GuiceData.composite_from_class(cls)
# 
#         if not guice_data.init:
#             instance = cls()
#         else:
#             kwargs = {}
#             for name, guicearg in guice_data.init.items():
#                 kwargs[name] = self.get_instance(guicearg.datatype,
#                                                  guicearg.annotation)
#             instance = cls(**kwargs)
# 
#         return instance
# 
#     def inject_members(self, instance):
#         # this may be a little slow; done twice
#         guice_data = _GuiceData.composite_from_class(instance.__class__)
# 
#         for name, gm in guice_data.methods.items():
#             kwargs = {}
#             for param, guicearg in gm.items():
#                 kwargs[param] = self.get_instance(guicearg.datatype,
#                                                   guicearg.annotation)
#             getattr(instance, name)(**kwargs)
#         return instance
# 
# Path: snakeguice/decorators.py
# def inject(**kwargs):
# 
#     scope = kwargs.get('scope')
#     if 'scope' in kwargs:
#         del kwargs['scope']
# 
#     def _inject(func):
#         class_locals = enclosing_frame().f_locals
# 
#         guice_data = GuiceData.from_class_dict(class_locals)
# 
#         annotations = getattr(func, '__guice_annotations__', {})
# 
#         gmethod = dict((k, GuiceArg(v, annotations.get(k)))
#                        for k, v in kwargs.items())
# 
#         _validate_func_args(func, kwargs)
#         if func.__name__ == '__init__':
#             guice_data.init = gmethod
#         else:
#             guice_data.methods[func.__name__] = gmethod
# 
#         return func
# 
#     return _inject
# 
# class annotate(object):
# 
#     def __init__(self, **kwargs):
#         self.kwargs = kwargs
# 
#     def __call__(self, method):
#         class_locals = enclosing_frame().f_locals
#         if '__guice__' in class_locals:
#             if method.__name__ in class_locals['__guice__'].methods:
#                 raise Exception('annotate must be applied before inject')
#         method.__guice_annotations__ = self.kwargs
#         return method


# Path: specs/inheritance_spec.py
from snakeguice import Injector, inject, annotate



def describe_a_child_inheriting_an_injected_init():
    class Parent(object):
        @inject(value=OldData)
        def __init__(self, value):
            self.value = value

    class Child(Parent):
        pass

    instance = Injector(Module()).get_instance(Child)

    def child_should_have_value_set():
        assert isinstance(instance.value, OldData)


def describe_a_child_inheriting_an_injected_method():
    class Parent(object):
        @inject(value=Data)
        @annotate(value='old')
        def set_parent_value(self, value):
            self.parent_value = value

    class Child(Parent):
        @inject(value=Data)
        @annotate(value='new')
        def set_child_value(self, value):
            self.child_value = value


    instance = Injector(Module()).get_instance(Child)