toml==0.10.2 (2026/04/30 現在の最新リリース版) では str 派生型のオブジェクトが 1 文字ずつの配列として dump されてしまう。
回避策としては、明示的に str にキャストしておけばよい。
なお、この問題は toml リポジトリの master ブランチでは既に修正されている。
参考文献
- toml/encoder.py (2026/04/30 現在の最新リリース版 0.10.2)
- toml/encoder.py (2026/04/30 現在の master の最新リビジョン 65bab75)
再現コード
import torch
import toml
# torch.__version__ (torch.torch_version.TorchVersion 型) を toml.dumps するとおかしい。
d = {'torch_version': torch.__version__}
s = toml.dumps(d)
assert s == 'torch_version = [ "2", ".", "9", ".", "1", "+", "c", "u", "1", "2", "6",]\n'
# str 型にキャストしておけば問題は起きない。
d = {'torch_version': str(torch.__version__)}
s = toml.dumps(d)
assert s == 'torch_version = "2.9.1+cu126"\n'
原因
import torch
from toml.encoder import TomlEncoder
v = torch.__version__
encoder = TomlEncoder()
# toml.dumps が内部でコールする encoder.dump_value の結果がおかしい。
s = encoder.dump_value(v)
assert s == '[ "2", ".", "9", ".", "1", "+", "c", "u", "1", "2", "6",]'
# encoder.dump_value をエミュレートすると
# torch.torch_version.TorchVersion は str のサブクラスだが
# str そのものではないので str 用のダンプ関数を引き当てられない。
# その場合、イテラブルなら list 用のダンプ関数が適用されてしまう。
dump_fn = encoder.dump_funcs.get(type(v))
assert dump_fn is None
if dump_fn is None and hasattr(v, '__iter__'):
dump_fn = encoder.dump_funcs[list]
assert dump_fn == encoder.dump_list
assert dump_fn(v) == '[ "2", ".", "9", ".", "1", "+", "c", "u", "1", "2", "6",]'
# 最新版 (65bab75) の encoder.dump_value では isinstance による判定に修正されており
# torch.torch_version.TorchVersion にも str 用のダンプ関数が適用される。
dump_fn = next((f for t, f in encoder.dump_funcs.items() if isinstance(v, t)), None)
assert dump_fn(v) == '"2.9.1+cu126"'