Skip to content

refactor type hinting - #44

Closed
jaymccon wants to merge 1 commit into
aws-cloudformation:masterfrom
jaymccon:cleaner_type_hints
Closed

jaymccon wants to merge 1 commit into
aws-cloudformation:masterfrom
jaymccon:cleaner_type_hints

Conversation

@jaymccon

@jaymccon jaymccon commented Nov 8, 2019

Copy link
Copy Markdown
Contributor

Issue #, if available:

Description of changes:

Main aim of this pr is to simplify the representation of type hints in the handler and improve IDE resolution of types for inline hinting/validation.

A notable sacrifice was that I had to set the type for the ResourceHandlerRequest in HandlerSignature to Any to get mypy to accept that the actual handler was using ResourceHandlerRequest not BaseResourceHandlerRequest.

Previously PyCharm (didn't test other IDE's) was not able to resolve types for ResourceModel or ProgressEvent. Type completion/validation now works as expected.

2019-11-08_13-53-42

By submitting this pull request, I confirm that my contribution is made under the terms of the Apache 2.0 license.

@jaymccon
jaymccon requested a review from tobywf November 8, 2019 22:12

@tobywf tobywf left a comment •

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I'm not super enthusiastic about undoing the generic stuff to work around what seems to be PyCharm bug, although quoting the type hinting is a great improvement over the type vars. I'll try this out a bit more to see if the type hinting works everywhere as intended, or if the auto-complete sometimes only shows e.g. BaseResourceModel. Some of the template stuff can be cleaned up I think.

{%- if used_models -%}(
{%- for name in used_models -%}
Generic[T{{ name }}]{%- if not loop.last -%}, {%- endif -%}
"{{ name }}"{%- if not loop.last -%}, {%- endif -%}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

since your code no longer uses the class_model_bindings or typevar_model_bindings macros, can't you just delete them?

def resource_name_suffix(name):
# add a suffix to prevent typing conflicts
if name != "ResourceModel":
return f"{name}ResourceModel"

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

there's only one resource model, so this is confusing. it's also pretty heavyweight. maybe something like we do in the Java plugin in a simpler solution? (models already are guaranteed to have unique names, so you only have to disambiguate clashes with languages types. as far as i can see, the same is true for type hints)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

ah, I see why you may have done this. interesting mypy errors happen when a variable has the same name as a type (the variable shadows the type for type-hints only)



def set_or_none(value: Optional[Sequence[T]]) -> Optional[AbstractSet[T]]:
def set_or_none(value: Optional[Sequence[Any]]) -> Optional[AbstractSet[Any]]:

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

if you keep T = TypeVar("T"), you can leave this as T and provide stronger type guarantees


@dataclass
class {{ model }}{{ class_model_bindings(properties) }}:
class {{ model|resource_name_suffix }}(BaseResourceModel):

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

sub-models aren't and shouldn't be valid instances of BaseResourceModel, so only the actual resource model should inherit from BaseResourceModel, right?

@jaymccon jaymccon mentioned this pull request Nov 20, 2019
@jaymccon

Copy link
Copy Markdown
Contributor Author

closing in favor of #51

@benbridts

benbridts commented Nov 24, 2019 •

Copy link
Copy Markdown
Contributor

@jaymccon @tobywf

Depending on the reasons to keep the type hinting and the behaviour of mypy, there might be a way to use generics and still have typehinting work in pycharm. It's not super clean, but might be workable:

Generating

model = request.desiredResourceState  # type: ResourceModel

does make pycharm work in that method. The big downside of going back to generics, is that that same ide still complains about the [] syntax in the type hints:

Screenshot 2019-11-24 16 36 32

@tobywf

tobywf commented Nov 24, 2019

Copy link
Copy Markdown
Contributor

oh, interesting! from my side, i'm happy with the approach Jay suggested. coming into a new code-base is always tough, especially with dynamic languages. so the auto-completion really helps getting resource authors going. (if someone accidentally deleted that line, i'm guessing it would break again?)

@benbridts

Copy link
Copy Markdown
Contributor

It would break indeed. It is basically telling pycharm/mypy/... "I know better, use this as the type".

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants