code: def esearch(database, query, userhistory=True, webenv=False, query_key=False, retstart=False, retmax=False,
              api_key=False, email=False, **kwargs) -> Optional[EsearchResult]:
      
      cleaned_query = urllib.parse.quote_plus(query, safe='/+')
  
      url = BASE_URL + f'esearch.fcgi?db={database}&term={cleaned_query}&retmode=json'
      url = check_userhistory(userhistory, url)
      url = check_webenv(webenv, url)
      url = check_query_key(query_key, url)
      url = check_retstart(retstart, url)
      url = check_retmax(retmax, url)
      url = check_api_key(api_key, url)
      url = check_email(email, url)
  
      time.sleep(PAUSE)
      resp = requests.get(url)
      if resp.status_code != 200:
          print('There was a server error')
          return
  
      text = resp.json()
      time.sleep(.5)
      return EsearchResult(
          text['esearchresult'].get('idlist', []),
          make_number(text['esearchresult'].get('count', ''), int),
          text['esearchresult'].get('webenv', ''),
          text['esearchresult'].get('querykey', '')
      )
docs: Search for a query using the Entrez ESearch API.
  
      Parameters
      ----------
      database : str
          Entez database to search.
      query : str
          Query string
      userhistory : bool
          Tells API to return a WebEnV and query_key.
      webenv : str
          An Entrez WebEnv to use saved history.
      query_key : str
          An Entrez query_key to use saved history.
      retstart : int
          Return values starting at this index.
      retmax : int
          Return at most this number of values.
      api_key : str
          A users API key which allows more requests per second
      email : str
          A users email which is required if not using API.
  
      Returns
      -------
      EsearchResult
          A named tuple with values [ids, count, webenv, query_key]