Pythonでソースコードのタイポを実行時に補正する typofixer
というモジュールを作りました。
これでタイポだらけのコードを書いても誰にも文句は言われません。
使い方
typofixer
をインポートして enable()
を呼び出せば準備完了です。
import typofixer
typofixer.enable()
以下は正規表現を使ってURLの文字列からプロトコルを抜き出す処理を、タイポしまくりのコードで書いた例です。
import typofixer
typofixer.enable()
import regex # 正:re
p = regex.compairu('^(.+)://.*$') # 正:compile
m = p.macchi('https://qiita.com') # 正:match
if m:
protocol = m.gruupu(1) # 正:group
print(protocol))
どう見ても動きそうにないコードですが、正常に動作します。
https
タイポに対応しているのは以下の箇所です。
- import文でのタイポ
- インポートしたモジュールの属性
以下の箇所では未対応です。
- 組み込み関数・組み込み型の呼び出し
- ローカル変数
注意点
typofixer では指定の名前に最も近い名前を検索して使用しますが、意図したものと違う名前にマッチしてしまう事もあります。
例えば、上の例で regex.compairu
の部分を regex.conpyre
にすると copyreg
にマッチしてしまい正常に動作しません。
この辺りは希望の結果になるようにうまくタイポして下さい。
技術解説
仕組みを簡単に説明すると、以下のような処理を行なっています。
- インポート処理をカスタマイズして、import文で指定された名前に最も近い名前のモジュールを検索してロードする
- インポートしたモジュールをラップして、属性にアクセスすると最も近い名前の属性を返す
インポート処理のカスタマイズ
Pythonではimport文を実行すると先ず sys.modules
からロード済みのモジュールが検索されます。
ここになかった場合に sys._import()
が実行されてモジュールがロードされます。
この sys._import()
を置き換えることでimport処理を書き換えたり、import前後に処理を追加することができます。
通常は完全一致した名前のモジュールがロードされますが、typofixer
ではインポート可能なモジュールの中から最も近い名前のモジュールを検索してロードするように書き換えています。
参考
インポート可能なモジュール一覧の取得
pkgutil モジュールではパッケージ・モジュールに関する情報を取得する機能が提供されています。
インポート可能なモジュールを調べるには pkgutil.iter_modules()
を使用します。
近い名前の検索
difflib モジュールでは文字列の比較をする機能が提供されています。
文字列の集合から指定の文字列に最も近い文字列を検索するには difflib.get_close_matches()
を使用します。
__getattr__
で動的に属性を提供する
__getattr__
はオブジェクトの属性にアクセスしようとした時にその属性がなかった時に呼ばれる特殊メソッドです。
このメソッドを実装して、指定の名前に最も近い属性を返すようにしています。