def __init__(self, dbpath, table_name, mode, height): limit = height self._limit = height try: # dbpath = ':memory:' conn = sqlite3.connect(dbpath) except sqlite3.OperationalError as raiz: if raiz.args[0] == 'unable to open database file': s = traceback.format_exc() logger.error(s) logger.error('dbpath is {}'.format(dbpath), file=sys.stderr) raise sqlite3.OperationalError(*raiz.args) conn = GeneralSQLConnection(conn) # print('conn =', conn) self.conn = conn self._make_sql_template(table_name, limit) logger.debug("mode is {} in Iasap.__init__()".format(mode)) if mode == 'curses': _iasap = IasapCurses() elif mode == 'tkinter': _iasap = IasapTkinter() elif mode == 'one-shot': _iasap = self else: logger.debug("mode = \"{}\"".format(mode)) raise ValueError( 'mode="{}" must be "curses" or "tkinter".'.format(mode)) _iasap.get_body = self.get_body self.start = _iasap.start
def getch(self, y, x): ch = self.stdscr.getch(y, x) if ch == 3: # enable Ctr-c in windows. logger.debug("stdscr.getch() raise KeyboardInterrupt.") raise KeyboardInterrupt return ch
def get_oneline(self, event): logger.debug("in get_oneline()") logger.debug("event.(type={}, keycode={}, keysysm={}, keysym_num={}, " "char=\'{}\')".format(event.type, event.keycode, event.keysym, event.keysym_num, event.char)) # index() が値を返す時、"y.x" の形式で、oneline の左端に cursor # がある時、返ってくる文字列は、"1.0"。 # なので、y=1, x=0 が開始っぽい。変なの。こういう癖、好きじゃない。 cursor_yx = self.oneline.index(tkinter.INSERT) logger.debug("cursor_yx={}".format(cursor_yx)) line, column = self.to_int(cursor_yx) current_oneline = self.oneline.get("1.0", tkinter.END) current_oneline = re.sub("\n$", "", current_oneline) query = current_oneline if line > 1: # 現在の oneline が複数行だったら。 # 現在の oneline から改行を削除して、 # 改行がない値を oneline に設定し直す。 query = current_oneline.replace("\n", "") self.oneline.delete("1.0", tkinter.END) self.oneline.insert(tkinter.END, query) if self.used_query != query: logger.debug('used_query={}, query={}'.format(self.used_query, query)) self.used_query = query self.need_to_search = True else: self.need_to_search = False logger.debug("need_to_search={}.".format(self.need_to_search))
def _effect_line(self, line, ss, y, width, effect): # count ascii charactor to ascii_counter for ascii_counter, c in enumerate(line): if len(c.encode()) > 1: break ss_lower = ss.lower() len_ss = len(ss) x = 0 while True: try: rel_index = line.lower().index(ss_lower) except ValueError as raiz: args = raiz.args if args[0] == "substring not found": break else: logger.debug("args = {}, in _effect_line()".format(args)) raise ValueError(*args) else: x += rel_index if x < width and x < ascii_counter: rev = line[rel_index:rel_index+len_ss] self.stdscr.addstr(y, x, rev, effect) x += len_ss line = line[rel_index+len_ss:] else: break
def create_table(self, table_info): cur = self.conn.cursor() table_name = table_info["table_name"] columns = [] for column_name, explain in table_info.items(): if column_name == "table_name": continue column = ' '.join([column_name, explain]) columns += [column] sql = 'create table {} ({})'.format(table_name, ', '.join(columns)) logger.debug(sql) cur.execute(sql) logger.info('created {} table.'.format(table_name)) # print(list(table_info.keys())) od = OrderedDict() od['id'] = None od['typename'] = table_name L = list(table_info.keys()) logger.debug('list(table_info.keys()) = {}'.format(L)) L.remove("table_name") od['field_names'] = ' '.join(L) self.insert('__namedtuples__', od) logger.info('2: inserted {} table info ' 'to __namedtuples__ table.'.format(table_name))
def main(cls, script_name, table_name, log_level=logger.INFO): if "--debug" in sys.argv: log_level = logger.DEBUG start_logger(script_name, log_dir=os.path.curdir, log_level=log_level) kv_merged, kv_defaults, kv_argment = \ merge_kv_by_defaults_and_argument(cls.DEFAULTS) kv = set_kv_for_regular(kv_defaults, kv_argment, kv_merged["conf"], table_name) if not os.path.isfile(kv["dbpath"]): raise OSError("cannot access \"{}\": No such file.".format( kv["dbpath"])) logger.debug("cls={}(dbpath={}, table_name={}, mode={}, limit={})".format( cls, kv["dbpath"], table_name, kv["mode"], kv["limit"])) iasap_obj = cls(kv["dbpath"], table_name, kv["mode"], kv["limit"]) logger.debug("iasap_obj = {}".format(iasap_obj)) if kv["mode"] == "one-shot": if not len(kv["args"]): msg = ("mode として one-shot を指定した場合は、" "one-shot の後に空白を一つ入れ、空白の後に検索語を一つ" "指定しなければなりません。") raise ValueError(msg) iasap_obj.start(kv["args"][0]) else: iasap_obj.start()
def _get_new_ch(self, cursor_x): try: new_ch = self.getch(0, cursor_x) except KeyboardInterrupt: new_ch = "__break__" logger.debug("new_ch = {} in _get_new_ch()".format(new_ch)) return new_ch
def get_body(self, search): sql, like_search = self._make_sql(search) tup = (like_search, ) rows = self._do_select(sql, tup) logger.debug('like_search = "{}"'.format(like_search)) if not search: return '' body = '\n'.join([text for text in self]) return body
def insert(self, table_name, columns=None): cur = self.conn.cursor() hatenas = '({})'.format(', '.join('?' * len(columns.values()))) sql_ = 'insert into {} {} values '.format(table_name, \ tuple(columns.keys())) values = tuple(columns.values()) logger.debug(sql_ + str(values)) cur.execute(sql_ + hatenas, values) cur.close()
def _do_select(self, sql, values): logger.debug('sql = "{}"'.format(sql)) logger.debug('values = "{}"'.format(values)) s = datetime.datetime.now() self.named_rows = self.conn.select(sql, values) e = datetime.datetime.now() d = (e - s).total_seconds() logger.debug('select start at {}'.format(s)) logger.debug('select end at {}'.format(e)) logger.debug('passed time is {}'.format(d))
def __next__(self): self._i += 1 row = None if not self.max_rows or self._i <= self.max_rows: row = self.cur.fetchone() if row: logger.debug("row = {}".format(row)) logger.debug("self.namedtup = {}".format(self.namedtup)) return self.namedtup(*row) else: self.cur.close() raise StopIteration
def char_key(self, event): logger.debug("char_key() keysym =", event.keysym) logger.debug("char_key() char =", event.char) d = { "BackSpace": "^H", "Delete": "^D", "Right": "^F", "Left": "^B", } keysym = event.keysym if keysym in d: char = d[keysym] else: char = event.char if not re.search("[-a-zA-Z0-9 &|]", char): return self.get_key(char)
def _get_namedtuple(self, typename): if not hasattr(self.__dict__, typename): cur = self.cur sql = ('select * from __namedtuples__ where ' 'typename = "{}"').format(typename) logger.debug(sql) result = cur.execute(sql) logger.info('got {} __namedtuples__ info.'.format(typename)) row = cur.fetchone() if not row: raise ValueError("typename={} is not in __namedtuples__") field_names = row[2] namedtup = namedtuple(typename, field_names) self.__dict__[typename] = namedtup else: namedtup = self.__dict__[typename] return namedtup
def run(self): new_ch_no = 0 cursor_x = 0 oneline = "" while True: logger.debug("new_ch_no = {} ==================".format(new_ch_no)) ymax, xmax = self.stdscr.getmaxyx() new_ch = self._get_new_ch(cursor_x) new_ch_no += 1 if new_ch == "__break__": self.stdscr.erase() break keyname = curses.keyname(new_ch) logger.debug("keyname = \"{}\", len(keyname) = {}, type(keyname) = {}, in run()".format(keyname, len(keyname), type(keyname))) keyname = keyname.decode() logger.debug("keyname = \"{}\", len(keyname) = {}, type(keyname) = {}, in run()".format(keyname, len(keyname), type(keyname))) oneline, cursor_x, new_query = \ self._update_oneline(oneline, cursor_x, keyname) if not len(oneline) < xmax: oneline = oneline[:xmax - 1] cursor_x -= 1 if not oneline and not cursor_x: self.stdscr.erase() if re.search("^ *$", oneline) or not new_query: continue self._init_screen() self._draw_oneline(oneline) height = ymax - 1 width = xmax curses_lines = self.get_body(oneline) lines = curses_lines.split("\n") offset_y = 1 for i, line in enumerate(lines): # logger.debug("i={}, line={}".format(i, line)) OK try: self._draw_line(line, oneline, i + offset_y, \ width, curses.A_NORMAL) except curses.error as raiz: break self.stdscr.erase() curses.nocbreak() self.stdscr.keypad(0) curses.echo() curses.endwin() logger.debug("oneline_curses finished.")
def _make_like(self, search): """ >>> import re >>> re.sub(" $", "%", " a ") ' a%' >>> re.sub("^ ", "%", " a ") '%a ' >>> re.sub("^ ", "%", " a ") '% a ' >>> re.sub(" $", "%", " a ") ' a %' >>> re.sub(" $", "%", "a") 'a' >>> re.sub("^ ", "%", "a") 'a' >>> s = " s " >>> re.sub("^ ", "%", s) '% s ' """ like_search = re.sub("^ ", "%", search) like_search = re.sub(" $", "%", like_search) logger.debug("search=\"{}\"".format(search)) logger.debug("like_search=\"{}\"".format(like_search)) return like_search
def create_namedtuples_table(self): conn = self.conn table_name = '__namedtuples__' sql = ''' create table __namedtuples__ ( id integer primary key, typename uniq text, field_names text )''' logger.debug(sql) conn.execute(sql) conn.commit() logger.info('created __namedtuples__ table.') od = OrderedDict() od['id'] = None od['typename'] = table_name od['field_names'] = '' od['field_names'] = ' '.join(od.keys()) logger.debug('od.keys() = {}'.format(od.keys)) self.insert('__namedtuples__', od) logger.info('1: inserted __namedtuples__ table info ' 'to __namedtuples__ table.')
def _mode_emacs(self, keyname): oneline = self.oneline cursor_x = self.cursor_x buffer = self.buffer logger.debug('oneline="{}", cursor_x={}, buffer="{}" enter in _mode_emacs(keyname="{}")'.format(oneline, cursor_x, buffer, keyname)) if keyname == "^A": # ctr-a "^A" cursor_x = 0 elif keyname == "^K": buffer = oneline[cursor_x:] oneline = oneline[:cursor_x] elif keyname == "^F": cursor_x += 1 if cursor_x > len(oneline): cursor_x = len(oneline) elif keyname == "^Y": oneline = "".join((oneline[:cursor_x], buffer, oneline[cursor_x:])) elif keyname == "^T": if len(oneline) >= 2 and cursor_x <= len(oneline) - 2: c0 = oneline[cursor_x+0] c1 = oneline[cursor_x+1] left = oneline[:cursor_x] right = oneline[cursor_x+2:] oneline = left + c1 + c0 + right elif keyname == "^E": cursor_x = len(oneline) elif keyname == "^D": oneline = oneline[:cursor_x] + oneline[cursor_x+1:] elif keyname == "^B": if cursor_x > 0: cursor_x -= 1 elif keyname == "^W": if not cursor_x: pass elif oneline[cursor_x-1] == " ": while cursor_x > 0 and oneline[cursor_x-1] == " ": oneline = oneline[:cursor_x-1] + oneline[cursor_x:] cursor_x -= 1 else: while cursor_x > 0 and oneline[cursor_x-1] != " ": oneline = oneline[:cursor_x-1] + oneline[cursor_x:] cursor_x -= 1 elif keyname in ("^H", "^?"): # ctr-h "^H" # backspace "^?" if not cursor_x: pass else: oneline = oneline[:cursor_x-1] + oneline[cursor_x:] cursor_x -= 1 elif len(keyname) >= 2: pass elif re.search("[-a-zA-Z0-9 &|]", keyname): # ord("a") => 0x61 # chr(0x61) => "a" oneline = oneline[:cursor_x] + keyname + oneline[cursor_x:] cursor_x += 1 self.oneline = oneline self.cursor_x = cursor_x self.buffer = buffer logger.debug('oneline="{}", cursor_x={}, buffer="{}" leave out _mode_emacs(keyname="{}")'.format(oneline, cursor_x, buffer, keyname))
def start(self, search): logger.debug("search: {}".format(search)) body = self.get_body(search) for line in body.split("\n"): print(line)
def _set_msg(self, oneline, body, cursor_x): logger.debug(".index(INSERT) =", self.txt.index(tkinter.INSERT)) logger.debug(".index(END) =", self.txt.index(tkinter.END)) sp = self.txt.index(tkinter.INSERT).split(".") index_oneline = "{}.0".format(4) self.txt.insert(index_oneline, body + b"\n")
def select(self, sql, values=None, max_rows=0): logger.debug(sql) logger.debug(values) return NamedRow(self.conn, sql, values, max_rows)