{
    "file_diffs": [
        {
            "old_file_content": "# emacs: -*- mode: python; py-indent-offset: 4; tab-width: 4; indent-tabs-mode: nil -*-\n# ex: set sts=4 ts=4 sw=4 noet:\n# ## ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ##\n#\n#   See COPYING file distributed along with the datalad package for the\n#   copyright and license terms.\n#\n# ## ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ##\n\"\"\"Simple wrappers to get uniform JSON input and output\n\"\"\"\n\n\nfrom io import open\nimport codecs\n\n# wrapped below\nfrom simplejson import load as jsonload\nfrom simplejson import dump as jsondump\n# simply mirrored for now\nfrom simplejson import loads\nfrom simplejson import JSONDecodeError\n\n\n# TODO think about minimizing the JSON output by default\njson_dump_kwargs = dict(indent=2, sort_keys=True, ensure_ascii=False, encoding='utf-8')\n\n# Let's just reuse top level one for now\nfrom ..log import lgr\nfrom ..dochelpers import exc_str\n\n\ndef dump(obj, fname):\n    with open(fname, 'wb') as f:\n        return jsondump(\n            obj,\n            codecs.getwriter('utf-8')(f),\n            **json_dump_kwargs)\n\n\ndef load(fname, fixup=True, **kw):\n    \"\"\"Load JSON from a file, possibly fixing it up if initial load attempt fails\n\n    Parameters\n    ----------\n    fixup : bool\n      In case of failed load, apply a set of fixups with hope to resolve issues\n      in JSON\n    **kw\n      Passed into the load (and loads after fixups) function\n    \"\"\"\n    with open(fname, 'r', encoding='utf-8') as f:\n        try:\n            return jsonload(f, **kw)\n        except JSONDecodeError as exc:\n            if not fixup:\n                raise\n            lgr.warning(\"Failed to decode content in %s: %s. Trying few tricks\", fname, exc_str(exc))\n\n    # Load entire content and replace common \"abusers\" which break JSON comprehension but in general\n    # are Ok\n    with open(fname, 'r', encoding='utf-8') as f:\n        s_orig = s = f.read()\n\n    for o, r in {\n        u\"\\xa0\": \" \",  # non-breaking space\n    }.items():\n        s = s.replace(o, r)\n\n    if s == s_orig:\n        # we have done nothing, so just reraise previous exception\n        raise\n    return loads(s, **kw)\n",
            "new_file_content": "# emacs: -*- mode: python; py-indent-offset: 4; tab-width: 4; indent-tabs-mode: nil -*-\n# ex: set sts=4 ts=4 sw=4 noet:\n# ## ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ##\n#\n#   See COPYING file distributed along with the datalad package for the\n#   copyright and license terms.\n#\n# ## ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ##\n\"\"\"Simple wrappers to get uniform JSON input and output\n\"\"\"\n\n\nfrom io import open\nimport codecs\n\n# wrapped below\nfrom simplejson import load as jsonload\nfrom simplejson import dump as jsondump\n# simply mirrored for now\nfrom simplejson import loads as json_loads\nfrom simplejson import JSONDecodeError\n\n\n# TODO think about minimizing the JSON output by default\njson_dump_kwargs = dict(indent=2, sort_keys=True, ensure_ascii=False, encoding='utf-8')\n\n# Let's just reuse top level one for now\nfrom ..log import lgr\nfrom ..dochelpers import exc_str\n\n\ndef dump(obj, fname):\n    with open(fname, 'wb') as f:\n        return jsondump(\n            obj,\n            codecs.getwriter('utf-8')(f),\n            **json_dump_kwargs)\n\n\ndef loads(s, *args, **kwargs):\n    \"\"\"Helper to log actual value which failed to be parsed\"\"\"\n    try:\n        return json_loads(s, *args, **kwargs)\n    except:\n        lgr.error(\n            \"Failed to load content from %r with args=%r kwargs=%r\"\n            % (s, args, kwargs)\n        )\n        raise\n\n\ndef load(fname, fixup=True, **kw):\n    \"\"\"Load JSON from a file, possibly fixing it up if initial load attempt fails\n\n    Parameters\n    ----------\n    fixup : bool\n      In case of failed load, apply a set of fixups with hope to resolve issues\n      in JSON\n    **kw\n      Passed into the load (and loads after fixups) function\n    \"\"\"\n    with open(fname, 'r', encoding='utf-8') as f:\n        try:\n            return jsonload(f, **kw)\n        except JSONDecodeError as exc:\n            if not fixup:\n                raise\n            lgr.warning(\"Failed to decode content in %s: %s. Trying few tricks\", fname, exc_str(exc))\n\n    # Load entire content and replace common \"abusers\" which break JSON comprehension but in general\n    # are Ok\n    with open(fname, 'r', encoding='utf-8') as f:\n        s_orig = s = f.read()\n\n    for o, r in {\n        u\"\\xa0\": \" \",  # non-breaking space\n    }.items():\n        s = s.replace(o, r)\n\n    if s == s_orig:\n        # we have done nothing, so just reraise previous exception\n        raise\n    return loads(s, **kw)\n",
            "header": {
                "file": {
                    "path": "datalad/support/json_py.py"
                },
                "misc_line": null
            },
            "index_line": {
                "old_commit_hash": "eddaf6883",
                "new_commit_hash": "db09168b1",
                "mode": "100644"
            },
            "is_binary_file": false,
            "binary_line": null,
            "minus_file": {
                "path": "a/datalad/support/json_py.py"
            },
            "plus_file": {
                "path": "b/datalad/support/json_py.py"
            },
            "hunks": [
                {
                    "descriptor": {
                        "old_range": {
                            "start": 17,
                            "length": 7
                        },
                        "new_range": {
                            "start": 17,
                            "length": 7
                        },
                        "section": "import codecs"
                    },
                    "line_group": {
                        "all_lines": [
                            {
                                "content": "from simplejson import load as jsonload",
                                "type": "context"
                            },
                            {
                                "content": "from simplejson import dump as jsondump",
                                "type": "context"
                            },
                            {
                                "content": "# simply mirrored for now",
                                "type": "context"
                            },
                            {
                                "content": "from simplejson import loads",
                                "type": "deleted"
                            },
                            {
                                "content": "from simplejson import loads as json_loads",
                                "type": "added"
                            },
                            {
                                "content": "from simplejson import JSONDecodeError",
                                "type": "context"
                            },
                            {
                                "content": "",
                                "type": "context"
                            },
                            {
                                "content": "",
                                "type": "context"
                            }
                        ]
                    },
                    "modified_entities": [],
                    "added_entities": [
                        {
                            "file_name": "datalad/support/json_py.py",
                            "type": "statement",
                            "name": "",
                            "content": "from simplejson import loads as json_loads",
                            "ast_type_str": "ImportFrom",
                            "start_lineno": 20,
                            "end_lineno": 20,
                            "parent": null
                        }
                    ],
                    "deleted_entities": [
                        {
                            "file_name": "datalad/support/json_py.py",
                            "type": "statement",
                            "name": "",
                            "content": "from simplejson import loads",
                            "ast_type_str": "ImportFrom",
                            "start_lineno": 20,
                            "end_lineno": 20,
                            "parent": null
                        }
                    ]
                },
                {
                    "descriptor": {
                        "old_range": {
                            "start": 37,
                            "length": 6
                        },
                        "new_range": {
                            "start": 37,
                            "length": 18
                        },
                        "section": "def dump(obj, fname):"
                    },
                    "line_group": {
                        "all_lines": [
                            {
                                "content": "            **json_dump_kwargs)",
                                "type": "context"
                            },
                            {
                                "content": "",
                                "type": "context"
                            },
                            {
                                "content": "",
                                "type": "context"
                            },
                            {
                                "content": "def loads(s, *args, **kwargs):",
                                "type": "added"
                            },
                            {
                                "content": "    \"\"\"Helper to log actual value which failed to be parsed\"\"\"",
                                "type": "added"
                            },
                            {
                                "content": "    try:",
                                "type": "added"
                            },
                            {
                                "content": "        return json_loads(s, *args, **kwargs)",
                                "type": "added"
                            },
                            {
                                "content": "    except:",
                                "type": "added"
                            },
                            {
                                "content": "        lgr.error(",
                                "type": "added"
                            },
                            {
                                "content": "            \"Failed to load content from %r with args=%r kwargs=%r\"",
                                "type": "added"
                            },
                            {
                                "content": "            % (s, args, kwargs)",
                                "type": "added"
                            },
                            {
                                "content": "        )",
                                "type": "added"
                            },
                            {
                                "content": "        raise",
                                "type": "added"
                            },
                            {
                                "content": "",
                                "type": "added"
                            },
                            {
                                "content": "",
                                "type": "added"
                            },
                            {
                                "content": "def load(fname, fixup=True, **kw):",
                                "type": "context"
                            },
                            {
                                "content": "    \"\"\"Load JSON from a file, possibly fixing it up if initial load attempt fails",
                                "type": "context"
                            },
                            {
                                "content": "",
                                "type": "context"
                            }
                        ]
                    },
                    "modified_entities": [],
                    "added_entities": [
                        {
                            "file_name": "datalad/support/json_py.py",
                            "type": "function",
                            "name": "loads",
                            "content": "def loads(s, *args, **kwargs):\n    \"\"\"Helper to log actual value which failed to be parsed\"\"\"\n    try:\n        return json_loads(s, *args, **kwargs)\n    except:\n        lgr.error(\n            \"Failed to load content from %r with args=%r kwargs=%r\"\n            % (s, args, kwargs)\n        )\n        raise",
                            "ast_type_str": "FunctionDef",
                            "start_lineno": 40,
                            "end_lineno": 49,
                            "parent": null
                        }
                    ],
                    "deleted_entities": []
                }
            ]
        },
        {
            "old_file_content": "# emacs: -*- mode: python; py-indent-offset: 4; tab-width: 4; indent-tabs-mode: nil -*-\n# ex: set sts=4 ts=4 sw=4 noet:\n# ## ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ##\n#\n#   See COPYING file distributed along with the datalad package for the\n#   copyright and license terms.\n#\n# ## ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ##\n\nimport logging\n\nfrom datalad.support.json_py import load\nfrom datalad.support.json_py import JSONDecodeError\n\nfrom datalad.tests.utils import with_tempfile\nfrom datalad.tests.utils import eq_\nfrom datalad.tests.utils import assert_raises\nfrom datalad.tests.utils import assert_in\nfrom datalad.tests.utils import swallow_logs\n\n\n@with_tempfile(content=b'{\"Authors\": [\"A1\"\\xc2\\xa0, \"A2\"]}')\ndef test_load_screwy_unicode(fname):\n    # test that we can tollerate some screwy unicode embeddings within json\n    assert_raises(JSONDecodeError, load, fname, fixup=False)\n    with swallow_logs(new_level=logging.WARNING) as cml:\n        eq_(load(fname), {'Authors': ['A1', 'A2']})\n        assert_in('Failed to decode content', cml.out)\n\n",
            "new_file_content": "# emacs: -*- mode: python; py-indent-offset: 4; tab-width: 4; indent-tabs-mode: nil -*-\n# ex: set sts=4 ts=4 sw=4 noet:\n# ## ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ##\n#\n#   See COPYING file distributed along with the datalad package for the\n#   copyright and license terms.\n#\n# ## ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ##\n\nimport logging\n\nfrom datalad.support.json_py import load\nfrom datalad.support.json_py import loads\nfrom datalad.support.json_py import JSONDecodeError\n\nfrom datalad.tests.utils import with_tempfile\nfrom datalad.tests.utils import eq_\nfrom datalad.tests.utils import assert_raises\nfrom datalad.tests.utils import assert_in\nfrom datalad.tests.utils import swallow_logs\n\n\n@with_tempfile(content=b'{\"Authors\": [\"A1\"\\xc2\\xa0, \"A2\"]}')\ndef test_load_screwy_unicode(fname):\n    # test that we can tollerate some screwy unicode embeddings within json\n    assert_raises(JSONDecodeError, load, fname, fixup=False)\n    with swallow_logs(new_level=logging.WARNING) as cml:\n        eq_(load(fname), {'Authors': ['A1', 'A2']})\n        assert_in('Failed to decode content', cml.out)\n\n\ndef test_loads():\n    eq_(loads('{\"a\": 2}'), {'a': 2})\n    with assert_raises(JSONDecodeError),\\\n            swallow_logs(new_level=logging.WARNING) as cml:\n        loads('{\"a\": 2}x')\n    assert_in('Failed to load content from', cml.out)",
            "header": {
                "file": {
                    "path": "datalad/support/tests/test_json_py.py"
                },
                "misc_line": null
            },
            "index_line": {
                "old_commit_hash": "a5dd01926",
                "new_commit_hash": "63cb62755",
                "mode": "100644"
            },
            "is_binary_file": false,
            "binary_line": null,
            "minus_file": {
                "path": "a/datalad/support/tests/test_json_py.py"
            },
            "plus_file": {
                "path": "b/datalad/support/tests/test_json_py.py"
            },
            "hunks": [
                {
                    "descriptor": {
                        "old_range": {
                            "start": 10,
                            "length": 6
                        },
                        "new_range": {
                            "start": 10,
                            "length": 7
                        },
                        "section": ""
                    },
                    "line_group": {
                        "all_lines": [
                            {
                                "content": "import logging",
                                "type": "context"
                            },
                            {
                                "content": "",
                                "type": "context"
                            },
                            {
                                "content": "from datalad.support.json_py import load",
                                "type": "context"
                            },
                            {
                                "content": "from datalad.support.json_py import loads",
                                "type": "added"
                            },
                            {
                                "content": "from datalad.support.json_py import JSONDecodeError",
                                "type": "context"
                            },
                            {
                                "content": "",
                                "type": "context"
                            },
                            {
                                "content": "from datalad.tests.utils import with_tempfile",
                                "type": "context"
                            }
                        ]
                    },
                    "modified_entities": [],
                    "added_entities": [
                        {
                            "file_name": "datalad/support/tests/test_json_py.py",
                            "type": "statement",
                            "name": "",
                            "content": "from datalad.support.json_py import loads",
                            "ast_type_str": "ImportFrom",
                            "start_lineno": 13,
                            "end_lineno": 13,
                            "parent": null
                        }
                    ],
                    "deleted_entities": []
                },
                {
                    "descriptor": {
                        "old_range": {
                            "start": 27,
                            "length": 3
                        },
                        "new_range": {
                            "start": 28,
                            "length": 10
                        },
                        "section": "def test_load_screwy_unicode(fname):"
                    },
                    "line_group": {
                        "all_lines": [
                            {
                                "content": "        eq_(load(fname), {'Authors': ['A1', 'A2']})",
                                "type": "context"
                            },
                            {
                                "content": "        assert_in('Failed to decode content', cml.out)",
                                "type": "context"
                            },
                            {
                                "content": "",
                                "type": "context"
                            },
                            {
                                "content": "",
                                "type": "added"
                            },
                            {
                                "content": "def test_loads():",
                                "type": "added"
                            },
                            {
                                "content": "    eq_(loads('{\"a\": 2}'), {'a': 2})",
                                "type": "added"
                            },
                            {
                                "content": "    with assert_raises(JSONDecodeError),\\",
                                "type": "added"
                            },
                            {
                                "content": "            swallow_logs(new_level=logging.WARNING) as cml:",
                                "type": "added"
                            },
                            {
                                "content": "        loads('{\"a\": 2}x')",
                                "type": "added"
                            },
                            {
                                "content": "    assert_in('Failed to load content from', cml.out)",
                                "type": "added"
                            },
                            {
                                "content": "No newline at end of file",
                                "type": "note"
                            },
                            {
                                "content": "",
                                "type": "context"
                            }
                        ]
                    },
                    "modified_entities": [],
                    "added_entities": [
                        {
                            "file_name": "datalad/support/tests/test_json_py.py",
                            "type": "function",
                            "name": "test_loads",
                            "content": "def test_loads():\n    eq_(loads('{\"a\": 2}'), {'a': 2})\n    with assert_raises(JSONDecodeError),\\\n            swallow_logs(new_level=logging.WARNING) as cml:\n        loads('{\"a\": 2}x')\n    assert_in('Failed to load content from', cml.out)",
                            "ast_type_str": "FunctionDef",
                            "start_lineno": 32,
                            "end_lineno": 37,
                            "parent": null
                        }
                    ],
                    "deleted_entities": []
                }
            ]
        }
    ],
    "old_commit_hash": "1a8d685baa45754b748c6175be338ddb1841e925^",
    "new_commit_hash": "1a8d685baa45754b748c6175be338ddb1841e925",
    "commit_message": "ENH: json_py.loads helper to log content failing to be loaded",
    "commit_date": "2018-03-14T12:24:58-04:00",
    "metadata": {}
}
{
    "repo_name": "datalad",
    "new_commit_hash": "1a8d685baa45754b748c6175be338ddb1841e925",
    "test_file_codes": [
        "# emacs: -*- mode: python; py-indent-offset: 4; tab-width: 4; indent-tabs-mode: nil -*-\n# ex: set sts=4 ts=4 sw=4 noet:\n# ## ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ##\n#\n#   See COPYING file distributed along with the datalad package for the\n#   copyright and license terms.\n#\n# ## ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ##\n\nimport logging\n\nfrom datalad.support.json_py import load\nfrom datalad.support.json_py import loads\nfrom datalad.support.json_py import JSONDecodeError\n\nfrom datalad.tests.utils import with_tempfile\nfrom datalad.tests.utils import eq_\nfrom datalad.tests.utils import assert_raises\nfrom datalad.tests.utils import assert_in\nfrom datalad.tests.utils import swallow_logs\n\n\n@with_tempfile(content=b'{\"Authors\": [\"A1\"\\xc2\\xa0, \"A2\"]}')\ndef test_load_screwy_unicode(fname):\n    # test that we can tollerate some screwy unicode embeddings within json\n    assert_raises(JSONDecodeError, load, fname, fixup=False)\n    with swallow_logs(new_level=logging.WARNING) as cml:\n        eq_(load(fname), {'Authors': ['A1', 'A2']})\n        assert_in('Failed to decode content', cml.out)\n\n\ndef test_loads():\n    eq_(loads('{\"a\": 2}'), {'a': 2})\n    with assert_raises(JSONDecodeError),\\\n            swallow_logs(new_level=logging.WARNING) as cml:\n        loads('{\"a\": 2}x')\n    assert_in('Failed to load content from', cml.out)",
        "import pytest\nimport tempfile\nimport os\n\n\n@pytest.fixture\ndef path():\n    with tempfile.TemporaryDirectory() as tmpdir:\n        yield tmpdir\n\n\n@pytest.fixture(autouse=True)\ndef setup_git_config():\n    with tempfile.TemporaryDirectory() as home:\n        old_home = os.environ.get(\"HOME\")\n        os.environ[\"HOME\"] = home\n        os.system('git config --global user.name \"DataLad Tester\"')\n        os.system('git config --global user.email \"test@example.com\"')\n        yield\n        if old_home:\n            os.environ[\"HOME\"] = old_home\n"
    ],
    "test_file_names": [
        "test_1.py",
        "conftest.py"
    ],
    "setup_res_code": 0,
    "setup_res_stdout": "Starting Datalad installation attempts...\nVerifying installation...\n❌ Verification failed\nPython 3.9 installation failed, trying Python 3.7...\nVerifying installation...\nDatalad version: 0.9.2.dev7\n✅ Installation successful!\nSuccessfully installed Datalad using Python 3.7\n",
    "setup_res_stderr": "Using CPython 3.9.21\nCreating virtual environment at: .venv\nActivate with: source .venv/bin/activate\nResolved 25 packages in 75ms\nInstalled 25 packages in 5.46s\n + coverage==7.6.10\n + docopt==0.6.2\n + exceptiongroup==1.2.2\n + grabbit==0.2.6\n + importlib-resources==6.4.5\n + iniconfig==2.0.0\n + nibabel==5.3.2\n + num2words==0.5.14\n + numpy==2.0.2\n + packaging==24.2\n + pandas==2.2.3\n + patsy==1.0.1\n + pluggy==1.5.0\n + pybids==0.6.5\n + pytest==8.3.4\n + pytest-cov==6.0.0\n + python-dateutil==2.9.0.post0\n + pytz==2024.2\n + scipy==1.13.1\n + setuptools==75.6.0\n + six==1.17.0\n + tomli==2.2.1\n + typing-extensions==4.12.2\n + tzdata==2024.2\n + zipp==3.21.0\nerror: The build backend returned an error\n  Caused by: Call to `setuptools.build_meta:__legacy__.build_editable` failed (exit status: 1)\n\n[stderr]\nTraceback (most recent call last):\n  File \"<string>\", line 14, in <module>\n  File \"/home/gcpuser/.cache/uv/builds-v0/.tmpVB8DHG/lib/python3.9/site-packages/setuptools/build_meta.py\", line 483, in get_requires_for_build_editable\n    return self.get_requires_for_build_wheel(config_settings)\n  File \"/home/gcpuser/.cache/uv/builds-v0/.tmpVB8DHG/lib/python3.9/site-packages/setuptools/build_meta.py\", line 334, in get_requires_for_build_wheel\n    return self._get_build_requires(config_settings, requirements=[])\n  File \"/home/gcpuser/.cache/uv/builds-v0/.tmpVB8DHG/lib/python3.9/site-packages/setuptools/build_meta.py\", line 304, in _get_build_requires\n    self.run_setup()\n  File \"/home/gcpuser/.cache/uv/builds-v0/.tmpVB8DHG/lib/python3.9/site-packages/setuptools/build_meta.py\", line 522, in run_setup\n    super().run_setup(setup_script=setup_script)\n  File \"/home/gcpuser/.cache/uv/builds-v0/.tmpVB8DHG/lib/python3.9/site-packages/setuptools/build_meta.py\", line 320, in run_setup\n    exec(code, locals())\n  File \"<string>\", line 48, in <module>\nAttributeError: module 'platform' has no attribute 'dist'\n\nhint: This usually indicates a problem with the package or the build environment.\nerror: The build backend returned an error\n  Caused by: Call to `setuptools.build_meta:__legacy__.build_editable` failed (exit status: 1)\n\n[stderr]\nTraceback (most recent call last):\n  File \"<string>\", line 14, in <module>\n  File \"/home/gcpuser/.cache/uv/builds-v0/.tmpyFBnBY/lib/python3.9/site-packages/setuptools/build_meta.py\", line 483, in get_requires_for_build_editable\n    return self.get_requires_for_build_wheel(config_settings)\n  File \"/home/gcpuser/.cache/uv/builds-v0/.tmpyFBnBY/lib/python3.9/site-packages/setuptools/build_meta.py\", line 334, in get_requires_for_build_wheel\n    return self._get_build_requires(config_settings, requirements=[])\n  File \"/home/gcpuser/.cache/uv/builds-v0/.tmpyFBnBY/lib/python3.9/site-packages/setuptools/build_meta.py\", line 304, in _get_build_requires\n    self.run_setup()\n  File \"/home/gcpuser/.cache/uv/builds-v0/.tmpyFBnBY/lib/python3.9/site-packages/setuptools/build_meta.py\", line 522, in run_setup\n    super().run_setup(setup_script=setup_script)\n  File \"/home/gcpuser/.cache/uv/builds-v0/.tmpyFBnBY/lib/python3.9/site-packages/setuptools/build_meta.py\", line 320, in run_setup\n    exec(code, locals())\n  File \"<string>\", line 48, in <module>\nAttributeError: module 'platform' has no attribute 'dist'\n\nhint: This usually indicates a problem with the package or the build environment.\nTraceback (most recent call last):\n  File \"<string>\", line 1, in <module>\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/datalad_1a8d685baa45754b748c6175be338ddb1841e925/datalad/__init__.py\", line 17, in <module>\n    from datalad.cmd import GitRunner\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/datalad_1a8d685baa45754b748c6175be338ddb1841e925/datalad/cmd.py\", line 35, in <module>\n    from .utils import on_windows, get_tempfile_kwargs, assure_unicode\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/datalad_1a8d685baa45754b748c6175be338ddb1841e925/datalad/utils.py\", line 24, in <module>\n    import wrapt\nModuleNotFoundError: No module named 'wrapt'\nUsing CPython 3.7.9\nCreating virtual environment at: .venv\nActivate with: source .venv/bin/activate\nResolved 26 packages in 246ms\nInstalled 26 packages in 3.06s\n + bids==0.0\n + coverage==7.2.7\n + docopt==0.6.2\n + exceptiongroup==1.2.2\n + fasteners==0.19\n + grabbit==0.2.6\n + importlib-metadata==6.7.0\n + iniconfig==2.0.0\n + nibabel==4.0.2\n + num2words==0.5.14\n + numpy==1.21.6\n + packaging==24.0\n + pandas==1.3.5\n + patsy==1.0.1\n + pluggy==1.2.0\n + pybids==0.6.5\n + pytest==7.4.4\n + pytest-cov==4.1.0\n + python-dateutil==2.9.0.post0\n + pytz==2024.2\n + scipy==1.7.3\n + setuptools==68.0.0\n + six==1.17.0\n + tomli==2.0.1\n + typing-extensions==4.7.1\n + zipp==3.15.0\nResolved 79 packages in 1.53s\nPrepared 1 package in 1.23s\nInstalled 73 packages in 50ms\n + appdirs==1.4.4\n + attrs==24.2.0\n + automat==22.10.0\n + beautifulsoup4==4.12.3\n + boto==2.49.0\n + cachetools==5.5.0\n + certifi==2024.12.14\n + cffi==1.15.1\n + charset-normalizer==3.4.1\n + citeproc-py==0.6.0\n + constantly==15.1.0\n + cryptography==44.0.0\n + cssselect==1.2.0\n + datalad==0.9.2.dev1 (from file:///home/gcpuser/buckets/local_repoeval_bucket/repos/datalad_1a8d685baa45754b748c6175be338ddb1841e925)\n + deprecated==1.2.15\n + duecredit==0.9.3\n + filelock==3.12.2\n + frozendict==2.4.6\n + gitdb==4.0.11\n + gitpython==3.1.43\n + httpretty==1.1.4\n + humanize==4.6.0\n + hyperlink==21.0.0\n + idna==3.10\n + importlib-resources==5.12.0\n + incremental==22.10.0\n + iso8601==2.1.0\n + itemadapter==0.8.0\n + itemloaders==1.1.0\n + jaraco-classes==3.2.3\n + jeepney==0.8.0\n + jmespath==1.0.1\n + jsmin==3.0.1\n + keyring==24.1.1\n + keyrings-alt==4.2.0\n + lxml==5.3.0\n + mock==5.1.0\n + more-itertools==9.1.0\n + msgpack==1.0.5\n + multidict==6.0.5\n + nose==1.3.7\n + parsel==1.8.1\n + patool==1.12\n + protego==0.3.0\n + pyasn1==0.5.1\n + pyasn1-modules==0.3.0\n + pycparser==2.21\n + pydispatcher==2.0.7\n + pygithub==2.3.0\n + pyjwt==2.8.0\n + pyld==2.0.4\n + pynacl==1.5.0\n + pyopenssl==24.3.0\n + pyyaml==6.0.1\n + queuelib==1.6.2\n + requests==2.31.0\n + requests-file==2.1.0\n + requests-ftp==0.3.1\n + scrapy==2.9.0\n + secretstorage==3.3.3\n + service-identity==21.1.0\n + simplejson==3.19.3\n + smmap==5.0.1\n + soupsieve==2.4.1\n + tldextract==4.0.0\n + tqdm==4.67.1\n + twisted==23.8.0\n + urllib3==2.0.7\n + vcrpy==4.3.0\n + w3lib==2.1.2\n + wrapt==1.16.0\n + yarl==1.9.4\n + zope-interface==6.4.post2\nResolved 101 packages in 192ms\nInstalled 19 packages in 52ms\n + alabaster==0.7.13\n + babel==2.14.0\n + docutils==0.19\n + imagesize==1.4.1\n + jinja2==3.1.5\n + markupsafe==2.1.5\n + nose-timer==1.0.1\n + pygments==2.17.2\n + pypandoc==1.14\n + snowballstemmer==2.2.0\n + sphinx==5.3.0\n + sphinx-rtd-theme==2.0.0\n + sphinxcontrib-applehelp==1.0.2\n + sphinxcontrib-devhelp==1.0.2\n + sphinxcontrib-htmlhelp==2.0.0\n + sphinxcontrib-jquery==4.1\n + sphinxcontrib-jsmath==1.0.1\n + sphinxcontrib-qthelp==1.0.3\n + sphinxcontrib-serializinghtml==1.1.5\n",
    "new_commit_res_code": 1,
    "new_commit_res_stdout": "============================= test session starts ==============================\nplatform linux -- Python 3.7.9, pytest-7.4.4, pluggy-1.2.0\nrootdir: /home/gcpuser/buckets/local_repoeval_bucket/repos/datalad_1a8d685baa45754b748c6175be338ddb1841e925\nplugins: cov-4.1.0\ncollected 2 items\n\nr2e_tests/test_1.py E.                                                   [100%]\n\n==================================== ERRORS ====================================\n__________________ ERROR at setup of test_load_screwy_unicode __________________\nfile /home/gcpuser/buckets/local_repoeval_bucket/repos/datalad_1a8d685baa45754b748c6175be338ddb1841e925/r2e_tests/test_1.py, line 23\n  @with_tempfile(content=b'{\"Authors\": [\"A1\"\\xc2\\xa0, \"A2\"]}')\n  def test_load_screwy_unicode(fname):\nE       fixture 'fname' not found\n>       available fixtures: cache, capfd, capfdbinary, caplog, capsys, capsysbinary, cov, doctest_namespace, monkeypatch, no_cover, path, pytestconfig, record_property, record_testsuite_property, record_xml_attribute, recwarn, setup_git_config, tmp_path, tmp_path_factory, tmpdir, tmpdir_factory\n>       use 'pytest --fixtures [testpath]' for help on them.\n\n/home/gcpuser/buckets/local_repoeval_bucket/repos/datalad_1a8d685baa45754b748c6175be338ddb1841e925/r2e_tests/test_1.py:23\n==================================== PASSES ====================================\n__________________________________ test_loads __________________________________\n------------------------------ Captured log call -------------------------------\nERROR    datalad:json_py.py:47 Failed to load content from '{\"a\": 2}x' with args=() kwargs={}\n=========================== short test summary info ============================\nPASSED r2e_tests/test_1.py::test_loads\nERROR r2e_tests/test_1.py::test_load_screwy_unicode\n========================== 1 passed, 1 error in 0.61s ==========================\n",
    "new_commit_res_stderr": "",
    "old_commit_res_code": 1,
    "old_commit_res_stdout": "============================= test session starts ==============================\nplatform linux -- Python 3.7.9, pytest-7.4.4, pluggy-1.2.0\nrootdir: /home/gcpuser/buckets/local_repoeval_bucket/repos/datalad_1a8d685baa45754b748c6175be338ddb1841e925\nplugins: cov-4.1.0\ncollected 2 items\n\nr2e_tests/test_1.py EF                                                   [100%]\n\n==================================== ERRORS ====================================\n__________________ ERROR at setup of test_load_screwy_unicode __________________\nfile /home/gcpuser/buckets/local_repoeval_bucket/repos/datalad_1a8d685baa45754b748c6175be338ddb1841e925/r2e_tests/test_1.py, line 23\n  @with_tempfile(content=b'{\"Authors\": [\"A1\"\\xc2\\xa0, \"A2\"]}')\n  def test_load_screwy_unicode(fname):\nE       fixture 'fname' not found\n>       available fixtures: cache, capfd, capfdbinary, caplog, capsys, capsysbinary, cov, doctest_namespace, monkeypatch, no_cover, path, pytestconfig, record_property, record_testsuite_property, record_xml_attribute, recwarn, setup_git_config, tmp_path, tmp_path_factory, tmpdir, tmpdir_factory\n>       use 'pytest --fixtures [testpath]' for help on them.\n\n/home/gcpuser/buckets/local_repoeval_bucket/repos/datalad_1a8d685baa45754b748c6175be338ddb1841e925/r2e_tests/test_1.py:23\n=================================== FAILURES ===================================\n__________________________________ test_loads __________________________________\n\n    def test_loads():\n        eq_(loads('{\"a\": 2}'), {'a': 2})\n        with assert_raises(JSONDecodeError),\\\n                swallow_logs(new_level=logging.WARNING) as cml:\n            loads('{\"a\": 2}x')\n>       assert_in('Failed to load content from', cml.out)\n\nr2e_tests/test_1.py:37: \n_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ \n../../../../.local/share/uv/python/cpython-3.7.9-linux-x86_64-gnu/lib/python3.7/unittest/case.py:1119: in assertIn\n    self.fail(self._formatMessage(msg, standardMsg))\n_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ \n\nself = <nose.tools.trivial.Dummy testMethod=nop>\nmsg = \"'Failed to load content from' not found in ''\"\n\n    def fail(self, msg=None):\n        \"\"\"Fail immediately, with the given message.\"\"\"\n>       raise self.failureException(msg)\nE       AssertionError: 'Failed to load content from' not found in ''\n\n../../../../.local/share/uv/python/cpython-3.7.9-linux-x86_64-gnu/lib/python3.7/unittest/case.py:693: AssertionError\n=========================== short test summary info ============================\nERROR r2e_tests/test_1.py::test_load_screwy_unicode\nFAILED r2e_tests/test_1.py::test_loads - AssertionError: 'Failed to load cont...\n========================== 1 failed, 1 error in 0.39s ==========================\n",
    "old_commit_res_stderr": ""
}
datalad/support/json_py.py datalad/support/tests/test_json_py.py
We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
[ISSUE]

**Title:** Missing log message when JSON parsing fails in `json_py.loads`

**Description:**

When using the `loads` function from `json_py.py` to parse JSON strings, if the content fails to parse due to invalid JSON, no log message is recorded indicating the problematic content. This absence of logging makes it challenging to identify and debug issues related to malformed JSON data.

**Example Code:**

```python
from datalad.support.json_py import loads

# Attempt to load invalid JSON
loads('{"a": 2}x')
```

**Expected Behavior:**

An error log message should be generated, indicating that loading the content failed, along with the content that could not be parsed.

**Actual Behavior:**

A `JSONDecodeError` is raised without any log message about the failed content, making it difficult to trace the source of the error.

[/ISSUE]
--- END ISSUE ---

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

--- BEGIN FILE ---
```
### datalad/support/json_py.py
# emacs: -*- mode: python; py-indent-offset: 4; tab-width: 4; indent-tabs-mode: nil -*-
# ex: set sts=4 ts=4 sw=4 noet:
# ## ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ##
#
#   See COPYING file distributed along with the datalad package for the
#   copyright and license terms.
#
# ## ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ##
"""Simple wrappers to get uniform JSON input and output
"""


from io import open
import codecs

# wrapped below
from simplejson import load as jsonload
from simplejson import dump as jsondump
# simply mirrored for now
from simplejson import loads
from simplejson import JSONDecodeError


# TODO think about minimizing the JSON output by default
json_dump_kwargs = dict(indent=2, sort_keys=True, ensure_ascii=False, encoding='utf-8')

# Let's just reuse top level one for now
from ..log import lgr
from ..dochelpers import exc_str


def dump(obj, fname):
    with open(fname, 'wb') as f:
        return jsondump(
            obj,
            codecs.getwriter('utf-8')(f),
            **json_dump_kwargs)


def load(fname, fixup=True, **kw):
    """Load JSON from a file, possibly fixing it up if initial load attempt fails

    Parameters
    ----------
    fixup : bool
      In case of failed load, apply a set of fixups with hope to resolve issues
      in JSON
    **kw
      Passed into the load (and loads after fixups) function
    """
    with open(fname, 'r', encoding='utf-8') as f:
        try:
            return jsonload(f, **kw)
        except JSONDecodeError as exc:
            if not fixup:
                raise
            lgr.warning("Failed to decode content in %s: %s. Trying few tricks", fname, exc_str(exc))

    # Load entire content and replace common "abusers" which break JSON comprehension but in general
    # are Ok
    with open(fname, 'r', encoding='utf-8') as f:
        s_orig = s = f.read()

    for o, r in {
        u"\xa0": " ",  # non-breaking space
    }.items():
        s = s.replace(o, r)

    if s == s_orig:
        # we have done nothing, so just reraise previous exception
        raise
    return loads(s, **kw)

```
--- 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:** Missing log message when JSON parsing fails in `json_py.loads`

**Description:**

When using the `loads` function from `json_py.py` to parse JSON strings, if the content fails to parse due to invalid JSON, no log message is recorded indicating the problematic content. This absence of logging makes it challenging to identify and debug issues related to malformed JSON data.

**Example Code:**

```python
from datalad.support.json_py import loads

# Attempt to load invalid JSON
loads('{"a": 2}x')
```

**Expected Behavior:**

An error log message should be generated, indicating that loading the content failed, along with the content that could not be parsed.

**Actual Behavior:**

A `JSONDecodeError` is raised without any log message about the failed content, making it difficult to trace the source of the error.

[/ISSUE]
{
    "test_loads": "PASSED",
    "test_load_screwy_unicode": "ERROR"
}
diff --git a/datalad/support/json_py.py b/datalad/support/json_py.py
index eddaf6883..db09168b1 100644
--- a/datalad/support/json_py.py
+++ b/datalad/support/json_py.py
@@ -17,7 +17,7 @@ import codecs
 from simplejson import load as jsonload
 from simplejson import dump as jsondump
 # simply mirrored for now
-from simplejson import loads
+from simplejson import loads as json_loads
 from simplejson import JSONDecodeError
 
 
@@ -37,6 +37,18 @@ def dump(obj, fname):
             **json_dump_kwargs)
 
 
+def loads(s, *args, **kwargs):
+    """Helper to log actual value which failed to be parsed"""
+    try:
+        return json_loads(s, *args, **kwargs)
+    except:
+        lgr.error(
+            "Failed to load content from %r with args=%r kwargs=%r"
+            % (s, args, kwargs)
+        )
+        raise
+
+
 def load(fname, fixup=True, **kw):
     """Load JSON from a file, possibly fixing it up if initial load attempt fails
 

{"datalad/support/json_py.py": "# emacs: -*- mode: python; py-indent-offset: 4; tab-width: 4; indent-tabs-mode: nil -*-\n# ex: set sts=4 ts=4 sw=4 noet:\n# ## ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ##\n#\n#   See COPYING file distributed along with the datalad package for the\n#   copyright and license terms.\n#\n# ## ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ##\n\"\"\"Simple wrappers to get uniform JSON input and output\n\"\"\"\n\n\nfrom io import open\nimport codecs\n\n# wrapped below\nfrom simplejson import load as jsonload\nfrom simplejson import dump as jsondump\n# simply mirrored for now\nfrom simplejson import loads\nfrom simplejson import JSONDecodeError\n\n\n# TODO think about minimizing the JSON output by default\njson_dump_kwargs = dict(indent=2, sort_keys=True, ensure_ascii=False, encoding='utf-8')\n\n# Let's just reuse top level one for now\nfrom ..log import lgr\nfrom ..dochelpers import exc_str\n\n\ndef dump(obj, fname):\n    with open(fname, 'wb') as f:\n        return jsondump(\n            obj,\n            codecs.getwriter('utf-8')(f),\n            **json_dump_kwargs)\n\n\ndef load(fname, fixup=True, **kw):\n    \"\"\"Load JSON from a file, possibly fixing it up if initial load attempt fails\n\n    Parameters\n    ----------\n    fixup : bool\n      In case of failed load, apply a set of fixups with hope to resolve issues\n      in JSON\n    **kw\n      Passed into the load (and loads after fixups) function\n    \"\"\"\n    with open(fname, 'r', encoding='utf-8') as f:\n        try:\n            return jsonload(f, **kw)\n        except JSONDecodeError as exc:\n            if not fixup:\n                raise\n            lgr.warning(\"Failed to decode content in %s: %s. Trying few tricks\", fname, exc_str(exc))\n\n    # Load entire content and replace common \"abusers\" which break JSON comprehension but in general\n    # are Ok\n    with open(fname, 'r', encoding='utf-8') as f:\n        s_orig = s = f.read()\n\n    for o, r in {\n        u\"\\xa0\": \" \",  # non-breaking space\n    }.items():\n        s = s.replace(o, r)\n\n    if s == s_orig:\n        # we have done nothing, so just reraise previous exception\n        raise\n    return loads(s, **kw)\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:** Missing log message when JSON parsing fails in `json_py.loads`

**Description:**

When using the `loads` function from `json_py.py` to parse JSON strings, if the content fails to parse due to invalid JSON, no log message is recorded indicating the problematic content. This absence of logging makes it challenging to identify and debug issues related to malformed JSON data.

**Example Code:**

```python
from datalad.support.json_py import loads

# Attempt to load invalid JSON
loads('{"a": 2}x')
```

**Expected Behavior:**

An error log message should be generated, indicating that loading the content failed, along with the content that could not be parsed.

**Actual Behavior:**

A `JSONDecodeError` is raised without any log message about the failed content, making it difficult to trace the source of the error.

[/ISSUE]
--- END ISSUE ---

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

--- BEGIN FILE ---
```
### datalad/support/json_py.py
# emacs: -*- mode: python; py-indent-offset: 4; tab-width: 4; indent-tabs-mode: nil -*-
# ex: set sts=4 ts=4 sw=4 noet:
# ## ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ##
#
#   See COPYING file distributed along with the datalad package for the
#   copyright and license terms.
#
# ## ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ##
"""Simple wrappers to get uniform JSON input and output
"""


from io import open
import codecs

# wrapped below
from simplejson import load as jsonload
from simplejson import dump as jsondump
# simply mirrored for now
from simplejson import loads
from simplejson import JSONDecodeError


# TODO think about minimizing the JSON output by default
json_dump_kwargs = dict(indent=2, sort_keys=True, ensure_ascii=False, encoding='utf-8')

# Let's just reuse top level one for now
from ..log import lgr
from ..dochelpers import exc_str


def dump(obj, fname):
    with open(fname, 'wb') as f:
        return jsondump(
            obj,
            codecs.getwriter('utf-8')(f),
            **json_dump_kwargs)


def load(fname, fixup=True, **kw):
    """Load JSON from a file, possibly fixing it up if initial load attempt fails

    Parameters
    ----------
    fixup : bool
      In case of failed load, apply a set of fixups with hope to resolve issues
      in JSON
    **kw
      Passed into the load (and loads after fixups) function
    """
    with open(fname, 'r', encoding='utf-8') as f:
        try:
            return jsonload(f, **kw)
        except JSONDecodeError as exc:
            if not fixup:
                raise
            lgr.warning("Failed to decode content in %s: %s. Trying few tricks", fname, exc_str(exc))

    # Load entire content and replace common "abusers" which break JSON comprehension but in general
    # are Ok
    with open(fname, 'r', encoding='utf-8') as f:
        s_orig = s = f.read()

    for o, r in {
        u"\xa0": " ",  # non-breaking space
    }.items():
        s = s.replace(o, r)

    if s == s_orig:
        # we have done nothing, so just reraise previous exception
        raise
    return loads(s, **kw)

```
--- 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