ほんとの手

主に開発や仕事のメモクリップ

dbt で Python UDF をテストファーストで作成する

dbt で Python UDF をテストファーストで作成する方法についての記事です。データウェアハウスは Snowflake で動作確認しています。

作成

macro で UDF を作成する

dbt で UDF を作成する方法について調べると、コミュニティの記事が見つかります。この内容を踏襲し、UDF を作成するマクロを作成してこれを実行することで dbt 実行時に UDF を自動で作成できるようにします。

// macro/create_function/python/create_function_add_col.sql

{% macro create_function_add_col() %}
create or replace function {{target.schema}}.f_py_add_col(
  json_str varchar,
  col_name varchar,
  col_value varchar
)
  returns varchar
  language python
  runtime_version = '3.8'
  handler = 'main'
as $$

import json

def main(json_str, col_name):
  try:
    obj = json.loads(json_str)
  except:
    return None

  obj[col_name] = 'col_value'
  return json.dumps(obj)

$$;
{% endmacro %}
  • macros/create_function/python/ 配下にマクロファイルを作成する(フォルダ名はお好み)
  • {{ target.schema }} で作成先のスキーマを指定する
  • create or replace function にして、関数が存在していても必ず置き換えるようにする
  • UDF の定義の記述については DWH の仕様に従う
    • snowflake だと、runtime_version の指定が必須、とかがあった
    • パラメータ、戻り値を varchar でやり取りしているが、VARIANT でもいいかも

pre_hook で UDF を利用するモデルの前処理で関数を作成する

UDF を利用する前に上記の macro を実行して関数を定義しておく必要がありますが、dbt_project.yml の on-run-start ではなく利用するモデルの config で pre_hook でマクロ実行することにより事前の定義を行うことにします。どちらが良いかは諸説ありそうですが、私の場合はどのモデルで利用しているかの関連性が明確になるようにモデル内の config で定義するようにしています。

// models/ ... /<model_name>.sql

{{ config(pre_hook=[create_function_add_col()]) }}

...

テスト

singular テストで、テストファーストで関数を実装する

UDF の実装はデータの準備、関数の定義、クエリの実行、UDF 内の関数の実行と複数のステップがあり、一つずつ挙動を確認しながら実装していくと時間が掛かります。そこで、dbt の singular テストを先に作成してテストが通るように実装していくことで実行→修正のサイクルを短く早く回していけるようにします。

// tests/singular/macros/create_function/python/create_function_add_col.sql

{# NOTE: 事前に create_function_add_col() の実行が必要 #}

{% set inputs = [
    '{"col_1": "a"}',
    '{"col_1": "a", "col_2": "b"}'
] %}

with

test1_src as (
    {# test: 値が1つある #}
    select
        '{{ inputs[0] }}'::varchar as input,
        '{"col_1": "a", "col_a": "col_value"}'::varchar as expected

    {# test: 値が2つある #}
    union all select
        '{{ inputs[1] }}'::varchar as input,
        '{"col_1": "a", "col_2": "b", "col_a": "col_value"}'::varchar as expected
),

test1_result as (
    select
        *,
        {{target.schema}}.f_py_add_col(input, 'col_a') as result
    from test1_src
    where
        coalesce(result, '') != expected
),

final as (
    select * from test1_result
    -- 他のテストを追加した場合は最後に union する
    -- union all
    -- select * from test2_result
)

select * from final
  • tests/singular/macros/create_function/python/ 配下に singular テストファイルを作成する(フォルダ名はお好み)
  • 入力するデータは JSON 文字列でベタ書きする。jinja を使って配列化するなど効率よく記述してもよい
  • CTE で分けて、src に input, expected、result に result の値を記述して UDF の入力値、期待する返り値、実際の結果を出力する。結果が一致しない ( != expected ) 場合は singular テストが fail する
  • dbt test -s create_function_add_col を実行し、テストを修正・追加したり UDF を修正したりして実装を進めていく

モデルで UDF を利用する

UDF の実装が完了したら、モデル側で利用します。

// models/ ... /<model_name>.sql

{{ config(pre_hook=[create_function_add_col()]) }}

with
import as (select * from {{ ref('ref_model') }}),

add_col as (
    select
        *,
        parse_json({{target.schema}}.f_py_add_col(col_1, 'new_col')) as col_2
    from import
),

extracted as (
    select
        t1.*,
        (row_number() over (partition by t1.id order by t2.value::varchar)) + 1 as index,
        t2.value::varchar as t2_val
    from
        add_col t1,
        lateral flatten(INPUT => t1.col_2) as t2
)

select * from extracted
  • UDF 実行時も頭に {{ target.schema }} をつけてスキーマを指定する
  • VARIANT を lateral flatten を使って複数行に展開する
  • 展開元のデータの順序を扱いたい場合、row_number() を使って行番号を出力する

dbt で UDF を作成・利用すると、モデルと同様にコード管理できるようになったりテストが書きやすくなってよいですね。dbt での UDF 利用のご紹介でした。

NURO光環境でDMZを使って別のルータをメインルータにする(ネットボランチDNSもやりたい)

調べた内容のメモです。まだ実践はしていない。

tech.blog.uribou.me

https://4mo.co/nuro-onu-with-your-own-router/を使う - 気さくなエンジニ屋)

www.nedia.ne.jp

www.hikari-au.net

takewind.net

fushiroyama.hatenablog.com

デジタルルームミラーを探す (海外編)

真面目な記事ではなく、ブックマーク整理記事。

デジタルルームミラーを探している。高品質は求めていないので、aliexpress を中心に物色する。

情報

車検もコレでOK!サイズ別ルームミラーモニターおすすめ20選|2画面モデルも | Picky's

【プロに聞いた】ルームミラー型ドライブレコーダーおすすめランキング41選を徹底比較|2023年版 by 車選びドットコム

中華製 ミラー型 ドライブレコーダーに関する情報まとめ - みんカラ

海外製 ミラー型ドライブレコーダーに関する情報まとめ - みんカラ (2ページ目)

シガーソケット裏から、分岐でIG電源/ACC電源を取り出す方法

エブリィにオススメ。デジタルインナーミラーを自分で取り付ける方法・使ってみたレビュー | DIYでプチカスタム

電源の取り方

メーカー別

AKEEYO

中国のメーカー。日本国内に正規販売店がある。品質は相対的に高めではありそう。 60FPS 対応を出しているメーカーのうちの一つ。MAXWIN も出してるらしい。 国産品ではどうなのかは知らない。ざっと見た感じほとんどなさそう(基本 30 FPS 以内)

AKEEYO()の評価・評判・口コミ|パーツレビューのみんカラ

AKEEYO デジタルミラー型ドライブレコーダー のパーツレビュー | コペン(しろこぺん) | みんカラ

AKEEYOのドライブレコーダーのまとめ

https://www.aliexpress.com/item/1005002599789341.html

OBEPEAK

多分中国のメーカー。情報が少ない。 安かろう、そこそこ、の雰囲気を感じている

どう考えても地雷ガジェットぽいけど前から欲しかったAndroid8.1搭載ルームミラー | 徒労日記

Imagebon

安かろう、そこそこ。OBEPEAK との差は不明

https://www.aliexpress.com/item/1005004917027218.html

360 度カメラ

これはおまけ

https://www.aliexpress.com/item/1005004917027218.html

その他は後で追記する

panasonic strada hdd 交換

ブラウザのタブ整理のためにリンクをまとめる。

HDDカーナビのSSD化: 心に和み

HDD のパスワード解除して SSD にコピーするまでの手順。

https://w.atwiki.jp/hddnavi2sdd/pages/17.html

wiki。報告コメントもちらほら。

http://car.panasonic.jp/support/manual/navi/data/h500d_wdtop.html

説明書。操作の参考に。

メモ: 映像から音を予測

ledge.ai

japan.zdnet.com

「映像に適した音がつく」(事実)と、「この絵・映像に音をつけたい」(表現)は認知による歪み、違いがある それを踏まえたライブラリやエンジン作成という需要はありそうだ

ブラウザのタブ棚卸し 2020-12-12

ts-node で TypeScript + node をサクッと実行する - Qiita

TypeScript で node 実行

テスト観点に基づくテスト開発方法論 VSTePの概要

PDF。テストモデリング(観点図)の解説

その後の『テストから見えてくるグーグルのソフトウェア開発』 - blog.8-p.info

SET から SETI への発展的解消。SRE もそうなるのか。(2017年の記事)

https://www.amazon.co.jp/dp/B086L8ZRRH

ほめ方叱り方。何となくできている気はするけど、網羅的な復習のために読みたい

棒グラフのデザイン集 | おしゃれで伝わるグラフの作り方|かわちゃん|note

棒グラフ。細かな OK/NG 例がわかりやすい

ソフトウェアテスト自動化カンファレンス2020

testautomationresearch.connpass.com

イベントのページ

LeanとDevOpsの科学[Accelerate]で統計学的に証明されていること|諏訪真一|note

組織のパフォーマンス向上を促すケイパビリティ。確か自動テストの効果を数値化する発表でコメントに貼られてた

ASTER-テスト設計コンテスト

テスト設計コンテスト

E2Eテストの面倒くさいことはCodeceptJSにお願いしよう - Qiita

CodeceptJS。WebdriverIO, Puppeteer など複数のテストツールのラッパー

E2Eテストのflakyと向き合う / stac2020 - Speaker Deck

flaky とは何か。flaky が出てきたらどうするか(を決めておくことが大事)

https://dl.acm.org/doi/abs/10.1145/3377813.3381370

Apple の flaky テストのモデリング・ランキングの論文

reg-suitとQA Wolfを活用したVisual Regression Test

エムスリーのビジュアルリグレッションテスト。ツールは使うけど目視がいいところは目視で

中の人が語るテスト自動化SaaSのCS - カスタマーサポート、そしてサクセスへ - STAC 2020 - Speaker Deck

Autify の人の発表。「このテスト動かないんだけど」の対応は人力

三国志

https://w.atwiki.jp/banba/pages/16.html#id_10efcda6 - えろっち鍋改 三國志 初代)

https://w.atwiki.jp/gcmatome/pages/5918.html

三国志7wiki【12/8更新】 - アットウィキ

三國志Ⅶ 三国志7 攻略メモ|kolooko|note

三国志7攻略サイト

まだまだ三国志やりたい。今は7やってる

ブラウザのタブ棚卸し 2020-12-10

OpenWrt

鉄PCブログ – 日々大破、それと側転少々。PC関連で気になったことをつらつらと。

OpenWrt の PR をこまめに出している人

ルータ一覧/ELECOM - DD-WRT OpenWrt 適材適所で両方使いたい人向け @ ウィキ - アットウィキ

OpenWrt が導入できる機器の一覧

仕事など

2021年 は Fullstack Next.js 元年なので、有望な Next.js 系フレームワークを全部試した

Next.js サッと使えるようになっておかないとなー

polyfill を深堀りする - mizdra's blog

polyfill の歴史や使う時の基本知識

JavaScript 長いループ 分割 - hitode909の日記

メインスレッドをブロックしないように処理を分割する

ブロック記号 - commentart2 @ ウィキ - アットウィキ

ブロック記号の一覧。プログレスバーの調査をしているときに見つけた

Unicode ブロック要素 - CyberLibrarian

ブロック記号

【保存版】個人事業主が年末にできる節税、年間を通してする節税 - INTERNET Watch

今年は副業の収入が少ないからあまり参考にならないかも

ゲーム

KOEI 三国志まとめサイト

三国志の攻略ページ

RumblingDice Main

三国志の攻略ページ(web.archive.org より)