code: def _search(self, searchfilter, attrs, basedn):
          
          if attrs == NO_ATTR:
              attrlist = []
          elif attrs == DISPLAYED_ATTRS:
              # fix me later (to much attributes)
              attrlist = self.attrlist
          elif attrs == LISTED_ATTRS:
              attrlist = self.attrlist
          elif attrs == ALL_ATTRS:
              attrlist = None
          else:
              attrlist = None
  
          self._logger(
              severity=logging.DEBUG,
              msg="%(backend)s: executing search "
                  "with filter '%(filter)s' in DN '%(dn)s'" % {
                      'backend': self.backend_name,
                      'dn': basedn,
                      'filter': self._uni(searchfilter)
                  }
          )
  
          # bind and search the ldap
          ldap_client = self._bind()
          try:
              r = ldap_client.search_s(
                  basedn,
                  ldap.SCOPE_SUBTREE,
                  searchfilter,
                  attrlist=attrlist
                  )
          except Exception as e:
              ldap_client.unbind_s()
              self._exception_handler(e)
  
          ldap_client.unbind_s()
  
          # python-ldap doesn't know utf-8,
          # it treates everything as bytes.
          # So it's necessary to reencode
          # it's output in utf-8.
          ret = []
          for entry in r:
              uni_dn = self._uni(entry[0])
              uni_attrs = {}
              for attr in entry[1]:
                  if type(entry[1][attr]) is list:
                      tmp = []
                      for value in entry[1][attr]:
                          tmp.append(self._uni(value))
                  else:
                      tmp = self._uni(entry[1][attr])
                  uni_attrs[self._uni(attr)] = tmp
              ret.append((uni_dn, uni_attrs))
          return ret
docs: Generic search