yaml でスキーマを定義し、それを使用して読み取り、 (または他のスキーマ検証ツールで)pyyaml
検証できるようにしたいと考えています。voluptuous
ただし、質問のタイトルに記載されているように、組み込みクラスstr
を文字列表現ではなく官能的にインスタンス化する必要があります。
from voluptuous import Schema
import yaml
y = '''
a: str
b: int
c:
d: float
e: str
'''
yaml_schema = yaml.load(y,
Loader=yaml.CLoader)
schema1 = Schema(yaml_schema, required=True)
str
ただし、このスキーマは現在、 の唯一の許容値として文字列を探していますa
。直接 pyyaml (例: 'a': !!python/int) を使用すると失敗します。代わりに、以下のスキーマが必要です。
schema2 = Schema({'a': str,
'b': int,
'c': {'d': float,
'e': str}},
required=True)
eval
これが本番ソリューションではないことは十分承知していますが、evaler
以下の関数は次のように変換schema1
されschema2
ます...
def evaler(d):
out = {}
for k, v in d.items():
if isinstance(v, dict):
out[k] = evaler(v)
else:
out[k] = eval(v)
return out
## Tests:
## passing
v.Schema(evaler(yaml_schema),
required=True)({'a': 'foo',
'b': 2,
'c': {'d': 2.0,
'e': 'bar'}})
## failling
v.Schema(evaler(yaml_schema),
required=True)({'a': 3,
'b': 2,
'c': {'d': 2.0,
'e': 1}})
また、空のクラスをインスタンス化できることも認識しています。
class foo: pass
globals()['foo']
しかし、ビルトインではこれは不可能です:
globals()['int']
# KeyError: 'int'
new
およびモジュールを調査しましたtype
が、運がありませんでした...