# 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
# 
# Path: snakeguice/interfaces.py
# class Injector(object):
#     """An interface automatically bound to the current Injector instance."""
# 
# Path: snakeguice/decorators.py
# class GuiceData(object):
# 
#     def __init__(self):
#         self.init = None
#         self.methods = {}
# 
#     @classmethod
#     def from_class(cls, target_class):
#         if '__guice__' not in target_class.__dict__:
#             guice_data = cls()
#             try:
#                 target_class.__guice__ = guice_data
#             except TypeError: # special case for builtin/extension types
#                 return guice_data
#         return target_class.__guice__
# 
#     @classmethod
#     def composite_from_class(cls, target_class):
#         composite_data = GuiceData()
#         for _cls in target_class.__mro__[-1::-1]:
#             data = GuiceData.from_class(_cls)
#             if data.init: # only the last class in the chain
#                 composite_data.init = data.init
#             for name, method in data.methods.items():
#                 composite_data.methods[name] = method
# 
#         return composite_data
# 
#     @classmethod
#     def from_class_dict(cls, class_dict):
#         if '__guice__' not in class_dict:
#             class_dict['__guice__'] = cls()
#         return class_dict['__guice__']
# 
# class GuiceArg(object):
# 
#     def __init__(self, datatype=None, annotation=None, scope=None):
#         self.datatype = datatype
#         self.annotation = annotation
#         self.scope = scope
# 
#     def __eq__(self, other):
#         return (self.datatype, self.annotation, self.scope
#                 ) == (other.datatype, other.annotation, other.scope)
# 
# def enclosing_frame(frame=None, level=2):
#     """Get an enclosing frame that skips decorator code"""
#     frame = frame or sys._getframe(level)
#     while frame.f_globals.get('__name__') == __name__: frame = frame.f_back
#     return frame


import inspect
from snakeguice import inject
from snakeguice.interfaces import Injector
from snakeguice.decorators import GuiceData, GuiceArg, enclosing_frame
from snakeguice.errors import AssistError

def assisted_inject(**kwargs):

    scope = kwargs.get('scope')
    if 'scope' in kwargs:
        del kwargs['scope']

    def _assisted_inject(func):
        if func.__name__ != '__init__':
            raise AssistError('assisted_inject can only be used on __init__s')

        class_locals = enclosing_frame().f_locals

        guice_data = GuiceData.from_class_dict(class_locals)
        guice_data.assisted = True # TODO: I don't like this, but it works for now

        annotations = getattr(func, '__guice_annotations__', {})

        guice_data.init = dict((k, GuiceArg(v, annotations.get(k)))
                                for k, v in kwargs.items())

        return func

    return _assisted_inject


assisted = object()


def AssistProvider(cls):

# 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
# 
# Path: snakeguice/interfaces.py
# class Injector(object):
#     """An interface automatically bound to the current Injector instance."""
# 
# Path: snakeguice/decorators.py
# class GuiceData(object):
# 
#     def __init__(self):
#         self.init = None
#         self.methods = {}
# 
#     @classmethod
#     def from_class(cls, target_class):
#         if '__guice__' not in target_class.__dict__:
#             guice_data = cls()
#             try:
#                 target_class.__guice__ = guice_data
#             except TypeError: # special case for builtin/extension types
#                 return guice_data
#         return target_class.__guice__
# 
#     @classmethod
#     def composite_from_class(cls, target_class):
#         composite_data = GuiceData()
#         for _cls in target_class.__mro__[-1::-1]:
#             data = GuiceData.from_class(_cls)
#             if data.init: # only the last class in the chain
#                 composite_data.init = data.init
#             for name, method in data.methods.items():
#                 composite_data.methods[name] = method
# 
#         return composite_data
# 
#     @classmethod
#     def from_class_dict(cls, class_dict):
#         if '__guice__' not in class_dict:
#             class_dict['__guice__'] = cls()
#         return class_dict['__guice__']
# 
# class GuiceArg(object):
# 
#     def __init__(self, datatype=None, annotation=None, scope=None):
#         self.datatype = datatype
#         self.annotation = annotation
#         self.scope = scope
# 
#     def __eq__(self, other):
#         return (self.datatype, self.annotation, self.scope
#                 ) == (other.datatype, other.annotation, other.scope)
# 
# def enclosing_frame(frame=None, level=2):
#     """Get an enclosing frame that skips decorator code"""
#     frame = frame or sys._getframe(level)
#     while frame.f_globals.get('__name__') == __name__: frame = frame.f_back
#     return frame


# Path: snakeguice/assist.py
import inspect
from snakeguice import inject
from snakeguice.interfaces import Injector
from snakeguice.decorators import GuiceData, GuiceArg, enclosing_frame
from snakeguice.errors import AssistError


def assisted_inject(**kwargs):

    scope = kwargs.get('scope')
    if 'scope' in kwargs:
        del kwargs['scope']

    def _assisted_inject(func):
        if func.__name__ != '__init__':
            raise AssistError('assisted_inject can only be used on __init__s')

        class_locals = enclosing_frame().f_locals

        guice_data = GuiceData.from_class_dict(class_locals)
        guice_data.assisted = True # TODO: I don't like this, but it works for now

        annotations = getattr(func, '__guice_annotations__', {})

        guice_data.init = dict((k, GuiceArg(v, annotations.get(k)))
                                for k, v in kwargs.items())

        return func

    return _assisted_inject


assisted = object()


def AssistProvider(cls):

    guice_data = GuiceData.from_class(cls)