/*  
    def adapter_hook(self, provided, object, name=u'', default=None):
        required = providedBy(object)
        cache = self._getcache(provided, name)
        factory = cache.get(required, _not_in_mapping)
        if factory is _not_in_mapping:
            factory = self.lookup((required, ), provided, name)

        if factory is not None:
            result = factory(object)
            if result is not None:
                return result

        return default
*/
static PyObject *
_adapter_hook(lookup *self, 
              PyObject *provided, PyObject *object,  PyObject *name, 
              PyObject *default_)
{
  PyObject *required, *factory, *result;

  required = providedBy(NULL, object);
  if (required == NULL)
    return NULL;
  
  factory = _lookup1(self, required, provided, name, Py_None);
  Py_DECREF(required);
  if (factory == NULL)
    return NULL;
  
  if (factory != Py_None)
    {
      result = PyObject_CallFunctionObjArgs(factory, object, NULL);
      Py_DECREF(factory);
      if (result == NULL || result != Py_None)
        return result;
    }
  else
    result = factory; /* None */

  if (default_ == NULL || default_ == result) /* No default specified, */
    return result;   /* Return None.  result is owned None */

  Py_DECREF(result);
  Py_INCREF(default_);

  return default_;
}
/*
    def adapter_hook(self, provided, object, name=u'', default=None):
        required = providedBy(object)
        cache = self._getcache(provided, name)
        factory = cache.get(required, _not_in_mapping)
        if factory is _not_in_mapping:
            factory = self.lookup((required, ), provided, name)

        if factory is not None:
            result = factory(object)
            if result is not None:
                return result

        return default
*/
static PyObject *
_adapter_hook(lookup *self,
              PyObject *provided, PyObject *object,  PyObject *name,
              PyObject *default_)
{
  PyObject *required, *factory, *result;

#ifdef PY3K
  if ( name && !PyUnicode_Check(name) )
#else
  if ( name && !PyString_Check(name) && !PyUnicode_Check(name) )
#endif
  {
    PyErr_SetString(PyExc_ValueError,
                    "name is not a string or unicode");
    return NULL;
  }

  required = providedBy(NULL, object);
  if (required == NULL)
    return NULL;

  factory = _lookup1(self, required, provided, name, Py_None);
  Py_DECREF(required);
  if (factory == NULL)
    return NULL;

  if (factory != Py_None)
    {
      result = PyObject_CallFunctionObjArgs(factory, object, NULL);
      Py_DECREF(factory);
      if (result == NULL || result != Py_None)
        return result;
    }
  else
    result = factory; /* None */

  if (default_ == NULL || default_ == result) /* No default specified, */
    return result;   /* Return None.  result is owned None */

  Py_DECREF(result);
  Py_INCREF(default_);

  return default_;
}
static PyObject *
Spec_providedBy(PyObject *self, PyObject *ob)
{
  PyObject *decl, *item;

  decl = providedBy(NULL, ob);
  if (decl == NULL)
    return NULL;

  if (PyObject_TypeCheck(decl, &SpecType))
    item = Spec_extends(decl, self);
  else
    /* decl is probably a security proxy.  We have to go the long way
       around.
    */
    item = PyObject_CallFunctionObjArgs(decl, self, NULL);

  Py_DECREF(decl);
  return item;
}
/*
    def __adapt__(self, obj):
        """Adapt an object to the reciever
        """
        if self.providedBy(obj):
            return obj

        for hook in adapter_hooks:
            adapter = hook(self, obj)
            if adapter is not None:
                return adapter


*/
static PyObject *
__adapt__(PyObject *self, PyObject *obj)
{
  PyObject *decl, *args, *adapter;
  int implements, i, l;

  decl = providedBy(NULL, obj);
  if (decl == NULL)
    return NULL;

  if (PyObject_TypeCheck(decl, &SpecType))
    {
      PyObject *implied;

      implied = inst_attr(decl, str_implied);
      if (implied == NULL)
        {
          Py_DECREF(decl);
          return NULL;
        }

      implements = PyDict_GetItem(implied, self) != NULL;
      Py_DECREF(decl);
    }
  else
    {
      /* decl is probably a security proxy.  We have to go the long way
         around.
      */
      PyObject *r;
      r = PyObject_CallFunctionObjArgs(decl, self, NULL);
      Py_DECREF(decl);
      if (r == NULL)
        return NULL;
      implements = PyObject_IsTrue(r);
      Py_DECREF(r);
    }

  if (implements)
    {
      Py_INCREF(obj);
      return obj;
    }

  l = PyList_GET_SIZE(adapter_hooks);
  args = PyTuple_New(2);
  if (args == NULL)
    return NULL;
  Py_INCREF(self);
  PyTuple_SET_ITEM(args, 0, self);
  Py_INCREF(obj);
  PyTuple_SET_ITEM(args, 1, obj);
  for (i = 0; i < l; i++)
    {
      adapter = PyObject_CallObject(PyList_GET_ITEM(adapter_hooks, i), args);
      if (adapter == NULL || adapter != Py_None)
        {
          Py_DECREF(args);
          return adapter;
        }
      Py_DECREF(adapter);
    }

  Py_DECREF(args);

  Py_INCREF(Py_None);
  return Py_None;
}