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

async DefaultAzureCredential incompatible with AsyncTokenCredential per pyright #27704

Closed
kristapratico opened this issue Nov 28, 2022 · 8 comments · Fixed by #31830
Closed
Assignees
Labels
Azure.Core Azure.Identity Client This issue points to a problem in the data-plane of the library.
Milestone

Comments

@kristapratico
Copy link
Member

Pyright reports a type error when the async DefaultAzureCredential is used anywhere where an AsyncTokenCredential is expected:

  C:\Users\krpratic\azure-sdk-for-python\sdk\cognitivelanguage\azure-ai-language-conversations\samples\async\sample_authentication_async.py:57:66 - error: Argument of type "DefaultAzureCredential" cannot be assigned to parameter "credential" of type "AzureKeyCredential | AsyncTokenCredential" in function "__init__"
    Type "DefaultAzureCredential" cannot be assigned to type "AzureKeyCredential | AsyncTokenCredential"
      "DefaultAzureCredential" is incompatible with "AzureKeyCredential"
      "DefaultAzureCredential" is incompatible with protocol "AsyncTokenCredential"
        "__aenter__" is an incompatible type
          Type "() -> Coroutine[Any, Any, DefaultAzureCredential]" cannot be assigned to type "() -> Coroutine[Any, Any, None]"
            Function return type "Coroutine[Any, Any, DefaultAzureCredential]" is incompatible with type "Coroutine[Any, Any, None]"
        "__aexit__" is an incompatible type
          Type "(*args: Unknown) -> Coroutine[Any, Any, None]" cannot be assigned to type "(exc_type: Unknown, exc_value: Unknown, traceback: Unknown) -> Coroutine[Any, Any, None]"

This is due to the difference in how the Protocol is typed vs. how it is typed in identity:

async def close(self) -> None:
pass
async def __aenter__(self):
pass
async def __aexit__(self, exc_type, exc_value, traceback) -> None:
pass

class AsyncContextManager(abc.ABC):
@abc.abstractmethod
async def close(self):
pass
async def __aenter__(self):
return self
async def __aexit__(self, *args):
await self.close()

Note that this doesn't occur with the sync credential since __enter__ and __exit__ are not described by TokenCredential.

@kristapratico kristapratico added Client This issue points to a problem in the data-plane of the library. Azure.Core labels Nov 28, 2022
@github-actions github-actions bot added the needs-triage Workflow: This is a new issue that needs to be triaged to the appropriate team. label Nov 28, 2022
@azure-sdk azure-sdk added Azure.Identity needs-team-triage Workflow: This issue needs the team to triage. labels Nov 28, 2022
@kristapratico kristapratico removed needs-triage Workflow: This is a new issue that needs to be triaged to the appropriate team. needs-team-triage Workflow: This issue needs the team to triage. labels Nov 28, 2022
@kristapratico
Copy link
Member Author

I think it would be less disruptive to update AsyncTokenCredential (although I'm not sure if this would be considered breaking):

 async def close(self) -> None: 
     pass 
  
 async def __aenter__(self) -> typing.Self: 
     pass 
  
 async def __aexit__(self, *args: Any) -> None: 
     pass 

@xiangyan99
Copy link
Member

@mccoyp is this something you are working on? (I want to avoid dup the work)

@mccoyp
Copy link
Member

mccoyp commented Nov 28, 2022

@xiangyan99 Looks like pyright is more strict than mypy, and in a similar boat as PyCharm's type checker. #25788 should resolve this.

When I last spoke with Laurent, he feels that we should update our type signatures to correctly implement the TokenCredential protocols (even when some of the kwargs can't be used, like tenant_id with ManagedIdentityCredential). We would just need to clearly document when these kwargs aren't being used.

@mccoyp mccoyp added this to the 2023-04 milestone Mar 3, 2023
@mccoyp mccoyp modified the milestones: 2023-04, 2023-05 Apr 11, 2023
@mccoyp mccoyp modified the milestones: 2023-05, 2023-06 May 11, 2023
@mccoyp mccoyp modified the milestones: 2023-06, 2023-07 Jun 17, 2023
@mccoyp mccoyp modified the milestones: 2023-07, 2023-08 Jul 10, 2023
@mccoyp
Copy link
Member

mccoyp commented Jul 28, 2023

I think it would be less disruptive to update AsyncTokenCredential (although I'm not sure if this would be considered breaking):

 async def close(self) -> None: 
     pass 
  
 async def __aenter__(self) -> typing.Self: 
     pass 
  
 async def __aexit__(self, *args: Any) -> None: 
     pass 

After taking a look at reference docs, I do think updating the protocol definition would be a better option since examples use *exc instead of exception type, value, and traceback positional parameters:

async def __aexit__(self, *exc):
    print('Finishing')
    return False

That said, I do think it would be a breaking change to put these named parameters into *args. You would no longer be able to pass named arguments in method calls without getting an "unexpected keyword argument" error. The question is whether this is a real scenario that we need to worry about; someone would have had to exactly implement the protocol and call the dunder method directly in order to see this.

@mccoyp
Copy link
Member

mccoyp commented Aug 8, 2023

Resolved by #31494.

@kristapratico
Copy link
Member Author

kristapratico commented Aug 14, 2023

Re-opening, needed to rollback the code that fixed this error. Details in #31585

@kristapratico kristapratico reopened this Aug 14, 2023
@pvaneck
Copy link
Member

pvaneck commented Aug 14, 2023

With the changes in #31585, seems like the fix for this is to update the __aexit__ implementations in azure-identity with the updated signature?

Like here.

    async def __aexit__(
        self,
        exc_type: Optional[Type[BaseException]] = None,
        exc_value: Optional[BaseException] = None,
        traceback: Optional[TracebackType] = None,
    ) -> None:
         await self.close()

@xiangyan99
Copy link
Member

@kristapratico kristapratico modified the milestones: 2023-08, 2023-09 Aug 17, 2023
@github-actions github-actions bot locked and limited conversation to collaborators Nov 26, 2023
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Azure.Core Azure.Identity Client This issue points to a problem in the data-plane of the library.
Projects
None yet
Development

Successfully merging a pull request may close this issue.

5 participants