Skip to content

Commit

Permalink
wip: py, tests, rust
Browse files Browse the repository at this point in the history
  • Loading branch information
luckasRanarison committed Dec 31, 2024
1 parent f0187f6 commit f1c8a91
Show file tree
Hide file tree
Showing 14 changed files with 392 additions and 74 deletions.
4 changes: 2 additions & 2 deletions src/metagen-client-rs/src/nodes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ where
.into(),
),
&[(self.root_name, self.root_meta)].into(),
"$q".into(),
&mut vec!["$q".to_string()],
)
.unwrap();
nodes.into_iter().next().unwrap()
Expand All @@ -121,7 +121,7 @@ where
.into(),
),
&[(self.root_name, self.root_meta)].into(),
"$q".into(),
&mut vec!["$q".to_string()],
)
.unwrap();
nodes.into_iter().next().unwrap()
Expand Down
34 changes: 15 additions & 19 deletions src/metagen-client-rs/src/selection.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ use crate::nodes::{NodeMeta, NodeMetaFn, SelectNodeErased, SubNodes};
pub fn selection_to_node_set(
selection: SelectionErasedMap,
metas: &HashMap<CowStr, NodeMetaFn>,
parent_path: String,
parent_path: &mut Vec<String>,
) -> Result<Vec<SelectNodeErased>, SelectionError> {
let mut out = vec![];
let mut selection = selection.0;
Expand Down Expand Up @@ -70,11 +70,12 @@ pub fn selection_to_node_set(
node_name.clone(),
args,
select,
&parent_path,
parent_path,
&meta,
)?)
}
}
parent_path.pop();
Ok(out)
}

Expand All @@ -83,7 +84,7 @@ pub fn selection_to_select_node(
node_name: CowStr,
args: NodeArgsErased,
select: Option<CompositeSelection>,
parent_path: &str,
parent_path: &mut Vec<String>,
meta: &NodeMeta,
) -> Result<SelectNodeErased, SelectionError> {
let args = if let Some(arg_types) = &meta.arg_types {
Expand All @@ -92,7 +93,7 @@ pub fn selection_to_select_node(
let instance_args = check_node_args(args, arg_types).map_err(|name| {
SelectionError::UnexpectedArgs {
name,
path: format!("{parent_path}.{instance_name}"),
path: format!("{}.{instance_name}", parent_path.join(".")),
}
})?;
Some(NodeArgsMerged::Inline(instance_args))
Expand All @@ -104,7 +105,7 @@ pub fn selection_to_select_node(
}),
NodeArgsErased::None => {
return Err(SelectionError::MissingArgs {
path: format!("{parent_path}.{instance_name}"),
path: format!("{}.{instance_name}", parent_path.join(".")),
})
}
}
Expand All @@ -117,26 +118,23 @@ pub fn selection_to_select_node(
(variants, sub_nodes) => {
let Some(select) = select else {
return Err(SelectionError::MissingSubNodes {
path: format!("{parent_path}.{instance_name}"),
path: format!("{}.{instance_name}", parent_path.join(".")),
});
};
match select {
CompositeSelection::Atomic(select) => {
let Some(sub_nodes) = sub_nodes else {
return Err(SelectionError::UnexpectedUnion {
path: format!("{parent_path}.{instance_name}"),
path: format!("{}.{instance_name}", parent_path.join(".")),
});
};
SubNodes::Atomic(selection_to_node_set(
select,
sub_nodes,
format!("{parent_path}.{instance_name}"),
)?)
parent_path.push(instance_name.to_string());
SubNodes::Atomic(selection_to_node_set(select, sub_nodes, parent_path)?)
}
CompositeSelection::Union(mut variant_select) => {
let Some(variants) = variants else {
return Err(SelectionError::MissingUnion {
path: format!("{parent_path}.{instance_name}"),
path: format!("{}.{instance_name}", parent_path.join(".")),
});
};
let mut out = HashMap::new();
Expand All @@ -147,11 +145,9 @@ pub fn selection_to_select_node(
continue;
};
let mut nodes = if let Some(select) = variant_select.remove(variant_ty) {
selection_to_node_set(
select,
&sub_nodes,
format!("{parent_path}.{instance_name}.variant({variant_ty})"),
)?
parent_path.push(instance_name.to_string());
parent_path.push(format!("variant({variant_ty})"));
selection_to_node_set(select, &sub_nodes, parent_path)?
} else {
vec![]
};
Expand All @@ -166,7 +162,7 @@ pub fn selection_to_select_node(
}
if !variant_select.is_empty() {
return Err(SelectionError::UnexpectedVariants {
path: format!("{parent_path}.{instance_name}"),
path: format!("{}.{instance_name}", parent_path.join(".")),
varaint_tys: variant_select.into_keys().collect(),
});
}
Expand Down
19 changes: 19 additions & 0 deletions src/metagen/src/client_py/static/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,25 @@ def selection_to_nodes(
raise Exception(
"unreachable: union/either NodeMetas can't have subnodes"
)

last_node = parent_path[-1]
flags = sub_selections.get("_")

if flags is not None:
assert isinstance(flags, SelectionFlags)
select_all = flags and flags.select_all or False
recursive_field = next(
(
node
for node in meta.sub_nodes.keys()
if node == last_node
),
None,
)
# skip recursive fields when using `select_all`
if select_all and recursive_field:
continue

parent_path.append(instance_name)
sub_nodes = selection_to_nodes(
typing.cast("SelectionErased", sub_selections),
Expand Down
2 changes: 1 addition & 1 deletion src/metagen/src/client_rs/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -270,7 +270,7 @@ impl QueryGraph {{
&[
("{node_name}".into(), node_metas::{meta_method} as NodeMetaFn),
].into(),
"$q".into(),
&mut vec!["$q".to_string()],
)
.unwrap();
{node_ty}(nodes.into_iter().next().unwrap(), PhantomData)
Expand Down
10 changes: 10 additions & 0 deletions tests/metagen/metagen_test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -592,6 +592,15 @@ Meta.test(
compositeNoArgs: postSchema,
compositeArgs: postSchema,
});
// Test for circular fields when using selectAll
const expectedSchemaR = zod.object({
circular: zod.object({
id: zod.string(),
owner: zod.object({
id: zod.string(),
}),
}),
});
const expectedSchema = zod.tuple([
expectedSchemaQ,
expectedSchemaQ,
Expand All @@ -604,6 +613,7 @@ Meta.test(
compositeUnion2: zod.object({}),
mixedUnion: zod.string(),
}),
expectedSchemaR,
]);
const cases = [
{
Expand Down
27 changes: 27 additions & 0 deletions tests/metagen/typegraphs/sample.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,14 @@ const _genPosts = () => [
{ slug: "hello", title: "Hello World!" },
];

const genFakeCircular = () => ({
id: "9da026ae-0d5d-450f-b219-c01f0c87bc59",
owner: {
id: "fef53dd5-3e75-4e47-9219-64b9eb612044",
props: [],
},
});

export const tg = await typegraph({
name: "sample",
builder(g) {
Expand All @@ -40,6 +48,22 @@ export const tg = await typegraph({
{ name: "user" },
);

const owner = t.struct(
{
id: t.uuid({ config: { auto: true } }).id(),
props: t.list(g.ref("circular")),
},
{ name: "owner" },
);

const circular = t.struct(
{
id: t.uuid({ config: { auto: true } }).id(),
owner: g.ref("owner"),
},
{ name: "circular" },
);

const compositeUnion = t.union([post, user]);
const scalarUnion = t.union([t.string(), t.integer()]);
const mixedUnion = t.union([post, user, t.string(), t.integer()]);
Expand All @@ -48,6 +72,9 @@ export const tg = await typegraph({
{
getUser: random.gen(user),
getPosts: random.gen(post),
getCircular: deno.func(t.struct({}), circular, {
code: genFakeCircular,
}),

scalarNoArgs: random.gen(t.string()),
scalarArgs: deno.func(post, t.string(), {
Expand Down
95 changes: 95 additions & 0 deletions tests/metagen/typegraphs/sample/py/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,25 @@ def selection_to_nodes(
raise Exception(
"unreachable: union/either NodeMetas can't have subnodes"
)

last_node = parent_path[-1]
flags = sub_selections.get("_")

if flags is not None:
assert isinstance(flags, SelectionFlags)
select_all = flags and flags.select_all or False
recursive_field = next(
(
node
for node in meta.sub_nodes.keys()
if node == last_node
),
None,
)
# skip recursive fields when using `select_all`
if select_all and recursive_field:
continue

parent_path.append(instance_name)
sub_nodes = selection_to_nodes(
typing.cast("SelectionErased", sub_selections),
Expand Down Expand Up @@ -850,6 +869,32 @@ def RootGetPostsFn():
variants=return_node.variants,
)

@staticmethod
def Owner():
return NodeMeta(
sub_nodes={
"id": NodeDescs.scalar,
"props": NodeDescs.Circular,
},
)

@staticmethod
def Circular():
return NodeMeta(
sub_nodes={
"id": NodeDescs.scalar,
"owner": NodeDescs.Owner,
},
)

@staticmethod
def RootGetCircularFn():
return_node = NodeDescs.Circular()
return NodeMeta(
sub_nodes=return_node.sub_nodes,
variants=return_node.variants,
)

@staticmethod
def RootScalarNoArgsFn():
return_node = NodeDescs.scalar()
Expand Down Expand Up @@ -978,6 +1023,26 @@ def RootMixedUnionFn():
total=False,
)

OwnerPropsCircularList = typing.List["Circular"]

Owner = typing.TypedDict(
"Owner",
{
"id": UserIdStringUuid,
"props": OwnerPropsCircularList,
},
total=False,
)

Circular = typing.TypedDict(
"Circular",
{
"id": UserIdStringUuid,
"owner": "Owner",
},
total=False,
)

RootScalarUnionFnOutputT1Integer = int

RootScalarUnionFnOutput = typing.Union[
Expand Down Expand Up @@ -1022,6 +1087,26 @@ def RootMixedUnionFn():
total=False,
)

OwnerSelections = typing.TypedDict(
"OwnerSelections",
{
"_": SelectionFlags,
"id": ScalarSelectNoArgs,
"props": CompositeSelectNoArgs["CircularSelections"],
},
total=False,
)

CircularSelections = typing.TypedDict(
"CircularSelections",
{
"_": SelectionFlags,
"id": ScalarSelectNoArgs,
"owner": CompositeSelectNoArgs["OwnerSelections"],
},
total=False,
)

RootCompositeUnionFnOutputSelections = typing.TypedDict(
"RootCompositeUnionFnOutputSelections",
{
Expand Down Expand Up @@ -1070,6 +1155,16 @@ def get_posts(self, select: PostSelections) -> QueryNode[Post]:
node.node_name, node.instance_name, node.args, node.sub_nodes, node.files
)

def get_circular(self, select: CircularSelections) -> QueryNode[Circular]:
node = selection_to_nodes(
{"getCircular": select},
{"getCircular": NodeDescs.RootGetCircularFn},
["$q"],
)[0]
return QueryNode(
node.node_name, node.instance_name, node.args, node.sub_nodes, node.files
)

def scalar_no_args(self) -> QueryNode[PostSlugString]:
node = selection_to_nodes(
{"scalarNoArgs": True},
Expand Down
8 changes: 7 additions & 1 deletion tests/metagen/typegraphs/sample/py/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -141,4 +141,10 @@
}
)

print(json.dumps([res1, res1a, res2, res3, res4, res5]))
res6 = gql_client.query(
{
"circular": qg.get_circular({"_": SelectionFlags(select_all=True)}),
}
)

print(json.dumps([res1, res1a, res2, res3, res4, res5, res6]))
19 changes: 19 additions & 0 deletions tests/metagen/typegraphs/sample/py_upload/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,25 @@ def selection_to_nodes(
raise Exception(
"unreachable: union/either NodeMetas can't have subnodes"
)

last_node = parent_path[-1]
flags = sub_selections.get("_")

if flags is not None:
assert isinstance(flags, SelectionFlags)
select_all = flags and flags.select_all or False
recursive_field = next(
(
node
for node in meta.sub_nodes.keys()
if node == last_node
),
None,
)
# skip recursive fields when using `select_all`
if select_all and recursive_field:
continue

parent_path.append(instance_name)
sub_nodes = selection_to_nodes(
typing.cast("SelectionErased", sub_selections),
Expand Down
Loading

0 comments on commit f1c8a91

Please sign in to comment.