-
-
Notifications
You must be signed in to change notification settings - Fork 661
feat: add lexicographic_sort_schema config option #4451
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,19 @@ | ||
| Release type: minor | ||
|
|
||
| Add a new `lexicographic_sort_schema` option to `StrawberryConfig`. When enabled, | ||
| the schema's types, fields and arguments are sorted alphabetically, affecting both | ||
| the introspection result and the exported SDL. This makes it easier to find | ||
| related fields (for example `userById`, `userByName`) in the GraphiQL UI and in | ||
| exported `schema.graphql` files. | ||
|
|
||
| ```python | ||
| import strawberry | ||
| from strawberry.schema.config import StrawberryConfig | ||
|
|
||
| schema = strawberry.Schema( | ||
| query=Query, | ||
| config=StrawberryConfig(lexicographic_sort_schema=True), | ||
| ) | ||
| ``` | ||
|
|
||
| It defaults to `False`, preserving the existing definition order. |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -34,6 +34,10 @@ class StrawberryConfig: | |
| any type (including NewType) to be used as a GraphQL scalar with | ||
| proper type checking support. | ||
| batching_config: Configuration for operation batching. | ||
| lexicographic_sort_schema: Whether to sort the schema's types, fields and | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Maybe just call this |
||
| arguments lexicographically. This affects both the introspection | ||
| result and the exported SDL, making it easier to find related | ||
| fields. Defaults to False, which preserves definition order. | ||
| """ | ||
|
|
||
| auto_camel_case: InitVar[bool] = None # pyright: reportGeneralTypeIssues=false | ||
|
|
@@ -47,6 +51,7 @@ class StrawberryConfig: | |
| _unsafe_disable_same_type_validation: bool = False | ||
| scalar_map: Mapping[object, ScalarDefinition] = field(default_factory=dict) | ||
| batching_config: BatchingConfig | None = None | ||
| lexicographic_sort_schema: bool = False | ||
|
|
||
| def __post_init__( | ||
| self, | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,5 +1,8 @@ | ||
| import textwrap | ||
|
|
||
| import pytest | ||
|
|
||
| import strawberry | ||
| from strawberry.schema.config import StrawberryConfig | ||
| from strawberry.types.info import Info | ||
|
|
||
|
|
@@ -37,3 +40,82 @@ def test_config_post_init_info_class_is_not_subclass(): | |
| StrawberryConfig(info_class=object) | ||
|
|
||
| assert str(exc_info.value) == "`info_class` must be a subclass of strawberry.Info" | ||
|
|
||
|
|
||
| def test_lexicographic_sort_schema_defaults_to_false(): | ||
| assert StrawberryConfig().lexicographic_sort_schema is False | ||
|
|
||
|
|
||
| def test_lexicographic_sort_schema_preserves_definition_order_by_default(): | ||
| @strawberry.type | ||
| class Query: | ||
| @strawberry.field | ||
| def zebra(self) -> int: ... | ||
|
|
||
| @strawberry.field | ||
| def apple(self) -> int: ... | ||
|
|
||
| schema = strawberry.Schema(query=Query) | ||
|
|
||
| expected = """\ | ||
| type Query { | ||
| zebra: Int! | ||
| apple: Int! | ||
| }""" | ||
|
|
||
| assert str(schema) == textwrap.dedent(expected).strip() | ||
|
|
||
|
|
||
| def test_lexicographic_sort_schema_sorts_fields_and_types(): | ||
| @strawberry.type | ||
| class User: | ||
| name: str | ||
| age: int | ||
|
|
||
| @strawberry.type | ||
| class Query: | ||
| @strawberry.field | ||
| def user_by_name(self, name: str) -> User: ... | ||
|
|
||
| @strawberry.field | ||
| def all_users(self) -> list[User]: ... | ||
|
|
||
|
Comment on lines
40
to
+82
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
The RELEASE.md and documentation both state that Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time! |
||
| @strawberry.field | ||
| def user_by_id(self, id: int) -> User: ... | ||
|
|
||
| schema = strawberry.Schema( | ||
| query=Query, | ||
| config=StrawberryConfig(lexicographic_sort_schema=True), | ||
| ) | ||
|
|
||
| expected = """\ | ||
| type Query { | ||
| allUsers: [User!]! | ||
| userById(id: Int!): User! | ||
| userByName(name: String!): User! | ||
| } | ||
|
|
||
| type User { | ||
| age: Int! | ||
| name: String! | ||
| }""" | ||
|
|
||
| assert str(schema) == textwrap.dedent(expected).strip() | ||
|
|
||
|
|
||
| def test_lexicographic_sort_schema_still_executes(): | ||
| @strawberry.type | ||
| class Query: | ||
| @strawberry.field | ||
| def hello(self, name: str) -> str: | ||
| return f"Hi {name}" | ||
|
|
||
| schema = strawberry.Schema( | ||
| query=Query, | ||
| config=StrawberryConfig(lexicographic_sort_schema=True), | ||
| ) | ||
|
|
||
| result = schema.execute_sync('{ hello(name: "Patrick") }') | ||
|
|
||
| assert not result.errors | ||
| assert result.data == {"hello": "Hi Patrick"} | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The opening paragraph mentions that types, fields and arguments are sorted, but the before/after SDL blocks only show the
Querytype. Readers learning about the option won't see what happens to the associatedUsertype's fields (name,age→age,name). Adding theUsertype to both the "before" and "after" blocks (matching what the test already asserts) would make the example complete and consistent with the introductory description.Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!