Skip to content

Commit 640bbaa

Browse files
committed
chore: Expose validate_scalar_strategy in the public API
1 parent b66ed3d commit 640bbaa

5 files changed

Lines changed: 34 additions & 26 deletions

File tree

docs/changelog.rst

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,10 @@ Changelog
44
`Unreleased`_ - TBD
55
-------------------
66

7+
**Added**
8+
9+
- Expose ``validate_scalar_strategy`` in the public API.
10+
711
`0.8.0`_ - 2022-04-27
812
---------------------
913

src/hypothesis_graphql/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
from ._strategies.validation import validate_scalar_strategy

src/hypothesis_graphql/_strategies/strategy.py

Lines changed: 10 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,10 @@
1111
from hypothesis.strategies._internal.utils import cacheable
1212

1313
from .. import nodes
14-
from ..types import AstPrinter, CustomScalars, Field, InputTypeNode, InterfaceOrObject, SelectionNodes
15-
from . import factories, primitives
14+
from ..types import AstPrinter, CustomScalarStrategies, Field, InputTypeNode, InterfaceOrObject, SelectionNodes
15+
from . import factories, primitives, validation
1616
from .ast import make_mutation, make_query
1717
from .containers import flatten
18-
from .validation import maybe_parse_schema, validate_custom_scalars, validate_fields
1918

2019
BY_NAME = operator.attrgetter("name")
2120
EMPTY_LISTS_STRATEGY = st.builds(list)
@@ -45,7 +44,7 @@ class GraphQLStrategy:
4544
"""Strategy for generating various GraphQL nodes."""
4645

4746
schema: graphql.GraphQLSchema = attr.ib()
48-
custom_scalars: CustomScalars = attr.ib(factory=dict)
47+
custom_scalars: CustomScalarStrategies = attr.ib(factory=dict)
4948
# As the schema is assumed to be immutable, there are a few strategy caches possible for internal components
5049
# This is a per-method cache without limits as they are proportionate to the schema size
5150
_cache: Dict[str, Dict] = attr.ib(factory=dict)
@@ -341,13 +340,13 @@ def _make_strategy(
341340
*,
342341
type_: graphql.GraphQLObjectType,
343342
fields: Optional[Iterable[str]] = None,
344-
custom_scalars: Optional[CustomScalars] = None,
343+
custom_scalars: Optional[CustomScalarStrategies] = None,
345344
) -> st.SearchStrategy[List[graphql.FieldNode]]:
346345
if fields is not None:
347346
fields = tuple(fields)
348-
validate_fields(fields, type_.fields)
347+
validation.validate_fields(fields, type_.fields)
349348
if custom_scalars:
350-
validate_custom_scalars(custom_scalars)
349+
validation.validate_custom_scalars(custom_scalars)
351350
return GraphQLStrategy(schema, custom_scalars or {}).selections(type_, fields=fields)
352351

353352

@@ -356,7 +355,7 @@ def queries(
356355
schema: Union[str, graphql.GraphQLSchema],
357356
*,
358357
fields: Optional[Iterable[str]] = None,
359-
custom_scalars: Optional[CustomScalars] = None,
358+
custom_scalars: Optional[CustomScalarStrategies] = None,
360359
print_ast: AstPrinter = graphql.print_ast,
361360
) -> st.SearchStrategy[str]:
362361
"""A strategy for generating valid queries for the given GraphQL schema.
@@ -368,7 +367,7 @@ def queries(
368367
:param custom_scalars: Strategies for generating custom scalars.
369368
:param print_ast: A function to convert the generated AST to a string.
370369
"""
371-
parsed_schema = maybe_parse_schema(schema)
370+
parsed_schema = validation.maybe_parse_schema(schema)
372371
if parsed_schema.query_type is None:
373372
raise ValueError("Query type is not defined in the schema")
374373
return (
@@ -383,7 +382,7 @@ def mutations(
383382
schema: Union[str, graphql.GraphQLSchema],
384383
*,
385384
fields: Optional[Iterable[str]] = None,
386-
custom_scalars: Optional[CustomScalars] = None,
385+
custom_scalars: Optional[CustomScalarStrategies] = None,
387386
print_ast: AstPrinter = graphql.print_ast,
388387
) -> st.SearchStrategy[str]:
389388
"""A strategy for generating valid mutations for the given GraphQL schema.
@@ -395,7 +394,7 @@ def mutations(
395394
:param custom_scalars: Strategies for generating custom scalars.
396395
:param print_ast: A function to convert the generated AST to a string.
397396
"""
398-
parsed_schema = maybe_parse_schema(schema)
397+
parsed_schema = validation.maybe_parse_schema(schema)
399398
if parsed_schema.mutation_type is None:
400399
raise ValueError("Mutation type is not defined in the schema")
401400
return (

src/hypothesis_graphql/_strategies/validation.py

Lines changed: 18 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
from hypothesis.errors import InvalidArgument
66

77
from ..cache import cached_build_schema
8-
from ..types import CustomScalars
8+
from ..types import CustomScalarStrategies
99

1010

1111
def maybe_parse_schema(schema: Union[str, graphql.GraphQLSchema]) -> graphql.GraphQLSchema:
@@ -14,21 +14,25 @@ def maybe_parse_schema(schema: Union[str, graphql.GraphQLSchema]) -> graphql.Gra
1414
return schema
1515

1616

17-
def validate_fields(fields: Tuple[str, ...], available_fields: Dict[str, graphql.GraphQLField]) -> None:
18-
if not fields:
17+
def validate_fields(fields_: Tuple[str, ...], available_fields: Dict[str, graphql.GraphQLField]) -> None:
18+
if not fields_:
1919
raise ValueError("If you pass `fields`, it should not be empty")
20-
invalid_fields = tuple(field for field in fields if field not in available_fields)
20+
invalid_fields = tuple(field for field in fields_ if field not in available_fields)
2121
if invalid_fields:
2222
raise ValueError(f"Unknown fields: {', '.join(invalid_fields)}")
2323

2424

25-
def validate_custom_scalars(custom_scalars: CustomScalars) -> None:
26-
assert isinstance(custom_scalars, dict)
27-
for name, strategy in custom_scalars.items():
28-
if not isinstance(name, str):
29-
raise InvalidArgument(f"scalar name {name!r} must be a string")
30-
if not isinstance(strategy, st.SearchStrategy):
31-
raise InvalidArgument(
32-
f"custom_scalars[{name!r}]={strategy!r} must be a Hypothesis "
33-
"strategy which generates AST nodes matching this scalar."
34-
)
25+
def validate_custom_scalars(strategies: CustomScalarStrategies) -> None:
26+
assert isinstance(strategies, dict)
27+
for name, strategy in strategies.items():
28+
validate_scalar_strategy(name, strategy)
29+
30+
31+
def validate_scalar_strategy(name: str, strategy: st.SearchStrategy) -> None:
32+
if not isinstance(name, str):
33+
raise InvalidArgument(f"scalar name {name!r} must be a string")
34+
if not isinstance(strategy, st.SearchStrategy):
35+
raise InvalidArgument(
36+
f"custom_scalars[{name!r}]={strategy!r} must be a Hypothesis "
37+
"strategy which generates AST nodes matching this scalar."
38+
)

src/hypothesis_graphql/types.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,4 +10,4 @@
1010
InterfaceOrObject = Union[graphql.GraphQLObjectType, graphql.GraphQLInterfaceType]
1111
SelectionNodes = List[graphql.SelectionNode]
1212
AstPrinter = Callable[[graphql.Node], str]
13-
CustomScalars = Dict[str, st.SearchStrategy[graphql.ValueNode]]
13+
CustomScalarStrategies = Dict[str, st.SearchStrategy[graphql.ValueNode]]

0 commit comments

Comments
 (0)