A simple and powerful validation library for Python.
Project description
ValidKit
ValidKit は、「直感的なスキーマ定義」と「日本語キーへの完全対応」を特徴とする、Python 用の軽量バリデーションライブラリです。
複雑にネストされた設定ファイルや、Discord ボットのユーザー設定、外部 API からのレスポンスなどを、シンプルかつ堅牢に検証するために設計されました。Pydantic ほど重厚ではなく、しかし辞書ベースの柔軟性と強力なチェーンメソッドを提供します。
最新リリースは 1.2.1 です。Schema[T] による IDE 補完、.coerce() による型変換、.default() / .examples() / .description()、Schema.generate_sample()、v.auto_infer() に対応しています。
🚀 なぜ ValidKit なのか?
- クラス定義不要: 辞書そのものがスキーマになります。既存の JSON/YAML 構造をそのまま定義に落とし込めます。
- 日本語キーにフレンドリー:
v.str()やv.int()を日本語のキー名と組み合わせて、可読性の高いバリデーションを記述できます。 - 高度な検証をシンプルに: 正規表現、数値範囲、カスタム関数、さらには「他のフィールドの値に応じた検証(条件付き検証)」も直感的に書けます。
- 仕様書づくりにも強い:
Schema.generate_sample()で設定テンプレートを生成し、v.auto_infer()で既存データからスキーマを逆生成できます。 - モダンな開発フロー: SLSA v3 準拠の来歴証明(provenance)に対応し、サプライチェーンの安全性を確保しています。
目次
最近のアップデート
- v1.2.1
v.auto_infer(data, type_map=None, schema_overrides=None)を追加Schema.generate_sample()の安全性を改善し、制約を満たせない候補はValueErrorを返すように修正.range()/.min()/.max()の境界矛盾を定義時に検出するよう改善
- v1.2.0
.default()/.examples()/.description()を追加Schema.generate_sample()でスキーマからサンプル設定を生成可能に
- v1.1.x
Schema[T]とvalidate()の型補完対応を強化.coerce()による自動型変換を追加
詳細は CHANGELOG.md を参照してください。API の詳説は docs/index.md にまとめています。
インストール
pip install validkit-py
クイックスタート
わずか数行で、複雑なデータ構造を検証できます。
from validkit import v, validate, ValidationError
# スキーマ定義:辞書の形がそのままバリデーション構造になります
SCHEMA = {
"ユーザー名": v.str().regex(r"^\w{3,15}$"),
"レベル": v.int().range(1, 100),
"スキル": v.list(v.oneof(["火", "水", "風"])),
"設定": {
"通知": v.bool(),
"言語": v.oneof(["日本語", "English"]).optional()
}
}
data = {
"ユーザー名": "nana_kit",
"レベル": 50,
"スキル": ["火", "風"],
"設定": {"通知": True} # 言語は optional なので省略可能
}
try:
# 検証実行
validated = validate(data, SCHEMA)
print(f"検証成功!レベル: {validated['レベル']}")
except ValidationError as e:
# どこで何がエラーになったか、分かりやすいパスが表示されます
print(f"エラー発生箇所: {e.path} - {e.message}")
特徴
- 📝 直感的なチェインメソッド —
v.int().range(1, 10).optional()のように流れるように記述。 - 🏷️ クラス記法対応 — Python クラスの型アノテーションをそのままスキーマとして使えます。
Optional[T]・List[T]・Dict[K,V]・カスタム型にも対応。 - 🌏 日本語キー対応 — 日本語のキー名をそのまま扱えるため、仕様書に近いコードが書けます。
- 🧠 型補完に強い —
Schema[T]と TypedDict を組み合わせると、IDE / 型チェッカーが戻り値の形を推論できます。 - 🔄 強力な変換・マイグレーション — 旧形式から新形式へのキー名変換や、値の動的変換を検証時に同時に行えます。
- 🛠️ デフォルト値とサンプル生成 —
.default()・.examples()・.description()とSchema.generate_sample()で設定テンプレート作成にも向きます。 - 🔍 全エラーの一括収集 — 最初のエラーで止まらず、すべての不備を洗い出すことが可能です。
API 例
詳細なリファレンスは docs/index.md、版ごとの変更点は CHANGELOG.md を参照してください。
基本バリデータ
v.str(): 文字列v.int()/v.float(): 数値v.bool(): 真偽値v.list(schema): リスト(要素のスキーマを指定)v.dict(key_type, value_schema): 辞書v.instance(type_cls): 任意のクラスの isinstance チェック
修飾メソッド
.optional(): 必須でないフィールドにする.default(value): 値がない場合のデフォルト値を指定(自動的に.optional()扱いとなる).examples(list): サンプル生成やドキュメント用の具体例を設定.description(str): フィールドの説明文を設定.regex(pattern): 正規表現チェック.range(min, max)/.min(val)/.max(val): 範囲または文字列長チェック(min <= maxが必須。不正な境界は定義時にValueError).custom(func): 独自の変換・検証ロジックを注入.coerce(): 入力値の型を自動的に変換(例:"123" -> 123)
高度な使い方
クラス記法によるスキーマ定義
辞書スキーマに加えて、Python のクラス型アノテーションをそのままスキーマとして使えます。
基本的なアノテーション
from validkit import v, validate
class UserProfile:
name: str
age: int
score: float
active: bool
data = {"name": "Alice", "age": 30, "score": 9.5, "active": True}
result = validate(data, UserProfile)
# -> {"name": "Alice", "age": 30, "score": 9.5, "active": True}
Optional / List / Dict など typing モジュールの型
from typing import Dict, List, Optional
from validkit import validate
class ServerConfig:
host: str
port: int
tags: Optional[List[str]] # 省略可能なリスト
metadata: Dict[str, int] # 辞書
# tags は省略してもエラーにならない
result = validate(
{"host": "db.local", "port": 5432, "metadata": {"connections": 10}},
ServerConfig,
)
# -> {"host": "db.local", "port": 5432, "metadata": {"connections": 10}}
Python 3.9 以降では list[T] / dict[K, V] の組み込みジェネリクス記法も使えます。
class Report:
scores: list[int]
labels: dict[str, str]
カスタム型 (オリジナルクラス)
任意のクラスをアノテーションに使うと、isinstance チェックが自動的に行われます。
from validkit import validate
class Timezone:
def __init__(self, name: str) -> None:
self.name = name
UTC = Timezone("UTC")
class Config:
name: str
age: int
timezone: Timezone # カスタム型 → isinstance チェック
result = validate({"name": "server1", "age": 5, "timezone": UTC}, Config)
v.instance() を使うと辞書スキーマ内でも同じチェックができます。
from validkit import v, validate
schema = {
"name": v.str(),
"timezone": v.instance(Timezone).default(UTC),
}
result = validate({"name": "server1"}, schema)
# timezone は省略時に UTC が補完される
クラス属性によるデフォルト値と Validator の組み合わせ
クラス属性に具体的な値を設定するとデフォルト値として機能します。 Validator インスタンスを直接クラス属性にすることで、詳細な制約も記述できます。
from typing import Optional
from validkit import v, validate
class Config:
host: str # 必須
port: int = 5432 # デフォルト値 5432
ssl: bool = False # デフォルト値 False
timeout: Optional[int] = 30 # オプション + デフォルト
role = v.str().default("worker") # Validator で詳細に定義
result = validate({"host": "db.local"}, Config)
# -> {"host": "db.local", "port": 5432, "ssl": False, "timeout": 30, "role": "worker"}
対応型ヒント一覧
| アノテーション | 動作 |
|---|---|
str / int / float / bool |
型チェック |
Optional[T] / Union[T, None] |
内部型をチェック・省略可能 |
List[T] / list[T] |
リスト要素の型チェック |
Dict[K, V] / dict[K, V] |
辞書の値の型チェック |
| 任意のクラス | isinstance チェック |
Any / 不明な型 |
チェックなし(パススルー) |
Validator インスタンス |
ValidKit の完全なバリデーション |
注意:
Union[int, str]/Union[int, str, None]やint | str/int | str | Noneのように、None以外の複数型を持つ Union は現在サポートしていません。validate()の呼び出し時(スキーマ変換フェーズ)にTypeErrorが送出されます。代わりにOptional[T](=Union[T, None])か具体的な単一型を使用してください。複数の型を受け付けたい場合はv.instance(MyBaseClass)などを検討してください。
IDE 補完を効かせる(TypedDict + Schema)
Schema[T] クラスを使うと、IDE(PyCharm / VS Code)での型補完が有効になります。
from typing import TypedDict
from validkit import v, validate
class UserDict(TypedDict):
name: str
level: int
data = {"name": "nana_kit", "level": 50}
plain_schema = {"name": v.str(), "level": v.int()}
result: UserDict = validate(data, plain_schema) # IDE への型ヒントは変数側で提供
注意:
collect_errors=Trueを指定した場合、validateはValidationResultを返します。そのため、Schema[T]を使っていても戻り値の型はTではなくValidationResultになります。
TypedDict を書くのが面倒な場合は、既存の辞書スキーマを渡す使い方もそのまま使えます。 型補完が不要なケースでは、変数側に型注釈を書くことで mypy / pyright に型を伝えられます。
# 型付きスキーマなし(従来の辞書スキーマ)— 変数側にアノテーションを付ける方法
plain_schema = {"name": v.str(), "level": v.int()}
result: UserDict = validate(data, plain_schema) # IDE への型ヒントは変数側で提供
デフォルト値の自動補完 (.default)
スキーマ定義時にデフォルト値を設定しておくと、データにそのキーが含まれていない場合に自動的に補完されます。
from validkit import v, validate
SCHEMA = {
"host": v.str().default("localhost"),
"port": v.int().default(5432),
}
# どちらも未指定でも、デフォルト値が補完される
result = validate({}, SCHEMA)
# -> {'host': 'localhost', 'port': 5432}
ネストされた辞書やリスト内でも同様に動作します。
サンプルデータの自動生成 (generate_sample)
定義したスキーマから、仕様書の雛形や設定ファイルのテンプレートとして使えるサンプルデータを自動生成できます。生成された値は各バリデータで再検証されるため、regex() や custom() を満たせない不正なサンプルは返しません。
from validkit import v, Schema
SCHEMA = Schema({
"app_name": v.str().examples(["MyAwesomeApp"]),
"port": v.int().default(8080).description("待機ポート"),
"debug": v.bool().default(False),
})
# スキーマからサンプルを辞書形式で取得
sample = SCHEMA.generate_sample()
# -> {'app_name': 'MyAwesomeApp', 'port': 8080, 'debug': False}
生成の優先順位:
.default()で設定された値.examples()リストの最初の要素- 各型のダミー値(
str:"example",int:0,bool:False等)
regex() / custom() などで上記候補が制約を満たせない場合、generate_sample() は ValueError を送出します。その場合は妥当な .default(...) または .examples([...]) を与えてください。
スキーマを既存データから逆生成する (v.auto_infer)
既存の設定ファイルや API レスポンスがすでにある場合、v.auto_infer() で ValidKit スキーマのたたき台を作れます。
from datetime import date
from validkit import v, validate
raw = {
"name": "Alice",
"age": 30,
"active": True,
"created_at": date(2026, 3, 1),
}
schema = v.auto_infer(
raw,
type_map={date: lambda value: value.isoformat()},
schema_overrides={
"age": v.int().range(0, 150),
},
)
normalized = {
"name": "Alice",
"age": 30,
"active": True,
"created_at": "2026-03-01",
}
result = validate(normalized, schema)
使いどころ:
- 既存データからスキーマをブートストラップしたいとき
- カスタム型を
type_mapでプリミティブへ落として推論したいとき - 一部のフィールドだけ
schema_overridesで明示的に厳しくしたいとき
部分更新とデフォルト値のマージ (base引数)
既存の辞書データを「ベース」として、入力された不完全なデータをマージする場合に便利です。これは .default() よりも優先されます。
from validkit import v, validate
SCHEMA = {
"言語": v.oneof(["English", "日本語"]),
"音量": v.int(),
}
DEFAULT_CONFIG = {"言語": "English", "音量": 50}
user_input = {"音量": 80}
# partial=True で不足キーを許容し、base でデフォルト値を補完
updated = validate(user_input, SCHEMA, partial=True, base=DEFAULT_CONFIG)
# -> {'言語': 'English', '音量': 80}
マイグレーション
古いバージョンの設定データを自動的に新しい形式へ変換します。
from validkit import v, validate
SCHEMA = {
"通知": v.str(),
"timeout": v.str(),
}
old_data = {"旧設定": "on", "timeout": 30}
migrated = validate(
old_data,
SCHEMA,
migrate={
"旧設定": "通知",
"timeout": lambda value: f"{value}s",
},
)
自動変換 (Coercion)
入力データの型が期待される型と異なる場合に、自動的に変換を試行します。
from validkit import v, validate
SCHEMA = {
"id": v.int().coerce(),
"is_active": v.bool().coerce(),
}
data = {"id": "1001", "is_active": 1}
validated = validate(data, SCHEMA)
# -> {'id': 1001, 'is_active': True}
各バリデータの変換ルール:
v.str().coerce():str(value)による変換v.int().coerce():int(value)による変換v.float().coerce():float(value)による変換v.bool().coerce():- 文字列:
"true","1","yes","on"->True/"false","0","no","off"->False - 数値:
1->True/0->False
- 文字列:
品質管理・セキュリティ
サプライチェーンセキュリティ
本プロジェクトは in-toto / SLSA v3 準拠の provenance(来歴証明) を公開しています。 PyPI に公開された成果物が、正しいソースコードから正しい手順でビルドされたことを数学的に証明できます。
# slsa-verifier を使った検証例
slsa-verifier verify-artifact dist/validkit-*.whl \
--provenance multiple.intoto.jsonl \
--source-uri github.com/disnana/ValidKit
開発品質
以下のツールを CI で常時実行し、高いコード品質を維持しています。
- Ruff: 高速な Lint & フォーマット
- mypy: 厳格な静的型チェック
- pytest: 網羅的な単体テスト
変更履歴
- 版ごとの詳細な変更点は
CHANGELOG.mdを参照してください。 - API の詳しい説明は
docs/index.mdにあります。 - 現在の公開バージョンは
1.2.1です。
貢献ガイドライン
Issue の報告や Pull Request を歓迎します!詳細は SECURITY.md または Issue テンプレートを確認してください。
ライセンス
本プロジェクトは MIT ライセンスの下で公開されています。 詳細は LICENSE ファイルをご覧ください.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file validkit_py-1.2.3.tar.gz.
File metadata
- Download URL: validkit_py-1.2.3.tar.gz
- Upload date:
- Size: 20.2 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
8f8197fecf19b55a0ae1cba9e8f5594adb6c33d7a1ae302a841df60cb4746b07
|
|
| MD5 |
45f2fa8b5c41b03e097f953176799e42
|
|
| BLAKE2b-256 |
79da6bb4303a949b9d948d2eb3fb87ea408308417586b90a2fe5f387394dfe50
|
Provenance
The following attestation bundles were made for validkit_py-1.2.3.tar.gz:
Publisher:
ci.yml on disnana/ValidKit
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
validkit_py-1.2.3.tar.gz -
Subject digest:
8f8197fecf19b55a0ae1cba9e8f5594adb6c33d7a1ae302a841df60cb4746b07 - Sigstore transparency entry: 1107704454
- Sigstore integration time:
-
Permalink:
disnana/ValidKit@294b2616eb68147512a8b29c584024cb2f4e827f -
Branch / Tag:
refs/heads/main - Owner: https://github.com/disnana
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
ci.yml@294b2616eb68147512a8b29c584024cb2f4e827f -
Trigger Event:
push
-
Statement type:
File details
Details for the file validkit_py-1.2.3-py3-none-any.whl.
File metadata
- Download URL: validkit_py-1.2.3-py3-none-any.whl
- Upload date:
- Size: 22.2 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
01ad034f941c6178b42a87a07d1c0ce2ec5867491d8740181720ab89a205fcc1
|
|
| MD5 |
4159c5372d69f8f685a61bd65ecd0a6b
|
|
| BLAKE2b-256 |
a10efced4880d692534d1889bce300da648ba80d4794d2769bb905359e791a75
|
Provenance
The following attestation bundles were made for validkit_py-1.2.3-py3-none-any.whl:
Publisher:
ci.yml on disnana/ValidKit
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
validkit_py-1.2.3-py3-none-any.whl -
Subject digest:
01ad034f941c6178b42a87a07d1c0ce2ec5867491d8740181720ab89a205fcc1 - Sigstore transparency entry: 1107704456
- Sigstore integration time:
-
Permalink:
disnana/ValidKit@294b2616eb68147512a8b29c584024cb2f4e827f -
Branch / Tag:
refs/heads/main - Owner: https://github.com/disnana
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
ci.yml@294b2616eb68147512a8b29c584024cb2f4e827f -
Trigger Event:
push
-
Statement type: