Skip to content

Commit fcfa19e

Browse files
committed
chore: mid work
1 parent 4ae6350 commit fcfa19e

2 files changed

Lines changed: 36 additions & 24 deletions

File tree

packages/jsii-pacmak/lib/targets/python.ts

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2180,10 +2180,27 @@ class PythonModule implements PythonType {
21802180
* indicating a full module import. Parses the sourcePackage string which
21812181
* has the format "module.name as _alias" to extract the module name and alias.
21822182
* Sorts assignments by alias for deterministic output.
2183+
*
2184+
* NOTE: All current code paths in type-name.ts produce `item: ''` (full
2185+
* module imports). If a non-empty item is encountered, it means a new import
2186+
* pattern was introduced without updating this method to handle it at runtime.
21832187
*/
21842188
private emitLazyProxyAssignments(code: CodeMaker, imports: PythonImports) {
2189+
// Verify all imports use the expected full-module pattern (item === '').
2190+
// If this assertion fires, a new import pattern was added to type-name.ts
2191+
// that needs a corresponding runtime lazy-loading strategy here.
2192+
for (const [sourcePackage, items] of Object.entries(imports)) {
2193+
const nonEmpty = Array.from(items).filter((i) => i !== '');
2194+
if (nonEmpty.length > 0) {
2195+
throw new Error(
2196+
`Unexpected non-empty import items for "${sourcePackage}": [${nonEmpty.join(', ')}]. ` +
2197+
`emitLazyProxyAssignments only supports full-module imports (empty item). ` +
2198+
`Update this method to handle per-item imports at runtime.`,
2199+
);
2200+
}
2201+
}
2202+
21852203
const assignments = Object.entries(imports)
2186-
.filter(([, items]) => items.has('')) // Only full module imports (empty string = import the whole module)
21872204
.map(([sourcePackage]) => {
21882205
// sourcePackage is like "aws_cdk.aws_iam as _aws_cdk_aws_iam_abcd1234"
21892206
const match = sourcePackage.match(/^(.+)\s+as\s+(.+)$/);

python-imports-4-review.md

Lines changed: 18 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -72,21 +72,13 @@ instead of the full 11-line class definition. Since `jsii` is already imported b
7272

7373
### 3. [Medium] `emitLazyProxyAssignments` silently drops non-empty items at runtime
7474

75-
**Status: Not a real concern today**
76-
77-
The `emitLazyProxyAssignments` method filters with:
78-
79-
```typescript
80-
.filter(([, items]) => items.has(''))
81-
```
82-
83-
If there were ever a `PythonImports` entry with non-empty items (e.g., `from foo import Bar`), it would appear in the `TYPE_CHECKING` block but have **no runtime equivalent** in the `else` branch.
75+
**Status: FIXED**
8476

85-
**Verified:** All `requiredImport` entries in `type-name.ts` use `item: ''`. There are exactly two code paths that produce `requiredImport` objects (foreign assembly imports at line 390, same-assembly cross-submodule imports at line 420), and both set `item: ''`. The old per-type import pattern (`item: 'TypeName as _TypeName_hash'`) was completely replaced by the new module-level approach. There is no code path that currently produces non-empty items for cross-module imports.
77+
The `emitLazyProxyAssignments` method previously filtered with `.filter(([, items]) => items.has(''))`, which would silently skip any import entry with non-empty items — meaning it would appear in the `TYPE_CHECKING` block for type checkers but have no runtime equivalent.
8678

87-
The `emitImportStatements` method (in the `TYPE_CHECKING` block) does handle both empty and non-empty items correctly, so type checkers would see correct imports regardless.
79+
**Fix:** Replaced the silent filter with an explicit assertion that throws an error if any non-empty items are encountered. This ensures that if a new import pattern is ever introduced in `type-name.ts`, the code generator will fail loudly at build time rather than producing subtly broken runtime code.
8880

89-
**Action:** Optional — add a comment in `emitLazyProxyAssignments` noting that only full-module imports (empty item) are expected. Not blocking.
81+
**Verified:** All current code paths produce `item: ''` (two locations in `type-name.ts`), so the assertion never fires today — it's purely a safety net for future changes.
9082

9183
---
9284

@@ -150,16 +142,13 @@ The review suggests relative imports would work without installation, but:
150142

151143
### 7. [Low] `_LazyImport` doesn't implement `__repr__`
152144

153-
**Status: Legit, very low priority**
145+
**Status: FIXED (as part of issue #2 fix)**
154146

155-
If someone inspects the proxy object in a debugger, they'll see `<_LazyImport object at 0x...>` rather than something informative.
147+
The `_LazyImport` class now lives in the jsii runtime and includes a `__repr__` method:
148+
- Before resolution: `_LazyImport('some_module')`
149+
- After resolution: delegates to the real module's `repr()`
156150

157-
However:
158-
- Users should never interact with `_LazyImport` objects directly — they're internal implementation details prefixed with `_`.
159-
- Once any attribute is accessed, the proxy resolves to the real module transparently.
160-
- Adding `__repr__` would add 2 more lines per module (compounding issue #2).
161-
162-
**Action:** Optional follow-up. Not blocking.
151+
This was added for free when moving the class to the runtime package.
163152

164153
---
165154

@@ -170,9 +159,15 @@ The implementation is sound and none of these issues are blocking. The approach
170159
| Issue | Verdict | Blocking? | Action |
171160
|-------|---------|-----------|--------|
172161
| 1. Eager resolution for base classes/decorators | Legit observation, not a bug | No | Document limitation in PR |
173-
| 2. `_LazyImport` duplication | Legit, reasonable tradeoff | No | Consider follow-up optimization |
174-
| 3. Silent drop of non-empty items | Not a real concern today | No | Optional defensive comment |
162+
| 2. `_LazyImport` duplication | ~~Legit concern~~ FIXED | No | Moved to jsii runtime package |
163+
| 3. Silent drop of non-empty items | ~~Not a real concern~~ FIXED | No | Added defensive assertion |
175164
| 4. Hash change causes churn | Legit, inherent to approach | No | Document in PR description |
176165
| 5. `__future__` emitted unnecessarily | Technically correct, harmless | No | None |
177166
| 6. Absolute vs relative imports | Not a real concern | No | None |
178-
| 7. Missing `__repr__` | Legit, very low priority | No | Optional follow-up |
167+
| 7. Missing `__repr__` | ~~Legit~~ FIXED (with #2) | No | Added to runtime class |
168+
169+
---
170+
171+
## Branch Status
172+
173+
Snapshot tests are now passing after the issue #2 fix. The `target-python` and `type-name` test suites both pass (78 tests, 126 snapshots).

0 commit comments

Comments
 (0)