Skip to content
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 mypy errors in Microsoft Azure provider #19923

Merged
merged 6 commits into from
Dec 6, 2021

Conversation

josh-fell
Copy link
Contributor

Part of #19891


^ Add meaningful description above

Read the Pull Request Guidelines for more information.
In case of fundamental code change, Airflow Improvement Proposal (AIP) is needed.
In case of a new dependency, check compliance with the ASF 3rd Party License Policy.
In case of backwards incompatible changes please leave a note in UPDATING.md.

@josh-fell
Copy link
Contributor Author

CC @potiuk

Comment on lines 147 to 152
if conn.login is not None and conn.password is not None:
credential = ClientSecretCredential(
client_id=conn.login, client_secret=conn.password, tenant_id=tenant
client_id=conn.login, client_secret=conn.password, tenant_id=tenant # type: ignore
)
else:
credential = DefaultAzureCredential()
credential = DefaultAzureCredential() # type: ignore
Copy link
Member

Choose a reason for hiding this comment

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

Add credential: Any before the if instead. These credential classes are opaque and internal to Azure, and we are passing them directly back to Azure. This is better than # type: ignore because it is more obvious what kind of errors we are trying to ignore.

Comment on lines 646 to 645
pipeline_run_status = self.get_pipeline_run_status(**pipeline_run_info)
pipeline_run_status = self.get_pipeline_run_status(**pipeline_run_info) # type: ignore
Copy link
Member

Choose a reason for hiding this comment

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

This feels unnecessary. What is the error we’re trying to work around here?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

airflow/providers/microsoft/azure/hooks/data_factory.py:671: error: Argument 1 to "get_pipeline_run_status" of "AzureDataFactoryHook" has incompatible type "**Dict[str, Optional[str]]"; expected
"str"
            pipeline_run_status = self.get_pipeline_run_status(**pipeline_run_info)

If I enforce keywords arguments on the get_pipeline_run_status() function, mypy doesn't complain. Although, we could always explicitly pass a dictionary rather than using the **kwargs syntax.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Oh I guess I could use a TypedDict here

Copy link
Contributor Author

Choose a reason for hiding this comment

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

pipeline_run_info: Dict[str, Any] = resolves the check as well but it's not entirely a correct typing.

Comment on lines 663 to 662
pipeline_run_status = self.get_pipeline_run_status(**pipeline_run_info)
pipeline_run_status = self.get_pipeline_run_status(**pipeline_run_info) # type: ignore
Copy link
Member

Choose a reason for hiding this comment

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

Same as above.

token_credential = ClientSecretCredential(tenant, app_id, app_secret)
token_credential = ClientSecretCredential(tenant, app_id, app_secret) # type: ignore
Copy link
Member

Choose a reason for hiding this comment

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

Same

Copy link
Contributor Author

Choose a reason for hiding this comment

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

The error here was:

airflow/providers/microsoft/azure/hooks/wasb.py:137: error: Argument 1 to "ClientSecretCredential" has incompatible type "Optional[Any]"; expected "str"
                token_credential = ClientSecretCredential(tenant, app_id, app_secret)

I'll address this properly.

@@ -177,7 +177,7 @@ def test_create_factory(hook: AzureDataFactoryHook, user_args, sdk_args):
implicit_factory=((MODEL,), (DEFAULT_RESOURCE_GROUP, DEFAULT_FACTORY, MODEL)),
)
def test_update_factory(hook: AzureDataFactoryHook, user_args, sdk_args):
hook._factory_exists = Mock(return_value=True)
hook._factory_exists = Mock(return_value=True) # type: ignore
Copy link
Member

Choose a reason for hiding this comment

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

I think we should find a much better way to have mypy satisfied here.

I think we shoudl (if that works) add spec='boolean' to mock's constructor?

Copy link
Contributor Author

@josh-fell josh-fell Dec 1, 2021

Choose a reason for hiding this comment

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

A patch.object(...) context manager does the trick. WDYT? Mypy still complained adding a spec unfortunately.

@@ -22,7 +22,7 @@
from azure.common import AzureHttpError

try:
from functools import cached_property
from functools import cached_property # type: ignore[attr-defined]
Copy link
Member

Choose a reason for hiding this comment

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

Oh nice. I have to do the same in one of my PRs :).


credential = None
try:
Copy link
Member

Choose a reason for hiding this comment

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

This is precisely why I think MyPy is useful! Getting " A Subscription ID is required to connect to Azure Data Factory." rather than "None error xxxx" is the whole world of difference for the users.

@@ -177,8 +177,9 @@ def test_create_factory(hook: AzureDataFactoryHook, user_args, sdk_args):
implicit_factory=((MODEL,), (DEFAULT_RESOURCE_GROUP, DEFAULT_FACTORY, MODEL)),
)
def test_update_factory(hook: AzureDataFactoryHook, user_args, sdk_args):
hook._factory_exists = Mock(return_value=True)
hook.update_factory(*user_args)
with patch.object(hook, "_factory_exists") as mock_factory_exists:
Copy link
Member

Choose a reason for hiding this comment

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

Hmmm. I really like this change. Somehow using generic Mock object for this case felt a bit weird. Seems like MyPy also forces on us a bit nicer approach for mocking.

Copy link
Member

Choose a reason for hiding this comment

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

@uranusjr - WDYT?

@potiuk potiuk merged commit 374574b into apache:main Dec 6, 2021
potiuk added a commit to potiuk/airflow that referenced this pull request Dec 6, 2021
The change apache#19923 introduced (accidentally) a required validation
for an azure extra, which caused an error in the connection
UI when the connection could not be added because the field was
missing.

This failed the test_crate_connection fail.

This change removes back the validation.
potiuk added a commit that referenced this pull request Dec 6, 2021
The change #19923 introduced (accidentally) a required validation
for an azure extra, which caused an error in the connection
UI when the connection could not be added because the field was
missing.

This failed the test_crate_connection fail.

This change removes back the validation.
@josh-fell josh-fell deleted the fix-mypy-errors-azure branch December 7, 2021 05:04
@potiuk potiuk added the mypy Fixing MyPy problems after bumpin MyPy to 0.990 label Dec 13, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area:logging area:providers area:secrets mypy Fixing MyPy problems after bumpin MyPy to 0.990 provider:microsoft-azure Azure-related issues
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants