Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ For released versions, see the [Releases](https://github.com/mirumee/ariadne-cod

## Unreleased

- Allow `schema_path` to accept a list of file/directory paths in addition to a single path string.

### ⚠️ Breaking Changes

### 📚 Documentation
Expand Down
11 changes: 8 additions & 3 deletions ariadne_codegen/schema.py
Original file line number Diff line number Diff line change
Expand Up @@ -133,9 +133,14 @@ def introspect_remote_schema(
return cast(IntrospectionQuery, data)


def get_graphql_schema_from_path(schema_path: str) -> GraphQLSchema:
"""Get graphql schema build from provided path."""
schema_str = load_graphql_files_from_path(Path(schema_path))
def get_graphql_schema_from_path(schema_path: str | list[str]) -> GraphQLSchema:
"""Get graphql schema build from the provided path or list of paths."""
if isinstance(schema_path, list):
schema_str = "\n".join(
load_graphql_files_from_path(Path(p)) for p in schema_path
)
else:
schema_str = load_graphql_files_from_path(Path(schema_path))
graphql_ast = parse(schema_str)
schema: GraphQLSchema = build_ast_schema(graphql_ast, assume_valid=True)
return schema
Expand Down
28 changes: 19 additions & 9 deletions ariadne_codegen/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ class IntrospectionSettings:

@dataclass
class BaseSettings:
schema_path: str = ""
schema_path: str | list[str] = ""
remote_schema_url: str = ""
remote_schema_headers: dict = field(default_factory=dict)
remote_schema_verify_ssl: bool = True
Expand All @@ -86,7 +86,11 @@ def __post_init__(self):
)

if self.schema_path:
assert_path_exists(self.schema_path)
if isinstance(self.schema_path, list):
for path in self.schema_path:
assert_path_exists(path)
else:
assert_path_exists(self.schema_path)

self.remote_schema_headers = resolve_headers(self.remote_schema_headers)
if self.remote_schema_url:
Expand All @@ -99,6 +103,16 @@ def using_remote_schema(self) -> bool:
"""
return bool(self.remote_schema_url) and not bool(self.schema_path)

@property
def schema_source(self) -> str:
if isinstance(self.schema_path, list):
return (
", ".join(self.schema_path)
if self.schema_path
else self.remote_schema_url
)
return self.schema_path if self.schema_path else self.remote_schema_url

@property
def introspection_settings(self) -> IntrospectionSettings:
"""
Expand Down Expand Up @@ -218,10 +232,6 @@ def _set_default_base_client_data(self):
self.base_client_name = name
self.base_client_file_path = path.as_posix()

@property
def schema_source(self) -> str:
return self.schema_path if self.schema_path else self.remote_schema_url

@property
def used_settings_message(self) -> str:
snake_case_msg = (
Expand Down Expand Up @@ -257,7 +267,7 @@ def used_settings_message(self) -> str:
return dedent(
f"""\
Selected strategy: {Strategy.CLIENT}
Using schema from '{self.schema_path or self.remote_schema_url}'.
Using schema from '{self.schema_source}'.
{introspection_msg}
Reading queries from '{self.queries_path}'.
Using '{self.target_package_name}' as package name.
Expand Down Expand Up @@ -307,7 +317,7 @@ def used_settings_message(self):
return dedent(
f"""\
Selected strategy: {Strategy.GRAPHQL_SCHEMA}
Using schema from {self.schema_path or self.remote_schema_url}
Using schema from {self.schema_source}
{introspection_msg}
Saving graphql schema to: {self.target_file_path}
Using {self.schema_variable_name} as variable name for schema.
Expand All @@ -319,7 +329,7 @@ def used_settings_message(self):
return dedent(
f"""\
Selected strategy: {Strategy.GRAPHQL_SCHEMA}
Using schema from {self.schema_path or self.remote_schema_url}
Using schema from {self.schema_source}
{introspection_msg}
Saving graphql schema to: {self.target_file_path}
{plugins_msg}
Expand Down
2 changes: 1 addition & 1 deletion docs/02-configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ queries_path = "queries.graphql"

One of the following 2 parameters is required, in case of providing both of them `schema_path` is prioritized:

- `schema_path` - path to file/directory with graphql schema
- `schema_path` - path to file/directory with graphql schema, or a list of paths whose contents will be concatenated
- `remote_schema_url` - url to graphql server, where introspection query can be perfomed

## Optional settings:
Expand Down
22 changes: 22 additions & 0 deletions tests/test_schema.py
Original file line number Diff line number Diff line change
Expand Up @@ -332,6 +332,28 @@ def test_get_graphql_schema_from_path_with_invalid_syntax_raises_invalid_graphql
get_graphql_schema_from_path(invalid_syntax_schema_file.as_posix())


def test_get_graphql_schema_from_path_accepts_list_of_paths(
single_file_schema, schemas_directory, schema_str, extra_type_str
):
schema = get_graphql_schema_from_path(
[single_file_schema.as_posix(), schemas_directory.as_posix()]
)

assert isinstance(schema, GraphQLSchema)
assert schema.get_type("Custom") is not None
assert schema.get_type("User") is not None


def test_get_graphql_schema_from_path_with_single_element_list_matches_single_path(
single_file_schema,
):
list_schema = get_graphql_schema_from_path([single_file_schema.as_posix()])
str_schema = get_graphql_schema_from_path(single_file_schema.as_posix())

assert isinstance(list_schema, GraphQLSchema)
assert list_schema.type_map.keys() == str_schema.type_map.keys()


def test_introspect_remote_schema_called_with_invalid_url_raises_introspection_error(
mocker,
):
Expand Down
66 changes: 66 additions & 0 deletions tests/test_settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,48 @@ def test_client_settings_without_schema_path_or_remote_schema_url_raises_excepti
ClientSettings(queries_path=queries_path)


def test_client_settings_accepts_list_for_schema_path(tmp_path):
schema_path_a = tmp_path / "schema_a.graphql"
schema_path_a.touch()
schema_path_b = tmp_path / "schema_b.graphql"
schema_path_b.touch()
queries_path = tmp_path / "queries.graphql"
queries_path.touch()

settings = ClientSettings(
schema_path=[schema_path_a.as_posix(), schema_path_b.as_posix()],
queries_path=queries_path.as_posix(),
)

assert settings.schema_path == [
schema_path_a.as_posix(),
schema_path_b.as_posix(),
]


def test_client_settings_raises_invalid_configuration_for_nonexistent_path_in_list(
tmp_path,
):
schema_path = tmp_path / "schema.graphql"
schema_path.touch()
queries_path = tmp_path / "queries.graphql"
queries_path.touch()

with pytest.raises(InvalidConfiguration):
ClientSettings(
schema_path=[schema_path.as_posix(), (tmp_path / "missing.graphql").as_posix()],
queries_path=queries_path.as_posix(),
)


def test_client_settings_with_empty_list_schema_path_and_no_remote_url_raises(tmp_path):
queries_path = tmp_path / "queries.graphql"
queries_path.touch()

with pytest.raises(InvalidConfiguration):
ClientSettings(schema_path=[], queries_path=queries_path.as_posix())


@pytest.mark.parametrize(
"configured_header, expected_header",
[
Expand Down Expand Up @@ -550,6 +592,30 @@ class BaseClient:
assert settings.using_remote_schema is False


def test_using_remote_schema_false_when_schema_path_is_non_empty_list(tmp_path):
"""
Test that using_remote_schema is False when schema_path is a non-empty list,
even if remote_schema_url is also provided.
"""
schema_path_a = tmp_path / "schema_a.graphql"
schema_path_a.touch()
schema_path_b = tmp_path / "schema_b.graphql"
schema_path_b.touch()
queries_path = tmp_path / "queries.graphql"
queries_path.touch()

settings = ClientSettings(
schema_path=[schema_path_a.as_posix(), schema_path_b.as_posix()],
remote_schema_url="http://testserver/graphql/",
queries_path=queries_path.as_posix(),
)

assert settings.using_remote_schema is False
assert settings.schema_source == ", ".join(
[schema_path_a.as_posix(), schema_path_b.as_posix()]
)


def test_introspection_settings_defaults(tmp_path):
"""
Test that introspection settings have the correct default values.
Expand Down