Skip to content

Commit 49de084

Browse files
authored
Feature dsl schema shortcuts (#566)
1 parent 1247877 commit 49de084

File tree

3 files changed

+51
-18
lines changed

3 files changed

+51
-18
lines changed

docs/advanced/dsl_module.rst

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -373,6 +373,14 @@ this can be written in a concise manner::
373373
DSLInlineFragment().on(ds.Human).select(ds.Human.homePlanet)
374374
)
375375

376+
Alternatively, you can use the DSL shortcut syntax to create an inline fragment by
377+
passing the string ``"..."`` directly to the :meth:`__call__ <gql.dsl.DSLSchema.__call__>` method::
378+
379+
query_with_inline_fragment = ds.Query.hero.args(episode=6).select(
380+
ds.Character.name,
381+
ds("...").on(ds.Human).select(ds.Human.homePlanet)
382+
)
383+
376384
Meta-fields
377385
^^^^^^^^^^^
378386

@@ -384,6 +392,15 @@ you can use the :class:`DSLMetaField <gql.dsl.DSLMetaField>` class::
384392
DSLMetaField("__typename")
385393
)
386394

395+
Alternatively, you can use the DSL shortcut syntax to create the same meta-field by
396+
passing the ``"__typename"`` string directly to the :meth:`__call__ <gql.dsl.DSLSchema.__call__>` method::
397+
398+
query = ds.Query.hero.select(
399+
ds.Character.name,
400+
ds("__typename")
401+
)
402+
403+
387404
Directives
388405
^^^^^^^^^^
389406

gql/dsl.py

Lines changed: 17 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -323,36 +323,35 @@ def __call__(
323323
self, shortcut: Literal["..."]
324324
) -> "DSLInlineFragment": ... # pragma: no cover
325325

326-
@overload
327-
def __call__(
328-
self, shortcut: Literal["fragment"], name: str
329-
) -> "DSLFragment": ... # pragma: no cover
330-
331326
@overload
332327
def __call__(self, shortcut: Any) -> "DSLDirective": ... # pragma: no cover
333328

334329
def __call__(
335-
self, shortcut: str, name: Optional[str] = None
336-
) -> Union["DSLMetaField", "DSLInlineFragment", "DSLFragment", "DSLDirective"]:
337-
"""Factory method for creating DSL objects.
330+
self, shortcut: str
331+
) -> Union["DSLMetaField", "DSLInlineFragment", "DSLDirective"]:
332+
"""Factory method for creating DSL objects from a shortcut string.
338333
339-
Currently, supports creating DSLDirective instances when name starts with '@'.
340-
Future support planned for meta-fields (__typename), inline fragments (...),
341-
and fragment definitions (fragment).
334+
The shortcut determines which DSL object is created:
342335
343-
:param shortcut: the name of the object to create
336+
* "__typename", "__schema", "__type" -> :class:`DSLMetaField`
337+
* "..." -> :class:`DSLInlineFragment`
338+
* "@<name>" -> :class:`DSLDirective`
339+
340+
:param shortcut: The shortcut string identifying the DSL object.
344341
:type shortcut: str
345342
346-
:return: :class:`DSLDirective` instance
343+
:return: A DSL object corresponding to the given shortcut.
344+
:rtype: DSLMetaField | DSLInlineFragment | DSLDirective
347345
348-
:raises ValueError: if shortcut format is not supported
346+
:raises ValueError: If the shortcut is not recognized.
349347
"""
348+
349+
if shortcut in ("__typename", "__schema", "__type"):
350+
return DSLMetaField(name=shortcut)
351+
if shortcut == "...":
352+
return DSLInlineFragment()
350353
if shortcut.startswith("@"):
351354
return DSLDirective(name=shortcut[1:], dsl_schema=self)
352-
# Future support:
353-
# if name.startswith("__"): return DSLMetaField(name)
354-
# if name == "...": return DSLInlineFragment()
355-
# if name.startswith("fragment "): return DSLFragment(name[9:])
356355

357356
raise ValueError(f"Unsupported shortcut: {shortcut}")
358357

tests/starwars/test_dsl.py

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323

2424
from gql import Client, gql
2525
from gql.dsl import (
26+
DSLDirective,
2627
DSLField,
2728
DSLFragment,
2829
DSLFragmentSpread,
@@ -1297,6 +1298,22 @@ def test_legacy_fragment_with_variables(ds):
12971298
assert print_ast(query.document) == expected
12981299

12991300

1301+
@pytest.mark.parametrize(
1302+
"shortcut,expected",
1303+
[
1304+
("__typename", DSLMetaField("__typename")),
1305+
("__schema", DSLMetaField("__schema")),
1306+
("__type", DSLMetaField("__type")),
1307+
("...", DSLInlineFragment()),
1308+
("@skip", DSLDirective(name="skip", dsl_schema=DSLSchema(StarWarsSchema))),
1309+
],
1310+
)
1311+
def test_dsl_schema_call_shortcuts(ds, shortcut, expected):
1312+
actual = ds(shortcut)
1313+
assert getattr(actual, "name", None) == getattr(expected, "name", None)
1314+
assert isinstance(actual, type(expected))
1315+
1316+
13001317
def test_dsl_schema_call_validation(ds):
13011318
with pytest.raises(ValueError, match="(?i)unsupported shortcut"):
13021319
ds("foo")

0 commit comments

Comments
 (0)