CAMEL-24337: Add Python 3 language component - #25551
Conversation
Maintainer Feedback RequestedI would particularly appreciate maintainer feedback on the HostAccess/default security model and its intentional difference from camel-python. The existing Jython component provides Java interoperability through the Jython runtime, whereas camel-python3 uses GraalVM HostAccess to establish a more restrictive default model. Before finalizing the API and documentation, I would like to confirm whether this is the preferred Camel approach, or whether camel-python3 should expose Java/Camel objects by default for compatibility with camel-python. |
|
🌟 Thank you for your contribution to the Apache Camel project! 🌟 🐫 Apache Camel Committers, please review the following items:
|
|
🧪 CI tested the following changed modules:
✅ POM dependency changes: targeted tests included Changed properties: graalpy-version Modules affected by dependency changes (1)
🔬 Scalpel shadow comparison — Scalpel: 569 tested, 22 compile-only — current: 561 all testedMaveniverse Scalpel detected 591 affected modules (current approach: 561).
|
atiaomar1978-hub
left a comment
There was a problem hiding this comment.
Review summary
AI-generated review on behalf of atiaomar1978-hub (Bugbot + manual review)
Impressive addition — GraalPy-based Python 3 is a meaningful upgrade path over legacy Jython (python / 2.7). The security model is thoughtfully designed: default bindings are data-only (body, headers, properties, exchangeId), HostAccess is restricted, and createWithHostAccess() is an explicit trusted opt-in.
Test coverage — strong ✅
Nine test classes (~1,000 lines) cover the areas that matter:
| Area | Test class |
|---|---|
| Syntax, types, predicates, concurrency | Python3LanguageEvalTest |
| Security (default + trusted, IO/process/class lookup) | Python3LanguageSecurityTest |
| Syntax vs evaluation exceptions | Python3ErrorHandlingTest |
| Classpath/file resources | Python3ResourceTest |
| SPI + registry override | Python3ResolutionTest |
Java DSL (setBody, filter, choice) |
Python3JavaDslTest, Python3ChoiceTest |
language:python3: endpoint |
Python3LanguageEndpointTest |
| Typed-language compliance | Python3LanguageTest |
Security tests are particularly thorough — this is the right bar for a scripting language.
Must fix
- Documentation — Variables table is misleading — the table lists
message,exchange, andcontextas available bindings, but defaultPython3Languageintentionally does not bind them (they raiseNameError). OnlycreateWithHostAccess()exposes them. Please split the table or mark those three as opt-in only.
Suggestions (non-blocking)
-
materialize()fallback — guest values that are not list/dict/primitive fall through tovalue.as(Object.class)(Python3Language.java:320), which may yield Polyglot proxies unusable afterContext#close(). Either materialize sets/tuples explicitly, document the limitation, or add a test asserting behaviour for{1, 2}/ custom objects. -
CI note — latest full build failed on unrelated
camel-pqcsurefire, notcamel-python3. The targetedbuildcheck passed. Worth re-running / confirming green before merge.
Verdict
Request changes for the docs fix. Test coverage and security posture are merge-ready otherwise.
Review performed with code inspection and Bugbot. Does not replace specialized tools (CodeRabbit, Sourcery, SonarCloud).
| |headers |Map |the message headers | ||
| |properties |Map |the exchange properties | ||
| |exchangeId |String |the exchange id | ||
| |message |Message |the message |
There was a problem hiding this comment.
Blocking — variables table contradicts default behaviour
This table lists message, exchange, and context as available variables, but default Python3Language intentionally does not bind them — scripts get NameError (see Python3LanguageSecurityTest.defaultDoesNotBindExchangeMessageOrContext).
Only a registry-installed Python3Language.createWithHostAccess() instance exposes those three.
Please either:
- remove them from the default table and document them under the trusted/host-access section, or
- add a column such as "Default / opt-in" marking
message/exchange/contextas opt-in only.
There was a problem hiding this comment.
Documentation updated to clearly distinguish the default bindings from the createWithHostAccess() trusted-mode bindings. message, exchange, and context are now documented as opt-in only.
| .isEqualTo(exchange.getExchangeId()); | ||
| } | ||
|
|
||
| @Test |
There was a problem hiding this comment.
Excellent security test coverage
This is exactly the test matrix a scripting language needs: default data bindings work, Camel host objects are unbound, Java method invocation is denied, class lookup/IO/process creation blocked, and trusted mode is verified separately without widening the sandbox.
Strong work — sets the bar for the component.
| } | ||
| return map; | ||
| } | ||
| return value.as(Object.class); |
There was a problem hiding this comment.
Suggestion — guest object materialization
materialize copies lists/dicts/primitives into plain Java types (well tested in Python3LanguageEvalTest), but other guest values fall through to value.as(Object.class) here. Python set / custom objects may remain Polyglot-backed and fail after Context#close().
Consider materializing sets (or documenting the limitation) and adding a test for {1, 2} / tuple returns.
There was a problem hiding this comment.
Implemented. Python sets/frozensets and tuples are now materialized into ordinary Java collections before the GraalPy context closes, including nested values. Added coverage for set, tuple, and nested set/tuple results. Custom guest objects remain unchanged. All 43 tests pass.
| * {@code allowIO}, or {@code allowCreateProcess}. {@code HostAccess.ALL} (trusted mode) only unlocks public members | ||
| * of already-bound host objects; it is not a sandbox and does not grant class lookup or IO. | ||
| */ | ||
| public static Context newContext(Engine engine, HostAccess hostAccess) { |
There was a problem hiding this comment.
Good security defaults
No allowAllAccess, no allowHostClassLookup, no allowIO, no allowCreateProcess, PolyglotAccess.NONE — paired with map/list-only HostAccess in default mode. Matches Camel's trust model for scripting languages.
There was a problem hiding this comment.
Thanks for confirming. We’ll keep these restrictive defaults and the current trusted-mode separation.
Review complete — test coverage assessmentAI-generated on behalf of atiaomar1978-hub Verdict: Request changes (docs fix required; tests are strong) Test coverage score: 8.5 / 10Bugbot found no critical security bugs. The test suite is one of the better scripting-language additions I've seen in Camel:
Gaps (non-blocking): Python Blocking: Variables table in Thanks @ramu11 — GraalPy is a great direction for Python 3 support. Fix the docs table and this is ready from a testing/security standpoint. |
| <google-cloud-texttospeech-version>2.96.0</google-cloud-texttospeech-version> | ||
| <google-genai-version>1.65.0</google-genai-version> | ||
| <graaljs-version>25.2.4</graaljs-version> | ||
| <graalpy-version>25.2.4</graalpy-version> |
There was a problem hiding this comment.
Instead of introducing a new version property, it might be better to rename <graaljs-version> to <graalvm-version> and use that. I don't think we'd ever need different versions of GraalJs and GraalPy. They should always be aligned.
Description
Add a new
camel-python3language component using GraalPy for Python 3 support.The existing
camel-pythoncomponent remains unchanged.Changes
camel-python3component based on GraalPyTesting
Tests are included for: