Skip to content

Commit

Permalink
Support keywords
Browse files Browse the repository at this point in the history
  • Loading branch information
harupy committed Jul 16, 2023
1 parent 25294a5 commit b136b46
Showing 1 changed file with 35 additions and 22 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -111,14 +111,8 @@ fn create_property_assignment_stmt(property: &str, annotation: &Expr) -> Stmt {
.into()
}

/// Create a list of property assignments from the `NamedTuple` arguments.
fn create_properties_from_args(args: &[Expr]) -> Result<Vec<Stmt>> {
let Some(fields) = args.get(1) else {
let node = Stmt::Pass(ast::StmtPass {
range: TextRange::default(),
});
return Ok(vec![node]);
};
/// Create a list of property assignments from the `NamedTuple` positional arguments.
fn create_properties_from_fields_arg(fields: &Expr) -> Result<Vec<Stmt>> {
let Expr::List(ast::ExprList { elts, .. }) = &fields else {
bail!("Expected argument to be `Expr::List`");
};
Expand Down Expand Up @@ -154,6 +148,20 @@ fn create_properties_from_args(args: &[Expr]) -> Result<Vec<Stmt>> {
.collect()
}

/// Create a list of property assignments from the `NamedTuple` keyword arguments.
fn create_properties_from_keywords(keywords: &[Keyword]) -> Result<Vec<Stmt>> {
keywords
.iter()
.map(|keyword| {
let Keyword { arg, value, .. } = keyword;
let Some(arg) = arg else {
bail!("Expected `keyword` to have an `arg`")
};
Ok(create_property_assignment_stmt(arg.as_str(), value))
})
.collect()
}

/// Generate a `StmtKind:ClassDef` statement based on the provided body and
/// keywords.
fn create_class_def_stmt(typename: &str, body: Vec<Stmt>, base_class: &Expr) -> Stmt {
Expand Down Expand Up @@ -195,26 +203,31 @@ pub(crate) fn convert_named_tuple_functional_to_class(
return;
};

// Ignore `NamedTuple` calls containing both a list of fields and keywords:
// ```
// NamedTuple(
// "MyType",
// [("a", int), ("b", str)],
// defaults=[0, ""],
// )
// ```
if args.len() > 1 && !keywords.is_empty() {
return;
}

let properties = match create_properties_from_args(args) {
let properties = match (&args[1..], keywords) {
// Ex) NamedTuple("MyType")
([], []) => {
let node = Stmt::Pass(ast::StmtPass {
range: TextRange::default(),
});
Ok(vec![node])
}
// Ex) NamedTuple("MyType", [("a", int), ("b", str)])
([fields], []) => create_properties_from_fields_arg(fields),
// Ex) NamedTuple("MyType", a=int, b=str)
([], keywords) => create_properties_from_keywords(keywords),
// Unfixable
_ => {
debug!("Skipping `NamedTuple` \"{typename}\": unfixable");
return;
}
};
let properties = match properties {
Ok(properties) => properties,
Err(err) => {
debug!("Skipping `NamedTuple` \"{typename}\": {err}");
return;
}
};

let mut diagnostic = Diagnostic::new(
ConvertNamedTupleFunctionalToClass {
name: typename.to_string(),
Expand Down

0 comments on commit b136b46

Please sign in to comment.