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

Provide args and kwargs attributes on mock call objects #65468

Closed
voidspace opened this issue Apr 16, 2014 · 11 comments
Closed

Provide args and kwargs attributes on mock call objects #65468

voidspace opened this issue Apr 16, 2014 · 11 comments
Assignees
Labels
3.8 only security fixes stdlib Python modules in the Lib dir type-bug An unexpected behavior, bug, or error

Comments

@voidspace
Copy link
Contributor

BPO 21269
Nosy @cjw296, @voidspace, @kushaldas, @remilapeyre, @tirkarthi, @kakshay21
PRs
  • bpo-21269: Provide args and kwargs attributes on mock call objects #11807
  • bpo-21269: Provide args and kwargs attributes on mock call objects #11807
  • bpo-21269: Provide args and kwargs attributes on mock call objects #11807
  • Note: these values reflect the state of the issue at the time it was migrated and might not reflect the current state.

    Show more details

    GitHub fields:

    assignee = 'https://github.com/voidspace'
    closed_at = <Date 2019-04-02.12:47:12.581>
    created_at = <Date 2014-04-16.20:47:42.524>
    labels = ['3.8', 'type-bug', 'library']
    title = 'Provide args and kwargs attributes on mock call objects'
    updated_at = <Date 2019-04-02.12:47:12.580>
    user = 'https://github.com/voidspace'

    bugs.python.org fields:

    activity = <Date 2019-04-02.12:47:12.580>
    actor = 'xtreak'
    assignee = 'michael.foord'
    closed = True
    closed_date = <Date 2019-04-02.12:47:12.581>
    closer = 'xtreak'
    components = ['Library (Lib)']
    creation = <Date 2014-04-16.20:47:42.524>
    creator = 'michael.foord'
    dependencies = []
    files = []
    hgrepos = []
    issue_num = 21269
    keywords = ['patch', 'patch', 'patch']
    message_count = 11.0
    messages = ['216585', '335136', '335140', '335144', '335146', '335160', '335161', '335162', '338084', '338590', '339331']
    nosy_count = 6.0
    nosy_names = ['cjw296', 'michael.foord', 'kushal.das', 'remi.lapeyre', 'xtreak', 'kakshay']
    pr_nums = ['11807', '11807', '11807']
    priority = 'normal'
    resolution = 'fixed'
    stage = 'resolved'
    status = 'closed'
    superseder = None
    type = 'behavior'
    url = 'https://bugs.python.org/issue21269'
    versions = ['Python 3.8']

    @voidspace
    Copy link
    Contributor Author

    The unittest.mock.call object could have args/kwargs attributes to easily access the arguments it was called with.

    @voidspace voidspace added the stdlib Python modules in the Lib dir label Apr 16, 2014
    @voidspace voidspace self-assigned this Apr 16, 2014
    @voidspace voidspace added the type-bug An unexpected behavior, bug, or error label Apr 16, 2014
    @tirkarthi
    Copy link
    Member

    args and kwargs property can be introduced on the call object to return the args and kwargs stored in the tuple. Currently wrapping call object with tuple can get a tuple of args and kwargs but a property would be helpful. A first attempt patch on this. Feedback on the API would be helpful.

    $ ./python.exe
    Python 3.8.0a1+ (heads/master:8a03ff2ff4, Feb  9 2019, 10:42:29)
    [Clang 7.0.2 (clang-700.1.81)] on darwin
    Type "help", "copyright", "credits" or "license" for more information.
    >>> from unittest.mock import Mock
    >>> m = Mock()
    >>> m(1, a=1)
    <Mock name='mock()' id='4325199504'>
    >>> m.call_args_list[0]
    call(1, a=1)
    >>> tuple(m.call_args_list[0]) # wrapping it with tuple can give args and kwargs currently
    ((1,), {'a': 1})
    >>> m.call_args_list[0].args # With patch return args
    (1,)
    >>> m.call_args_list[0].kwargs # With patch return kwargs
    {'a': 1}

    A simple patch would be as below :

    ➜ cpython git:(master) ✗ git diff | cat
    diff --git a/Lib/unittest/mock.py b/Lib/unittest/mock.py
    index ef5c55d6a1..ef1aa1dcea 100644
    --- a/Lib/unittest/mock.py
    +++ b/Lib/unittest/mock.py
    @@ -2124,6 +2124,24 @@ class _Call(tuple):
    def index(self, *args, **kwargs):
    return self.__getattr__('index')(*args, **kwargs)

    + @Property
    + def args(self):
    + if len(self) == 2:
    + args, kwargs = self
    + else:
    + name, args, kwargs = self
    +
    + return args
    +
    + @Property
    + def kwargs(self):
    + if len(self) == 2:
    + args, kwargs = self
    + else:
    + name, args, kwargs = self
    +
    + return kwargs
    +
    def __repr__(self):
    if not self._mock_from_kall:
    name = self._mock_name or 'call'

    @tirkarthi tirkarthi added the 3.8 only security fixes label Feb 9, 2019
    @kakshay21
    Copy link
    Mannequin

    kakshay21 mannequin commented Feb 9, 2019

    Hey @XTreak, if you're not working on this, can I submit the patch?

    @tirkarthi
    Copy link
    Member

    @kakshay, I am not working on it so feel free to pick it up. I stumbled upon this while looking into mock issues and I just posted a patch to gather API feedback. I guess it would be helpful if someone confirms it would be a good addition so that there is less rework.

    Thanks

    @kakshay21
    Copy link
    Mannequin

    kakshay21 mannequin commented Feb 10, 2019

    Thanks @XTreak!
    I've added a PR with the following API

    ➜  cpython git:(fix-issue-21269) ✗ ./python.exe
    Python 3.8.0a0 (heads/fix-issue-21269-dirty:2433a2ab70, Feb 10 2019, 14:24:54)
    [Clang 10.0.0 (clang-1000.10.44.4)] on darwin
    Type "help", "copyright", "credits" or "license" for more information.
    >>> from unittest.mock import Mock
    >>> m = Mock()
    >>> m(1, a=23)
    <Mock name='mock()' id='4552188368'>
    >>> m.call_args
    call(1, a=23)
    >>> m.call_args.args     #after this patch
    (1,)
    >>> m.call_args.kwargs   #after this patch
    {'a': 23}
    >>> m.call_args_list[0].args    #after this patch
    (1,)
    >>> m.call_args_list[0].kwargs   #after this patch
    {'a': 23}

    @remilapeyre
    Copy link
    Mannequin

    remilapeyre mannequin commented Feb 10, 2019

    I like this patch, working with calls often feels weird and this change simplify attribute access.

    @remilapeyre
    Copy link
    Mannequin

    remilapeyre mannequin commented Feb 10, 2019

    @XTreak, couldn't we have made _Call inherit from namedtuple to achieve a similar result (albeit the handling of name would be weird)?

    @tirkarthi
    Copy link
    Member

    This feels safer to me with respect to backwards compatibility and also that it might be easier to backport this to mock on GitHub which works with Python 2.7. I have less knowledge on difference between tuple and namedtuple internals so I might be wrong here.

    @kakshay21
    Copy link
    Mannequin

    kakshay21 mannequin commented Mar 16, 2019

    ping..😬

    @cjw296
    Copy link
    Contributor

    cjw296 commented Mar 22, 2019

    New changeset b0df45e by Chris Withers (Kumar Akshay) in branch 'master':
    bpo-21269: Provide args and kwargs attributes on mock call objects GH11807
    b0df45e

    @tirkarthi
    Copy link
    Member

    Thanks @kakshay for the patch.

    @ezio-melotti ezio-melotti transferred this issue from another repository Apr 10, 2022
    EliahKagan added a commit to EliahKagan/subaudit that referenced this issue May 6, 2023
    From the mock package from PyPI, insead of the standard library
    unittest.mock.
    
    The standalone module backports new unittest.mock features. This
    helps with Python 3.7, where unittest.mock._Call objects (that is,
    objects returned by unittest.mock.call) don't have args attributes.
    (More precisely, they don't know about args attributes or give them
    any speical meaning, so it just represents accessing an "args"
    attribute on a hypothetical object returned by the call that the
    _Call object represents.)
    
    See:
    
    - https://stackoverflow.com/a/60119333
    - https://bugs.python.org/issue21269
    - python/cpython#65468
    
    Using the standalone mock module fixes a number of text failures or
    errors. The tests now all pass on Python 3.7 (other than the ones
    already marked xfail).
    Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
    Labels
    3.8 only security fixes stdlib Python modules in the Lib dir type-bug An unexpected behavior, bug, or error
    Projects
    None yet
    Development

    No branches or pull requests

    3 participants