Skip to content

Commit 229ff7c

Browse files
committed
Add snake_to_camel and transform_options utils
Also add tests
1 parent 7355175 commit 229ff7c

File tree

2 files changed

+94
-1
lines changed

2 files changed

+94
-1
lines changed

labkey/utils.py

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
from functools import wraps
1818
from datetime import date, datetime
1919
from base64 import b64encode
20+
from typing import List
2021
from urllib import parse
2122

2223

@@ -91,3 +92,34 @@ def waf_encode(value: str) -> str:
9192
if value:
9293
return "/*{{base64/x-www-form-urlencoded/wafText}}*/" + btoa(encode_uri_component(value))
9394
return value
95+
96+
97+
def snake_to_camel(value: str):
98+
"""
99+
Converts a snake_case string to camelCase
100+
"""
101+
if not value:
102+
return value
103+
104+
if "_" not in value:
105+
return value
106+
107+
parts = [part for part in value.split("_") if part]
108+
109+
if len(parts) == 0:
110+
return ""
111+
112+
return parts[0].lower() + "".join([part.title() for part in parts[1:]])
113+
114+
115+
def transform_options(options: dict, expected_keys: List[str]) -> dict:
116+
"""
117+
Converts a dict with snake_case keys to a new dict with camelCase keys, only copying keys from expected_keys
118+
"""
119+
transformed_options = {}
120+
121+
for key, item in options.items():
122+
if key in expected_keys:
123+
transformed_options[snake_to_camel(key)] = item
124+
125+
return transformed_options

test/unit/test_utils.py

Lines changed: 62 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
from labkey.utils import btoa, encode_uri_component, waf_encode
1+
from labkey.utils import btoa, encode_uri_component, waf_encode, snake_to_camel, transform_options
22

33

44
def test_btoa():
@@ -30,3 +30,64 @@ def test_waf_encode():
3030
waf_encode("><&/%' \"1äöüÅ")
3131
== prefix + "JTNFJTNDJTI2JTJGJTI1JyUyMCUyMjElQzMlQTQlQzMlQjYlQzMlQkMlQzMlODU="
3232
)
33+
34+
35+
def test_snake_to_camel():
36+
assert snake_to_camel("snake_case") == "snakeCase"
37+
assert snake_to_camel("multiple_word_snake_case") == "multipleWordSnakeCase"
38+
assert snake_to_camel("alreadyCamelCase") == "alreadyCamelCase"
39+
assert snake_to_camel("single") == "single"
40+
assert snake_to_camel("UPPER_SNAKE_CASE") == "upperSnakeCase"
41+
assert snake_to_camel("_leading_underscore") == "leadingUnderscore"
42+
assert snake_to_camel("trailing_underscore_") == "trailingUnderscore"
43+
assert snake_to_camel("multiple__underscores") == "multipleUnderscores"
44+
assert snake_to_camel("") == ""
45+
46+
47+
def test_transform_options():
48+
options = {
49+
"include_columns": True,
50+
"include_system_queries": False,
51+
"include_title": False,
52+
"include_user_queries": False,
53+
"include_view_data_url": True,
54+
"query_detail_columns": False,
55+
}
56+
expected_keys = [
57+
"include_columns",
58+
"include_system_queries",
59+
"include_user_queries",
60+
"include_view_data_url",
61+
]
62+
transformed_options = transform_options(options, expected_keys)
63+
assert transformed_options == {
64+
"includeColumns": True,
65+
"includeSystemQueries": False,
66+
"includeUserQueries": False,
67+
"includeViewDataUrl": True,
68+
}
69+
assert transformed_options["includeColumns"] is True
70+
71+
# Empty options
72+
assert transform_options({}, ["any_key"]) == {}
73+
74+
# Empty expected_keys
75+
assert transform_options({"any_key": 1}, []) == {}
76+
77+
# Filtering behavior: only keys in expected_keys are kept and transformed
78+
options = {"keep_me": 1, "ignore_me": 2}
79+
expected = ["keep_me"]
80+
result = transform_options(options, expected)
81+
assert result == {"keepMe": 1}
82+
83+
# Keys in expected_keys but not in options are ignored
84+
options = {"present_key": "I am present!"}
85+
expected = ["present_key", "absent_key"]
86+
result = transform_options(options, expected)
87+
assert result == {"presentKey": "I am present!"}
88+
89+
# Non-snake_case keys that are in expected_keys
90+
options = {"alreadyCamel": 1, "simple": 2, "UPPER_SNAKE": 3}
91+
expected = ["alreadyCamel", "simple", "UPPER_SNAKE"]
92+
result = transform_options(options, expected)
93+
assert result == {"alreadyCamel": 1, "simple": 2, "upperSnake": 3}

0 commit comments

Comments
 (0)