Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

unittest.mock.patch andunittest.mock.patch.object are wrongly typed when new_callable is provided #14339

Open
@leonarduschen

Description

@leonarduschen

Steps to reproduce

fromunittest.mockimportpatchclassNewPrinter:passwithpatch("pprint.PrettyPrinter",new_callable=lambda:NewPrinter)aspatched_printer:print(patched_printer)# <class '__main__.NewPrinter'>reveal_type(patched_printer)# "Union[unittest.mock.MagicMock, unittest.mock.AsyncMock]"

Same deal withunittest.mock.patch.object

fromunittest.mockimportpatchimportpprintclassNewPrinter:    ...withpatch.object(pprint,"PrettyPrinter",new_callable=lambda:NewPrinter)aspatched_printer:print(patched_printer)# <class '__main__.NewPrinter'>reveal_type(patched_printer)# "Union[unittest.mock.MagicMock, unittest.mock.AsyncMock]"

Suggested fix

We discussunittest.mock.patch in the following, but the same principles apply tounittest.mock.patch.object too

Current signatures:

@overloaddef__call__(self,target:str,new:_T,spec:Any|None= ...,create:bool= ...,spec_set:Any|None= ...,autospec:Any|None= ...,new_callable:Any|None= ...,**kwargs:Any,    )->_patch[_T]: ...@overloaddef__call__(self,target:str,*,spec:Any|None= ...,create:bool= ...,spec_set:Any|None= ...,autospec:Any|None= ...,new_callable:Any|None= ...,**kwargs:Any,    )->_patch_default_new: ...

There are 2 problems here:

  • new_callable shouldn't beAny | None in the first place, it should only acceptCallable| None, as the it will raise if the provided value is not a callable
    withpatch("pprint.PrettyPrinter",new_callable=1)aspatched_printer:# TypeError: 'int' object is not callable
  • Need to differentiate the case where new_callable is provided and left as default None
    • Whennew_callable: Callable[..., T], returns_patch[_T]
    • Whennew_callable: None = ..., returns_patch_default_new

Seems like this would do the job:

@overloaddef__call__(self,target:str,new:_T,spec:Any|None= ...,create:bool= ...,spec_set:Any|None= ...,autospec:Any|None= ...,new_callable:Callable[...,Any]|None= ...,**kwargs:Any,    )->_patch[_T]: ...@overloaddef__call__(self,target:str,*,spec:Any|None= ...,create:bool= ...,spec_set:Any|None= ...,autospec:Any|None= ...,new_callable:Callable[...,_T],**kwargs:Any,    )->_patch[_T]    @overloaddef__call__(self,target:str,*,spec:Any|None= ...,create:bool= ...,spec_set:Any|None= ...,autospec:Any|None= ...,new_callable:None= ...,**kwargs:Any,    )->_patch_default_new: ...

Testing results

fromunittest.mockimportpatchclassNewPrinter:passwithpatch("pprint.PrettyPrinter")aspatched_printer:print(patched_printer)# <MagicMock name='PrettyPrinter' id='125908774402896'>reveal_type(patched_printer)# MagicMock | AsyncMockwithpatch("pprint.PrettyPrinter",new=NewPrinter)aspatched_printer:print(patched_printer)# <class '__main__.NewPrinter'>reveal_type(patched_printer)# type[NewPrinter]withpatch("pprint.PrettyPrinter",new_callable=lambda:NewPrinter)aspatched_printer:print(patched_printer)# <class '__main__.NewPrinter'>reveal_type(patched_printer)# type[NewPrinter]# No overload variant matches for non-callable typewithpatch("pprint.PrettyPrinter",new_callable="non-callable")aspatched_printer:    ...

Haven't triedunittest.mock.patch.object yet, but probably same thing


Would be great to see what the maintainers think.

I'll dig deeper and try to open a PR, maybe this weekend, will be my first PR in typeshed :)

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions


      [8]ページ先頭

      ©2009-2025 Movatter.jp