Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
Pydantic x Database API:turu-pyの開発
Search
yassun7010
September 27, 2024
Programming
1
1.2k
Pydantic x Database API:turu-pyの開発
PyCon JP 2024 で登壇した、データ分析基盤を開発しているチームで Snowflake を安全に利用するために、 Turu-py というライブラリを開発した紹介のスライドです。
yassun7010
September 27, 2024
Tweet
Share
Other Decks in Programming
See All in Programming
Updates on MLS on Ruby (and maybe more)
sylph01
1
180
Putting The Genie in the Bottle - A Crash Course on running LLMs on Android
iurysza
0
140
Tool Catalog Agent for Bedrock AgentCore Gateway
licux
6
2.4k
go test -json そして testing.T.Attr / Kyoto.go #63
utgwkk
3
290
ソフトウェアテスト徹底指南書の紹介
goyoki
1
150
JSONataを使ってみよう Step Functionsが楽しくなる実践テクニック #devio2025
dafujii
1
520
ぬるぬる動かせ! Riveでアニメーション実装🐾
kno3a87
1
210
Compose Multiplatform × AI で作る、次世代アプリ開発支援ツールの設計と実装
thagikura
0
140
パッケージ設計の黒魔術/Kyoto.go#63
lufia
3
430
ユーザーも開発者も悩ませない TV アプリ開発 ~Compose の内部実装から学ぶフォーカス制御~
taked137
0
150
ファインディ株式会社におけるMCP活用とサービス開発
starfish719
0
310
今だからこそ入門する Server-Sent Events (SSE)
nearme_tech
PRO
2
120
Featured
See All Featured
Context Engineering - Making Every Token Count
addyosmani
1
37
Writing Fast Ruby
sferik
628
62k
RailsConf 2023
tenderlove
30
1.2k
Understanding Cognitive Biases in Performance Measurement
bluesmoon
29
1.9k
Being A Developer After 40
akosma
90
590k
How STYLIGHT went responsive
nonsquared
100
5.8k
Why You Should Never Use an ORM
jnunemaker
PRO
59
9.5k
Faster Mobile Websites
deanohume
309
31k
It's Worth the Effort
3n
187
28k
How GitHub (no longer) Works
holman
315
140k
Rails Girls Zürich Keynote
gr2m
95
14k
Art, The Web, and Tiny UX
lynnandtonic
303
21k
Transcript
Pydantic x Database API Turu-py の開発 yassun7010 GitHub Repo
自己紹介 GitHub Account: yassun7010 所属企業: サイバーエージェント AI事業本部 バックエンドエンジニア 業務内容 小売事業のデータ分析基盤を開発中
Github ロ ゴ マ ー ク - ダ ウ ン ロ ー ド 無 料 の ア イ コ ン
本日のお題目 • 夢のクエリビルダへの挑戦! …と断念 • Turu-py の誕生:Pydantic x Database API
への転換
発表の動機 Python × Snowflake で 型ヒントの恩恵を受けた 型安全でロバスト な開発がしたかった
Snowflake - SaaS型データプラットフォーム - メリット • ストレージとコンピューティングが分離・個別にスケール可能 • パフォーマンスが優れている •
AI に向けた機能も豊富 デメリット • ローカル開発ができないため、自動テストに工夫が必要 • 独自の機能があるため ORM で利用できない機能も多い
当初は snowflake-sqlalchemy を検討する SQLAlchemy の V2 に対応していないことが判明(2024/05/28 PyCon応募時点) V2 を利用したかったためマージされるまで見送り
当初は snowflake-sqlalchemy を検討する SQLAlchemy の V2 に対応していないことが判明(2024/05/28 PyCon応募時点) V2 を利用したかったためマージされるまで見送り
SQLAlchemy V2 も型安全ではない SQLAlchemy V2 は、より SQL に近い書き方に変わったものの 型安全な開発ができていないのが現状
ところで Python 3.12 が出た ジェネリックプログラミングが非常に書きやすくなった。 これで何か遊びたい…
Snowflake を扱える データベースクライアント ライブラリを作ってみよう
ライブラリ開発の方針(ざっくり) • 静的解析の恩恵を受け、変更に強いチーム開発がしたい • コードの変更による影響範囲を自動検出。ロバストな開発によるチームの生産性の向上 • チームの学習コストを下げたい(よく知られた UI) • SQL
のクエリを知っていれば OK • 自動テストを簡単に書けるようにしたい • Mock 機能をライブラリ側で提供 • 複雑な機能は外部ライブラリに頼りたい • Pydantic を利用。省エネは大事 データサイエンティストの多いチーム。みんな SQL が書けた。 分析が主な用途だったので 複雑な SQL 文 を書けることが重要。
クエリ文字列で型推論 クエリビルダで型推論 クエリ文から 戻り値の型を 推測してくれたらなぁ… まるでSQLのように 書けたらなぁ… 理想のデータベースアクセスを夢想する
理想のデータベースアクセスを夢想する クエリ文字列で型推論 クエリビルダで型推論 クエリ文から 戻り値の型を 推測してくれたらなぁ… まずこちらを検討 まるでSQLのように 書けたらなぁ…
余談:クエリ文字列でも開発しやすくなっている エディタ上で色がつく! 関数の補完も効く! 自動フォーマット・レコードの型推論が課題… リテラル文字列の多機能化は TypeScript が先行の印象
開発し始めてからしばらく…ついに
型安全なクエリビルダの検討…を断念 SELECT 文は複雑 単体のテーブルクエリは作れたが… 複数のテーブル合成の戻り型を作れず… フィールドの部分取得の 推論が困難 テーブルの結合が困難 CTEなどを型で表現できない テーブルのレコードを
そのまま返すのは可能
振り返り)ここが面白かった クラスでテーブルを表現する場合、直感的には Class:テーブル Instance:レコード ただし、 __init__ の型定義は上手くできない ※ 現状の dataclass_transform
という仕組みで コンストラクタ引数の型を指定できない Class / Instance プロパティ型を別に定義可能 SQLAlchemy などで実装実績あり User.id ⇨ Column[int] user.id ⇨ int クラスプロパティと インスタンスプロパティで 別の型を指定可能 コンストラクタは Field[int] を要求
振り返り)こんな機能があったらよかった 1. Generic な型を既定クラスにできれば… 2. dataclass_transform の機能不足 dataclass 風のクラスを作る機能。 コンストラクタ引数の型定義のために
converter が欲しかった (PEP 712 など 関連する議論 あり。前のスライドの問題) 3. プロパティを動的に型推論できれば… 写像や JOIN の結果を 型で表現できた… Proxy +追加機能で SQLの式を 定義できた…
(現状) 理想のクエリビルダを 作れないことはわかった…
Turu-py の誕生
コンセプトは Pydantic x Database API execute (query run) + map
(results validation) ⇨ execute_map メソッドを追加
ライブラリ開発の方針 • 静的解析の恩恵を受け、変更に強いチーム開発がしたい • コードの変更による影響範囲を自動検出。ロバストな開発によるチームの生産性の向上 • チームの学習コストを下げたい(よく知られた UI) • SQL
のクエリを知っていれば OK • PEP 249: Python Database API Specification v2.0 • 複雑な機能は外部ライブラリに頼りたい • Pydantic ・既存のDBクライアントを利用。省エネは大事 • 自動テストを簡単に書けるようにしたい • Mock 機能をライブラリ側で提供
PEP 249:Python Database API Specification v2.0 データベースクライアントが実装すべき API ・非常に枯れている(1999年〜) ・異なる
DB を同じインターフェースで扱える ・複数のデータベースサポートが容易 ・学習コストが少ない これを前提にすると…
Turu-py は戻り値の型を保証した Database API execute execute_map turu-py の追加機能 +Map to
Pydantic Model
余談: Snowflake 向けの特殊機能 Snowflake 拡張 Pandas / PyArrow への対応 Pandera
による Dataframe の検証への対応
多くの PEP 249 に従った Python ライブラリが存在 PEP 249 に従った typing.Protocol
を定義して 各lib の conn を受け取れば楽できないか PostgreSQL:psycopg2 MySQL:mysql-connector-python SQLite:sqlite3 Snowflake:snowflake-connector-python DuckDB:duckdb BigQuery:google-cloud-bigquery データベースとのやり取りは既存のライブラリにお任せ
Protocol とは ライブラリ間の依存関係はないから継承より Protocol が適切 どの DB クライアントも PEP に従っているから大丈夫
検討理由 Protocol: 継承ではなく ダックタイピングによる型安全 Protocol の利用イメージ 各ライブラリが提供する Connection クラスを そのまま渡せば動くかな?
Protocol は上手くいかなかった 定義が厳密に一致していないといけない だがしかし! • 引数名が微妙に違う(parameters ≠ params) • 引数の型が微妙に違う(
Sequence ≠ list ) • 各ライブラリには独自の追加引数があったり… 本来ならば PEP 249 のメソッド仕様の一部
Protocol は上手くいかなかった 定義が厳密に一致していないといけない だがしかし! • 引数名が微妙に違う(parameters ≠ params) • 引数の型が微妙に違う(
Sequence ≠ list ) • 各ライブラリには独自の追加引数があったり… 本来ならば 検討したすべてのライブラリが不一致 結局ラッパークラスを各 DB ごとに定義
Pydantic と DB Client を 直接使うだけでいいのでは?
NO! 時代はデータベース SaaS 時代 分散トランザクション・AI 機能・ベクトルデータの対応など SQL で独自機能が加わったデータベースの SaaS で利益が出せる時代
PostgreSQL・MySQL・SQLite のようなコンテナデータベースと異なり 複数人が同時に自動テストを行うことは困難 クラウドネイティブのデータベースは自動テストしにくい 独自の方言を持つクラウドネイティブ DB ビジネスの発展
Turu-py による自動テスト用モックの提供 Snowflake はローカル環境を提供しないため 自動テストが困難 期待値を型安全に注入できるモックツールを用意 本番コードだけでなく 自動テストでも型安全に テスト方法を公式が提供し、コードの作法を統一 ライブラリは自動テスト用のモック機能も提供すべき
テストデータ挿入 テストデータで実行 モッククライアント作成
チームでの利用例:レコード機能 + モック クエリの正しさは実際のデータベースで動作確認 したいが Snowflake はローカル上で実行できない 妥協案として テストデータを簡単に作れる 方針を採用
① ローカル環境時に dev 環境の Snowflake を実行 ENABLE_RECORDING 環境変数が true の場合のみ Git レポジトリ上の自動テストデータ を更新 ③ 自動テストでは記録したデータを再生
まとめ 型安全なクエリビルダに挑戦 テーブル結合の結果の戻り型を自動生成できず断念 でも Python 3.12 のジェネリックプログラミングは快適 Pydantic x Database
API でシンプルな turu-py を作成 自動テスト用のモック機能をライブラリ側で用意
おまけ: 懲りずに型安全なクエリビルダ snowman-py ターゲットDBを Snowflake に限定 INSERT / UPDATE を最初の標的
• 単一テーブルで完結できる • 定型のクエリ記述量が多い 型安全にできる機能を徐々に拡大中
おわり