Skip to content

Commit 7ead117

Browse files
committed
docs: clarify intent examples in docstrings and format code
- Update docstrings for `generate_templates` and `generate_facets` to show explicit examples for optional intent - Format code with `ruff`
1 parent 4ae80a5 commit 7ead117

File tree

7 files changed

+72
-62
lines changed

7 files changed

+72
-62
lines changed

mcp/facet/facet_generator.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,12 +31,14 @@ async def generate_facets_from_items(
3131
facet_text = item.get("sql_snippet", item.get("facet"))
3232
if not facet_text:
3333
# Skip malformed items or raise error? For now, we might want to be robust
34-
# But if both are missing, we might have an issue.
34+
# But if both are missing, we might have an issue.
3535
# Let's assume validation happened or we just let it fail later if None.
3636
# Actually, to be safe and avoid KeyError if strict logic elsewhere:
3737
raise KeyError("Each item must have a 'sql_snippet' or 'facet' key.")
3838

39-
intent = item.get("intent", question) # Use provided intent or fallback to question
39+
intent = item.get(
40+
"intent", question
41+
) # Use provided intent or fallback to question
4042

4143
# 1. Extract value phrases from the question
4244
phrases = await parameterizer.extract_value_phrases(nl_query=question)

mcp/main.py

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -48,9 +48,10 @@ async def generate_templates(
4848
Generates final templates from a list of user-approved question, SQL statement, and optional intent.
4949
5050
Args:
51-
template_inputs_json: A JSON string representing a list of dictionaries,
51+
template_inputs_json: A JSON string representing a list of dictionaries (template inputs),
5252
where each dictionary has "question", "sql", and optional "intent" keys.
53-
Example: '[{"question": "...", "sql": "...", "intent": "..."}]'
53+
Example (with intent): '[{"question": "How many users?", "sql": "SELECT count(*) FROM users", "intent": "Count total users"}]'
54+
Example (default intent): '[{"question": "List all items", "sql": "SELECT * FROM items"}]'
5455
sql_dialect: The SQL dialect to use for parameterization. Accepted
5556
values are 'postgresql', 'mysql', or 'googlesql'.
5657
@@ -70,9 +71,10 @@ async def generate_facets(
7071
Generates final facets from a list of user-approved question, SQL snippet, and optional intent.
7172
7273
Args:
73-
facet_inputs_json: A JSON string representing a list of dictionaries,
74+
facet_inputs_json: A JSON string representing a list of dictionaries (facet inputs),
7475
where each dictionary has "question", "sql_snippet", and optional "intent".
75-
Example: '[{"question": "...", "sql_snippet": "...", "intent": "..."}]'
76+
Example (with intent): '[{"question": "expensive items", "sql_snippet": "price > 1000", "intent": "Filter by high price"}]'
77+
Example (default intent): '[{"question": "active users", "sql_snippet": "status = 'active'"}]'
7678
sql_dialect: The SQL dialect to use for parameterization. Accepted
7779
values are 'postgresql', 'mysql', or 'googlesql'.
7880

mcp/model/context.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,4 +68,3 @@ class ContextSet(BaseModel):
6868
description="A list of SQL facets.",
6969
validation_alias=AliasChoices("facets", "fragments"),
7070
)
71-

mcp/template/template_generator.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,9 @@ async def generate_templates_from_items(
2828
for item in item_list:
2929
question = item["question"]
3030
sql = item["sql"]
31-
intent = item.get("intent", question) # Use provided intent or fallback to question
31+
intent = item.get(
32+
"intent", question
33+
) # Use provided intent or fallback to question
3234

3335
# 1. Extract value phrases from the question
3436
phrases = await parameterizer.extract_value_phrases(nl_query=question)

mcp/tests/facet/facet_generator_test.py

Lines changed: 6 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@ async def test_generate_facets_from_items_simple():
1818
with patch(
1919
"common.parameterizer.parameterize_sql_and_intent"
2020
) as mock_parameterize_sql_and_intent:
21-
2221
mock_extract_value_phrases.return_value = mock_phrases
2322
mock_parameterize_sql_and_intent.return_value = {
2423
"sql": "city = $1",
@@ -61,7 +60,6 @@ async def test_generate_facets_from_items_multiple_phrases():
6160
with patch(
6261
"common.parameterizer.parameterize_sql_and_intent"
6362
) as mock_parameterize_sql_and_intent:
64-
6563
mock_extract_value_phrases.return_value = mock_phrases
6664
mock_parameterize_sql_and_intent.return_value = {
6765
"sql": "name = $1 AND city = $2",
@@ -76,16 +74,13 @@ async def test_generate_facets_from_items_multiple_phrases():
7674
facet = result_context_set.facets[0]
7775
assert facet.sql_snippet == "name = 'John Doe' AND city = 'New York'"
7876
assert facet.intent == "Find users named John Doe in New York"
79-
assert (
80-
facet.manifest == "Find users named a given person in a given city"
81-
)
77+
assert facet.manifest == "Find users named a given person in a given city"
8278
assert (
8379
facet.parameterized.parameterized_sql_snippet
8480
== "name = $1 AND city = $2"
8581
)
8682
assert (
87-
facet.parameterized.parameterized_intent
88-
== "Find users named $1 in $2"
83+
facet.parameterized.parameterized_intent == "Find users named $1 in $2"
8984
)
9085

9186
mock_extract_value_phrases.assert_called_once_with(
@@ -96,9 +91,7 @@ async def test_generate_facets_from_items_multiple_phrases():
9691

9792
@pytest.mark.asyncio
9893
async def test_generate_facets_from_items_empty_phrases():
99-
facet_inputs_json = json.dumps(
100-
[{"question": "List all users", "facet": "TRUE"}]
101-
)
94+
facet_inputs_json = json.dumps([{"question": "List all users", "facet": "TRUE"}])
10295
mock_phrases = {}
10396

10497
with patch(
@@ -107,7 +100,6 @@ async def test_generate_facets_from_items_empty_phrases():
107100
with patch(
108101
"common.parameterizer.parameterize_sql_and_intent"
109102
) as mock_parameterize_sql_and_intent:
110-
111103
mock_extract_value_phrases.return_value = mock_phrases
112104
mock_parameterize_sql_and_intent.return_value = {
113105
"sql": "TRUE",
@@ -157,7 +149,7 @@ async def test_generate_facets_from_items_with_explicit_intent():
157149
{
158150
"question": "luxury items",
159151
"facet": "description LIKE '%luxury%'",
160-
"intent": "Filter by luxury description"
152+
"intent": "Filter by luxury description",
161153
}
162154
]
163155
)
@@ -169,7 +161,6 @@ async def test_generate_facets_from_items_with_explicit_intent():
169161
with patch(
170162
"common.parameterizer.parameterize_sql_and_intent"
171163
) as mock_parameterize_sql_and_intent:
172-
173164
mock_extract_value_phrases.return_value = mock_phrases
174165
mock_parameterize_sql_and_intent.return_value = {
175166
"sql": "description LIKE '%luxury%'",
@@ -183,7 +174,7 @@ async def test_generate_facets_from_items_with_explicit_intent():
183174
assert len(result_context_set.facets) == 1
184175
facet = result_context_set.facets[0]
185176
assert facet.intent == "Filter by luxury description"
186-
177+
187178
# Verify parameterizer was called with explicit intent
188179
# args match: phrases, facet_text, intent, db_dialect
189180
args, _ = mock_parameterize_sql_and_intent.call_args
@@ -198,7 +189,7 @@ async def test_generate_facets_from_items_with_sql_snippet_key():
198189
{
199190
"question": "expensive items",
200191
"sql_snippet": "price > 1000",
201-
"intent": "Filter by expensive items"
192+
"intent": "Filter by expensive items",
202193
}
203194
]
204195
)
@@ -210,7 +201,6 @@ async def test_generate_facets_from_items_with_sql_snippet_key():
210201
with patch(
211202
"common.parameterizer.parameterize_sql_and_intent"
212203
) as mock_parameterize_sql_and_intent:
213-
214204
mock_extract_value_phrases.return_value = mock_phrases
215205
mock_parameterize_sql_and_intent.return_value = {
216206
"sql": "price > 1000",

mcp/tests/main_test.py

Lines changed: 33 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -5,21 +5,25 @@
55
from main import attach_context_set
66
from model.context import ContextSet
77

8+
89
@pytest.fixture
910
def clean_context_set_json():
10-
return json.dumps({
11-
"facets": [
12-
{
13-
"sql_snippet": "new_snippet",
14-
"intent": "new_intent",
15-
"manifest": "new_manifest",
16-
"parameterized": {
17-
"parameterized_sql_snippet": "p_new_snippet",
18-
"parameterized_intent": "p_new_intent"
11+
return json.dumps(
12+
{
13+
"facets": [
14+
{
15+
"sql_snippet": "new_snippet",
16+
"intent": "new_intent",
17+
"manifest": "new_manifest",
18+
"parameterized": {
19+
"parameterized_sql_snippet": "p_new_snippet",
20+
"parameterized_intent": "p_new_intent",
21+
},
1922
}
20-
}
21-
]
22-
})
23+
]
24+
}
25+
)
26+
2327

2428
def test_attach_context_set_legacy_compatibility(tmp_path, clean_context_set_json):
2529
"""Test attaching new context to a file with legacy 'fragment' and 'fragments' keys."""
@@ -32,32 +36,35 @@ def test_attach_context_set_legacy_compatibility(tmp_path, clean_context_set_jso
3236
"manifest": "old_manifest",
3337
"parameterized": {
3438
"parameterized_fragment": "p_old_snippet",
35-
"parameterized_intent": "p_old_intent"
36-
}
39+
"parameterized_intent": "p_old_intent",
40+
},
3741
}
3842
]
3943
}
4044
legacy_file.write_text(json.dumps(legacy_content))
4145

4246
# Call the tool
43-
attach_context_set.fn(context_set_json=clean_context_set_json, file_path=str(legacy_file))
47+
attach_context_set.fn(
48+
context_set_json=clean_context_set_json, file_path=str(legacy_file)
49+
)
4450

4551
# Verify the file was updated and migrated
4652
updated_content = json.loads(legacy_file.read_text())
47-
53+
4854
# Check that legacy content was correctly parsed and migrated to 'facets' and 'sql_snippet'
4955
assert "facets" in updated_content
5056
assert "fragments" not in updated_content
5157
assert len(updated_content["facets"]) == 2
52-
58+
5359
# Check old item (migrated)
5460
old_item = updated_content["facets"][0]
5561
assert old_item["sql_snippet"] == "old_snippet"
56-
62+
5763
# Check new item
5864
new_item = updated_content["facets"][1]
5965
assert new_item["sql_snippet"] == "new_snippet"
6066

67+
6168
def test_attach_context_set_standard(tmp_path, clean_context_set_json):
6269
"""Test attaching new context to a file with standard 'facets' key."""
6370
standard_file = tmp_path / "standard_context.json"
@@ -69,27 +76,29 @@ def test_attach_context_set_standard(tmp_path, clean_context_set_json):
6976
"manifest": "existing_manifest",
7077
"parameterized": {
7178
"parameterized_sql_snippet": "p_existing_snippet",
72-
"parameterized_intent": "p_existing_intent"
73-
}
79+
"parameterized_intent": "p_existing_intent",
80+
},
7481
}
7582
]
7683
}
7784
standard_file.write_text(json.dumps(standard_content))
7885

7986
# Call the tool
80-
attach_context_set.fn(context_set_json=clean_context_set_json, file_path=str(standard_file))
87+
attach_context_set.fn(
88+
context_set_json=clean_context_set_json, file_path=str(standard_file)
89+
)
8190

8291
# Verify the file was updated
8392
updated_content = json.loads(standard_file.read_text())
84-
93+
8594
assert "facets" in updated_content
8695
assert "fragments" not in updated_content
8796
assert len(updated_content["facets"]) == 2
88-
97+
8998
# Check existing item
9099
existing_item = updated_content["facets"][0]
91100
assert existing_item["sql_snippet"] == "existing_snippet"
92-
101+
93102
# Check new item
94103
new_item = updated_content["facets"][1]
95104
assert new_item["sql_snippet"] == "new_snippet"

mcp/tests/template/template_generator_test.py

Lines changed: 20 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -17,12 +17,14 @@ async def test_generate_templates_from_items_simple():
1717
)
1818
mock_phrases = {"New York": ["city"]}
1919

20-
with patch(
21-
"common.parameterizer.extract_value_phrases", new_callable=AsyncMock
22-
) as mock_extract_value_phrases, patch(
23-
"common.parameterizer.parameterize_sql_and_intent"
24-
) as mock_parameterize_sql_and_intent:
25-
20+
with (
21+
patch(
22+
"common.parameterizer.extract_value_phrases", new_callable=AsyncMock
23+
) as mock_extract_value_phrases,
24+
patch(
25+
"common.parameterizer.parameterize_sql_and_intent"
26+
) as mock_parameterize_sql_and_intent,
27+
):
2628
mock_extract_value_phrases.return_value = mock_phrases
2729
mock_parameterize_sql_and_intent.return_value = {
2830
"sql": "SELECT count(*) FROM users WHERE city = $1",
@@ -70,25 +72,29 @@ async def test_generate_templates_from_items_invalid_dialect():
7072
)
7173
assert "error" in result_json
7274
assert "Invalid database dialect specified" in result_json
75+
76+
7377
@pytest.mark.asyncio
7478
async def test_generate_templates_from_items_with_explicit_intent():
7579
template_inputs_json = json.dumps(
7680
[
7781
{
7882
"question": "How many users?",
7983
"sql": "SELECT count(*) FROM users",
80-
"intent": "Count all users"
84+
"intent": "Count all users",
8185
}
8286
]
8387
)
8488
mock_phrases = {}
8589

86-
with patch(
87-
"common.parameterizer.extract_value_phrases", new_callable=AsyncMock
88-
) as mock_extract_value_phrases, patch(
89-
"common.parameterizer.parameterize_sql_and_intent"
90-
) as mock_parameterize_sql_and_intent:
91-
90+
with (
91+
patch(
92+
"common.parameterizer.extract_value_phrases", new_callable=AsyncMock
93+
) as mock_extract_value_phrases,
94+
patch(
95+
"common.parameterizer.parameterize_sql_and_intent"
96+
) as mock_parameterize_sql_and_intent,
97+
):
9298
mock_extract_value_phrases.return_value = mock_phrases
9399
mock_parameterize_sql_and_intent.return_value = {
94100
"sql": "SELECT count(*) FROM users",
@@ -102,7 +108,7 @@ async def test_generate_templates_from_items_with_explicit_intent():
102108
assert len(result_context_set.templates) == 1
103109
template = result_context_set.templates[0]
104110
assert template.intent == "Count all users"
105-
111+
106112
# Verify parameterizer was called with explicit intent
107113
# args match: phrases, sql, intent, db_dialect
108114
args, _ = mock_parameterize_sql_and_intent.call_args

0 commit comments

Comments
 (0)