microsoft / microsoft/kiota

Python: SnakeCaseNamespaceNames never executes — CrawlTree inside empty-name guard

Open
#7,715 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
C#
Stars
3.8k
Forks
333
Avg merge
16h 29m
Merged PRs (30d)
116

Description

## Description

The `PythonRefiner.SnakeCaseNamespaceNames` method (which was removed in #7714 to avoid a breaking change) was intended to convert namespace segments to snake_case at the CodeDOM level before code generation. However, it never actually executed because `CrawlTree` was placed inside the `if (currentElement is CodeNamespace codeNamespace && !string.IsNullOrEmpty(codeNamespace.Name))` guard.

Since `RefineAsync` passes the root namespace (which has an empty name), the guard fails at the root and traversal never starts.

### Impact

- CodeNamespace.Name values remain in their original casing (e.g., `exportNamespace` instead of `export_namespace`)
- The path segmenter and import manager apply `.ToSnakeCase()` downstream, so generated **file paths and import statements are already correct**
- The only observable effect is in the public API export surface, which reflects the raw CodeNamespace.Name

### Why this wasn't fixed in #7714

Simply moving `CrawlTree` outside the guard (the obvious fix) causes a **breaking change**: `GetDifferential()` in `CodeNamespace.cs` strips the namespace prefix by character count (`Name[prefixLength..]`). The `clientNamespaceName` passed to the writer comes directly from the user's config and is NOT snake_cased. After snake_casing CodeNamespace.Name, the prefix length no longer matches, corrupting import path computation.

### Proper fix

To properly fix this, both changes are needed together:
1. Move `CrawlTree` outside the guard in `SnakeCaseNamespaceNames`
2. Snake_case the `clientNamespaceName` before passing it to `PythonWriter`/`PythonRelativeImportManager`

This ensures prefix stripping in `GetDifferential` works correctly with the now-snake_cased namespace names.

### Related

Split out from #7714 to avoid scope creep and breaking changes.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with PythonRefiner.SnakeCaseNamespaceNames and RefineAsync, then inspect CodeNamespace.GetDifferential() to understand its prefix slicing. Trace how clientNamespaceName reaches PythonWriter and PythonRelativeImportManager. Done means namespace names are snake_cased without corrupting generated import paths or file paths, with the public API export surface reflecting the converted names.

Written by the indexing model from the issue text.

Assessment

Tech stack
csharp, python
Domain
tooling
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
52/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.