text: """Copyright 2013 Google Inc. All Rights Reserved.
  
  Licensed under the Apache License, Version 2.0 (the "License");
  you may not use this file except in compliance with the License.
  You may obtain a copy of the License at
  
      http://www.apache.org/licenses/LICENSE-2.0
  
  Unless required by applicable law or agreed to in writing, software
  distributed under the License is distributed on an "AS IS" BASIS,
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  See the License for the specific language governing permissions and
  limitations under the License.
  """
  
  
  from . import support
  from . import arg_binding_keys
  from . import decorators
  from . import errors
  
  
  class ObjectProvider(object):
  
      def __init__(self, binding_mapping, bindable_scopes, allow_injecting_none):
          self._binding_mapping = binding_mapping
          self._bindable_scopes = bindable_scopes
          self._allow_injecting_none = allow_injecting_none
  
      def provide_from_arg_binding_key(
              self, injection_site_fn, arg_binding_key, injection_context):
          binding_key = arg_binding_key.binding_key
          binding = self._binding_mapping.get(
              binding_key, injection_context.get_injection_site_desc())
          scope = self._bindable_scopes.get_sub_scope(binding)
          def Provide(*pargs, **kwargs):
              # TODO(kurts): probably capture back frame's file:line for
              # DirectlyPassingInjectedArgsError.
              child_injection_context = injection_context.get_child(
                  injection_site_fn, binding)
              provided = scope.provide(
                  binding_key,
                  lambda: binding.proviser_fn(child_injection_context, self,
                                              pargs, kwargs))
              if (provided is None) and not self._allow_injecting_none:
                  raise errors.InjectingNoneDisallowedError(
                      binding.get_binding_target_desc_fn())
              return provided
          provider_indirection = arg_binding_key.provider_indirection
          try:
              provided = provider_indirection.StripIndirectionIfNeeded(Provide)
          except TypeError:
              # TODO(kurts): it feels like there may be other TypeErrors that
              # occur.  Instead, decorators.get_injectable_arg_binding_keys()
              # should probably do all appropriate validation?
              raise errors.OnlyInstantiableViaProviderFunctionError(
                  injection_site_fn, arg_binding_key,
                  binding.get_binding_target_desc_fn())
          return provided
  
      def provide_class(self, cls, injection_context,
                        direct_init_pargs, direct_init_kwargs):
          if support.is_constructor_defined(cls):
              init_pargs, init_kwargs = self.get_injection_pargs_kwargs(
                  cls.__init__, injection_context,
                  direct_init_pargs, direct_init_kwargs)
          else:
              init_pargs = direct_init_pargs
              init_kwargs = direct_init_kwargs
          return cls(*init_pargs, **init_kwargs)
  
      def call_with_injection(self, provider_fn, injection_context,
                              direct_pargs, direct_kwargs):
          pargs, kwargs = self.get_injection_pargs_kwargs(
              provider_fn, injection_context, direct_pargs, direct_kwargs)
          return provider_fn(*pargs, **kwargs)
  
      def get_injection_pargs_kwargs(self, fn, injection_context,
                                     direct_pargs, direct_kwargs):
          di_kwargs = arg_binding_keys.create_kwargs(
              decorators.get_injectable_arg_binding_keys(
                  fn, direct_pargs, direct_kwargs),
              lambda abk: self.provide_from_arg_binding_key(
                  fn, abk, injection_context))
          duplicated_args = set(di_kwargs.keys()) & set(direct_kwargs.keys())
          if duplicated_args:
              raise errors.DirectlyPassingInjectedArgsError(
                  duplicated_args, injection_context.get_injection_site_desc(),
                  fn)
          all_kwargs = dict(di_kwargs)
          all_kwargs.update(direct_kwargs)
          return direct_pargs, all_kwargs
  