Skip to content

Instantly share code, notes, and snippets.

@podhmo
Forked from altnight/gist:8107f38ce58689b21221
Last active August 29, 2015 14:21
Show Gist options
  • Save podhmo/f97024e0441abf6533de to your computer and use it in GitHub Desktop.
Save podhmo/f97024e0441abf6533de to your computer and use it in GitHub Desktop.
# -*- coding:utf-8 -*-
def echo(barg, arg=''):
if arg:
ret = arg
elif barg:
ret = barg
else:
ret = ''
return ret
def moge(barg, arg='?'):
return '!moge' + barg + arg + 'moge!'
def whitespace(barg):
return ' '.join([c for c in barg])
def insert_delimiter(barg, delimiter=','):
return '{}'.format(delimiter).join([c for c in barg])
# -*- coding: utf-8 -*-
import parse # todo rename
import actions
from collections import OrderedDict
class Parser(object):
def __init__(self):
pass
def _tokenize(self, strs):
return parse.parse_input_string(strs)
def _parse(self, tokens):
return parse.parse_command(tokens)
def __call__(self, strs):
return self._parse(self._tokenize(strs))
class Executor(object):
def __init__(self):
self.actions = OrderedDict()
def register(self, action, name=None):
name = name or action.__name__
self.actions[name] = action
def __call__(self, name, *args, **kwargs):
return self._get_action(name)(*args, **kwargs)
def _get_action(self, name):
try:
return self.actions[name]
except KeyError:
raise RuntimeError("action:{} is not found".format(name))
class EchoBot(object):
def __init__(self, parser, executor, default_func=actions.echo):
self.parser = parser
self.fn = executor
self.default_fn = default_func
def do_action(self, ret):
return print(ret)
def __call__(self, input_string):
return self.evaluate(self.parser(input_string))
def evaluate(self, cmds):
ret = ''
while len(cmds) > 0:
_c = cmds.pop(0)
fn_str = _c[0]
args = _c[1:]
try:
ret = self.fn(fn_str, ret, *args)
except RuntimeError:
ret = self.default_fn(''.join(_c))
return self.do_action(ret)
if __name__ == "__main__":
# setup
executor = Executor()
executor.register(actions.echo)
executor.register(actions.moge)
executor.register(actions.whitespace)
executor.register(actions.insert_delimiter)
bot = EchoBot(Parser(), executor)
# run time
cmd = 'hoge | moge 1 | insert_delimiter ! | whitespace'
bot(cmd)

備忘録

  • pep8に対応していないので対応する
  • とくに理由なく関数内でimportしている。importは原則トップレベルに書くべき

あと、なんだろうな。実行と定義が分離できていない気がする。 __name__ == '__main__' の部分は実行のみにしたい。

定義の部分は別途他のでも使えるようにしたい。

  • たぶんコマンドの登録はobjectが良い。
  • テスト用の入力値(実行コード)と関数定義がまとまっていない感じなので辛い。

とりあえず、ひとつのオブジェクトにしてみる。

何だか1つのオブジェクトだと再利用性が悪い気がする。

以下の3つくらいに分ける

  • 登録していたアクションを実行するexecutor
  • 渡された入力値を解析して、実行しやすい形式に変更するparser
  • デフォルトの動作を決めたりするbot

botがexecutor,parserを利用するという感じにすると良い気がする。

あと、細かな関数と全体のinterfaceは別なのでたぶん細かな関数はそのまま残しておいて、 各オブジェクトのメソッドなどでは直接実装を書かないという方が良い。

import shlex
def parse_input_string(strs):
parsed = shlex.split(strs)
print(parsed)
return parsed
def parse_command(parsed):
ret = []
current = []
while parsed:
c = parsed.pop(0)
if c == "|":
ret.append(current)
current = []
else:
current.append(c)
ret.append(current)
return ret
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment