-
Notifications
You must be signed in to change notification settings - Fork 8
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
fix(Python): Support orphaned shapes, update Config shape generation #626
Conversation
@@ -252,7 +252,7 @@ protected boolean isOptionalDefault(MemberShape member) { | |||
&& (target.isDocumentShape() || target.isListShape() || target.isMapShape()); | |||
} | |||
|
|||
private void writeClassDocs(boolean isError) { | |||
protected void writeClassDocs(boolean isError) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Unfortunately, this change means another
make mvn_local_deploy_polymorph_python_dependencies
on merging this from main, but I think this is better than duplicating the code.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm inclined to add mvn_local_deploy_polymorph_dependencies
as a dependency of all polymorph targets, given it should be cheap and hopefully Gradle-cached anyway.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good idea. I'll include this
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Quite happy with the general approach to handle orphaned shapes. Cut #627 for longer term follow up on the problem.
Are you dependent on an OrphanedShapes test model to get added to test these changes?
@@ -252,7 +252,7 @@ protected boolean isOptionalDefault(MemberShape member) { | |||
&& (target.isDocumentShape() || target.isListShape() || target.isMapShape()); | |||
} | |||
|
|||
private void writeClassDocs(boolean isError) { | |||
protected void writeClassDocs(boolean isError) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm inclined to add mvn_local_deploy_polymorph_dependencies
as a dependency of all polymorph targets, given it should be cheap and hopefully Gradle-cached anyway.
codegen/smithy-dafny-codegen/src/main/java/software/amazon/polymorph/utils/ModelUtils.java
Show resolved
Hide resolved
codegen/smithy-dafny-codegen/src/main/java/software/amazon/polymorph/utils/ModelUtils.java
Outdated
Show resolved
Hide resolved
orderedShapes.add(shape); | ||
} | ||
} | ||
for (Shape shape : topologicalIndex.getRecursiveShapes()) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I wasn't 100% sure from the TopologicalIndex documentation, but is this guaranteed to be a superset of getOrderedShapes()
?
Would be nice to have an explicit unit test just for getTopologicallyOrderedOrphanedShapesForService
, especially since it can clarify what is or isn't a recursive shape.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I wasn't 100% sure from the TopologicalIndex documentation, but is this guaranteed to be a superset of getOrderedShapes()?
I suspect they're disjoint, otherwise some shapes would be generated multiple times.
Would be nice to have an explicit unit test just for getTopologicallyOrderedOrphanedShapesForService, especially since it can clarify what is or isn't a recursive shape.
I think a unit test might be more effort than it's worth --
Primarily, I'm inclined to trust whatever Smithy-Core is doing here, but verify it against a TestModel/real projects. I built this PR against the MPL and DBESDK, it picked up orphaned shapes, and I can run the code. I don't think the test you're proposing gets us as much ROI.
For a unit test, we'd have to create a Smithy model as a POJO (sort of like this), which seems more brittle than is worth doing.
Let me know your thoughts.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I suspect they're disjoint, otherwise some shapes would be generated multiple times.
Good point, I think they must be.
For a unit test, we'd have to create a Smithy model as a POJO (sort of like this), which seems more brittle than is worth doing.
You can include a *.smithy file as a resource and read it in pretty easily instead: https://github.com/smithy-lang/smithy-dafny/blob/main-1.x/codegen/smithy-dafny-codegen/src/test/java/software/amazon/polymorph/smithyjava/modeled/ModeledShapeValueTest.java#L77-L82
But I'll leave it to your judgement on whether you want to bother with that on this PR, I won't block on it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's pretty nifty -- I'll plan to do this when I do the OrphanedShapes TestModel, but not now.
I don't think so, but let me know if you disagree. I built this PR into the MPL and DBESDK, and both of those projects are still passing.
This (plus the MPL PR) is ideally the last PR I'll to land before I release the Python MPL, so I'm trying to push any non-essential work out until after that lands. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM, some non-blocking questions
@@ -269,6 +272,7 @@ transpile_dependencies_test: | |||
# make polymorph_code_gen CODEGEN_CLI_ROOT=/path/to/smithy-dafny/codegen/smithy-dafny-codegen-cli | |||
# StandardLibrary is filtered out from dependent-model patsubst list; | |||
# Its model is contained in $(LIBRARY_ROOT)/model, not $(LIBRARY_ROOT)/../StandardLibrary/Model. | |||
_polymorph: mvn_local_deploy_polymorph_dependencies |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
❤️
() -> { | ||
writer.write("self,"); | ||
if (!shape.members().isEmpty()) { | ||
// Adding this star to the front prevents the use of positional arguments. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Was this lifted from smithy-python too then? It's a great idea but I wasn't sure if they'd acted on it yet.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes
@@ -203,7 +309,14 @@ protected void writePropertyForMember( | |||
); | |||
} | |||
|
|||
if (target.hasTrait(ReferenceTrait.class)) { | |||
// Reference shapes require forward reference to avoid circular import, | |||
// but references to AWS SDKs don't |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit picking, but isn't it more accurately that shapes from dependencies are already declared?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is actually about circular dependencies within one project.
I'm going to write about this problem and solutions in a Smithy-Dafny Python dev guide, but an overview/instance of the problem is that models.py
can't import references.py
at the top-level because references.py
depends on models.py
at the top-level, but models.py
still needs to import references.py
to use its classes.
One solution is to defer the imports like I've done here.
I wrote a fair amount about this and drew some graphs, but I'm going to collate all that later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I will be thrilled to review a PR that targets docs/python
in the future :)
) { | ||
Model transformedModel = model; | ||
transformedModel = | ||
addWrappedLocalServiceTrait(transformedModel, serviceShape); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
off topic question: what does this transformation do exactly?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In preprocessing, it replaces a LocalServiceTrait on the ServiceTrait with a WrappedLocalServiceTrait.
This results in some different codegen; wrapped LocalServices don't get all the codegen from LocalServices. (No models, etc.)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah thanks! I wasn't aware of that trait.
Issue #, if available:
Description of changes:
Python:
Check out this MPL PR for sample generated code: aws/aws-cryptographic-material-providers-library#831
By submitting this pull request, I confirm that you can use, modify, copy, and redistribute this contribution, under the terms of your choice.