# Path: pytablereader/_constant.py
# class TableNameTemplate:
#     __FORMAT = "%({:s})s"
#     DEFAULT = __FORMAT.format("default")
#     FILENAME = __FORMAT.format("filename")
#     FORMAT_NAME = __FORMAT.format("format_name")
#     FORMAT_ID = __FORMAT.format("format_id")
#     GLOBAL_ID = __FORMAT.format("global_id")
#     KEY = __FORMAT.format("key")
#     TITLE = __FORMAT.format("title")
#     SHEET = __FORMAT.format("sheet")
# 
# Path: pytablereader/_validator.py
# class TextValidator(BaseValidator):
#     """
#     Validator class for text object data source.
#     """
# 
#     @property
#     def source_type(self):
#         return SourceType.TEXT
# 
#     def validate(self):
#         if typepy.is_null_string(self.source):
#             raise DataError("data source is empty")
# 
# Path: pytablereader/error.py
# class APIError(Exception):
#     """
#     Exception raised when failed to execute API requests.
#     """
# 
# class OpenError(IOError):
#     """
#     Exception raised when failed to open a file.
#     """
# 
# Path: pytablereader/spreadsheet/core.py
# class SpreadSheetLoader(AbstractTableReader):
#     """
#     An abstract class of table data.
#     Especially spreadsheets that consists multiple rows.
# 
#     .. py:attribute:: start_row
# 
#         The first row to search header row.
#     """
# 
#     def __init__(self, source, quoting_flags, type_hints, type_hint_rules):
#         super().__init__(source, quoting_flags, type_hints, type_hint_rules)
# 
#         self.start_row = 0
#         self._worksheet = None
#         self._start_col_idx = None
#         self._end_col_idx = None
# 
#     @abc.abstractproperty
#     def _sheet_name(self):  # pragma: no cover
#         pass
# 
#     @abc.abstractproperty
#     def _row_count(self):  # pragma: no cover
#         pass
# 
#     @abc.abstractproperty
#     def _col_count(self):  # pragma: no cover
#         pass
# 
#     @abc.abstractmethod
#     def _is_empty_sheet(self):  # pragma: no cover
#         pass
# 
#     @abc.abstractmethod
#     def _get_start_row_idx(self):  # pragma: no cover
#         pass
# 
#     @property
#     def format_name(self):
#         return "spreadsheet"
# 
#     def _make_table_name(self):
#         kv_mapping = self._get_basic_tablename_keyvalue_mapping()
# 
#         try:
#             kv_mapping[tnt.SHEET] = self._sheet_name
#         except AttributeError:
#             kv_mapping[tnt.SHEET] = ""
# 
#         return self._expand_table_name_format(kv_mapping)
# 
#     def _get_default_table_name_template(self):
#         return f"{tnt.SHEET:s}"
# 
#     def _extract_type_hints(self, headers=None):
#         if self.type_hints:
#             return self.type_hints
# 
#         if not self.type_hint_rules or not headers:
#             return []
# 
#         type_hints = []
#         for header in headers:
#             for regexp, type_hint in self.type_hint_rules.items():
#                 if regexp.search(header):
#                     type_hints.append(type_hint)
#                     break
#             else:
#                 type_hints.append(None)
# 
#         return type_hints


import typepy
        import gspread
from tabledata import TableData
from .._constant import TableNameTemplate as tnt
from .._validator import TextValidator
from ..error import APIError, OpenError
from .core import SpreadSheetLoader
        from oauth2client.service_account import ServiceAccountCredentials
        from simplesqlite import connect_memdb
        from simplesqlite.query import Attr, AttrList
                    type_hints=self._extract_type_hints(headers),
                )
        except gspread.exceptions.SpreadsheetNotFound:
            raise OpenError(f"spreadsheet '{self.title}' not found")
        except gspread.exceptions.APIError as e:
            raise APIError(e)

    def _is_empty_sheet(self):
        return len(self.__all_values) <= 1

    def _get_start_row_idx(self):
        row_idx = 0
        for row_values in self.__all_values:
            if all([typepy.is_not_null_string(value) for value in row_values]):
                break

            row_idx += 1

        return self.start_row + row_idx

    def _validate_title(self):
        if typepy.is_null_string(self.title):
            raise ValueError("spreadsheet title is empty")

    def _make_table_name(self):
        self._validate_title()

        kv_mapping = self._get_basic_tablename_keyvalue_mapping()
        kv_mapping[tnt.TITLE] = self.title
        try:

# Path: pytablereader/_constant.py
# class TableNameTemplate:
#     __FORMAT = "%({:s})s"
#     DEFAULT = __FORMAT.format("default")
#     FILENAME = __FORMAT.format("filename")
#     FORMAT_NAME = __FORMAT.format("format_name")
#     FORMAT_ID = __FORMAT.format("format_id")
#     GLOBAL_ID = __FORMAT.format("global_id")
#     KEY = __FORMAT.format("key")
#     TITLE = __FORMAT.format("title")
#     SHEET = __FORMAT.format("sheet")
# 
# Path: pytablereader/_validator.py
# class TextValidator(BaseValidator):
#     """
#     Validator class for text object data source.
#     """
# 
#     @property
#     def source_type(self):
#         return SourceType.TEXT
# 
#     def validate(self):
#         if typepy.is_null_string(self.source):
#             raise DataError("data source is empty")
# 
# Path: pytablereader/error.py
# class APIError(Exception):
#     """
#     Exception raised when failed to execute API requests.
#     """
# 
# class OpenError(IOError):
#     """
#     Exception raised when failed to open a file.
#     """
# 
# Path: pytablereader/spreadsheet/core.py
# class SpreadSheetLoader(AbstractTableReader):
#     """
#     An abstract class of table data.
#     Especially spreadsheets that consists multiple rows.
# 
#     .. py:attribute:: start_row
# 
#         The first row to search header row.
#     """
# 
#     def __init__(self, source, quoting_flags, type_hints, type_hint_rules):
#         super().__init__(source, quoting_flags, type_hints, type_hint_rules)
# 
#         self.start_row = 0
#         self._worksheet = None
#         self._start_col_idx = None
#         self._end_col_idx = None
# 
#     @abc.abstractproperty
#     def _sheet_name(self):  # pragma: no cover
#         pass
# 
#     @abc.abstractproperty
#     def _row_count(self):  # pragma: no cover
#         pass
# 
#     @abc.abstractproperty
#     def _col_count(self):  # pragma: no cover
#         pass
# 
#     @abc.abstractmethod
#     def _is_empty_sheet(self):  # pragma: no cover
#         pass
# 
#     @abc.abstractmethod
#     def _get_start_row_idx(self):  # pragma: no cover
#         pass
# 
#     @property
#     def format_name(self):
#         return "spreadsheet"
# 
#     def _make_table_name(self):
#         kv_mapping = self._get_basic_tablename_keyvalue_mapping()
# 
#         try:
#             kv_mapping[tnt.SHEET] = self._sheet_name
#         except AttributeError:
#             kv_mapping[tnt.SHEET] = ""
# 
#         return self._expand_table_name_format(kv_mapping)
# 
#     def _get_default_table_name_template(self):
#         return f"{tnt.SHEET:s}"
# 
#     def _extract_type_hints(self, headers=None):
#         if self.type_hints:
#             return self.type_hints
# 
#         if not self.type_hint_rules or not headers:
#             return []
# 
#         type_hints = []
#         for header in headers:
#             for regexp, type_hint in self.type_hint_rules.items():
#                 if regexp.search(header):
#                     type_hints.append(type_hint)
#                     break
#             else:
#                 type_hints.append(None)
# 
#         return type_hints


# Path: pytablereader/spreadsheet/gsloader.py
import typepy
        import gspread
from tabledata import TableData
from .._constant import TableNameTemplate as tnt
from .._validator import TextValidator
from ..error import APIError, OpenError
from .core import SpreadSheetLoader
        from oauth2client.service_account import ServiceAccountCredentials
        from simplesqlite import connect_memdb
        from simplesqlite.query import Attr, AttrList

                    type_hints=self._extract_type_hints(headers),
                )
        except gspread.exceptions.SpreadsheetNotFound:
            raise OpenError(f"spreadsheet '{self.title}' not found")
        except gspread.exceptions.APIError as e:
            raise APIError(e)

    def _is_empty_sheet(self):
        return len(self.__all_values) <= 1

    def _get_start_row_idx(self):
        row_idx = 0
        for row_values in self.__all_values:
            if all([typepy.is_not_null_string(value) for value in row_values]):
                break

            row_idx += 1

        return self.start_row + row_idx

    def _validate_title(self):
        if typepy.is_null_string(self.title):
            raise ValueError("spreadsheet title is empty")

    def _make_table_name(self):
        self._validate_title()

        kv_mapping = self._get_basic_tablename_keyvalue_mapping()
        kv_mapping[tnt.TITLE] = self.title
        try:

            kv_mapping[tnt.SHEET] = self._sheet_name