Python入門 (10) - YAMLの構文チェック
「YAML」の構文チェックツール「Yamale」の使い方をまとめました。
前回
1. Yamale
「Yamale」は「YAML」の構文チェックツールです。
2. インストール
Pythonの仮想環境(3.6以降)で、以下のコマンドでインストールします。
$ pip install yamale
3. コマンドライン
「Yamale」は、コマンドラインから利用できます。検索対象フォルダで「YAML」を検索し、見つけたら同じフォルダにある「スキーマ」(構文定義ファイル)を使って、構文チェックを行います。
$ yamale [-h] [-s SCHEMA] [-n CPU_NUM] [-p PARSER] [--no-strict] [PATH]
PATH : YAMLの検索対象フォルダ (デフォルト:カレント)
-h, --help : ヘルプ
-s SCHEMA, --schema SCHEMA : スキーマの指定 (デフォルト:schema.yaml)
-n CPU_NUM, --cpu-num CPU_NUM : CPUの数 (デフォルト:4)
-p PARSER, --parser PARSER : YAMLライブラリ (ruamel, pyyaml(デフォルト))
--no-strict : strictモード無効
構文チェックの手順は、次のとおりです。
(1) チェック対象のYAMLの準備
・data.yaml
name: Bill
age: 26
height: 6.2
awesome: True
(2) スキーマの準備
・schema.yaml
name: str()
age: int(max=200)
height: num()
awesome: bool()
(3) 構文チェック。
$ yamale
Finding yaml files...
Found 1 yaml files.
Validating...
Validation success! 👍
5. API
「Yamale」は、APIからも利用できます。
import yamale
try:
# スキーマの準備
schema = yamale.make_schema('./schema.yaml')
# チェック対象のYAMLの準備
data = yamale.make_data('./data.yaml')
# 構文チェック
yamale.validate(schema, data)
except ValueError as e:
print('Validation failed!', e)
有効なデータの場合は何も起きず、無効なデータの場合はValueErrorが投げられます。
6. スキーマ
「Yamale」を使用するには、「スキーマ」を準備する必要があります。
6-1. データ型
キーとデータ型のペアを次のように定義します。
・スキーマ
optional: str(required=False)
optional_min: int(min=1, required=False)
min: num(min=1.5)
max: int(max=100)
・有効なデータ
optional_min: 10
min: 1.6
max: 100
主なデータ型は、次のとおりです。
・str() : 文字列
・int() : 整数
・num() : 数値
主なデータ型の引数は、次のとおりです。
・required : 必須かどうか
・min : 最小
・max : 最大
6-2. インクルード
ノードの構文定義を別途定義して、インクルードで呼び出すことで、繰り返しや再帰的に利用できるようにします。従来のスキーマとノード毎の構文定義は、「---」で区切って記述します。
・スキーマ
customerA: include('customer')
customerB: include('customer')
recursion: include('recurse')
---
customer:
name: str()
age: int()
custom: include('custom_type')
custom_type:
integer: int()
recurse:
level: int()
again: include('recurse', required=False)
・有効なデータ
customerA:
name: bob
age: 900
custom:
integer: 1
customerB:
name: jill
age: 1
custom:
integer: 3
recursion:
level: 1
again:
level: 2
again:
level: 3
again:
level: 4
6-3. リスト
リストの定義例は、次のとおりです。
・スキーマ
list_with_two_types: list(str(), include('variant'))
questions: list(include('question'))
---
variant:
rsid: str()
name: str()
question:
choices: list(include('choices'))
questions: list(include('question'), required=False)
choices:
id: str()
・有効なデータ
list_with_two_types:
- 'some'
- rsid: 'rs123'
name: 'some SNP'
- 'thing'
- rsid: 'rs312'
name: 'another SNP'
questions:
- choices:
- id: 'id_str'
- id: 'id_str1'
questions:
- choices:
- id: 'id_str'
- id: 'id_str1'
6-4. 最上位ノードがないリスト
最上位ノードがないリストの定義例は、次のとおりです。
・スキーマ
list(include('human'), min=2, max=2)
---
human:
name: str()
age: int(max=200)
height: num()
awesome: bool()
・有効データ
- name: Bill
age: 26
height: 6.2
awesome: True
- name: Adrian
age: 23
height: 6.3
awesome: True
7. データ型
データ型の引数には、必須かどうかを示すrequiredを必ず持ちます。デフォルトはTrueです。
str(required=False)
値のNoneを許さないことを示すには、noneを使用します。デフォルトはFalseです。
str(required=False, none=False)
7-1. String - str(min=int, max=int, exclude=string)
文字列。
◎ 引数
min : len(string) >= min
max : len(string) <= max
exclude : 除外すべき文字
◎ 例
str(max=10, exclude='?!')
7-2. Regex - regex([patterns], name=string, ignore_case=False, multiline=False, dotall=False)
正規表現の文字列。
◎ 引数
[pattern] : 1 つ以上の Python 正規表現のパターン
name : パターンの説明
ignore_case : 大文字と小文字を区別しない
multiline : パターン内の^と$は、文字列全体の最初と最後での一致に加え、文字列の各行の最初と最後で一致
dotall : 「.」が、改行以外の全ての文字に一致するだけでなく、検証済み文字列内の改行文字にも一致
◎ 例
regex('^[^?!]{,10}$')
regex(r'^(\d+)(\s\1)+$', name='repeated natural')
regex('.*^apples$', multiline=True, dotall=True)
7-3. Integer - int(min=int, max=int)
整数。
◎ 引数
min : int >= min
max : int <= max
7-4. Number - num(min=float, max=float)
数値。
◎ 引数
min : num >= min
max : num <= max
7-5. Boolean - bool()
ブーリアン値。
7-6. Null - null()
Null値の構文定義。
7-7. Enum - enum([primitives])
列挙値。
◎ 引数
primitives : 定数
◎ 例
enum('a string', 1, False)
7-8. Day - day(min=date, max=date)
年月日 (YYYY-MM-DD)。
◎ 引数
min : date >= min
max : date <= max
◎ 例
day(min='2001-01-01', max='2100-01-01')
7-9. Timestamp - timestamp(min=time, max=time)
年月日時分秒 (YYYY-MM-DD HH:MM:SS)。
◎ 引数
min : time >= min
max : time <= max
◎ 例
timestamp(min='2001-01-01 01:00:00', max='2100-01-01 23:00:00')
7-10. List - list([validators], min=int, max=int)
リスト。
◎ 引数
validators : データ型
min : len(list) >= min
max : len(list) <= max
◎ 例
list()
list(include('custom'), int(), min=4)
7-11. Map - map([validators], key=validator)
マップ。
◎ 引数
validators : データ型
key : キー
◎ 例
map()
map(str(), int())
map(str(), key=int())
7-12. IP Address - ip()
IPアドレス。
◎ 引数
version : 4 or 6
◎ 例
ip()
ip(version=4)
ip(version=6)
7-13. MAC Address - mac()
Macアドレス。
◎ 例
mac()
7-14. Any - any([validators])
共用体。
◎ 引数
validators : データ型
◎ 例
any(int(), null())
any(num(), include('vector'))
any(str(min=3, max=3),str(min=5, max=5),str(min=7, max=7))
any()
7-15. Subset - subset([validators], allow_empty=False)
サブセット。
◎ 引数
validators : データ型
allow_empty : 空を許可するかどうか
◎ 例
subset(int(), str())
subset(int(), str(), allow_empty=True)
7-16. Include - include(include_name)
インクルード。
◎ 引数
include_name : インクルード名
◎ 例
include('person')
7-17. カスタム
import yamale
import datetime
from yamale.validators import DefaultValidators, Validator
class Date(Validator):
tag = 'date'
def _is_valid(self, value):
return isinstance(value, datetime.date)
validators = DefaultValidators.copy() # This is a dictionary
validators[Date.tag] = Date
schema = yamale.make_schema('./schema.yaml', validators=validators)
次回
この記事が気に入ったらサポートをしてみませんか?