Fix Python namespace normalization during refinement - #7991
Conversation
There was a problem hiding this comment.
Pull request overview
This pull request fixes Python namespace normalization at the CodeDOM refinement stage by ensuring namespace segments are converted to snake_case during refinement (including proper traversal from the root namespace) and by normalizing the configured client namespace prefix before Python path/import logic computes namespace differentials.
Changes:
- Normalize Python
CodeNamespace.Namesegments tosnake_caseduringPythonRefiner.RefineAsync, ensuring traversal starts from the root namespace. - Normalize
clientNamespaceNametosnake_caseinsidePythonWriterbefore initializing the path segmenter and namespace-dependent writers. - Update and extend tests to validate refined namespace casing, writer prefix normalization behavior, and public API export expectations.
Reviewed changes
Copilot reviewed 6 out of 6 changed files in this pull request and generated no comments.
Show a summary per file
| File | Description |
|---|---|
src/Kiota.Builder/Refiners/PythonRefiner.cs |
Adds a refinement pass to snake_case namespace segments and ensures traversal runs from the root namespace. |
src/Kiota.Builder/Writers/Python/PythonWriter.cs |
Normalizes the configured client namespace prefix to snake_case before path/import computations. |
tests/Kiota.Builder.Tests/Refiners/PythonLanguageRefinerTests.cs |
Adds coverage asserting namespace segment snake_casing and namespace lookup consistency post-refinement. |
tests/Kiota.Builder.Tests/Writers/Python/PythonWriterTests.cs |
Adds coverage ensuring client namespace prefix normalization affects path segmentation as expected. |
tests/Kiota.Builder.Tests/Export/PublicAPIExportServiceTests.cs |
Updates expected Python export namespace strings to reflect refined snake_case namespace names. |
tests/Kiota.Builder.Tests/KiotaBuilderTests.cs |
Updates a namespace lookup expectation for Python to match snake_cased namespaces after refinement. |
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 6 out of 6 changed files in this pull request and generated no new comments.
Comments suppressed due to low confidence (2)
src/Kiota.Builder/Refiners/PythonRefiner.cs:180
- SnakeCaseNamespaceNames can leave the CodeDOM in an inconsistent state when two sibling namespaces normalize to the same snake_case name: one namespace gets renamed, and the other is left with a name that no longer starts with its parent’s (renamed) namespace. This breaks invariants like CodeNamespace.IsParentOf and can also corrupt namespace differentials/import paths for the skipped namespace when the client namespace snake_casing changes the prefix length by >1.
Consider always renaming, and when a collision is detected, generate a unique snake_case name (e.g., append an incrementing suffix) so every namespace under a renamed parent still shares the normalized prefix.
if (!codeNamespace.Name.Equals(normalizedName, StringComparison.Ordinal))
{
if (codeNamespace.Parent is CodeNamespace parentNamespace)
{
if (parentNamespace.FindChildByName<CodeNamespace>(normalizedName, false) is null)
parentNamespace.RenameChildElement(codeNamespace.Name, normalizedName);
}
src/Kiota.Builder/Writers/Python/PythonWriter.cs:16
- ToSnakeCase() assumes that a '-' is never the final character in the input span (it reads nameSpan[i + 1] when current == '-'), so a client namespace segment like "foo-" (e.g., "foo-.bar") will throw IndexOutOfRangeException here. Since clientNamespaceName is user-configured and SanitizeClientNamespaceName can still yield segments ending with '-', this normalization should defensively trim such segments (or ToSnakeCase should be fixed globally).
var normalizedClientNamespaceName = string.Join('.',
clientNamespaceName
.Split('.', StringSplitOptions.RemoveEmptyEntries)
.Select(static x => x.ToSnakeCase()));
Summary
Normalizes Python CodeDOM namespace segments to snake_case during language refinement. Normalizes the configured client namespace before path and import writers calculate namespace differentials. Updates public API export expectations and adds coverage for root traversal and configured namespace casing.
Validation
dotnet test tests/Kiota.Builder.Tests/Kiota.Builder.Tests.csproj --no-restore --nologo --filter 'FullyQualifiedName!~KiotaSearcherTests' --verbosity quiet(2,185 passed, 2 skipped)Focused Python namespace, writer, export, and builder tests: 41 passed.
Fixes #7715