まず
xonshと言ったらばんくしさんのブログを見ましょう。これを見れば大体できます。
目次
- cookiecutter-xontribが使えない!
- 関数を別モジュールに切り出したい
- -eとgitでモジュールが読めなくなる話
- テストを書きたい話
cookiecutter-xontribが使えない!
xontribの雛形を作るのに便利ですが、 https://github.com/laerus/cookiecutter-xontrib
がなくなってしまっています。
xonsh公式が出しているのでそちらをそのまま使いましょう。 https://github.com/xonsh/xontrib-cookiecutter
作成直後の構造↓
.
├── LICENSE
├── README.rst
├── setup.cfg
├── setup.py
└── xontrib
└── sample.xsh
ちなみに、公式版では新しく setup.cfg
が追加されていますが、今までsetup関数に与えていた引数を別出ししているだけなので特に変わりなく使えます。
関数を別モジュールに切り出したい
公式のチュートリアルにもあるように、libモジュールを作成して読み込みたい時
xontrib/
|- javert.xsh # "javert", because in xontrib
|- your.py # "your",
|- eyes/
|- __init__.py
|- scream.xsh # "eyes.scream", because eyes is in xontrib
[javert.xsh]
from .eyes import scream # ○
from eyes import scream # ×
xontribよりpython全般の話になってきますが、相対読み込みを使わないとこけます。半日溶かしました
xpip install -e と pip install git+ で動きが違う(動かなくなる)話
前者は動き、後者は動かなく(module not found)なりました。
結論としては、setupの書き方に問題がありました。
...
package_data = {'xontrib': [ここ]},
...
xontribの先人の方々は *.xsh
と書いていたため、「この部分にパッケージに含めるファイルを記述する」と推測して ./**/*.py
と記述すると動きます。
これも半日溶かしました。
テストを書きたい
こちらの記事(すごい!)を参考にして全てpyに置き換えている前提です。
普通にunittestを走らせると、 builtins.__xonsh__.env
を呼んでいるタイミングで落ちると思います。xonshがないので当然といえば当然です。
なので、mockを使います。
import unittest
from unittest.mock import patch, MagicMock
# 別ファイルにすると見栄えがいい
sample_xonsh = {
"env": {
# モックにしておきたい環境変数を作る
},
"execer": MagicMock()
}
mock_xonsh = MagicMock()
mock_xonsh.__getitem__.side_effect = sample_xonsh.__getitem__
mock_aliases = MagicMock()
# -------------------------
class TestSample(unittest.TestCase):
def setUp(self):
self.patcher_xonsh = patch('builtins.__xonsh__', new=mock_xonsh, create=True)
self.patcher_aliases = patch('builtins.aliases', new=mock_aliases, create=True)
self.mock_xonsh = self.patcher_xonsh.start()
self.mock_aliases = self.patcher_aliases.start()
def tearDown(self):
self.patcher_xonsh.stop()
self.patcher_aliases.stop()
def test_sample(self):
from xontrib.hellolib import hello
# テストを行う
if __name__ == "__main__":
unittest.main()
ポイントは
-
create=True
でパッチを作成すること(上書きではないので) - xontribのインポートは各テスト関数内で行うこと(patchより先にインポートしてしまうとモック化の意味がない(エラー))
- execerにMagicMockを代入しておくこと(execer.evalは関数なので引数を後から見れた方が良い感じ)
xontribのテストはモックの量がめちゃめちゃに多くなりそうで悲しくなっています。
また詰まったときは追記していきます。