diff --git a/CHANGELOG.md b/CHANGELOG.md index 27af4305a..4f8ab3a3a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,6 +16,9 @@ CHANGELOG - Ensure Go accessor methods correctly support nested fields of optional outputs [#4456](https://github.com/pulumi/pulumi/pull/4456) +- Ensure generated Python module names are keyword-safe. + [#4473](https://github.com/pulumi/pulumi/pull/4473) + ## 2.0.0 (2020-04-16) diff --git a/pkg/codegen/python/gen.go b/pkg/codegen/python/gen.go index 61a5dcc01..9a96dca19 100644 --- a/pkg/codegen/python/gen.go +++ b/pkg/codegen/python/gen.go @@ -1152,7 +1152,7 @@ func GeneratePackage(tool string, pkg *schema.Package, extraFiles map[string][]b var getMod func(token string) *modContext getMod = func(token string) *modContext { - modName := pkg.TokenToModule(token) + modName := PyName(pkg.TokenToModule(token)) mod, ok := modules[modName] if !ok { mod = &modContext{ diff --git a/pkg/codegen/python/gen_program.go b/pkg/codegen/python/gen_program.go index 92913ab73..7a6cf8ff1 100644 --- a/pkg/codegen/python/gen_program.go +++ b/pkg/codegen/python/gen_program.go @@ -72,7 +72,7 @@ func pyName(pulumiName string, isObjectKey bool) string { if isObjectKey { return fmt.Sprintf("%q", pulumiName) } - return PyName(cleanName(pulumiName)) + return PyName(pulumiName) } // genLeadingTrivia generates the list of leading trivia assicated with a given token. @@ -167,7 +167,13 @@ func (g *generator) genNode(w io.Writer, n hcl2.Node) { func resourceTypeName(r *hcl2.Resource) (string, string, string, hcl.Diagnostics) { // Compute the resource type from the Pulumi type token. pkg, module, member, diagnostics := r.DecomposeToken() - return pyName(pkg, false), strings.Replace(module, "/", ".", -1), title(member), diagnostics + + components := strings.Split(module, ".") + for i, component := range components { + components[i] = PyName(component) + } + + return pyName(pkg, false), strings.Join(components, "."), title(member), diagnostics } // makeResourceName returns the expression that should be emitted for a resource's "name" parameter given its base name diff --git a/pkg/codegen/python/gen_program_expressions.go b/pkg/codegen/python/gen_program_expressions.go index 74d823a5f..27548c0be 100644 --- a/pkg/codegen/python/gen_program_expressions.go +++ b/pkg/codegen/python/gen_program_expressions.go @@ -172,9 +172,15 @@ func functionName(tokenArg model.Expression) (string, string, string, hcl.Diagno token := tokenArg.(*model.TemplateExpression).Parts[0].(*model.LiteralValueExpression).Value.AsString() tokenRange := tokenArg.SyntaxNode().Range() - // Compute the resource type from the Pulumi type token. + // Compute the function name from the Pulumi type token. pkg, module, member, diagnostics := hcl2.DecomposeToken(token, tokenRange) - return cleanName(pkg), strings.Replace(module, "/", ".", -1), title(member), diagnostics + + components := strings.Split(module, ".") + for i, component := range components { + components[i] = PyName(component) + } + + return cleanName(pkg), strings.Join(components, "."), title(member), diagnostics } var functionImports = map[string]string{ @@ -439,7 +445,7 @@ func (g *generator) GenTemplateExpression(w io.Writer, expr *model.TemplateExpre } } - prefix, isMultiLine, quotes := "", false, `"` + formatted, isMultiLine, quotes := false, false, `"` for i, part := range expr.Parts { if lit, ok := part.(*model.LiteralValueExpression); ok { if !isMultiLine && lit.Type() == model.StringType { @@ -455,17 +461,21 @@ func (g *generator) GenTemplateExpression(w io.Writer, expr *model.TemplateExpre isMultiLine, quotes = true, `"""` } } else { - prefix = "f" + formatted = true } } b := bufio.NewWriter(w) defer b.Flush() + prefix := "" + if formatted { + prefix = "f" + } g.Fprintf(b, "%s%s", prefix, quotes) for _, expr := range expr.Parts { if lit, ok := expr.(*model.LiteralValueExpression); ok && lit.Type() == model.StringType { - g.genEscapedString(b, lit.Value.AsString(), !isMultiLine, true) + g.genEscapedString(b, lit.Value.AsString(), !isMultiLine, formatted) } else { g.Fgenf(b, "{%.v}", expr) } diff --git a/pkg/codegen/python/python.go b/pkg/codegen/python/python.go index 607481ee2..e0f990c72 100644 --- a/pkg/codegen/python/python.go +++ b/pkg/codegen/python/python.go @@ -72,7 +72,7 @@ func PyName(name string) string { var components []string // The components that will be joined together with underscores var currentComponent []rune // The characters composing the current component being built state := stateFirst - for _, char := range name { + for _, char := range cleanName(name) { switch state { case stateFirst: if unicode.IsUpper(char) {