-
Notifications
You must be signed in to change notification settings - Fork 4k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
aws_cdk.core.Stack.of() returns wrong class type (in Python) #8262
Comments
Looks like you're running foul of the reality that python is not a "first class citizen" in cdk world, only typescript. The python implementation is a mapping to typescript. This mapping only goes one way - to typescript and does not go the other way, from typescript to python. So the Stack.of method calls the typescript equivalent and the typescript returns a stack. But the typescript unable to return the original python type - it seems - unless that python type matches the type it was called on. I suspect that original mapping is not kept as there is no mapping from typescript to python. I'm not sure what options you have... If you really want it to sing the thing to do would be to code your api or library in typescript, add jsii bindings and generate the python... I think you'd get a lot of mileage if you did that. |
This statements might not be true. As I stated above, jssi is perfectly capable to return the correct class type when the Stack.of()-method is called on
As such I am confident that jsii could be able to return the proper class type even in the currently failing case, where the .of()-Method is called on the subclass of my custom stack class directly. |
@RomainMuller @MrArnoldPalmer I was under the impression that jsii should return the actual type of the object and not the type declared on the method. Am I missing something? |
This is a gross oversimplification of what jsii is doing.
This is incorrect. If an instance of some python type is passed to JavaScript, then that same instance should be what is seen from Python's point of view if that is ever read back from JavaScript. If that isomorphism does not happen for a given class instance, then there is a bug. TL;DR: Something weird/abnormal seems to be happening here, and I'll be looking into that to understand exactly what. |
So the return type of your @classmethod
def of(cls, construct: core.Construct) -> core.Stack:
stack = super().of(construct)
print(type(stack))
return stack I have tested with the following reproduction code (vertically the same as your code): #!/usr/bin/env python3
from aws_cdk import core
class MyParentStack(core.Stack):
...
class MyChildStack(MyParentStack):
...
app = core.App()
stack_parent_instance = MyParentStack(app, 'Parent')
stack_child_instance = MyChildStack(app, 'Child')
print("Parent: " + type(core.Stack.of(stack_parent_instance)))
print("Child: " + type(core.Stack.of(stack_child_instance)))
app.synth() And it produces the following output:
I reckon this is conform to what you were expecting to see, so I am presently unable to reproduce your problem. My
|
Thanks @RomainMuller for attending to the issue. To be sorry, the reproduction steps from my original example did not really work - or at least did work as I would it expect from CDK. However I could strip down my production code to a minimal example which can be run as-is and reproduces the
As you can see, the behavior has nothing to to with subclassing, as I accidentially thought first. It rather occurs if the Because I stripped down the code to reproduce the behavior, there is maybe the question why I would call the As Python is during the construction aleady aware of the class type, I suppose that TypeScript is not and simply returns the type of the derived class. This is my first thought about the reasoning, why |
I see. What could possibly go wrong here is that the reference might be read back from JavaScript before it's identifier has been bound to the current instance (possibly because it is being initialized). Consequently, a new proxy reference is initialized on reading back from JS, instead of re-using the original instance. I must admit this is a super interesting bug... I'll dig into that today. |
Yup - the culprit is definitely that the metaclass registers the reference into it's registry only after |
Within the `__init__` of a class, reading `self` back from the JS process would result in a proxy object created for the parent type, instead of returning `self`. This is because the `JSIIMeta` metaclass only registered the instance in the rerefence map **after** the constructor had returned. This adds an additional registration point right after the `create` API returned from the kernel, making the reference available as early as it can possibly be known. Fixes aws/aws-cdk#8262
Within the `__init__` of a class, reading `self` back from the JS process would result in a proxy object created for the parent type, instead of returning `self`. This is because the `JSIIMeta` metaclass only registered the instance in the rerefence map **after** the constructor had returned. This adds an additional registration point right after the `create` API returned from the kernel, making the reference available as early as it can possibly be known. Fixes aws/aws-cdk#8262 --- By submitting this pull request, I confirm that my contribution is made under the terms of the [Apache 2.0 license]. [Apache 2.0 license]: https://www.apache.org/licenses/LICENSE-2.0
Cool, that was quick. Will the fix be part of the next jsii release? Or how do I get to know when this fix will be released? Thanks again for the quick responses and the fix. |
aws_cdk.core.Stack.of() returns wrong class type in Python
Reproduction Steps
Here is a minimal, not directly runnable (and in this context not very useful) Python code example of the behavior:
I would expect, that
MyParentStack.of(stack_child_instance)
would return a stack of typeMyChildStack
.The behavior occurs only if the
Stack.of()
method is called directly on a subclass ofaws_cdk.core.Stack
and not on constructs within the stack itself.Other
Yes, the example shown seems not to be very useful. But in my custom CDK library I have a 'base' stack class with custom properties and further custom stack classes derived from that base stack.
When calling the
.of()
-Method of my base stack on an arbitrary construct, I will ensure that the returned type of the stack is of my base stack or a subclass of it, such that I can access the custom properties.This is 🐛 Bug Report
The text was updated successfully, but these errors were encountered: