diff --git a/antlir/bzl/shape2/ir2code.rs b/antlir/bzl/shape2/ir2code.rs index b17c10453f4..eb1671893b6 100644 --- a/antlir/bzl/shape2/ir2code.rs +++ b/antlir/bzl/shape2/ir2code.rs @@ -231,6 +231,7 @@ impl RegisterTemplates for Module { templates.read_template("module.pydantic.handlebars")?, ) .context("Trying to register preamble template")?; + hb.register_helper("lint-directive", Box::new(py_lint_directive)); hb.register_helper("type-hint", Box::new(py_type_hint)); hb.register_helper("literal", Box::new(py_literal)); Ok(hb) @@ -391,6 +392,25 @@ impl TypeExt for Type { } } +trait FieldExt { + fn py_lint_directive(&self) -> &str; +} + +impl FieldExt for Field { + fn py_lint_directive(&self) -> &str { + if let Type::List { .. } = *self.ty { + // In py_type_hint() we lie and convert Lists to Tuples to + // discourage mutation, so here we pay penance by suppressing + // typing errors + " # pyre-ignore: Incompatible attribute type [8]:" + } else { + "" + } + } +} + +handlebars_helper!(py_lint_directive: |field: Field| field.py_lint_directive().to_string()); + handlebars_helper!(has_default_value: |field: Field| Value::Bool(field.default_value.is_some())); handlebars_helper!(py_type_hint: |ty: Type| ty.py_type_hint().to_string()); diff --git a/antlir/bzl/shape2/templates/struct.pydantic.handlebars b/antlir/bzl/shape2/templates/struct.pydantic.handlebars index ff5388e97a4..1c48e4865d9 100644 --- a/antlir/bzl/shape2/templates/struct.pydantic.handlebars +++ b/antlir/bzl/shape2/templates/struct.pydantic.handlebars @@ -3,8 +3,8 @@ class {{name}}(Shape): {{#each fields}} {{#if required}} - {{@key}}: {{type-hint type}} {{#if (has-default-value this)}}= {{literal default_value type}}{{/if}} + {{@key}}: {{type-hint type}} {{#if (has-default-value this)}}= {{literal default_value type}}{{lint-directive this}}{{/if}} {{else}} - {{@key}}: typing.Optional[{{type-hint type}}] = {{#if (has-default-value this)}}{{literal default_value type}}{{else}}None{{/if}} + {{@key}}: typing.Optional[{{type-hint type}}] = {{#if (has-default-value this)}}{{literal default_value type}}{{else}}None{{lint-directive this}}{{/if}} {{/if}} {{/each}}