Skip to content

feat: add Python IntelliSense for generated APIs - #2676

Merged
Rana Singh (ranadeepsingh) merged 2 commits into
microsoft:masterfrom
ranadeepsingh:rana/python-intellisense-codegen
Aug 24, 2026
Merged

feat: add Python IntelliSense for generated APIs#2676
Rana Singh (ranadeepsingh) merged 2 commits into
microsoft:masterfrom
ranadeepsingh:rana/python-intellisense-codegen

Conversation

@ranadeepsingh

@ranadeepsingh Rana Singh (ranadeepsingh) commented Aug 23, 2026

Copy link
Copy Markdown
Collaborator

Related Issues/PRs

Closes #1013.

What changes are proposed in this pull request?

SynapseML's generated Python wrappers expose runtime keyword names, but they do
not currently ship PEP 561 typing metadata. Editors therefore infer many
setters and optional parameters as Unknown, and package-level class discovery
is inconsistent.

This PR:

  • generates adjacent .pyi files for generated transformers, estimators, and
    models, including typed constructors, setParams, Params, setters, getters,
    estimator model returns, and Python-only generated methods;
  • infers precise scalar and collection types, including OpenAI
    ServiceParam values such as concurrency, temperature, and
    deploymentName, without changing runtime converters or the public
    ParamInfo JVM shape;
  • generates explicit package stub exports and PEP 561 markers in
    component-owned namespace subpackages, and packages them in both component
    and aggregate wheels;
  • adds a manual stub for the exceptional UDFTransformer wrapper, which does
    not inherit its generated base class;
  • cleans the aggregate Python merge directory before packaging so removed
    generated files cannot survive into later wheels; and
  • documents automatic Pylance/editor support after wheel installation.

The generated runtime .py execution structure remains unchanged; only
documentation type labels become more precise.

How is this patch tested?

  • I have written tests and confirmed the proposed feature works.

Validation on the final rebased commit:

  • 24 focused Scala codegen and type-inference tests passed.
  • The full com.microsoft.azure.synapse.ml.core.** selector passed, including
    the production-stage discovery suite that caught test-only fixture leakage.
  • Aggregate compile, Test / compile, scalastyle, and
    Test / scalastyle passed across all six modules.
  • black==22.3.0 --check and git diff --check passed.
  • Full codegen succeeded for core, deep-learning, cognitive, VW, LightGBM,
    and OpenCV.
  • packageSynapseML produced an installable aggregate wheel containing 221
    .pyi files and 17 namespace-safe py.typed markers.
  • Pyright reported zero errors for representative APIs, every generated class
    stub, and 140 package-level exports; the same stubs also passed with a
    Python 3.8 target.
  • Negative Pyright coverage rejected 10 invalid constructor/setter calls with
    the expected types.
  • Jedi resolved OpenAI classes and method completions, and reported all 73
    OpenAIPrompt constructor parameters including concurrency.
  • The installed wheel imported successfully, and no .pyi file was loaded by
    the Python runtime.
  • The public PythonWrappable trait has no new abstract JVM members compared
    with the target-branch binary surface.
  • Normalized AST comparison found zero execution-structure differences across
    all 310 generated runtime .py files.
  • Alternating cold import measurements showed no runtime regression
    (typed median 1.495s vs. baseline 1.521s). Comparable dirty-worktree codegen
    was within local noise (60.06s vs. 58.89s).
  • Azure build
    232486498
    passed 76 checks, including UnitTests core. Its only failed job is the
    unrelated Fabric E2E cleanup, which aborted before running tests because
    GET https://api.fabric.microsoft.com/v1/workspaces returned HTTP 500 on
    both the initial run and a failed-job-only retry.

Does this PR change any dependencies?

  • No. You can skip this section.
  • Yes. Make sure the dependencies are resolved correctly, and list changes here.

Does this PR add a new feature? If so, have you added samples on website?

  • No new transformer API is added. Installation documentation is updated.
  • Yes. Make sure you have added samples following below steps.

AB#1984585

## Summary
Generate and package PEP 561 type stubs for SynapseML Python wrappers, with precise constructor, Param, setter, getter, estimator, and package export types across all components. Add namespace-safe typing markers, a manual UDFTransformer stub, deterministic packaging cleanup, regression tests, and installation guidance.

## Prompting Intent
Implement reliable IDE and notebook IntelliSense for SynapseML OpenAI and other generated Python APIs in an isolated worktree, including parameters such as concurrency. Preserve runtime behavior and JVM compatibility, rebase on current master, validate published-wheel behavior, and review repeatedly for correctness and performance regressions.

## Linked Sources
- Requirements issue: microsoft#1013

## Rationale
Use adjacent .pyi files rather than runtime annotations so Python execution and imports remain unchanged while Pylance, Pyright, and Jedi receive precise signatures. Keep stub-only metadata separate from ParamInfo to preserve its JVM constructor shape, retain fluent public-wrapper subtypes with a bound TypeVar, place py.typed markers in component-owned namespace subpackages to avoid wheel ownership conflicts, and clean aggregate merge output so removed generated files cannot leak into later wheels.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Copilot-Session: 7dc287c1-b6cf-42f8-a26e-bf673be9f3d3
Copilot AI lite review requested due to automatic review settings August 23, 2026 05:46
@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines:
There may be pipelines that require an authorized user to comment /azp run to run.

@github-actions

Copy link
Copy Markdown

Hey Rana Singh (@ranadeepsingh) 👋!
Thank you so much for contributing to our repository 🙌.
Someone from SynapseML Team will be reviewing this pull request soon.

We use semantic commit messages to streamline the release process.
Before your pull request can be merged, you should make sure your first commit and PR title start with a semantic prefix.
This helps us to create release messages and credit you for your hard work!

Examples of commit messages with semantic prefixes:

  • fix: Fix LightGBM crashes with empty partitions
  • feat: Make HTTP on Spark back-offs configurable
  • docs: Update Spark Serving usage
  • build: Add codecov support
  • perf: improve LightGBM memory usage
  • refactor: make python code generation rely on classes
  • style: Remove nulls from CNTKModel
  • test: Add test coverage for CNTKModel

To test your commit locally, please follow our guild on building from source.
Check out the developer guide for additional guidance on testing your change.

@ranadeepsingh

Copy link
Copy Markdown
Collaborator Author

/azp run

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines:
Successfully started running 1 pipeline(s).

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds PEP 561 typing support for SynapseML’s generated Python wrappers by emitting .pyi stubs and py.typed markers during codegen and ensuring both component and aggregate wheels package these typing artifacts, improving editor IntelliSense for constructors, params, setters/getters, and estimator model returns.

Changes:

  • Generate per-wrapper .pyi stub files (including inferred types for ServiceParam) alongside existing runtime .py wrappers.
  • Generate __init__.pyi stub exports and py.typed markers for typed subpackages; include *.pyi/py.typed in wheel package_data.
  • Add targeted Scala tests for stub/type inference behavior and clean the aggregate merged Python directory before packaging.
Show a summary per file
File Description
docs/Get Started/Install SynapseML.md Documents that wheels ship PEP 561 typing metadata and how editors pick it up.
core/src/test/scala/com/microsoft/azure/synapse/ml/codegen/VerifyDefaultParamInfo.scala Adds tests validating pyi type strings and ServiceParam stub-type inference.
core/src/test/scala/com/microsoft/azure/synapse/ml/codegen/PyCodegenSuite.scala Adds end-to-end tests asserting generated .pyi, __init__.pyi, and wheel packaging behavior.
core/src/main/scala/com/microsoft/azure/synapse/ml/codegen/Wrappable.scala Emits .pyi stubs for generated wrappers (typed __init__, setParams, param accessors, and extra methods).
core/src/main/scala/com/microsoft/azure/synapse/ml/codegen/PyCodegen.scala Generates __init__.pyi exports, creates py.typed markers, and packages typing artifacts.
core/src/main/scala/com/microsoft/azure/synapse/ml/codegen/DefaultParamInfo.scala Introduces PythonTypeInfo + reflection-based type inference for more precise stub types.
core/src/main/python/synapse/ml/stages/UDFTransformer.pyi Adds a manual stub for the exceptional UDFTransformer wrapper.
build.sbt Ensures aggregate wheel includes typing artifacts and cleans merged Python sources before packaging.

Review details

💡 Configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

  • Files reviewed: 7/8 changed files
  • Comments generated: 2
  • Review effort level: Lite

## Summary
Nest typed codegen test fixtures so FuzzingTest ignores them while retaining generated class names for stub assertions. This prevents test-only stages from being interpreted as production pipeline stages.

## Prompting Intent
The engineer requested fully validated SynapseML IntelliSense support with repeated review and no regressions. Azure CI exposed a core discovery failure after the initial PR, so this change fixes the root cause and validates the exact failing suite.

## Linked Sources
- GitHub PR: microsoft#2676
- GitHub issue: microsoft#1013
- Azure CI build: https://msdata.visualstudio.com/A365/_build/results?buildId=232483047

## Rationale
Production-stage fuzzing intentionally ignores nested classes. Nesting the fixtures confines the fix to tests and preserves runtime and wheel behavior; explicit fixture class-name overrides keep generated stub expectations deterministic. Adding a fuzzing exemption instead would weaken coverage for real stages.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Copilot-Session: 7dc287c1-b6cf-42f8-a26e-bf673be9f3d3
Copilot AI review requested due to automatic review settings August 23, 2026 06:22
@ranadeepsingh

Copy link
Copy Markdown
Collaborator Author

/azp run

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines:
Successfully started running 1 pipeline(s).

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review details

  • Files reviewed: 7/8 changed files
  • Comments generated: 0 new
  • Review effort level: Lite

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review details

Suppressed comments (1)

core/src/main/scala/com/microsoft/azure/synapse/ml/codegen/PyCodegen.scala:141

  • packageFolder becomes values like "/services" in the recursion (packageFolder + "/" + f.getName). Passing that directly into FileUtilities.join(conf.pySrcDir, ..., packageFolder) can cause dir to resolve to an absolute filesystem path (because the last segment starts with "/"), which would make init/stub generation read/write outside conf.pySrcDir. Normalize packageFolder (strip the leading slash) for filesystem paths, while keeping the original packageFolder for the special-case comparisons ("/services", "/cognitive").
      }
    }
    makeInitStub(conf, dir, packageFolder, packageString)
    dir.listFiles().filter(_.isDirectory).foreach(f =>
      makeInitFiles(conf, packageFolder + "/" + f.getName)
  • Files reviewed: 7/8 changed files
  • Comments generated: 1
  • Review effort level: Lite

@ranadeepsingh
Rana Singh (ranadeepsingh) merged commit 57c799b into microsoft:master Aug 24, 2026
78 of 80 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Python mmlspark typing information

3 participants