{
    "file_diffs": [
        {
            "old_file_content": "from PIL import ContainerIO, Image\n\nfrom .helper import hopper\n\nTEST_FILE = \"Tests/images/dummy.container\"\n\n\ndef test_sanity():\n    dir(Image)\n    dir(ContainerIO)\n\n\ndef test_isatty():\n    with hopper() as im:\n        container = ContainerIO.ContainerIO(im, 0, 0)\n\n    assert container.isatty() is False\n\n\ndef test_seek_mode_0():\n    # Arrange\n    mode = 0\n    with open(TEST_FILE, \"rb\") as fh:\n        container = ContainerIO.ContainerIO(fh, 22, 100)\n\n        # Act\n        container.seek(33, mode)\n        container.seek(33, mode)\n\n        # Assert\n        assert container.tell() == 33\n\n\ndef test_seek_mode_1():\n    # Arrange\n    mode = 1\n    with open(TEST_FILE, \"rb\") as fh:\n        container = ContainerIO.ContainerIO(fh, 22, 100)\n\n        # Act\n        container.seek(33, mode)\n        container.seek(33, mode)\n\n        # Assert\n        assert container.tell() == 66\n\n\ndef test_seek_mode_2():\n    # Arrange\n    mode = 2\n    with open(TEST_FILE, \"rb\") as fh:\n        container = ContainerIO.ContainerIO(fh, 22, 100)\n\n        # Act\n        container.seek(33, mode)\n        container.seek(33, mode)\n\n        # Assert\n        assert container.tell() == 100\n\n\ndef test_read_n0():\n    # Arrange\n    with open(TEST_FILE, \"rb\") as fh:\n        container = ContainerIO.ContainerIO(fh, 22, 100)\n\n        # Act\n        container.seek(81)\n        data = container.read()\n\n        # Assert\n        assert data == b\"7\\nThis is line 8\\n\"\n\n\ndef test_read_n():\n    # Arrange\n    with open(TEST_FILE, \"rb\") as fh:\n        container = ContainerIO.ContainerIO(fh, 22, 100)\n\n        # Act\n        container.seek(81)\n        data = container.read(3)\n\n        # Assert\n        assert data == b\"7\\nT\"\n\n\ndef test_read_eof():\n    # Arrange\n    with open(TEST_FILE, \"rb\") as fh:\n        container = ContainerIO.ContainerIO(fh, 22, 100)\n\n        # Act\n        container.seek(100)\n        data = container.read()\n\n        # Assert\n        assert data == b\"\"\n\n\ndef test_readline():\n    # Arrange\n    with open(TEST_FILE, \"rb\") as fh:\n        container = ContainerIO.ContainerIO(fh, 0, 120)\n\n        # Act\n        data = container.readline()\n\n        # Assert\n        assert data == b\"This is line 1\\n\"\n\n\ndef test_readlines():\n    # Arrange\n    expected = [\n        b\"This is line 1\\n\",\n        b\"This is line 2\\n\",\n        b\"This is line 3\\n\",\n        b\"This is line 4\\n\",\n        b\"This is line 5\\n\",\n        b\"This is line 6\\n\",\n        b\"This is line 7\\n\",\n        b\"This is line 8\\n\",\n    ]\n    with open(TEST_FILE, \"rb\") as fh:\n        container = ContainerIO.ContainerIO(fh, 0, 120)\n\n        # Act\n        data = container.readlines()\n\n        # Assert\n\n        assert data == expected\n",
            "new_file_content": "from PIL import ContainerIO, Image\n\nfrom .helper import hopper\n\nTEST_FILE = \"Tests/images/dummy.container\"\n\n\ndef test_sanity():\n    dir(Image)\n    dir(ContainerIO)\n\n\ndef test_isatty():\n    with hopper() as im:\n        container = ContainerIO.ContainerIO(im, 0, 0)\n\n    assert container.isatty() is False\n\n\ndef test_seek_mode_0():\n    # Arrange\n    mode = 0\n    with open(TEST_FILE, \"rb\") as fh:\n        container = ContainerIO.ContainerIO(fh, 22, 100)\n\n        # Act\n        container.seek(33, mode)\n        container.seek(33, mode)\n\n        # Assert\n        assert container.tell() == 33\n\n\ndef test_seek_mode_1():\n    # Arrange\n    mode = 1\n    with open(TEST_FILE, \"rb\") as fh:\n        container = ContainerIO.ContainerIO(fh, 22, 100)\n\n        # Act\n        container.seek(33, mode)\n        container.seek(33, mode)\n\n        # Assert\n        assert container.tell() == 66\n\n\ndef test_seek_mode_2():\n    # Arrange\n    mode = 2\n    with open(TEST_FILE, \"rb\") as fh:\n        container = ContainerIO.ContainerIO(fh, 22, 100)\n\n        # Act\n        container.seek(33, mode)\n        container.seek(33, mode)\n\n        # Assert\n        assert container.tell() == 100\n\n\ndef test_read_n0():\n    # Arrange\n    for bytesmode in (True, False):\n        with open(TEST_FILE, \"rb\" if bytesmode else \"r\") as fh:\n            container = ContainerIO.ContainerIO(fh, 22, 100)\n\n            # Act\n            container.seek(81)\n            data = container.read()\n\n            # Assert\n            if bytesmode:\n                data = data.decode()\n            assert data == \"7\\nThis is line 8\\n\"\n\n\ndef test_read_n():\n    # Arrange\n    for bytesmode in (True, False):\n        with open(TEST_FILE, \"rb\" if bytesmode else \"r\") as fh:\n            container = ContainerIO.ContainerIO(fh, 22, 100)\n\n            # Act\n            container.seek(81)\n            data = container.read(3)\n\n            # Assert\n            if bytesmode:\n                data = data.decode()\n            assert data == \"7\\nT\"\n\n\ndef test_read_eof():\n    # Arrange\n    for bytesmode in (True, False):\n        with open(TEST_FILE, \"rb\" if bytesmode else \"r\") as fh:\n            container = ContainerIO.ContainerIO(fh, 22, 100)\n\n            # Act\n            container.seek(100)\n            data = container.read()\n\n            # Assert\n            if bytesmode:\n                data = data.decode()\n            assert data == \"\"\n\n\ndef test_readline():\n    # Arrange\n    for bytesmode in (True, False):\n        with open(TEST_FILE, \"rb\" if bytesmode else \"r\") as fh:\n            container = ContainerIO.ContainerIO(fh, 0, 120)\n\n            # Act\n            data = container.readline()\n\n            # Assert\n            if bytesmode:\n                data = data.decode()\n            assert data == \"This is line 1\\n\"\n\n\ndef test_readlines():\n    # Arrange\n    for bytesmode in (True, False):\n        expected = [\n            \"This is line 1\\n\",\n            \"This is line 2\\n\",\n            \"This is line 3\\n\",\n            \"This is line 4\\n\",\n            \"This is line 5\\n\",\n            \"This is line 6\\n\",\n            \"This is line 7\\n\",\n            \"This is line 8\\n\",\n        ]\n        with open(TEST_FILE, \"rb\" if bytesmode else \"r\") as fh:\n            container = ContainerIO.ContainerIO(fh, 0, 120)\n\n            # Act\n            data = container.readlines()\n\n            # Assert\n            if bytesmode:\n                data = [line.decode() for line in data]\n            assert data == expected\n",
            "header": {
                "file": {
                    "path": "Tests/test_file_container.py"
                },
                "misc_line": null
            },
            "index_line": {
                "old_commit_hash": "d494e1088",
                "new_commit_hash": "b752e217f",
                "mode": "100644"
            },
            "is_binary_file": false,
            "binary_line": null,
            "minus_file": {
                "path": "a/Tests/test_file_container.py"
            },
            "plus_file": {
                "path": "b/Tests/test_file_container.py"
            },
            "hunks": [
                {
                    "descriptor": {
                        "old_range": {
                            "start": 61,
                            "length": 73
                        },
                        "new_range": {
                            "start": 61,
                            "length": 87
                        },
                        "section": "def test_seek_mode_2():"
                    },
                    "line_group": {
                        "all_lines": [
                            {
                                "content": "",
                                "type": "context"
                            },
                            {
                                "content": "def test_read_n0():",
                                "type": "context"
                            },
                            {
                                "content": "    # Arrange",
                                "type": "context"
                            },
                            {
                                "content": "    with open(TEST_FILE, \"rb\") as fh:",
                                "type": "deleted"
                            },
                            {
                                "content": "        container = ContainerIO.ContainerIO(fh, 22, 100)",
                                "type": "deleted"
                            },
                            {
                                "content": "    for bytesmode in (True, False):",
                                "type": "added"
                            },
                            {
                                "content": "        with open(TEST_FILE, \"rb\" if bytesmode else \"r\") as fh:",
                                "type": "added"
                            },
                            {
                                "content": "            container = ContainerIO.ContainerIO(fh, 22, 100)",
                                "type": "added"
                            },
                            {
                                "content": "",
                                "type": "context"
                            },
                            {
                                "content": "        # Act",
                                "type": "deleted"
                            },
                            {
                                "content": "        container.seek(81)",
                                "type": "deleted"
                            },
                            {
                                "content": "        data = container.read()",
                                "type": "deleted"
                            },
                            {
                                "content": "            # Act",
                                "type": "added"
                            },
                            {
                                "content": "            container.seek(81)",
                                "type": "added"
                            },
                            {
                                "content": "            data = container.read()",
                                "type": "added"
                            },
                            {
                                "content": "",
                                "type": "context"
                            },
                            {
                                "content": "        # Assert",
                                "type": "deleted"
                            },
                            {
                                "content": "        assert data == b\"7\\nThis is line 8\\n\"",
                                "type": "deleted"
                            },
                            {
                                "content": "            # Assert",
                                "type": "added"
                            },
                            {
                                "content": "            if bytesmode:",
                                "type": "added"
                            },
                            {
                                "content": "                data = data.decode()",
                                "type": "added"
                            },
                            {
                                "content": "            assert data == \"7\\nThis is line 8\\n\"",
                                "type": "added"
                            },
                            {
                                "content": "",
                                "type": "context"
                            },
                            {
                                "content": "",
                                "type": "context"
                            },
                            {
                                "content": "def test_read_n():",
                                "type": "context"
                            },
                            {
                                "content": "    # Arrange",
                                "type": "context"
                            },
                            {
                                "content": "    with open(TEST_FILE, \"rb\") as fh:",
                                "type": "deleted"
                            },
                            {
                                "content": "        container = ContainerIO.ContainerIO(fh, 22, 100)",
                                "type": "deleted"
                            },
                            {
                                "content": "    for bytesmode in (True, False):",
                                "type": "added"
                            },
                            {
                                "content": "        with open(TEST_FILE, \"rb\" if bytesmode else \"r\") as fh:",
                                "type": "added"
                            },
                            {
                                "content": "            container = ContainerIO.ContainerIO(fh, 22, 100)",
                                "type": "added"
                            },
                            {
                                "content": "",
                                "type": "context"
                            },
                            {
                                "content": "        # Act",
                                "type": "deleted"
                            },
                            {
                                "content": "        container.seek(81)",
                                "type": "deleted"
                            },
                            {
                                "content": "        data = container.read(3)",
                                "type": "deleted"
                            },
                            {
                                "content": "            # Act",
                                "type": "added"
                            },
                            {
                                "content": "            container.seek(81)",
                                "type": "added"
                            },
                            {
                                "content": "            data = container.read(3)",
                                "type": "added"
                            },
                            {
                                "content": "",
                                "type": "context"
                            },
                            {
                                "content": "        # Assert",
                                "type": "deleted"
                            },
                            {
                                "content": "        assert data == b\"7\\nT\"",
                                "type": "deleted"
                            },
                            {
                                "content": "            # Assert",
                                "type": "added"
                            },
                            {
                                "content": "            if bytesmode:",
                                "type": "added"
                            },
                            {
                                "content": "                data = data.decode()",
                                "type": "added"
                            },
                            {
                                "content": "            assert data == \"7\\nT\"",
                                "type": "added"
                            },
                            {
                                "content": "",
                                "type": "context"
                            },
                            {
                                "content": "",
                                "type": "context"
                            },
                            {
                                "content": "def test_read_eof():",
                                "type": "context"
                            },
                            {
                                "content": "    # Arrange",
                                "type": "context"
                            },
                            {
                                "content": "    with open(TEST_FILE, \"rb\") as fh:",
                                "type": "deleted"
                            },
                            {
                                "content": "        container = ContainerIO.ContainerIO(fh, 22, 100)",
                                "type": "deleted"
                            },
                            {
                                "content": "    for bytesmode in (True, False):",
                                "type": "added"
                            },
                            {
                                "content": "        with open(TEST_FILE, \"rb\" if bytesmode else \"r\") as fh:",
                                "type": "added"
                            },
                            {
                                "content": "            container = ContainerIO.ContainerIO(fh, 22, 100)",
                                "type": "added"
                            },
                            {
                                "content": "",
                                "type": "context"
                            },
                            {
                                "content": "        # Act",
                                "type": "deleted"
                            },
                            {
                                "content": "        container.seek(100)",
                                "type": "deleted"
                            },
                            {
                                "content": "        data = container.read()",
                                "type": "deleted"
                            },
                            {
                                "content": "            # Act",
                                "type": "added"
                            },
                            {
                                "content": "            container.seek(100)",
                                "type": "added"
                            },
                            {
                                "content": "            data = container.read()",
                                "type": "added"
                            },
                            {
                                "content": "",
                                "type": "context"
                            },
                            {
                                "content": "        # Assert",
                                "type": "deleted"
                            },
                            {
                                "content": "        assert data == b\"\"",
                                "type": "deleted"
                            },
                            {
                                "content": "            # Assert",
                                "type": "added"
                            },
                            {
                                "content": "            if bytesmode:",
                                "type": "added"
                            },
                            {
                                "content": "                data = data.decode()",
                                "type": "added"
                            },
                            {
                                "content": "            assert data == \"\"",
                                "type": "added"
                            },
                            {
                                "content": "",
                                "type": "context"
                            },
                            {
                                "content": "",
                                "type": "context"
                            },
                            {
                                "content": "def test_readline():",
                                "type": "context"
                            },
                            {
                                "content": "    # Arrange",
                                "type": "context"
                            },
                            {
                                "content": "    with open(TEST_FILE, \"rb\") as fh:",
                                "type": "deleted"
                            },
                            {
                                "content": "        container = ContainerIO.ContainerIO(fh, 0, 120)",
                                "type": "deleted"
                            },
                            {
                                "content": "    for bytesmode in (True, False):",
                                "type": "added"
                            },
                            {
                                "content": "        with open(TEST_FILE, \"rb\" if bytesmode else \"r\") as fh:",
                                "type": "added"
                            },
                            {
                                "content": "            container = ContainerIO.ContainerIO(fh, 0, 120)",
                                "type": "added"
                            },
                            {
                                "content": "",
                                "type": "context"
                            },
                            {
                                "content": "        # Act",
                                "type": "deleted"
                            },
                            {
                                "content": "        data = container.readline()",
                                "type": "deleted"
                            },
                            {
                                "content": "            # Act",
                                "type": "added"
                            },
                            {
                                "content": "            data = container.readline()",
                                "type": "added"
                            },
                            {
                                "content": "",
                                "type": "context"
                            },
                            {
                                "content": "        # Assert",
                                "type": "deleted"
                            },
                            {
                                "content": "        assert data == b\"This is line 1\\n\"",
                                "type": "deleted"
                            },
                            {
                                "content": "            # Assert",
                                "type": "added"
                            },
                            {
                                "content": "            if bytesmode:",
                                "type": "added"
                            },
                            {
                                "content": "                data = data.decode()",
                                "type": "added"
                            },
                            {
                                "content": "            assert data == \"This is line 1\\n\"",
                                "type": "added"
                            },
                            {
                                "content": "",
                                "type": "context"
                            },
                            {
                                "content": "",
                                "type": "context"
                            },
                            {
                                "content": "def test_readlines():",
                                "type": "context"
                            },
                            {
                                "content": "    # Arrange",
                                "type": "context"
                            },
                            {
                                "content": "    expected = [",
                                "type": "deleted"
                            },
                            {
                                "content": "        b\"This is line 1\\n\",",
                                "type": "deleted"
                            },
                            {
                                "content": "        b\"This is line 2\\n\",",
                                "type": "deleted"
                            },
                            {
                                "content": "        b\"This is line 3\\n\",",
                                "type": "deleted"
                            },
                            {
                                "content": "        b\"This is line 4\\n\",",
                                "type": "deleted"
                            },
                            {
                                "content": "        b\"This is line 5\\n\",",
                                "type": "deleted"
                            },
                            {
                                "content": "        b\"This is line 6\\n\",",
                                "type": "deleted"
                            },
                            {
                                "content": "        b\"This is line 7\\n\",",
                                "type": "deleted"
                            },
                            {
                                "content": "        b\"This is line 8\\n\",",
                                "type": "deleted"
                            },
                            {
                                "content": "    ]",
                                "type": "deleted"
                            },
                            {
                                "content": "    with open(TEST_FILE, \"rb\") as fh:",
                                "type": "deleted"
                            },
                            {
                                "content": "        container = ContainerIO.ContainerIO(fh, 0, 120)",
                                "type": "deleted"
                            },
                            {
                                "content": "",
                                "type": "deleted"
                            },
                            {
                                "content": "        # Act",
                                "type": "deleted"
                            },
                            {
                                "content": "        data = container.readlines()",
                                "type": "deleted"
                            },
                            {
                                "content": "",
                                "type": "deleted"
                            },
                            {
                                "content": "        # Assert",
                                "type": "deleted"
                            },
                            {
                                "content": "",
                                "type": "deleted"
                            },
                            {
                                "content": "        assert data == expected",
                                "type": "deleted"
                            },
                            {
                                "content": "    for bytesmode in (True, False):",
                                "type": "added"
                            },
                            {
                                "content": "        expected = [",
                                "type": "added"
                            },
                            {
                                "content": "            \"This is line 1\\n\",",
                                "type": "added"
                            },
                            {
                                "content": "            \"This is line 2\\n\",",
                                "type": "added"
                            },
                            {
                                "content": "            \"This is line 3\\n\",",
                                "type": "added"
                            },
                            {
                                "content": "            \"This is line 4\\n\",",
                                "type": "added"
                            },
                            {
                                "content": "            \"This is line 5\\n\",",
                                "type": "added"
                            },
                            {
                                "content": "            \"This is line 6\\n\",",
                                "type": "added"
                            },
                            {
                                "content": "            \"This is line 7\\n\",",
                                "type": "added"
                            },
                            {
                                "content": "            \"This is line 8\\n\",",
                                "type": "added"
                            },
                            {
                                "content": "        ]",
                                "type": "added"
                            },
                            {
                                "content": "        with open(TEST_FILE, \"rb\" if bytesmode else \"r\") as fh:",
                                "type": "added"
                            },
                            {
                                "content": "            container = ContainerIO.ContainerIO(fh, 0, 120)",
                                "type": "added"
                            },
                            {
                                "content": "",
                                "type": "added"
                            },
                            {
                                "content": "            # Act",
                                "type": "added"
                            },
                            {
                                "content": "            data = container.readlines()",
                                "type": "added"
                            },
                            {
                                "content": "",
                                "type": "added"
                            },
                            {
                                "content": "            # Assert",
                                "type": "added"
                            },
                            {
                                "content": "            if bytesmode:",
                                "type": "added"
                            },
                            {
                                "content": "                data = [line.decode() for line in data]",
                                "type": "added"
                            },
                            {
                                "content": "            assert data == expected",
                                "type": "added"
                            }
                        ]
                    },
                    "modified_entities": [
                        {
                            "file_name": "Tests/test_file_container.py",
                            "type": "function",
                            "name": "test_read_n0",
                            "content": "def test_read_n0():\n    # Arrange\n    with open(TEST_FILE, \"rb\") as fh:\n        container = ContainerIO.ContainerIO(fh, 22, 100)\n\n        # Act\n        container.seek(81)\n        data = container.read()\n\n        # Assert\n        assert data == b\"7\\nThis is line 8\\n\"",
                            "ast_type_str": "FunctionDef",
                            "start_lineno": 62,
                            "end_lineno": 72,
                            "parent": null
                        },
                        {
                            "file_name": "Tests/test_file_container.py",
                            "type": "function",
                            "name": "test_read_n",
                            "content": "def test_read_n():\n    # Arrange\n    with open(TEST_FILE, \"rb\") as fh:\n        container = ContainerIO.ContainerIO(fh, 22, 100)\n\n        # Act\n        container.seek(81)\n        data = container.read(3)\n\n        # Assert\n        assert data == b\"7\\nT\"",
                            "ast_type_str": "FunctionDef",
                            "start_lineno": 75,
                            "end_lineno": 85,
                            "parent": null
                        },
                        {
                            "file_name": "Tests/test_file_container.py",
                            "type": "function",
                            "name": "test_readline",
                            "content": "def test_readline():\n    # Arrange\n    with open(TEST_FILE, \"rb\") as fh:\n        container = ContainerIO.ContainerIO(fh, 0, 120)\n\n        # Act\n        data = container.readline()\n\n        # Assert\n        assert data == b\"This is line 1\\n\"",
                            "ast_type_str": "FunctionDef",
                            "start_lineno": 101,
                            "end_lineno": 110,
                            "parent": null
                        },
                        {
                            "file_name": "Tests/test_file_container.py",
                            "type": "function",
                            "name": "test_read_eof",
                            "content": "def test_read_eof():\n    # Arrange\n    with open(TEST_FILE, \"rb\") as fh:\n        container = ContainerIO.ContainerIO(fh, 22, 100)\n\n        # Act\n        container.seek(100)\n        data = container.read()\n\n        # Assert\n        assert data == b\"\"",
                            "ast_type_str": "FunctionDef",
                            "start_lineno": 88,
                            "end_lineno": 98,
                            "parent": null
                        },
                        {
                            "file_name": "Tests/test_file_container.py",
                            "type": "function",
                            "name": "test_readlines",
                            "content": "def test_readlines():\n    # Arrange\n    expected = [\n        b\"This is line 1\\n\",\n        b\"This is line 2\\n\",\n        b\"This is line 3\\n\",\n        b\"This is line 4\\n\",\n        b\"This is line 5\\n\",\n        b\"This is line 6\\n\",\n        b\"This is line 7\\n\",\n        b\"This is line 8\\n\",\n    ]\n    with open(TEST_FILE, \"rb\") as fh:\n        container = ContainerIO.ContainerIO(fh, 0, 120)\n\n        # Act\n        data = container.readlines()\n\n        # Assert\n\n        assert data == expected",
                            "ast_type_str": "FunctionDef",
                            "start_lineno": 113,
                            "end_lineno": 133,
                            "parent": null
                        }
                    ],
                    "added_entities": [],
                    "deleted_entities": []
                }
            ]
        },
        {
            "old_file_content": "#\n# The Python Imaging Library.\n# $Id$\n#\n# a class to read from a container file\n#\n# History:\n# 1995-06-18 fl     Created\n# 1995-09-07 fl     Added readline(), readlines()\n#\n# Copyright (c) 1997-2001 by Secret Labs AB\n# Copyright (c) 1995 by Fredrik Lundh\n#\n# See the README file for information on usage and redistribution.\n#\n\n##\n# A file object that provides read access to a part of an existing\n# file (for example a TAR file).\n\nimport io\n\n\nclass ContainerIO:\n    def __init__(self, file, offset, length):\n        \"\"\"\n        Create file object.\n\n        :param file: Existing file.\n        :param offset: Start of region, in bytes.\n        :param length: Size of region, in bytes.\n        \"\"\"\n        self.fh = file\n        self.pos = 0\n        self.offset = offset\n        self.length = length\n        self.fh.seek(offset)\n\n    ##\n    # Always false.\n\n    def isatty(self):\n        return False\n\n    def seek(self, offset, mode=io.SEEK_SET):\n        \"\"\"\n        Move file pointer.\n\n        :param offset: Offset in bytes.\n        :param mode: Starting position. Use 0 for beginning of region, 1\n           for current offset, and 2 for end of region.  You cannot move\n           the pointer outside the defined region.\n        \"\"\"\n        if mode == 1:\n            self.pos = self.pos + offset\n        elif mode == 2:\n            self.pos = self.length + offset\n        else:\n            self.pos = offset\n        # clamp\n        self.pos = max(0, min(self.pos, self.length))\n        self.fh.seek(self.offset + self.pos)\n\n    def tell(self):\n        \"\"\"\n        Get current file pointer.\n\n        :returns: Offset from start of region, in bytes.\n        \"\"\"\n        return self.pos\n\n    def read(self, n=0):\n        \"\"\"\n        Read data.\n\n        :param n: Number of bytes to read. If omitted or zero,\n            read until end of region.\n        :returns: An 8-bit string.\n        \"\"\"\n        if n:\n            n = min(n, self.length - self.pos)\n        else:\n            n = self.length - self.pos\n        if not n:  # EOF\n            return b\"\"\n        self.pos = self.pos + n\n        return self.fh.read(n)\n\n    def readline(self):\n        \"\"\"\n        Read a line of text.\n\n        :returns: An 8-bit string.\n        \"\"\"\n        s = b\"\"\n        while True:\n            c = self.read(1)\n            if not c:\n                break\n            s = s + c\n            if c == b\"\\n\":\n                break\n        return s\n\n    def readlines(self):\n        \"\"\"\n        Read multiple lines of text.\n\n        :returns: A list of 8-bit strings.\n        \"\"\"\n        lines = []\n        while True:\n            s = self.readline()\n            if not s:\n                break\n            lines.append(s)\n        return lines\n",
            "new_file_content": "#\n# The Python Imaging Library.\n# $Id$\n#\n# a class to read from a container file\n#\n# History:\n# 1995-06-18 fl     Created\n# 1995-09-07 fl     Added readline(), readlines()\n#\n# Copyright (c) 1997-2001 by Secret Labs AB\n# Copyright (c) 1995 by Fredrik Lundh\n#\n# See the README file for information on usage and redistribution.\n#\n\n##\n# A file object that provides read access to a part of an existing\n# file (for example a TAR file).\n\nimport io\n\n\nclass ContainerIO:\n    def __init__(self, file, offset, length):\n        \"\"\"\n        Create file object.\n\n        :param file: Existing file.\n        :param offset: Start of region, in bytes.\n        :param length: Size of region, in bytes.\n        \"\"\"\n        self.fh = file\n        self.pos = 0\n        self.offset = offset\n        self.length = length\n        self.fh.seek(offset)\n\n    ##\n    # Always false.\n\n    def isatty(self):\n        return False\n\n    def seek(self, offset, mode=io.SEEK_SET):\n        \"\"\"\n        Move file pointer.\n\n        :param offset: Offset in bytes.\n        :param mode: Starting position. Use 0 for beginning of region, 1\n           for current offset, and 2 for end of region.  You cannot move\n           the pointer outside the defined region.\n        \"\"\"\n        if mode == 1:\n            self.pos = self.pos + offset\n        elif mode == 2:\n            self.pos = self.length + offset\n        else:\n            self.pos = offset\n        # clamp\n        self.pos = max(0, min(self.pos, self.length))\n        self.fh.seek(self.offset + self.pos)\n\n    def tell(self):\n        \"\"\"\n        Get current file pointer.\n\n        :returns: Offset from start of region, in bytes.\n        \"\"\"\n        return self.pos\n\n    def read(self, n=0):\n        \"\"\"\n        Read data.\n\n        :param n: Number of bytes to read. If omitted or zero,\n            read until end of region.\n        :returns: An 8-bit string.\n        \"\"\"\n        if n:\n            n = min(n, self.length - self.pos)\n        else:\n            n = self.length - self.pos\n        if not n:  # EOF\n            return b\"\" if \"b\" in self.fh.mode else \"\"\n        self.pos = self.pos + n\n        return self.fh.read(n)\n\n    def readline(self):\n        \"\"\"\n        Read a line of text.\n\n        :returns: An 8-bit string.\n        \"\"\"\n        s = b\"\" if \"b\" in self.fh.mode else \"\"\n        while True:\n            c = self.read(1)\n            if not c:\n                break\n            s = s + c\n            if c == (b\"\\n\" if \"b\" in self.fh.mode else \"\\n\"):\n                break\n        return s\n\n    def readlines(self):\n        \"\"\"\n        Read multiple lines of text.\n\n        :returns: A list of 8-bit strings.\n        \"\"\"\n        lines = []\n        while True:\n            s = self.readline()\n            if not s:\n                break\n            lines.append(s)\n        return lines\n",
            "header": {
                "file": {
                    "path": "src/PIL/ContainerIO.py"
                },
                "misc_line": null
            },
            "index_line": {
                "old_commit_hash": "8e9041210",
                "new_commit_hash": "48c0081fc",
                "mode": "100644"
            },
            "is_binary_file": false,
            "binary_line": null,
            "minus_file": {
                "path": "a/src/PIL/ContainerIO.py"
            },
            "plus_file": {
                "path": "b/src/PIL/ContainerIO.py"
            },
            "hunks": [
                {
                    "descriptor": {
                        "old_range": {
                            "start": 82,
                            "length": 7
                        },
                        "new_range": {
                            "start": 82,
                            "length": 7
                        },
                        "section": "class ContainerIO:"
                    },
                    "line_group": {
                        "all_lines": [
                            {
                                "content": "        else:",
                                "type": "context"
                            },
                            {
                                "content": "            n = self.length - self.pos",
                                "type": "context"
                            },
                            {
                                "content": "        if not n:  # EOF",
                                "type": "context"
                            },
                            {
                                "content": "            return b\"\"",
                                "type": "deleted"
                            },
                            {
                                "content": "            return b\"\" if \"b\" in self.fh.mode else \"\"",
                                "type": "added"
                            },
                            {
                                "content": "        self.pos = self.pos + n",
                                "type": "context"
                            },
                            {
                                "content": "        return self.fh.read(n)",
                                "type": "context"
                            },
                            {
                                "content": "",
                                "type": "context"
                            }
                        ]
                    },
                    "modified_entities": [
                        {
                            "file_name": "src/PIL/ContainerIO.py",
                            "type": "method",
                            "name": "ContainerIO.read",
                            "content": "class ContainerIO:\n    def __init__(self, file, offset, length):\n        \"\"\"\n        Create file object.\n\n        :param file: Existing file.\n        :param offset: Start of region, in bytes.\n        :param length: Size of region, in bytes.\n        \"\"\"\n        self.fh = file\n        self.pos = 0\n        self.offset = offset\n        self.length = length\n        self.fh.seek(offset)\n\n    ##\n    # Always false.\n\n    def isatty(self):\n        return False\n\n    def seek(self, offset, mode=io.SEEK_SET):\n        \"\"\"\n        Move file pointer.\n\n        :param offset: Offset in bytes.\n        :param mode: Starting position. Use 0 for beginning of region, 1\n           for current offset, and 2 for end of region.  You cannot move\n           the pointer outside the defined region.\n        \"\"\"\n        if mode == 1:\n            self.pos = self.pos + offset\n        elif mode == 2:\n            self.pos = self.length + offset\n        else:\n            self.pos = offset\n        # clamp\n        self.pos = max(0, min(self.pos, self.length))\n        self.fh.seek(self.offset + self.pos)\n\n    def tell(self):\n        \"\"\"\n        Get current file pointer.\n\n        :returns: Offset from start of region, in bytes.\n        \"\"\"\n        return self.pos\n\n    def read(self, n=0):\n        \"\"\"\n        Read data.\n\n        :param n: Number of bytes to read. If omitted or zero,\n            read until end of region.\n        :returns: An 8-bit string.\n        \"\"\"\n        if n:\n            n = min(n, self.length - self.pos)\n        else:\n            n = self.length - self.pos\n        if not n:  # EOF\n            return b\"\"\n        self.pos = self.pos + n\n        return self.fh.read(n)\n\n    def readline(self):\n        \"\"\"\n        Read a line of text.\n\n        :returns: An 8-bit string.\n        \"\"\"\n        s = b\"\"\n        while True:\n            c = self.read(1)\n            if not c:\n                break\n            s = s + c\n            if c == b\"\\n\":\n                break\n        return s\n\n    def readlines(self):\n        \"\"\"\n        Read multiple lines of text.\n\n        :returns: A list of 8-bit strings.\n        \"\"\"\n        lines = []\n        while True:\n            s = self.readline()\n            if not s:\n                break\n            lines.append(s)\n        return lines",
                            "ast_type_str": "ClassDef",
                            "start_lineno": 72,
                            "end_lineno": 87,
                            "parent": {
                                "file_name": "src/PIL/ContainerIO.py",
                                "type": "class",
                                "name": "ContainerIO",
                                "content": "class ContainerIO:\n    def __init__(self, file, offset, length):\n        \"\"\"\n        Create file object.\n\n        :param file: Existing file.\n        :param offset: Start of region, in bytes.\n        :param length: Size of region, in bytes.\n        \"\"\"\n        self.fh = file\n        self.pos = 0\n        self.offset = offset\n        self.length = length\n        self.fh.seek(offset)\n\n    ##\n    # Always false.\n\n    def isatty(self):\n        return False\n\n    def seek(self, offset, mode=io.SEEK_SET):\n        \"\"\"\n        Move file pointer.\n\n        :param offset: Offset in bytes.\n        :param mode: Starting position. Use 0 for beginning of region, 1\n           for current offset, and 2 for end of region.  You cannot move\n           the pointer outside the defined region.\n        \"\"\"\n        if mode == 1:\n            self.pos = self.pos + offset\n        elif mode == 2:\n            self.pos = self.length + offset\n        else:\n            self.pos = offset\n        # clamp\n        self.pos = max(0, min(self.pos, self.length))\n        self.fh.seek(self.offset + self.pos)\n\n    def tell(self):\n        \"\"\"\n        Get current file pointer.\n\n        :returns: Offset from start of region, in bytes.\n        \"\"\"\n        return self.pos\n\n    def read(self, n=0):\n        \"\"\"\n        Read data.\n\n        :param n: Number of bytes to read. If omitted or zero,\n            read until end of region.\n        :returns: An 8-bit string.\n        \"\"\"\n        if n:\n            n = min(n, self.length - self.pos)\n        else:\n            n = self.length - self.pos\n        if not n:  # EOF\n            return b\"\"\n        self.pos = self.pos + n\n        return self.fh.read(n)\n\n    def readline(self):\n        \"\"\"\n        Read a line of text.\n\n        :returns: An 8-bit string.\n        \"\"\"\n        s = b\"\"\n        while True:\n            c = self.read(1)\n            if not c:\n                break\n            s = s + c\n            if c == b\"\\n\":\n                break\n        return s\n\n    def readlines(self):\n        \"\"\"\n        Read multiple lines of text.\n\n        :returns: A list of 8-bit strings.\n        \"\"\"\n        lines = []\n        while True:\n            s = self.readline()\n            if not s:\n                break\n            lines.append(s)\n        return lines",
                                "ast_type_str": "ClassDef",
                                "start_lineno": 24,
                                "end_lineno": 117,
                                "parent": null
                            }
                        },
                        {
                            "file_name": "src/PIL/ContainerIO.py",
                            "type": "class",
                            "name": "ContainerIO",
                            "content": "class ContainerIO:\n    def __init__(self, file, offset, length):\n        \"\"\"\n        Create file object.\n\n        :param file: Existing file.\n        :param offset: Start of region, in bytes.\n        :param length: Size of region, in bytes.\n        \"\"\"\n        self.fh = file\n        self.pos = 0\n        self.offset = offset\n        self.length = length\n        self.fh.seek(offset)\n\n    ##\n    # Always false.\n\n    def isatty(self):\n        return False\n\n    def seek(self, offset, mode=io.SEEK_SET):\n        \"\"\"\n        Move file pointer.\n\n        :param offset: Offset in bytes.\n        :param mode: Starting position. Use 0 for beginning of region, 1\n           for current offset, and 2 for end of region.  You cannot move\n           the pointer outside the defined region.\n        \"\"\"\n        if mode == 1:\n            self.pos = self.pos + offset\n        elif mode == 2:\n            self.pos = self.length + offset\n        else:\n            self.pos = offset\n        # clamp\n        self.pos = max(0, min(self.pos, self.length))\n        self.fh.seek(self.offset + self.pos)\n\n    def tell(self):\n        \"\"\"\n        Get current file pointer.\n\n        :returns: Offset from start of region, in bytes.\n        \"\"\"\n        return self.pos\n\n    def read(self, n=0):\n        \"\"\"\n        Read data.\n\n        :param n: Number of bytes to read. If omitted or zero,\n            read until end of region.\n        :returns: An 8-bit string.\n        \"\"\"\n        if n:\n            n = min(n, self.length - self.pos)\n        else:\n            n = self.length - self.pos\n        if not n:  # EOF\n            return b\"\"\n        self.pos = self.pos + n\n        return self.fh.read(n)\n\n    def readline(self):\n        \"\"\"\n        Read a line of text.\n\n        :returns: An 8-bit string.\n        \"\"\"\n        s = b\"\"\n        while True:\n            c = self.read(1)\n            if not c:\n                break\n            s = s + c\n            if c == b\"\\n\":\n                break\n        return s\n\n    def readlines(self):\n        \"\"\"\n        Read multiple lines of text.\n\n        :returns: A list of 8-bit strings.\n        \"\"\"\n        lines = []\n        while True:\n            s = self.readline()\n            if not s:\n                break\n            lines.append(s)\n        return lines",
                            "ast_type_str": "ClassDef",
                            "start_lineno": 24,
                            "end_lineno": 117,
                            "parent": null
                        }
                    ],
                    "added_entities": [],
                    "deleted_entities": []
                },
                {
                    "descriptor": {
                        "old_range": {
                            "start": 92,
                            "length": 13
                        },
                        "new_range": {
                            "start": 92,
                            "length": 13
                        },
                        "section": "class ContainerIO:"
                    },
                    "line_group": {
                        "all_lines": [
                            {
                                "content": "",
                                "type": "context"
                            },
                            {
                                "content": "        :returns: An 8-bit string.",
                                "type": "context"
                            },
                            {
                                "content": "        \"\"\"",
                                "type": "context"
                            },
                            {
                                "content": "        s = b\"\"",
                                "type": "deleted"
                            },
                            {
                                "content": "        s = b\"\" if \"b\" in self.fh.mode else \"\"",
                                "type": "added"
                            },
                            {
                                "content": "        while True:",
                                "type": "context"
                            },
                            {
                                "content": "            c = self.read(1)",
                                "type": "context"
                            },
                            {
                                "content": "            if not c:",
                                "type": "context"
                            },
                            {
                                "content": "                break",
                                "type": "context"
                            },
                            {
                                "content": "            s = s + c",
                                "type": "context"
                            },
                            {
                                "content": "            if c == b\"\\n\":",
                                "type": "deleted"
                            },
                            {
                                "content": "            if c == (b\"\\n\" if \"b\" in self.fh.mode else \"\\n\"):",
                                "type": "added"
                            },
                            {
                                "content": "                break",
                                "type": "context"
                            },
                            {
                                "content": "        return s",
                                "type": "context"
                            },
                            {
                                "content": "",
                                "type": "context"
                            },
                            {
                                "content": "",
                                "type": "context"
                            }
                        ]
                    },
                    "modified_entities": [
                        {
                            "file_name": "src/PIL/ContainerIO.py",
                            "type": "method",
                            "name": "ContainerIO.readline",
                            "content": "class ContainerIO:\n    def __init__(self, file, offset, length):\n        \"\"\"\n        Create file object.\n\n        :param file: Existing file.\n        :param offset: Start of region, in bytes.\n        :param length: Size of region, in bytes.\n        \"\"\"\n        self.fh = file\n        self.pos = 0\n        self.offset = offset\n        self.length = length\n        self.fh.seek(offset)\n\n    ##\n    # Always false.\n\n    def isatty(self):\n        return False\n\n    def seek(self, offset, mode=io.SEEK_SET):\n        \"\"\"\n        Move file pointer.\n\n        :param offset: Offset in bytes.\n        :param mode: Starting position. Use 0 for beginning of region, 1\n           for current offset, and 2 for end of region.  You cannot move\n           the pointer outside the defined region.\n        \"\"\"\n        if mode == 1:\n            self.pos = self.pos + offset\n        elif mode == 2:\n            self.pos = self.length + offset\n        else:\n            self.pos = offset\n        # clamp\n        self.pos = max(0, min(self.pos, self.length))\n        self.fh.seek(self.offset + self.pos)\n\n    def tell(self):\n        \"\"\"\n        Get current file pointer.\n\n        :returns: Offset from start of region, in bytes.\n        \"\"\"\n        return self.pos\n\n    def read(self, n=0):\n        \"\"\"\n        Read data.\n\n        :param n: Number of bytes to read. If omitted or zero,\n            read until end of region.\n        :returns: An 8-bit string.\n        \"\"\"\n        if n:\n            n = min(n, self.length - self.pos)\n        else:\n            n = self.length - self.pos\n        if not n:  # EOF\n            return b\"\"\n        self.pos = self.pos + n\n        return self.fh.read(n)\n\n    def readline(self):\n        \"\"\"\n        Read a line of text.\n\n        :returns: An 8-bit string.\n        \"\"\"\n        s = b\"\"\n        while True:\n            c = self.read(1)\n            if not c:\n                break\n            s = s + c\n            if c == b\"\\n\":\n                break\n        return s\n\n    def readlines(self):\n        \"\"\"\n        Read multiple lines of text.\n\n        :returns: A list of 8-bit strings.\n        \"\"\"\n        lines = []\n        while True:\n            s = self.readline()\n            if not s:\n                break\n            lines.append(s)\n        return lines",
                            "ast_type_str": "ClassDef",
                            "start_lineno": 89,
                            "end_lineno": 103,
                            "parent": {
                                "file_name": "src/PIL/ContainerIO.py",
                                "type": "class",
                                "name": "ContainerIO",
                                "content": "class ContainerIO:\n    def __init__(self, file, offset, length):\n        \"\"\"\n        Create file object.\n\n        :param file: Existing file.\n        :param offset: Start of region, in bytes.\n        :param length: Size of region, in bytes.\n        \"\"\"\n        self.fh = file\n        self.pos = 0\n        self.offset = offset\n        self.length = length\n        self.fh.seek(offset)\n\n    ##\n    # Always false.\n\n    def isatty(self):\n        return False\n\n    def seek(self, offset, mode=io.SEEK_SET):\n        \"\"\"\n        Move file pointer.\n\n        :param offset: Offset in bytes.\n        :param mode: Starting position. Use 0 for beginning of region, 1\n           for current offset, and 2 for end of region.  You cannot move\n           the pointer outside the defined region.\n        \"\"\"\n        if mode == 1:\n            self.pos = self.pos + offset\n        elif mode == 2:\n            self.pos = self.length + offset\n        else:\n            self.pos = offset\n        # clamp\n        self.pos = max(0, min(self.pos, self.length))\n        self.fh.seek(self.offset + self.pos)\n\n    def tell(self):\n        \"\"\"\n        Get current file pointer.\n\n        :returns: Offset from start of region, in bytes.\n        \"\"\"\n        return self.pos\n\n    def read(self, n=0):\n        \"\"\"\n        Read data.\n\n        :param n: Number of bytes to read. If omitted or zero,\n            read until end of region.\n        :returns: An 8-bit string.\n        \"\"\"\n        if n:\n            n = min(n, self.length - self.pos)\n        else:\n            n = self.length - self.pos\n        if not n:  # EOF\n            return b\"\"\n        self.pos = self.pos + n\n        return self.fh.read(n)\n\n    def readline(self):\n        \"\"\"\n        Read a line of text.\n\n        :returns: An 8-bit string.\n        \"\"\"\n        s = b\"\"\n        while True:\n            c = self.read(1)\n            if not c:\n                break\n            s = s + c\n            if c == b\"\\n\":\n                break\n        return s\n\n    def readlines(self):\n        \"\"\"\n        Read multiple lines of text.\n\n        :returns: A list of 8-bit strings.\n        \"\"\"\n        lines = []\n        while True:\n            s = self.readline()\n            if not s:\n                break\n            lines.append(s)\n        return lines",
                                "ast_type_str": "ClassDef",
                                "start_lineno": 24,
                                "end_lineno": 117,
                                "parent": null
                            }
                        },
                        {
                            "file_name": "src/PIL/ContainerIO.py",
                            "type": "class",
                            "name": "ContainerIO",
                            "content": "class ContainerIO:\n    def __init__(self, file, offset, length):\n        \"\"\"\n        Create file object.\n\n        :param file: Existing file.\n        :param offset: Start of region, in bytes.\n        :param length: Size of region, in bytes.\n        \"\"\"\n        self.fh = file\n        self.pos = 0\n        self.offset = offset\n        self.length = length\n        self.fh.seek(offset)\n\n    ##\n    # Always false.\n\n    def isatty(self):\n        return False\n\n    def seek(self, offset, mode=io.SEEK_SET):\n        \"\"\"\n        Move file pointer.\n\n        :param offset: Offset in bytes.\n        :param mode: Starting position. Use 0 for beginning of region, 1\n           for current offset, and 2 for end of region.  You cannot move\n           the pointer outside the defined region.\n        \"\"\"\n        if mode == 1:\n            self.pos = self.pos + offset\n        elif mode == 2:\n            self.pos = self.length + offset\n        else:\n            self.pos = offset\n        # clamp\n        self.pos = max(0, min(self.pos, self.length))\n        self.fh.seek(self.offset + self.pos)\n\n    def tell(self):\n        \"\"\"\n        Get current file pointer.\n\n        :returns: Offset from start of region, in bytes.\n        \"\"\"\n        return self.pos\n\n    def read(self, n=0):\n        \"\"\"\n        Read data.\n\n        :param n: Number of bytes to read. If omitted or zero,\n            read until end of region.\n        :returns: An 8-bit string.\n        \"\"\"\n        if n:\n            n = min(n, self.length - self.pos)\n        else:\n            n = self.length - self.pos\n        if not n:  # EOF\n            return b\"\"\n        self.pos = self.pos + n\n        return self.fh.read(n)\n\n    def readline(self):\n        \"\"\"\n        Read a line of text.\n\n        :returns: An 8-bit string.\n        \"\"\"\n        s = b\"\"\n        while True:\n            c = self.read(1)\n            if not c:\n                break\n            s = s + c\n            if c == b\"\\n\":\n                break\n        return s\n\n    def readlines(self):\n        \"\"\"\n        Read multiple lines of text.\n\n        :returns: A list of 8-bit strings.\n        \"\"\"\n        lines = []\n        while True:\n            s = self.readline()\n            if not s:\n                break\n            lines.append(s)\n        return lines",
                            "ast_type_str": "ClassDef",
                            "start_lineno": 24,
                            "end_lineno": 117,
                            "parent": null
                        }
                    ],
                    "added_entities": [],
                    "deleted_entities": []
                }
            ]
        }
    ],
    "old_commit_hash": "f958e2f8ed7b12582836a6b6c83468c51230182a^",
    "new_commit_hash": "f958e2f8ed7b12582836a6b6c83468c51230182a",
    "commit_message": "Return strings or bytes from ContainerIO according to the file object mode",
    "commit_date": "2020-02-15T22:13:10+11:00",
    "metadata": {}
}
{
    "repo_name": "pillow",
    "new_commit_hash": "f958e2f8ed7b12582836a6b6c83468c51230182a",
    "test_file_codes": [
        "from PIL import ContainerIO, Image\n\nfrom .helper import hopper\n\nTEST_FILE = \"Tests/images/dummy.container\"\n\n\ndef test_sanity():\n    dir(Image)\n    dir(ContainerIO)\n\n\ndef test_isatty():\n    with hopper() as im:\n        container = ContainerIO.ContainerIO(im, 0, 0)\n\n    assert container.isatty() is False\n\n\ndef test_seek_mode_0():\n    # Arrange\n    mode = 0\n    with open(TEST_FILE, \"rb\") as fh:\n        container = ContainerIO.ContainerIO(fh, 22, 100)\n\n        # Act\n        container.seek(33, mode)\n        container.seek(33, mode)\n\n        # Assert\n        assert container.tell() == 33\n\n\ndef test_seek_mode_1():\n    # Arrange\n    mode = 1\n    with open(TEST_FILE, \"rb\") as fh:\n        container = ContainerIO.ContainerIO(fh, 22, 100)\n\n        # Act\n        container.seek(33, mode)\n        container.seek(33, mode)\n\n        # Assert\n        assert container.tell() == 66\n\n\ndef test_seek_mode_2():\n    # Arrange\n    mode = 2\n    with open(TEST_FILE, \"rb\") as fh:\n        container = ContainerIO.ContainerIO(fh, 22, 100)\n\n        # Act\n        container.seek(33, mode)\n        container.seek(33, mode)\n\n        # Assert\n        assert container.tell() == 100\n\n\ndef test_read_n0():\n    # Arrange\n    for bytesmode in (True, False):\n        with open(TEST_FILE, \"rb\" if bytesmode else \"r\") as fh:\n            container = ContainerIO.ContainerIO(fh, 22, 100)\n\n            # Act\n            container.seek(81)\n            data = container.read()\n\n            # Assert\n            if bytesmode:\n                data = data.decode()\n            assert data == \"7\\nThis is line 8\\n\"\n\n\ndef test_read_n():\n    # Arrange\n    for bytesmode in (True, False):\n        with open(TEST_FILE, \"rb\" if bytesmode else \"r\") as fh:\n            container = ContainerIO.ContainerIO(fh, 22, 100)\n\n            # Act\n            container.seek(81)\n            data = container.read(3)\n\n            # Assert\n            if bytesmode:\n                data = data.decode()\n            assert data == \"7\\nT\"\n\n\ndef test_read_eof():\n    # Arrange\n    for bytesmode in (True, False):\n        with open(TEST_FILE, \"rb\" if bytesmode else \"r\") as fh:\n            container = ContainerIO.ContainerIO(fh, 22, 100)\n\n            # Act\n            container.seek(100)\n            data = container.read()\n\n            # Assert\n            if bytesmode:\n                data = data.decode()\n            assert data == \"\"\n\n\ndef test_readline():\n    # Arrange\n    for bytesmode in (True, False):\n        with open(TEST_FILE, \"rb\" if bytesmode else \"r\") as fh:\n            container = ContainerIO.ContainerIO(fh, 0, 120)\n\n            # Act\n            data = container.readline()\n\n            # Assert\n            if bytesmode:\n                data = data.decode()\n            assert data == \"This is line 1\\n\"\n\n\ndef test_readlines():\n    # Arrange\n    for bytesmode in (True, False):\n        expected = [\n            \"This is line 1\\n\",\n            \"This is line 2\\n\",\n            \"This is line 3\\n\",\n            \"This is line 4\\n\",\n            \"This is line 5\\n\",\n            \"This is line 6\\n\",\n            \"This is line 7\\n\",\n            \"This is line 8\\n\",\n        ]\n        with open(TEST_FILE, \"rb\" if bytesmode else \"r\") as fh:\n            container = ContainerIO.ContainerIO(fh, 0, 120)\n\n            # Act\n            data = container.readlines()\n\n            # Assert\n            if bytesmode:\n                data = [line.decode() for line in data]\n            assert data == expected\n"
    ],
    "test_file_names": [
        "test_1.py"
    ],
    "setup_res_code": 0,
    "setup_res_stdout": "Starting Pillow installation attempts...\nVerifying Pillow installation...\n✅ Pillow installation successful!\nSuccessfully installed Pillow\n",
    "setup_res_stderr": "Using CPython 3.9.21\nCreating virtual environment at: .venv\nActivate with: source .venv/bin/activate\nResolved 12 packages in 19ms\nInstalled 12 packages in 105ms\n + coverage==7.6.10\n + exceptiongroup==1.2.2\n + iniconfig==2.0.0\n + packaging==24.2\n + pluggy==1.5.0\n + pyqt5==5.15.11\n + pyqt5-qt5==5.15.16\n + pyqt5-sip==12.16.1\n + pytest==8.3.4\n + pytest-cov==6.0.0\n + setuptools==75.8.0\n + tomli==2.2.1\nResolved 1 package in 769ms\nPrepared 1 package in 34.45s\nInstalled 1 package in 1ms\n + pillow==7.1.0.dev0 (from file:///home/gcpuser/buckets/local_repoeval_bucket/repos/pillow_f958e2f8ed7b12582836a6b6c83468c51230182a)\n",
    "new_commit_res_code": 0,
    "new_commit_res_stdout": "============================= test session starts ==============================\nplatform linux -- Python 3.9.21, pytest-8.3.4, pluggy-1.5.0\nrootdir: /home/gcpuser/buckets/local_repoeval_bucket/repos/pillow_f958e2f8ed7b12582836a6b6c83468c51230182a\nconfigfile: setup.cfg\nplugins: cov-6.0.0\ncollected 10 items\n\nr2e_tests/test_1.py ..........                                           [100%]\n\n==================================== PASSES ====================================\n=========================== short test summary info ============================\nPASSED r2e_tests/test_1.py::test_sanity\nPASSED r2e_tests/test_1.py::test_isatty\nPASSED r2e_tests/test_1.py::test_seek_mode_0\nPASSED r2e_tests/test_1.py::test_seek_mode_1\nPASSED r2e_tests/test_1.py::test_seek_mode_2\nPASSED r2e_tests/test_1.py::test_read_n0\nPASSED r2e_tests/test_1.py::test_read_n\nPASSED r2e_tests/test_1.py::test_read_eof\nPASSED r2e_tests/test_1.py::test_readline\nPASSED r2e_tests/test_1.py::test_readlines\n============================== 10 passed in 0.09s ==============================\n",
    "new_commit_res_stderr": "",
    "old_commit_res_code": 1,
    "old_commit_res_stdout": "============================= test session starts ==============================\nplatform linux -- Python 3.9.21, pytest-8.3.4, pluggy-1.5.0\nrootdir: /home/gcpuser/buckets/local_repoeval_bucket/repos/pillow_f958e2f8ed7b12582836a6b6c83468c51230182a\nconfigfile: setup.cfg\nplugins: cov-6.0.0\ncollected 10 items\n\nr2e_tests/test_1.py .......FFF                                           [100%]\n\n=================================== FAILURES ===================================\n________________________________ test_read_eof _________________________________\n\n    def test_read_eof():\n        # Arrange\n        for bytesmode in (True, False):\n            with open(TEST_FILE, \"rb\" if bytesmode else \"r\") as fh:\n                container = ContainerIO.ContainerIO(fh, 22, 100)\n    \n                # Act\n                container.seek(100)\n                data = container.read()\n    \n                # Assert\n                if bytesmode:\n                    data = data.decode()\n>               assert data == \"\"\nE               AssertionError: assert b'' == ''\n\nr2e_tests/test_1.py:107: AssertionError\n________________________________ test_readline _________________________________\n\n    def test_readline():\n        # Arrange\n        for bytesmode in (True, False):\n            with open(TEST_FILE, \"rb\" if bytesmode else \"r\") as fh:\n                container = ContainerIO.ContainerIO(fh, 0, 120)\n    \n                # Act\n>               data = container.readline()\n\nr2e_tests/test_1.py:117: \n_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ \n\nself = <PIL.ContainerIO.ContainerIO object at 0x728149b7eee0>\n\n    def readline(self):\n        \"\"\"\n        Read a line of text.\n    \n        :returns: An 8-bit string.\n        \"\"\"\n        s = b\"\"\n        while True:\n            c = self.read(1)\n            if not c:\n                break\n>           s = s + c\nE           TypeError: can't concat str to bytes\n\nsrc/PIL/ContainerIO.py:100: TypeError\n________________________________ test_readlines ________________________________\n\n    def test_readlines():\n        # Arrange\n        for bytesmode in (True, False):\n            expected = [\n                \"This is line 1\\n\",\n                \"This is line 2\\n\",\n                \"This is line 3\\n\",\n                \"This is line 4\\n\",\n                \"This is line 5\\n\",\n                \"This is line 6\\n\",\n                \"This is line 7\\n\",\n                \"This is line 8\\n\",\n            ]\n            with open(TEST_FILE, \"rb\" if bytesmode else \"r\") as fh:\n                container = ContainerIO.ContainerIO(fh, 0, 120)\n    \n                # Act\n>               data = container.readlines()\n\nr2e_tests/test_1.py:142: \n_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ \nsrc/PIL/ContainerIO.py:113: in readlines\n    s = self.readline()\n_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ \n\nself = <PIL.ContainerIO.ContainerIO object at 0x728149b7e730>\n\n    def readline(self):\n        \"\"\"\n        Read a line of text.\n    \n        :returns: An 8-bit string.\n        \"\"\"\n        s = b\"\"\n        while True:\n            c = self.read(1)\n            if not c:\n                break\n>           s = s + c\nE           TypeError: can't concat str to bytes\n\nsrc/PIL/ContainerIO.py:100: TypeError\n==================================== PASSES ====================================\n=========================== short test summary info ============================\nPASSED r2e_tests/test_1.py::test_sanity\nPASSED r2e_tests/test_1.py::test_isatty\nPASSED r2e_tests/test_1.py::test_seek_mode_0\nPASSED r2e_tests/test_1.py::test_seek_mode_1\nPASSED r2e_tests/test_1.py::test_seek_mode_2\nPASSED r2e_tests/test_1.py::test_read_n0\nPASSED r2e_tests/test_1.py::test_read_n\nFAILED r2e_tests/test_1.py::test_read_eof - AssertionError: assert b'' == ''\nFAILED r2e_tests/test_1.py::test_readline - TypeError: can't concat str to bytes\nFAILED r2e_tests/test_1.py::test_readlines - TypeError: can't concat str to b...\n========================= 3 failed, 7 passed in 0.08s ==========================\n",
    "old_commit_res_stderr": ""
}
Tests/test_file_container.py src/PIL/ContainerIO.py
We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
[ISSUE]
**Title:** ContainerIO Returns Bytes Instead of Strings in Text Mode

**Description:**
When using `ContainerIO` with a file opened in text mode (`'r'`), the methods `read()`, `readline()`, and `readlines()` incorrectly return bytes instead of strings. This leads to type errors and unexpected behavior when attempting to manipulate the returned data as strings.

**Example Code:**
```python
with open("test_file.txt", "r") as fh:
    container = ContainerIO.ContainerIO(fh, 22, 100)
    data = container.read()
    concatenated = data + " additional text"  # Raises TypeError
```

**Expected Behavior:**
When the file is opened in text mode, `ContainerIO` methods should return strings. In the example above, concatenating `" additional text"` to `data` should work seamlessly.

**Actual Behavior:**
The `read()` method returns bytes instead of a string, causing a `TypeError` when attempting to concatenate with a string:
```
TypeError: can't concat str to bytes
```
[/ISSUE]
--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.

--- BEGIN FILE ---
```
### src/PIL/ContainerIO.py
#
# The Python Imaging Library.
# $Id$
#
# a class to read from a container file
#
# History:
# 1995-06-18 fl     Created
# 1995-09-07 fl     Added readline(), readlines()
#
# Copyright (c) 1997-2001 by Secret Labs AB
# Copyright (c) 1995 by Fredrik Lundh
#
# See the README file for information on usage and redistribution.
#

##
# A file object that provides read access to a part of an existing
# file (for example a TAR file).

import io


class ContainerIO:
    def __init__(self, file, offset, length):
        """
        Create file object.

        :param file: Existing file.
        :param offset: Start of region, in bytes.
        :param length: Size of region, in bytes.
        """
        self.fh = file
        self.pos = 0
        self.offset = offset
        self.length = length
        self.fh.seek(offset)

    ##
    # Always false.

    def isatty(self):
        return False

    def seek(self, offset, mode=io.SEEK_SET):
        """
        Move file pointer.

        :param offset: Offset in bytes.
        :param mode: Starting position. Use 0 for beginning of region, 1
           for current offset, and 2 for end of region.  You cannot move
           the pointer outside the defined region.
        """
        if mode == 1:
            self.pos = self.pos + offset
        elif mode == 2:
            self.pos = self.length + offset
        else:
            self.pos = offset
        # clamp
        self.pos = max(0, min(self.pos, self.length))
        self.fh.seek(self.offset + self.pos)

    def tell(self):
        """
        Get current file pointer.

        :returns: Offset from start of region, in bytes.
        """
        return self.pos

    def read(self, n=0):
        """
        Read data.

        :param n: Number of bytes to read. If omitted or zero,
            read until end of region.
        :returns: An 8-bit string.
        """
        if n:
            n = min(n, self.length - self.pos)
        else:
            n = self.length - self.pos
        if not n:  # EOF
            return b""
        self.pos = self.pos + n
        return self.fh.read(n)

    def readline(self):
        """
        Read a line of text.

        :returns: An 8-bit string.
        """
        s = b""
        while True:
            c = self.read(1)
            if not c:
                break
            s = s + c
            if c == b"\n":
                break
        return s

    def readlines(self):
        """
        Read multiple lines of text.

        :returns: A list of 8-bit strings.
        """
        lines = []
        while True:
            s = self.readline()
            if not s:
                break
            lines.append(s)
        return lines

```
--- END FILE ---

Please first localize the bug based on the issue statement, and then generate *SEARCH/REPLACE* edits to fix the issue.

Every *SEARCH/REPLACE* edit must use this format:
1. The file path
2. The start of search block: <<<<<<< SEARCH
3. A contiguous chunk of lines to search for in the existing source code
4. The dividing line: =======
5. The lines to replace into the source code
6. The end of the replace block: >>>>>>> REPLACE

Here is an example:

```python
### mathweb/flask/app.py
<<<<<<< SEARCH
from flask import Flask
=======
import math
from flask import Flask
>>>>>>> REPLACE
```
</solution>

Please note that the *SEARCH/REPLACE* edit REQUIRES PROPER INDENTATION. If you would like to add the line '        print(x)', you must fully write that out, with all those spaces before the code!
Wrap each *SEARCH/REPLACE* edit in a code block as shown in the example above. If you have multiple *SEARCH/REPLACE* edits, use a separate code block for each one.
[ISSUE]
**Title:** ContainerIO Returns Bytes Instead of Strings in Text Mode

**Description:**
When using `ContainerIO` with a file opened in text mode (`'r'`), the methods `read()`, `readline()`, and `readlines()` incorrectly return bytes instead of strings. This leads to type errors and unexpected behavior when attempting to manipulate the returned data as strings.

**Example Code:**
```python
with open("test_file.txt", "r") as fh:
    container = ContainerIO.ContainerIO(fh, 22, 100)
    data = container.read()
    concatenated = data + " additional text"  # Raises TypeError
```

**Expected Behavior:**
When the file is opened in text mode, `ContainerIO` methods should return strings. In the example above, concatenating `" additional text"` to `data` should work seamlessly.

**Actual Behavior:**
The `read()` method returns bytes instead of a string, causing a `TypeError` when attempting to concatenate with a string:
```
TypeError: can't concat str to bytes
```
[/ISSUE]
{
    "test_sanity": "PASSED",
    "test_isatty": "PASSED",
    "test_seek_mode_0": "PASSED",
    "test_seek_mode_1": "PASSED",
    "test_seek_mode_2": "PASSED",
    "test_read_n0": "PASSED",
    "test_read_n": "PASSED",
    "test_read_eof": "PASSED",
    "test_readline": "PASSED",
    "test_readlines": "PASSED"
}
diff --git a/src/PIL/ContainerIO.py b/src/PIL/ContainerIO.py
index 8e9041210..48c0081fc 100644
--- a/src/PIL/ContainerIO.py
+++ b/src/PIL/ContainerIO.py
@@ -82,7 +82,7 @@ class ContainerIO:
         else:
             n = self.length - self.pos
         if not n:  # EOF
-            return b""
+            return b"" if "b" in self.fh.mode else ""
         self.pos = self.pos + n
         return self.fh.read(n)
 
@@ -92,13 +92,13 @@ class ContainerIO:
 
         :returns: An 8-bit string.
         """
-        s = b""
+        s = b"" if "b" in self.fh.mode else ""
         while True:
             c = self.read(1)
             if not c:
                 break
             s = s + c
-            if c == b"\n":
+            if c == (b"\n" if "b" in self.fh.mode else "\n"):
                 break
         return s
 
 

{"src/PIL/ContainerIO.py": "#\n# The Python Imaging Library.\n# $Id$\n#\n# a class to read from a container file\n#\n# History:\n# 1995-06-18 fl     Created\n# 1995-09-07 fl     Added readline(), readlines()\n#\n# Copyright (c) 1997-2001 by Secret Labs AB\n# Copyright (c) 1995 by Fredrik Lundh\n#\n# See the README file for information on usage and redistribution.\n#\n\n##\n# A file object that provides read access to a part of an existing\n# file (for example a TAR file).\n\nimport io\n\n\nclass ContainerIO:\n    def __init__(self, file, offset, length):\n        \"\"\"\n        Create file object.\n\n        :param file: Existing file.\n        :param offset: Start of region, in bytes.\n        :param length: Size of region, in bytes.\n        \"\"\"\n        self.fh = file\n        self.pos = 0\n        self.offset = offset\n        self.length = length\n        self.fh.seek(offset)\n\n    ##\n    # Always false.\n\n    def isatty(self):\n        return False\n\n    def seek(self, offset, mode=io.SEEK_SET):\n        \"\"\"\n        Move file pointer.\n\n        :param offset: Offset in bytes.\n        :param mode: Starting position. Use 0 for beginning of region, 1\n           for current offset, and 2 for end of region.  You cannot move\n           the pointer outside the defined region.\n        \"\"\"\n        if mode == 1:\n            self.pos = self.pos + offset\n        elif mode == 2:\n            self.pos = self.length + offset\n        else:\n            self.pos = offset\n        # clamp\n        self.pos = max(0, min(self.pos, self.length))\n        self.fh.seek(self.offset + self.pos)\n\n    def tell(self):\n        \"\"\"\n        Get current file pointer.\n\n        :returns: Offset from start of region, in bytes.\n        \"\"\"\n        return self.pos\n\n    def read(self, n=0):\n        \"\"\"\n        Read data.\n\n        :param n: Number of bytes to read. If omitted or zero,\n            read until end of region.\n        :returns: An 8-bit string.\n        \"\"\"\n        if n:\n            n = min(n, self.length - self.pos)\n        else:\n            n = self.length - self.pos\n        if not n:  # EOF\n            return b\"\"\n        self.pos = self.pos + n\n        return self.fh.read(n)\n\n    def readline(self):\n        \"\"\"\n        Read a line of text.\n\n        :returns: An 8-bit string.\n        \"\"\"\n        s = b\"\"\n        while True:\n            c = self.read(1)\n            if not c:\n                break\n            s = s + c\n            if c == b\"\\n\":\n                break\n        return s\n\n    def readlines(self):\n        \"\"\"\n        Read multiple lines of text.\n\n        :returns: A list of 8-bit strings.\n        \"\"\"\n        lines = []\n        while True:\n            s = self.readline()\n            if not s:\n                break\n            lines.append(s)\n        return lines\n"}
A user will ask you to solve a task. You should first draft your thinking process (inner monologue). Then, generate the solution.

Your response format must follow the template below:
<think>
Your thoughts or/and draft, like working through an exercise on scratch paper. Be as casual and as long as you want until you are confident to generate a correct solution.
</think>
<solution>
Final solution presented to the user.
</solution>
system
We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
[ISSUE]
**Title:** ContainerIO Returns Bytes Instead of Strings in Text Mode

**Description:**
When using `ContainerIO` with a file opened in text mode (`'r'`), the methods `read()`, `readline()`, and `readlines()` incorrectly return bytes instead of strings. This leads to type errors and unexpected behavior when attempting to manipulate the returned data as strings.

**Example Code:**
```python
with open("test_file.txt", "r") as fh:
    container = ContainerIO.ContainerIO(fh, 22, 100)
    data = container.read()
    concatenated = data + " additional text"  # Raises TypeError
```

**Expected Behavior:**
When the file is opened in text mode, `ContainerIO` methods should return strings. In the example above, concatenating `" additional text"` to `data` should work seamlessly.

**Actual Behavior:**
The `read()` method returns bytes instead of a string, causing a `TypeError` when attempting to concatenate with a string:
```
TypeError: can't concat str to bytes
```
[/ISSUE]
--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.

--- BEGIN FILE ---
```
### src/PIL/ContainerIO.py
#
# The Python Imaging Library.
# $Id$
#
# a class to read from a container file
#
# History:
# 1995-06-18 fl     Created
# 1995-09-07 fl     Added readline(), readlines()
#
# Copyright (c) 1997-2001 by Secret Labs AB
# Copyright (c) 1995 by Fredrik Lundh
#
# See the README file for information on usage and redistribution.
#

##
# A file object that provides read access to a part of an existing
# file (for example a TAR file).

import io


class ContainerIO:
    def __init__(self, file, offset, length):
        """
        Create file object.

        :param file: Existing file.
        :param offset: Start of region, in bytes.
        :param length: Size of region, in bytes.
        """
        self.fh = file
        self.pos = 0
        self.offset = offset
        self.length = length
        self.fh.seek(offset)

    ##
    # Always false.

    def isatty(self):
        return False

    def seek(self, offset, mode=io.SEEK_SET):
        """
        Move file pointer.

        :param offset: Offset in bytes.
        :param mode: Starting position. Use 0 for beginning of region, 1
           for current offset, and 2 for end of region.  You cannot move
           the pointer outside the defined region.
        """
        if mode == 1:
            self.pos = self.pos + offset
        elif mode == 2:
            self.pos = self.length + offset
        else:
            self.pos = offset
        # clamp
        self.pos = max(0, min(self.pos, self.length))
        self.fh.seek(self.offset + self.pos)

    def tell(self):
        """
        Get current file pointer.

        :returns: Offset from start of region, in bytes.
        """
        return self.pos

    def read(self, n=0):
        """
        Read data.

        :param n: Number of bytes to read. If omitted or zero,
            read until end of region.
        :returns: An 8-bit string.
        """
        if n:
            n = min(n, self.length - self.pos)
        else:
            n = self.length - self.pos
        if not n:  # EOF
            return b""
        self.pos = self.pos + n
        return self.fh.read(n)

    def readline(self):
        """
        Read a line of text.

        :returns: An 8-bit string.
        """
        s = b""
        while True:
            c = self.read(1)
            if not c:
                break
            s = s + c
            if c == b"\n":
                break
        return s

    def readlines(self):
        """
        Read multiple lines of text.

        :returns: A list of 8-bit strings.
        """
        lines = []
        while True:
            s = self.readline()
            if not s:
                break
            lines.append(s)
        return lines

```
--- END FILE ---

Please first localize the bug based on the issue statement, and then generate *SEARCH/REPLACE* edits to fix the issue.

Every *SEARCH/REPLACE* edit must use this format:
1. The file path
2. The start of search block: <<<<<<< SEARCH
3. A contiguous chunk of lines to search for in the existing source code
4. The dividing line: =======
5. The lines to replace into the source code
6. The end of the replace block: >>>>>>> REPLACE

Here is an example:

```python
### mathweb/flask/app.py
<<<<<<< SEARCH
from flask import Flask
=======
import math
from flask import Flask
>>>>>>> REPLACE
```
</solution>

Please note that the *SEARCH/REPLACE* edit REQUIRES PROPER INDENTATION. If you would like to add the line '        print(x)', you must fully write that out, with all those spaces before the code!
Wrap each *SEARCH/REPLACE* edit in a code block as shown in the example above. If you have multiple *SEARCH/REPLACE* edits, use a separate code block for each one.
user