class_docstr: Implementation for the emails table for Gmail
class_docstr_tok: ["Implementation","for","the","emails","table","for","Gmail"]
docstr: Pulls emails from Gmail "users.messages.list" API
  
  Parameters
  ----------
  query : ast.Select
     Given SQL SELECT query
  
  Returns
  -------
  pd.DataFrame
      Email matching the query
  
  Raises
  ------
  NotImplementedError
      If the query contains an unsupported operation or condition
docstr_tok: ["Pulls","emails","from","Gmail","``","users.messages.list","''","API","Parameters","--","--","--","--","--","query",":","ast.Select","Given","SQL","SELECT","query","Returns","--","--","--","-","pd.DataFrame","Email","matching","the","query","Raises","--","--","--","NotImplementedError","If","the","query","contains","an","unsupported","operation","or","condition"]
code: def select(self, query: ast.Select) -> pd.DataFrame:
      """Pulls emails from Gmail "users.messages.list" API
  
      Parameters
      ----------
      query : ast.Select
         Given SQL SELECT query
  
      Returns
      -------
      pd.DataFrame
          Email matching the query
  
      Raises
      ------
      NotImplementedError
          If the query contains an unsupported operation or condition
      """
  
      conditions = extract_comparison_conditions(query.where)
  
      params = {}
      include_attachments = False
      for op, arg1, arg2 in conditions:
          if op == "or":
              raise NotImplementedError(f"OR is not supported")
  
          if arg1 in [
              "query",
              "label_ids",
              "include_spam_trash",
              "include_attachments",
          ]:
              if op == "=":
                  if arg1 == "query":
                      params["q"] = arg2
                  elif arg1 == "label_ids":
                      params["labelIds"] = arg2.split(",")
                  elif arg1 == "include_attachments":
                      include_attachments = arg2 == "true"
                  else:
                      params["includeSpamTrash"] = arg2
              else:
                  raise NotImplementedError(f"Unknown op: {op}")
  
          else:
              raise NotImplementedError(f"Unknown clause: {arg1}")
  
      if query.limit is not None:
          params["maxResults"] = query.limit.value
  
      result = self.handler.call_gmail_api(
          method_name="list_messages", params=params
      )
      attachments = []
      if include_attachments:
          attachments = self.handler.get_attachments(result)
      # filter targets
      columns = []
      for target in query.targets:
          if isinstance(target, ast.Star):
              columns = self.get_columns()
              break
          elif isinstance(target, ast.Identifier):
              columns.append(target.parts[-1])
          else:
              raise NotImplementedError(
                  f"Unknown query target {type(target)}"
              )
  
      # columns to lower case
      columns = [name.lower() for name in columns]
  
      if len(result) == 0:
          return pd.DataFrame([], columns=columns)
  
      # add absent columns
      for col in set(columns) & set(result.columns) ^ set(columns):
          result[col] = None
  
      # filter by columns
      result = result[columns]
  
      # Rename columns
      for target in query.targets:
          if target.alias:
              result.rename(
                  columns={target.parts[-1]: str(target.alias)},
                  inplace=True,
              )
  
      return result
  
imports: import json
  from shutil import copyfile
  from collections import OrderedDict
  import requests
  from mindsdb.integrations.libs.response import HandlerStatusResponse, HandlerResponse
  from mindsdb.integrations.libs.const import HANDLER_CONNECTION_ARG_TYPE
  from mindsdb.integrations.utilities.sql_utils import extract_comparison_conditions
  from mindsdb.integrations.libs.api_handler import APIHandler, APITable
  from mindsdb_sql.parser import ast
  from mindsdb.utilities import log
  from mindsdb_sql import parse_sql
  from mindsdb.utilities.config import Config
  import os
  import time
  from typing import List
  import pandas
  from google.auth.transport.requests import Request
  from google.oauth2.credentials import Credentials
  from google_auth_oauthlib.flow import Flow
  from googleapiclient.discovery import build
  from googleapiclient.errors import HttpError
  from email.message import EmailMessage
  from base64 import urlsafe_b64encode, urlsafe_b64decode
  from .utils import AuthException, google_auth_flow, save_creds_to_file
label_desc: Use image node_id 1 for calling the EmailsTable obj's underlying member method code with example usage: obj.select(query) and returns: result, pd