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

Add __iter__ support for mock_open #65457

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

Add __iter__ support for mock_open #65457

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

Comments

@voidspace
Copy link
Contributor

BPO 21258
Nosy @voidspace, @berkerpeksag, @kushaldas, @gsauthof, @TonyFlury, @frenzymadness
Superseder
  • bpo-32933: mock_open does not support iteration around text files.
  • Files
  • 213.patch
  • mock.diff: Patch for bug
  • testwith.diff: mock_open test suite patch
  • mock_new.diff
  • 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 2018-09-12.22:27:20.328>
    created_at = <Date 2014-04-16.17:56:45.150>
    labels = ['type-bug', 'library']
    title = 'Add __iter__ support for mock_open'
    updated_at = <Date 2018-09-12.22:27:20.326>
    user = 'https://github.com/voidspace'

    bugs.python.org fields:

    activity = <Date 2018-09-12.22:27:20.326>
    actor = 'berker.peksag'
    assignee = 'michael.foord'
    closed = True
    closed_date = <Date 2018-09-12.22:27:20.328>
    closer = 'berker.peksag'
    components = ['Library (Lib)']
    creation = <Date 2014-04-16.17:56:45.150>
    creator = 'michael.foord'
    dependencies = []
    files = ['34917', '35597', '35598', '37908']
    hgrepos = []
    issue_num = 21258
    keywords = ['patch']
    message_count = 8.0
    messages = ['216522', '220371', '220373', '222279', '234985', '285508', '325196', '325199']
    nosy_count = 10.0
    nosy_names = ['michael.foord', 'Arve.Knudsen', 'berker.peksag', 'kushal.das', 'pkoning', 'Jos\xc3\xa9.Luis.Lafuente', 'mucka', 'gms', 'anthony-flury', 'frenzy']
    pr_nums = []
    priority = 'normal'
    resolution = 'duplicate'
    stage = 'resolved'
    status = 'closed'
    superseder = '32933'
    type = 'behavior'
    url = 'https://bugs.python.org/issue21258'
    versions = ['Python 3.4', 'Python 3.5', 'Python 3.6']

    @voidspace
    Copy link
    Contributor Author

    mock_open returns a mock object suitable for using as a mock file handle. File handles support iteration, so mock_open should support that. If possible it should be integrated with the current read/readlines support (only if possible), so the suggested patch may not be enough.

    1. Want to mock this:
      with open(source_file, 'r') as f:
      for line_num, line_text in enumerate(f):
      print line_text

    2. Tried this:
      with patch('__builtin__.open', mock_open(read_data='text'), create=True) as p:

    3. enumerate causes a call to __iter__() which is not handled by the mock_open code.

    What is the expected output? What do you see instead?

    The __iter__ is allowed on the returned file handle

    What version of the product are you using? On what operating system?

    latest

    Please provide any additional information below.

    Patch would have mock_open setup handle.__iter__.return_value to a passed in parm or if none, possibly a iter(StringIO(read_data)) on the existing read_data parm to keep the interface unchanged.

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

    pkoning mannequin commented Jun 12, 2014

    I created a fix for this. This also fixes a second issue in mock_open, which is that readline() raises StopIteration at EOF rather than returning empty strings. See attached diff.
    (Is there a better procedure for submitting fixes?)

    @pkoning
    Copy link
    Mannequin

    pkoning mannequin commented Jun 12, 2014

    This is the corresponding patch to the test suite.

    @ArveKnudsen
    Copy link
    Mannequin

    ArveKnudsen mannequin commented Jul 4, 2014

    I noticed this issue too, thanks for fixing it!

    @mucka
    Copy link
    Mannequin

    mucka mannequin commented Jan 29, 2015

    Provided path did not work for me. Probably because lack of __next__ handler. I noticed that issue when interacting with cvs.reader and cvs.DictReader. After simple modification it seems to work fine.

    @gsauthof
    Copy link
    Mannequin

    gsauthof mannequin commented Jan 15, 2017

    For working around this issue on Python 3.5 it is sufficient to overwrite just the return_value.__iter__ method of the object returned by mock_open() with an iterator that calls the mocked readline() method until it returns the empty string.

    cf. e.g. https://github.com/gsauthof/utility/blob/6489c7215dac341be4e40e5348e64d69461766dd/user-installed.py#L176-L179

    This also works in combination with csv.reader(), i.e. when calling it with the mocked file object.

    @TonyFlury
    Copy link
    Mannequin

    TonyFlury mannequin commented Sep 12, 2018

    The lack of dunder_iter support on mock_open has been resolved in bpo-32933 (Git Hub 5974).

    Can I suggest that once the above PR is merged into 3.8 (due imminently allegedly <smile>), that we should then backport that fix into 3.5, 3.6 & 3.7 as a minimum ?

    I am by no means an expert though.

    @berkerpeksag
    Copy link
    Member

    Closing this as a duplicate of bpo-32933. Let's discuss backporting to maintenance branches there.

    @ezio-melotti ezio-melotti transferred this issue from another repository Apr 10, 2022
    @petropolis10
    Copy link

    Can someone explain how to use the functionality where you can give an iterator for the results of the open mock? I have a function like

    def read_file(fname: str):
      with open(fname, "r") as file_object:
        ...
        for line in file_object:
            ...
    

    I want to return n lines for the for loop:

    def n_lines(n):
        for _ in range(n):
            yield "string"
    
    mopen = mock_open()
    with patch("builtins.open", mopen):
        mopen.return_value = n_lines # Can't do this
        read_file("foo")
    

    or something like that. I'm using Python 3.8.

    Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
    Labels
    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