Created
September 1, 2023 01:29
-
-
Save camsaul/c80a72ac0bf81475f0e33599ae9e1e06 to your computer and use it in GitHub Desktop.
Kebab Case Key Hating Map
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(ns metabase.util.kebab-hating-map | |
"This is a map type that catches attempts to get `:kebab-case` values from it. In prod, it logs a warning and gets the | |
value for the equivalent `snake_case` key; in tests and dev it throws an Exception. | |
This is here so we can catch driver code is still supposed to be using Toucan instances rather than MLv2 Metadata. | |
This is intended to be only temporary; after everything in the QP is converted to MLv2 we can remove this." | |
(:require | |
[clojure.string :as str] | |
[metabase.config :as config] | |
[metabase.driver :as driver] | |
[metabase.util :as u] | |
[metabase.util.log :as log] | |
[potemkin :as p] | |
[pretty.core :as pretty] | |
[toucan2.core :as t2] | |
[toucan2.instance :as t2.instance])) | |
(defn- kebab-cased-key? [k] | |
(str/includes? k "-")) | |
(defn- warn-about-using-kebab-case [k] | |
(let [e (ex-info (format "Driver %s is accessing legacy metadata using :kebab-case key %s. This is not supported yet. Use %s instead." | |
(or driver/*driver* "") | |
(pr-str k) | |
(pr-str (u/->snake_case_en k))) | |
{:driver driver/*driver*, :k k})] | |
(if config/is-prod? | |
(log/warn e) | |
(throw e)))) | |
(defn- normalize-key [k] | |
(if (kebab-cased-key? k) | |
(do | |
(warn-about-using-kebab-case k) | |
(u/->snake_case_en k)) | |
k)) | |
(declare ->KebabHatingMap) | |
(p/def-map-type KebabHatingMap [m] | |
(get [_this k default-value] | |
(get m (normalize-key k) default-value)) | |
(assoc [this k v] | |
(let [m' (assoc m (normalize-key k) v)] | |
(if (identical? m m') | |
this | |
(->KebabHatingMap m')))) | |
(dissoc [this k] | |
(let [m' (dissoc m k)] | |
(if (identical? m m') | |
this | |
(->KebabHatingMap m')))) | |
(keys [_this] | |
(keys m)) | |
(meta [_this] | |
(meta m)) | |
(with-meta [this metta] | |
(let [m' (with-meta m metta)] | |
(if (identical? m m') | |
this | |
(->KebabHatingMap m')))) | |
pretty/PrettyPrintable | |
(pretty [_this] | |
(list `kebab-hating-map m))) | |
(defn kebab-hating-map | |
"Create a new map that handles either `snake_case` or `kebab-case` keys, but warns is you use `kebab-case` keys (in | |
prod) or throws an Exception (in dev and tests). This is here so we can catch code that needs to be updated to use | |
MLv2 metadata in 48+." | |
([] | |
(->KebabHatingMap {})) | |
([m] | |
(if (t2/instance? m) | |
(t2.instance/update-current m ->KebabHatingMap) | |
(->KebabHatingMap (or m {})))) | |
([k v & more] | |
(->KebabHatingMap (into {} (cons [k v] (partition-all 2 more)))))) | |
(defn kebab-hating-map? [m] | |
(instance? KebabHatingMap m)) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment