Skip to content

Hide engine-only extension methods and the OrderTicket int conversion from Python - #9988

Merged
jhonabreul merged 3 commits into
QuantConnect:masterfrom
jhonabreul:feature-hide-engine-only-extensions-from-python
Oct 29, 2026
Merged

jhonabreul merged 3 commits into
QuantConnect:masterfrom
jhonabreul:feature-hide-engine-only-extensions-from-python

Conversation

@jhonabreul

Copy link
Copy Markdown
Collaborator

Description

Python.NET 2.0.67 (QuantConnect/pythonnet#150 and #151) binds C# extension methods to the type they extend and gives types with an implicit numeric conversion the Python number protocol. The stubs follow suit in QuantConnect/quantconnect-stubs-generator#104. Two things on the Lean side should stay out of the user-facing surface:

  • Engine-only extension methods on IAlgorithm, Symbol, Order and SubscriptionDataConfig, such as ProcessSecurityChanges, RequiresMapping, ShouldEmitData or TryGetContingentOrders, are marked EditorBrowsable(Never). Python.NET and the stubs keep them in their static form instead of binding them to the instance.
  • OrderTicket's implicit operator int is marked StubsIgnore, so the stubs do not give tickets the number protocol.

Split out of #9896 so it can ship together with the stubs generator PR.

Related Issue

N/A

Motivation and Context

Without the attributes, every Python Symbol, Order or algorithm instance advertises engine plumbing like self.set_runtime_error() or symbol.requires_mapping(), and OrderTicket gets __add__ and friends in the stubs.

Requires Documentation Change

No.

How Has This Been Tested?

Types of changes

  • Bug fix (non-breaking change which fixes an issue)
  • Refactor (non-breaking change which improves implementation)
  • Performance (non-breaking change which improves performance. Please add associated performance test and results)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to change)
  • Non-functional change (xml comments/documentation/etc)

Checklist:

  • My code follows the code style of this project.
  • I have read the CONTRIBUTING document.
  • I have added tests to cover my changes.
  • All new and existing tests passed.
  • My branch follows the naming convention bug-<issue#>-<description> or feature-<issue#>-<description>

@quantconnect-kronos-reviewer quantconnect-kronos-reviewer Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Approving. The change is small and does what the description says. I verified it myself:

  • CI: all checks pass. The unit test job ran 39,185 tests with 0 failures.
  • The new test catches the regression: I reverted only the EditorBrowsable commit and ran EditorBrowsableNeverExtensionMethodsAreNotBoundToPythonInstances. It fails (hasattr(symbol, 'requires_mapping') is True). It passes on the head commit, along with the other 485 tests in ExtensionsTests, ContingentOrder* and OrderTicket*.
  • Mechanism: pythonnet 2.0.67 (already on master since #9964) skips EditorBrowsable(Never) members when it binds extension methods to instances (IsHidden in pythonnet's ExtensionMethods.cs). The attribute changes nothing for C# callers, so engine and user C# code still compile and run as before.
  • End to end: I ran a Python backtest on a build of this branch. hasattr was False for symbol.requires_mapping, self.set_runtime_error and self.process_security_changes. Extensions.requires_mapping(symbol) still worked. Market and combo orders filled. order.is_contingent() stayed bound, and int(ticket) still returned the order id at runtime. StubsIgnore only hides the conversion from the stubs, not from Python.
  • Callers: none of the newly hidden methods are called in instance form from any Python algorithm in this repository or in the documentation examples.

Smaller points, none of them blocking:

  • CreateOptionChain and CreateFutureChain (both this IAlgorithm) are still bound to Python algorithm instances, as self.create_option_chain(...). They look just as engine-only as ProcessSecurityChanges. Was leaving them out intentional?
  • An inline nit on the using order in Extensions.cs.
  • It would help to add the end-to-end outcome to the description's testing section.

Affected repositories: QuantConnect/quantconnect-stubs-generator#104 (still open) should ship with this PR, as the description says. No other repository needs an update.

Risk: risk:high. This changes Lean's Python algorithm API. Release 18215 already includes pythonnet 2.0.67, so a Python algorithm can call these methods in instance form today (e.g. symbol.requires_mapping()). After this PR they only exist in their static form. That is very unlikely to affect anyone, since these methods are engine plumbing, and the change is easy to revert. But removing user-visible members is a high-risk trait regardless of the evidence.

Comment thread Common/Extensions.cs
* limitations under the License.
*/

using System.ComponentModel;

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Nit: this goes above using System;, while the rest of the block is sorted. Moving it after using System.Collections.Immutable; keeps the order.

@quantconnect-kronos-reviewer quantconnect-kronos-reviewer Bot added risk:high High risk and removed kronos:review:working review: in progress labels Oct 29, 2026
@jhonabreul
jhonabreul merged commit 93fa093 into QuantConnect:master Oct 29, 2026
8 checks passed
@jhonabreul
jhonabreul deleted the feature-hide-engine-only-extensions-from-python branch October 29, 2026 16:34
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

risk:high High risk

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants