{
    "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\"\"\"(comparable) descriptors of the file status\n\n\"\"\"\n\n__docformat__ = 'restructuredtext'\n\nfrom ..utils import auto_repr\n\n@auto_repr\nclass FileStatus(object):\n    \"\"\"Description of the file status to e.g. check if newer version is available\n\n    \"\"\"\n\n    def __init__(self, size=None, mtime=None, filename=None):\n        self.size = size\n        self.mtime = mtime\n        # TODO: actually not sure if filename should be here!\n        self.filename = filename\n\n    def __eq__(self, other):\n        # Disallow comparison of empty ones\n        if self.size is None and self.mtime is None and self.filename is None:\n            return NotImplemented\n        if other.size is None and other.mtime is None and other.filename is None:\n            return NotImplemented\n\n        same = \\\n            self.size == other.size and \\\n            self.filename == other.filename\n        if not same:\n            return False\n\n        # now deal with time.\n\n        # TODO: provide a config option for mtime comparison precision\n        #  we might want to claim times equal up to a second precision\n        #  since e.g. some file systems do not even store sub-sec timing\n        # TODO: config crawl.mtime_delta\n\n        # if any of them int and another float -- we need to trim float to int\n        if self.mtime == other.mtime:\n            return True\n        elif self.mtime is None or other.mtime is None:\n            return False\n\n        # none is None if here and not equal exactly\n        if isinstance(self.mtime, int) or isinstance(other.mtime, int):\n            return int(self.mtime) == int(other.mtime)\n        return False\n\n    def __ne__(self, other):\n        out = self == other\n        if isinstance(out, bool):\n            return not out\n        elif out is NotImplemented:\n            return out\n        else:\n            raise RuntimeError(\"Unknown return %r\" % (out,))",
            "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\"\"\"(comparable) descriptors of the file status\n\n\"\"\"\n\n__docformat__ = 'restructuredtext'\n\nfrom ..utils import auto_repr\n\n@auto_repr\nclass FileStatus(object):\n    \"\"\"Description of the file status to e.g. check if newer version is available\n\n    \"\"\"\n\n    def __init__(self, size=None, mtime=None, filename=None):\n        self.size = size\n        self.mtime = mtime\n        # TODO: actually not sure if filename should be here!\n        self.filename = filename\n\n    def __eq__(self, other):\n        # If other is still None, we must be different\n        if not other:\n            return False\n        # Disallow comparison of empty ones\n        if self.size is None and self.mtime is None and self.filename is None:\n            return NotImplemented\n        if other.size is None and other.mtime is None and other.filename is None:\n            return NotImplemented\n\n        same = \\\n            self.size == other.size and \\\n            self.filename == other.filename\n        if not same:\n            return False\n\n        # now deal with time.\n\n        # TODO: provide a config option for mtime comparison precision\n        #  we might want to claim times equal up to a second precision\n        #  since e.g. some file systems do not even store sub-sec timing\n        # TODO: config crawl.mtime_delta\n\n        # if any of them int and another float -- we need to trim float to int\n        if self.mtime == other.mtime:\n            return True\n        elif self.mtime is None or other.mtime is None:\n            return False\n\n        # none is None if here and not equal exactly\n        if isinstance(self.mtime, int) or isinstance(other.mtime, int):\n            return int(self.mtime) == int(other.mtime)\n        return False\n\n    def __ne__(self, other):\n        out = self == other\n        if isinstance(out, bool):\n            return not out\n        elif out is NotImplemented:\n            return out\n        else:\n            raise RuntimeError(\"Unknown return %r\" % (out,))\n",
            "header": {
                "file": {
                    "path": "datalad/support/status.py"
                },
                "misc_line": null
            },
            "index_line": {
                "old_commit_hash": "513537e1e",
                "new_commit_hash": "c65eb8138",
                "mode": "100644"
            },
            "is_binary_file": false,
            "binary_line": null,
            "minus_file": {
                "path": "a/datalad/support/status.py"
            },
            "plus_file": {
                "path": "b/datalad/support/status.py"
            },
            "hunks": [
                {
                    "descriptor": {
                        "old_range": {
                            "start": 27,
                            "length": 6
                        },
                        "new_range": {
                            "start": 27,
                            "length": 9
                        },
                        "section": "class FileStatus(object):"
                    },
                    "line_group": {
                        "all_lines": [
                            {
                                "content": "        self.filename = filename",
                                "type": "context"
                            },
                            {
                                "content": "",
                                "type": "context"
                            },
                            {
                                "content": "    def __eq__(self, other):",
                                "type": "context"
                            },
                            {
                                "content": "        # If other is still None, we must be different",
                                "type": "added"
                            },
                            {
                                "content": "        if not other:",
                                "type": "added"
                            },
                            {
                                "content": "            return False",
                                "type": "added"
                            },
                            {
                                "content": "        # Disallow comparison of empty ones",
                                "type": "context"
                            },
                            {
                                "content": "        if self.size is None and self.mtime is None and self.filename is None:",
                                "type": "context"
                            },
                            {
                                "content": "            return NotImplemented",
                                "type": "context"
                            }
                        ]
                    },
                    "modified_entities": [
                        {
                            "file_name": "datalad/support/status.py",
                            "type": "method",
                            "name": "FileStatus.__eq__",
                            "content": "class FileStatus(object):\n    \"\"\"Description of the file status to e.g. check if newer version is available\n\n    \"\"\"\n\n    def __init__(self, size=None, mtime=None, filename=None):\n        self.size = size\n        self.mtime = mtime\n        # TODO: actually not sure if filename should be here!\n        self.filename = filename\n\n    def __eq__(self, other):\n        # If other is still None, we must be different\n        if not other:\n            return False\n        # Disallow comparison of empty ones\n        if self.size is None and self.mtime is None and self.filename is None:\n            return NotImplemented\n        if other.size is None and other.mtime is None and other.filename is None:\n            return NotImplemented\n\n        same = \\\n            self.size == other.size and \\\n            self.filename == other.filename\n        if not same:\n            return False\n\n        # now deal with time.\n\n        # TODO: provide a config option for mtime comparison precision\n        #  we might want to claim times equal up to a second precision\n        #  since e.g. some file systems do not even store sub-sec timing\n        # TODO: config crawl.mtime_delta\n\n        # if any of them int and another float -- we need to trim float to int\n        if self.mtime == other.mtime:\n            return True\n        elif self.mtime is None or other.mtime is None:\n            return False\n\n        # none is None if here and not equal exactly\n        if isinstance(self.mtime, int) or isinstance(other.mtime, int):\n            return int(self.mtime) == int(other.mtime)\n        return False\n\n    def __ne__(self, other):\n        out = self == other\n        if isinstance(out, bool):\n            return not out\n        elif out is NotImplemented:\n            return out\n        else:\n            raise RuntimeError(\"Unknown return %r\" % (out,))",
                            "ast_type_str": "ClassDef",
                            "start_lineno": 29,
                            "end_lineno": 61,
                            "parent": {
                                "file_name": "datalad/support/status.py",
                                "type": "class",
                                "name": "FileStatus",
                                "content": "class FileStatus(object):\n    \"\"\"Description of the file status to e.g. check if newer version is available\n\n    \"\"\"\n\n    def __init__(self, size=None, mtime=None, filename=None):\n        self.size = size\n        self.mtime = mtime\n        # TODO: actually not sure if filename should be here!\n        self.filename = filename\n\n    def __eq__(self, other):\n        # If other is still None, we must be different\n        if not other:\n            return False\n        # Disallow comparison of empty ones\n        if self.size is None and self.mtime is None and self.filename is None:\n            return NotImplemented\n        if other.size is None and other.mtime is None and other.filename is None:\n            return NotImplemented\n\n        same = \\\n            self.size == other.size and \\\n            self.filename == other.filename\n        if not same:\n            return False\n\n        # now deal with time.\n\n        # TODO: provide a config option for mtime comparison precision\n        #  we might want to claim times equal up to a second precision\n        #  since e.g. some file systems do not even store sub-sec timing\n        # TODO: config crawl.mtime_delta\n\n        # if any of them int and another float -- we need to trim float to int\n        if self.mtime == other.mtime:\n            return True\n        elif self.mtime is None or other.mtime is None:\n            return False\n\n        # none is None if here and not equal exactly\n        if isinstance(self.mtime, int) or isinstance(other.mtime, int):\n            return int(self.mtime) == int(other.mtime)\n        return False\n\n    def __ne__(self, other):\n        out = self == other\n        if isinstance(out, bool):\n            return not out\n        elif out is NotImplemented:\n            return out\n        else:\n            raise RuntimeError(\"Unknown return %r\" % (out,))",
                                "ast_type_str": "ClassDef",
                                "start_lineno": 18,
                                "end_lineno": 70,
                                "parent": null
                            }
                        },
                        {
                            "file_name": "datalad/support/status.py",
                            "type": "class",
                            "name": "FileStatus",
                            "content": "class FileStatus(object):\n    \"\"\"Description of the file status to e.g. check if newer version is available\n\n    \"\"\"\n\n    def __init__(self, size=None, mtime=None, filename=None):\n        self.size = size\n        self.mtime = mtime\n        # TODO: actually not sure if filename should be here!\n        self.filename = filename\n\n    def __eq__(self, other):\n        # If other is still None, we must be different\n        if not other:\n            return False\n        # Disallow comparison of empty ones\n        if self.size is None and self.mtime is None and self.filename is None:\n            return NotImplemented\n        if other.size is None and other.mtime is None and other.filename is None:\n            return NotImplemented\n\n        same = \\\n            self.size == other.size and \\\n            self.filename == other.filename\n        if not same:\n            return False\n\n        # now deal with time.\n\n        # TODO: provide a config option for mtime comparison precision\n        #  we might want to claim times equal up to a second precision\n        #  since e.g. some file systems do not even store sub-sec timing\n        # TODO: config crawl.mtime_delta\n\n        # if any of them int and another float -- we need to trim float to int\n        if self.mtime == other.mtime:\n            return True\n        elif self.mtime is None or other.mtime is None:\n            return False\n\n        # none is None if here and not equal exactly\n        if isinstance(self.mtime, int) or isinstance(other.mtime, int):\n            return int(self.mtime) == int(other.mtime)\n        return False\n\n    def __ne__(self, other):\n        out = self == other\n        if isinstance(out, bool):\n            return not out\n        elif out is NotImplemented:\n            return out\n        else:\n            raise RuntimeError(\"Unknown return %r\" % (out,))",
                            "ast_type_str": "ClassDef",
                            "start_lineno": 18,
                            "end_lineno": 70,
                            "parent": null
                        }
                    ],
                    "added_entities": [],
                    "deleted_entities": []
                },
                {
                    "descriptor": {
                        "old_range": {
                            "start": 64,
                            "length": 4
                        },
                        "new_range": {
                            "start": 67,
                            "length": 4
                        },
                        "section": "class FileStatus(object):"
                    },
                    "line_group": {
                        "all_lines": [
                            {
                                "content": "        elif out is NotImplemented:",
                                "type": "context"
                            },
                            {
                                "content": "            return out",
                                "type": "context"
                            },
                            {
                                "content": "        else:",
                                "type": "context"
                            },
                            {
                                "content": "            raise RuntimeError(\"Unknown return %r\" % (out,))",
                                "type": "deleted"
                            },
                            {
                                "content": "No newline at end of file",
                                "type": "note"
                            },
                            {
                                "content": "            raise RuntimeError(\"Unknown return %r\" % (out,))",
                                "type": "added"
                            }
                        ]
                    },
                    "modified_entities": [
                        {
                            "file_name": "datalad/support/status.py",
                            "type": "method",
                            "name": "FileStatus.__ne__",
                            "content": "class FileStatus(object):\n    \"\"\"Description of the file status to e.g. check if newer version is available\n\n    \"\"\"\n\n    def __init__(self, size=None, mtime=None, filename=None):\n        self.size = size\n        self.mtime = mtime\n        # TODO: actually not sure if filename should be here!\n        self.filename = filename\n\n    def __eq__(self, other):\n        # Disallow comparison of empty ones\n        if self.size is None and self.mtime is None and self.filename is None:\n            return NotImplemented\n        if other.size is None and other.mtime is None and other.filename is None:\n            return NotImplemented\n\n        same = \\\n            self.size == other.size and \\\n            self.filename == other.filename\n        if not same:\n            return False\n\n        # now deal with time.\n\n        # TODO: provide a config option for mtime comparison precision\n        #  we might want to claim times equal up to a second precision\n        #  since e.g. some file systems do not even store sub-sec timing\n        # TODO: config crawl.mtime_delta\n\n        # if any of them int and another float -- we need to trim float to int\n        if self.mtime == other.mtime:\n            return True\n        elif self.mtime is None or other.mtime is None:\n            return False\n\n        # none is None if here and not equal exactly\n        if isinstance(self.mtime, int) or isinstance(other.mtime, int):\n            return int(self.mtime) == int(other.mtime)\n        return False\n\n    def __ne__(self, other):\n        out = self == other\n        if isinstance(out, bool):\n            return not out\n        elif out is NotImplemented:\n            return out\n        else:\n            raise RuntimeError(\"Unknown return %r\" % (out,))",
                            "ast_type_str": "ClassDef",
                            "start_lineno": 60,
                            "end_lineno": 67,
                            "parent": {
                                "file_name": "datalad/support/status.py",
                                "type": "class",
                                "name": "FileStatus",
                                "content": "class FileStatus(object):\n    \"\"\"Description of the file status to e.g. check if newer version is available\n\n    \"\"\"\n\n    def __init__(self, size=None, mtime=None, filename=None):\n        self.size = size\n        self.mtime = mtime\n        # TODO: actually not sure if filename should be here!\n        self.filename = filename\n\n    def __eq__(self, other):\n        # Disallow comparison of empty ones\n        if self.size is None and self.mtime is None and self.filename is None:\n            return NotImplemented\n        if other.size is None and other.mtime is None and other.filename is None:\n            return NotImplemented\n\n        same = \\\n            self.size == other.size and \\\n            self.filename == other.filename\n        if not same:\n            return False\n\n        # now deal with time.\n\n        # TODO: provide a config option for mtime comparison precision\n        #  we might want to claim times equal up to a second precision\n        #  since e.g. some file systems do not even store sub-sec timing\n        # TODO: config crawl.mtime_delta\n\n        # if any of them int and another float -- we need to trim float to int\n        if self.mtime == other.mtime:\n            return True\n        elif self.mtime is None or other.mtime is None:\n            return False\n\n        # none is None if here and not equal exactly\n        if isinstance(self.mtime, int) or isinstance(other.mtime, int):\n            return int(self.mtime) == int(other.mtime)\n        return False\n\n    def __ne__(self, other):\n        out = self == other\n        if isinstance(out, bool):\n            return not out\n        elif out is NotImplemented:\n            return out\n        else:\n            raise RuntimeError(\"Unknown return %r\" % (out,))",
                                "ast_type_str": "ClassDef",
                                "start_lineno": 18,
                                "end_lineno": 67,
                                "parent": null
                            }
                        },
                        {
                            "file_name": "datalad/support/status.py",
                            "type": "class",
                            "name": "FileStatus",
                            "content": "class FileStatus(object):\n    \"\"\"Description of the file status to e.g. check if newer version is available\n\n    \"\"\"\n\n    def __init__(self, size=None, mtime=None, filename=None):\n        self.size = size\n        self.mtime = mtime\n        # TODO: actually not sure if filename should be here!\n        self.filename = filename\n\n    def __eq__(self, other):\n        # Disallow comparison of empty ones\n        if self.size is None and self.mtime is None and self.filename is None:\n            return NotImplemented\n        if other.size is None and other.mtime is None and other.filename is None:\n            return NotImplemented\n\n        same = \\\n            self.size == other.size and \\\n            self.filename == other.filename\n        if not same:\n            return False\n\n        # now deal with time.\n\n        # TODO: provide a config option for mtime comparison precision\n        #  we might want to claim times equal up to a second precision\n        #  since e.g. some file systems do not even store sub-sec timing\n        # TODO: config crawl.mtime_delta\n\n        # if any of them int and another float -- we need to trim float to int\n        if self.mtime == other.mtime:\n            return True\n        elif self.mtime is None or other.mtime is None:\n            return False\n\n        # none is None if here and not equal exactly\n        if isinstance(self.mtime, int) or isinstance(other.mtime, int):\n            return int(self.mtime) == int(other.mtime)\n        return False\n\n    def __ne__(self, other):\n        out = self == other\n        if isinstance(out, bool):\n            return not out\n        elif out is NotImplemented:\n            return out\n        else:\n            raise RuntimeError(\"Unknown return %r\" % (out,))",
                            "ast_type_str": "ClassDef",
                            "start_lineno": 18,
                            "end_lineno": 67,
                            "parent": null
                        }
                    ],
                    "added_entities": [],
                    "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\nfrom ..status import FileStatus\nfrom ...tests.utils import assert_equal, assert_false\nfrom nose.tools import assert_not_equal\n\ndef test_FileStatus_basic():\n    assert_equal(FileStatus(size=0), FileStatus(size=0))\n    assert_not_equal(FileStatus(size=0), FileStatus(size=1))\n    # mtimes allow trimming if one is int\n    assert_equal(FileStatus(mtime=0), FileStatus(mtime=0.9999))\n    assert_equal(FileStatus(mtime=0), FileStatus(mtime=0.0001))\n    assert_not_equal(FileStatus(mtime=0.2), FileStatus(mtime=0.1))\n    assert_not_equal(FileStatus(mtime=0.2), FileStatus(mtime=None))\n    assert_not_equal(FileStatus(mtime=1), FileStatus(mtime=None))\n    # adding more information would result in not-equal\n    assert_not_equal(FileStatus(size=0), FileStatus(size=0, mtime=123))\n    # empty ones can't be compared\n    # TODO: actually not clear why that NotImplemented singleton is not returned\n    assert_not_equal(FileStatus(), FileStatus())\n    #assert_false(FileStatus() != FileStatus())",
            "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\nfrom ..status import FileStatus\nfrom ...tests.utils import assert_equal, assert_false\nfrom nose.tools import assert_not_equal\n\ndef test_FileStatus_basic():\n    assert_equal(FileStatus(size=0), FileStatus(size=0))\n    assert_not_equal(FileStatus(size=0), FileStatus(size=1))\n    # mtimes allow trimming if one is int\n    assert_equal(FileStatus(mtime=0), FileStatus(mtime=0.9999))\n    assert_equal(FileStatus(mtime=0), FileStatus(mtime=0.0001))\n    assert_not_equal(FileStatus(mtime=0.2), FileStatus(mtime=0.1))\n    assert_not_equal(FileStatus(mtime=0.2), FileStatus(mtime=None))\n    assert_not_equal(FileStatus(mtime=1), FileStatus(mtime=None))\n    # And with None should be False\n    assert_not_equal(FileStatus(mtime=1), None)\n    assert_not_equal(None, FileStatus(mtime=1))\n    # adding more information would result in not-equal\n    assert_not_equal(FileStatus(size=0), FileStatus(size=0, mtime=123))\n    # empty ones can't be compared\n    # TODO: actually not clear why that NotImplemented singleton is not returned\n    assert_not_equal(FileStatus(), FileStatus())\n    #assert_false(FileStatus() != FileStatus())\n",
            "header": {
                "file": {
                    "path": "datalad/support/tests/test_status.py"
                },
                "misc_line": null
            },
            "index_line": {
                "old_commit_hash": "f11e717b0",
                "new_commit_hash": "edc0c55f2",
                "mode": "100644"
            },
            "is_binary_file": false,
            "binary_line": null,
            "minus_file": {
                "path": "a/datalad/support/tests/test_status.py"
            },
            "plus_file": {
                "path": "b/datalad/support/tests/test_status.py"
            },
            "hunks": [
                {
                    "descriptor": {
                        "old_range": {
                            "start": 20,
                            "length": 9
                        },
                        "new_range": {
                            "start": 20,
                            "length": 12
                        },
                        "section": "def test_FileStatus_basic():"
                    },
                    "line_group": {
                        "all_lines": [
                            {
                                "content": "    assert_not_equal(FileStatus(mtime=0.2), FileStatus(mtime=0.1))",
                                "type": "context"
                            },
                            {
                                "content": "    assert_not_equal(FileStatus(mtime=0.2), FileStatus(mtime=None))",
                                "type": "context"
                            },
                            {
                                "content": "    assert_not_equal(FileStatus(mtime=1), FileStatus(mtime=None))",
                                "type": "context"
                            },
                            {
                                "content": "    # And with None should be False",
                                "type": "added"
                            },
                            {
                                "content": "    assert_not_equal(FileStatus(mtime=1), None)",
                                "type": "added"
                            },
                            {
                                "content": "    assert_not_equal(None, FileStatus(mtime=1))",
                                "type": "added"
                            },
                            {
                                "content": "    # adding more information would result in not-equal",
                                "type": "context"
                            },
                            {
                                "content": "    assert_not_equal(FileStatus(size=0), FileStatus(size=0, mtime=123))",
                                "type": "context"
                            },
                            {
                                "content": "    # empty ones can't be compared",
                                "type": "context"
                            },
                            {
                                "content": "    # TODO: actually not clear why that NotImplemented singleton is not returned",
                                "type": "context"
                            },
                            {
                                "content": "    assert_not_equal(FileStatus(), FileStatus())",
                                "type": "context"
                            },
                            {
                                "content": "    #assert_false(FileStatus() != FileStatus())",
                                "type": "deleted"
                            },
                            {
                                "content": "No newline at end of file",
                                "type": "note"
                            },
                            {
                                "content": "    #assert_false(FileStatus() != FileStatus())",
                                "type": "added"
                            },
                            {
                                "content": "",
                                "type": "context"
                            }
                        ]
                    },
                    "modified_entities": [
                        {
                            "file_name": "datalad/support/tests/test_status.py",
                            "type": "function",
                            "name": "test_FileStatus_basic",
                            "content": "def test_FileStatus_basic():\n    assert_equal(FileStatus(size=0), FileStatus(size=0))\n    assert_not_equal(FileStatus(size=0), FileStatus(size=1))\n    # mtimes allow trimming if one is int\n    assert_equal(FileStatus(mtime=0), FileStatus(mtime=0.9999))\n    assert_equal(FileStatus(mtime=0), FileStatus(mtime=0.0001))\n    assert_not_equal(FileStatus(mtime=0.2), FileStatus(mtime=0.1))\n    assert_not_equal(FileStatus(mtime=0.2), FileStatus(mtime=None))\n    assert_not_equal(FileStatus(mtime=1), FileStatus(mtime=None))\n    # And with None should be False\n    assert_not_equal(FileStatus(mtime=1), None)\n    assert_not_equal(None, FileStatus(mtime=1))\n    # adding more information would result in not-equal\n    assert_not_equal(FileStatus(size=0), FileStatus(size=0, mtime=123))\n    # empty ones can't be compared\n    # TODO: actually not clear why that NotImplemented singleton is not returned\n    assert_not_equal(FileStatus(), FileStatus())",
                            "ast_type_str": "FunctionDef",
                            "start_lineno": 14,
                            "end_lineno": 30,
                            "parent": null
                        }
                    ],
                    "added_entities": [],
                    "deleted_entities": []
                }
            ]
        }
    ],
    "old_commit_hash": "f4c2561bf156350d4b6e67a252e5ca83d23c18b4^",
    "new_commit_hash": "f4c2561bf156350d4b6e67a252e5ca83d23c18b4",
    "commit_message": "Merge pull request #574 from glalteva/enh-stats-none\n\nBF: comparing statuses in FileStatus -- if the other status is None, return False",
    "commit_date": "2016-06-20T17:31:25-04:00",
    "metadata": {}
}
{
    "repo_name": "datalad",
    "new_commit_hash": "f4c2561bf156350d4b6e67a252e5ca83d23c18b4",
    "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\nfrom datalad.support.status import FileStatus\nfrom datalad.tests.utils import assert_equal, assert_false\nfrom nose.tools import assert_not_equal\n\ndef test_FileStatus_basic():\n    assert_equal(FileStatus(size=0), FileStatus(size=0))\n    assert_not_equal(FileStatus(size=0), FileStatus(size=1))\n    # mtimes allow trimming if one is int\n    assert_equal(FileStatus(mtime=0), FileStatus(mtime=0.9999))\n    assert_equal(FileStatus(mtime=0), FileStatus(mtime=0.0001))\n    assert_not_equal(FileStatus(mtime=0.2), FileStatus(mtime=0.1))\n    assert_not_equal(FileStatus(mtime=0.2), FileStatus(mtime=None))\n    assert_not_equal(FileStatus(mtime=1), FileStatus(mtime=None))\n    # And with None should be False\n    assert_not_equal(FileStatus(mtime=1), None)\n    assert_not_equal(None, FileStatus(mtime=1))\n    # adding more information would result in not-equal\n    assert_not_equal(FileStatus(size=0), FileStatus(size=0, mtime=123))\n    # empty ones can't be compared\n    # TODO: actually not clear why that NotImplemented singleton is not returned\n    assert_not_equal(FileStatus(), FileStatus())\n    #assert_false(FileStatus() != FileStatus())\n",
        "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.2.1.dev160\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 106ms\nInstalled 25 packages in 5.38s\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/.tmpZjID4Z/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/.tmpZjID4Z/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/.tmpZjID4Z/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/.tmpZjID4Z/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/.tmpZjID4Z/lib/python3.9/site-packages/setuptools/build_meta.py\", line 320, in run_setup\n    exec(code, locals())\n  File \"<string>\", line 39, 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/.tmpH6dT6X/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/.tmpH6dT6X/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/.tmpH6dT6X/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/.tmpH6dT6X/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/.tmpH6dT6X/lib/python3.9/site-packages/setuptools/build_meta.py\", line 320, in run_setup\n    exec(code, locals())\n  File \"<string>\", line 39, 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_f4c2561bf156350d4b6e67a252e5ca83d23c18b4/datalad/__init__.py\", line 20, in <module>\n    from .config import ConfigManager\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/datalad_f4c2561bf156350d4b6e67a252e5ca83d23c18b4/datalad/config.py\", line 17, in <module>\n    from appdirs import AppDirs\nModuleNotFoundError: No module named 'appdirs'\nUsing CPython 3.7.9\nCreating virtual environment at: .venv\nActivate with: source .venv/bin/activate\nResolved 26 packages in 267ms\nInstalled 26 packages in 5.80s\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 67 packages in 2.94s\nPrepared 1 package in 838ms\nInstalled 61 packages in 77ms\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 + certifi==2024.12.14\n + cffi==1.15.1\n + charset-normalizer==3.4.1\n + constantly==15.1.0\n + cryptography==44.0.0\n + cssselect==1.2.0\n + datalad==0.2.1.dev1 (from file:///home/gcpuser/buckets/local_repoeval_bucket/repos/datalad_f4c2561bf156350d4b6e67a252e5ca83d23c18b4)\n + filelock==3.12.2\n + gitdb==4.0.12\n + gitpython==3.1.44\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 + 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 + 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-python==0.5.6\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 + 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 + scrapy==2.9.0\n + secretstorage==3.3.3\n + service-identity==21.1.0\n + smmap==5.0.2\n + soupsieve==2.4.1\n + testtools==2.7.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\nAudited 1 package in 11ms\n/home/gcpuser/buckets/local_repoeval_bucket/repos/datalad_f4c2561bf156350d4b6e67a252e5ca83d23c18b4/.venv/lib/python3.7/site-packages/urllib3/__init__.py:38: NotOpenSSLWarning: urllib3 v2.0 only supports OpenSSL 1.1.1+, currently the 'ssl' module is compiled with 'LibreSSL 3.1.4'. See: https://github.com/urllib3/urllib3/issues/3020\n  exceptions.NotOpenSSLWarning,\n",
    "new_commit_res_code": 0,
    "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_f4c2561bf156350d4b6e67a252e5ca83d23c18b4\nplugins: cov-4.1.0\ncollected 1 item\n\nr2e_tests/test_1.py .                                                    [100%]\n\n==================================== PASSES ====================================\n=========================== short test summary info ============================\nPASSED r2e_tests/test_1.py::test_FileStatus_basic\n============================== 1 passed in 0.96s ===============================\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_f4c2561bf156350d4b6e67a252e5ca83d23c18b4\nplugins: cov-4.1.0\ncollected 1 item\n\nr2e_tests/test_1.py F                                                    [100%]\n\n=================================== FAILURES ===================================\n____________________________ test_FileStatus_basic _____________________________\n\n    def test_FileStatus_basic():\n        assert_equal(FileStatus(size=0), FileStatus(size=0))\n        assert_not_equal(FileStatus(size=0), FileStatus(size=1))\n        # mtimes allow trimming if one is int\n        assert_equal(FileStatus(mtime=0), FileStatus(mtime=0.9999))\n        assert_equal(FileStatus(mtime=0), FileStatus(mtime=0.0001))\n        assert_not_equal(FileStatus(mtime=0.2), FileStatus(mtime=0.1))\n        assert_not_equal(FileStatus(mtime=0.2), FileStatus(mtime=None))\n        assert_not_equal(FileStatus(mtime=1), FileStatus(mtime=None))\n        # And with None should be False\n>       assert_not_equal(FileStatus(mtime=1), None)\n\nr2e_tests/test_1.py:24: \n_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ \n../../../../.local/share/uv/python/cpython-3.7.9-linux-x86_64-gnu/lib/python3.7/unittest/case.py:858: in assertNotEqual\n    if not first != second:\ndatalad/support/status.py:61: in __ne__\n    out = self == other\n_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ \n\nself = FileStatus(filename=None, mtime=1, size=None), other = None\n\n    def __eq__(self, other):\n        # Disallow comparison of empty ones\n        if self.size is None and self.mtime is None and self.filename is None:\n            return NotImplemented\n>       if other.size is None and other.mtime is None and other.filename is None:\nE       AttributeError: 'NoneType' object has no attribute 'size'\n\ndatalad/support/status.py:33: AttributeError\n=========================== short test summary info ============================\nFAILED r2e_tests/test_1.py::test_FileStatus_basic - AttributeError: 'NoneType...\n============================== 1 failed in 0.39s ===============================\n",
    "old_commit_res_stderr": ""
}
datalad/support/status.py datalad/support/tests/test_status.py
We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
[ISSUE]
**Title:** Comparing `FileStatus` to `None` Raises AttributeError

**Description:**
When attempting to compare a `FileStatus` instance with `None`, an `AttributeError` is thrown instead of returning `False`.

**Example Code:**
```python
file_status = FileStatus(mtime=1)
result = file_status == None  # This line raises an AttributeError
```

**Expected Behavior:**
Comparing a `FileStatus` object with `None` should safely return `False` without any errors.

**Actual Behavior:**
An `AttributeError` is raised because the comparison tries to access the `size` attribute of `None`, which does not exist.
[/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/status.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.
#
# ## ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ##
"""(comparable) descriptors of the file status

"""

__docformat__ = 'restructuredtext'

from ..utils import auto_repr

@auto_repr
class FileStatus(object):
    """Description of the file status to e.g. check if newer version is available

    """

    def __init__(self, size=None, mtime=None, filename=None):
        self.size = size
        self.mtime = mtime
        # TODO: actually not sure if filename should be here!
        self.filename = filename

    def __eq__(self, other):
        # Disallow comparison of empty ones
        if self.size is None and self.mtime is None and self.filename is None:
            return NotImplemented
        if other.size is None and other.mtime is None and other.filename is None:
            return NotImplemented

        same = \
            self.size == other.size and \
            self.filename == other.filename
        if not same:
            return False

        # now deal with time.

        # TODO: provide a config option for mtime comparison precision
        #  we might want to claim times equal up to a second precision
        #  since e.g. some file systems do not even store sub-sec timing
        # TODO: config crawl.mtime_delta

        # if any of them int and another float -- we need to trim float to int
        if self.mtime == other.mtime:
            return True
        elif self.mtime is None or other.mtime is None:
            return False

        # none is None if here and not equal exactly
        if isinstance(self.mtime, int) or isinstance(other.mtime, int):
            return int(self.mtime) == int(other.mtime)
        return False

    def __ne__(self, other):
        out = self == other
        if isinstance(out, bool):
            return not out
        elif out is NotImplemented:
            return out
        else:
            raise RuntimeError("Unknown return %r" % (out,))
```
--- 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:** Comparing `FileStatus` to `None` Raises AttributeError

**Description:**
When attempting to compare a `FileStatus` instance with `None`, an `AttributeError` is thrown instead of returning `False`.

**Example Code:**
```python
file_status = FileStatus(mtime=1)
result = file_status == None  # This line raises an AttributeError
```

**Expected Behavior:**
Comparing a `FileStatus` object with `None` should safely return `False` without any errors.

**Actual Behavior:**
An `AttributeError` is raised because the comparison tries to access the `size` attribute of `None`, which does not exist.
[/ISSUE]
{
    "test_FileStatus_basic": "PASSED"
}
diff --git a/datalad/support/status.py b/datalad/support/status.py
index 513537e1e..c65eb8138 100644
--- a/datalad/support/status.py
+++ b/datalad/support/status.py
@@ -27,6 +27,9 @@ class FileStatus(object):
         self.filename = filename
 
     def __eq__(self, other):
+        # If other is still None, we must be different
+        if not other:
+            return False
         # Disallow comparison of empty ones
         if self.size is None and self.mtime is None and self.filename is None:
             return NotImplemented
@@ -64,4 +67,4 @@ class FileStatus(object):
         elif out is NotImplemented:
             return out
         else:
-            raise RuntimeError("Unknown return %r" % (out,))
\ No newline at end of file
+            raise RuntimeError("Unknown return %r" % (out,))

{"datalad/support/status.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\"\"\"(comparable) descriptors of the file status\n\n\"\"\"\n\n__docformat__ = 'restructuredtext'\n\nfrom ..utils import auto_repr\n\n@auto_repr\nclass FileStatus(object):\n    \"\"\"Description of the file status to e.g. check if newer version is available\n\n    \"\"\"\n\n    def __init__(self, size=None, mtime=None, filename=None):\n        self.size = size\n        self.mtime = mtime\n        # TODO: actually not sure if filename should be here!\n        self.filename = filename\n\n    def __eq__(self, other):\n        # Disallow comparison of empty ones\n        if self.size is None and self.mtime is None and self.filename is None:\n            return NotImplemented\n        if other.size is None and other.mtime is None and other.filename is None:\n            return NotImplemented\n\n        same = \\\n            self.size == other.size and \\\n            self.filename == other.filename\n        if not same:\n            return False\n\n        # now deal with time.\n\n        # TODO: provide a config option for mtime comparison precision\n        #  we might want to claim times equal up to a second precision\n        #  since e.g. some file systems do not even store sub-sec timing\n        # TODO: config crawl.mtime_delta\n\n        # if any of them int and another float -- we need to trim float to int\n        if self.mtime == other.mtime:\n            return True\n        elif self.mtime is None or other.mtime is None:\n            return False\n\n        # none is None if here and not equal exactly\n        if isinstance(self.mtime, int) or isinstance(other.mtime, int):\n            return int(self.mtime) == int(other.mtime)\n        return False\n\n    def __ne__(self, other):\n        out = self == other\n        if isinstance(out, bool):\n            return not out\n        elif out is NotImplemented:\n            return out\n        else:\n            raise RuntimeError(\"Unknown return %r\" % (out,))"}
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:** Comparing `FileStatus` to `None` Raises AttributeError

**Description:**
When attempting to compare a `FileStatus` instance with `None`, an `AttributeError` is thrown instead of returning `False`.

**Example Code:**
```python
file_status = FileStatus(mtime=1)
result = file_status == None  # This line raises an AttributeError
```

**Expected Behavior:**
Comparing a `FileStatus` object with `None` should safely return `False` without any errors.

**Actual Behavior:**
An `AttributeError` is raised because the comparison tries to access the `size` attribute of `None`, which does not exist.
[/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/status.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.
#
# ## ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ##
"""(comparable) descriptors of the file status

"""

__docformat__ = 'restructuredtext'

from ..utils import auto_repr

@auto_repr
class FileStatus(object):
    """Description of the file status to e.g. check if newer version is available

    """

    def __init__(self, size=None, mtime=None, filename=None):
        self.size = size
        self.mtime = mtime
        # TODO: actually not sure if filename should be here!
        self.filename = filename

    def __eq__(self, other):
        # Disallow comparison of empty ones
        if self.size is None and self.mtime is None and self.filename is None:
            return NotImplemented
        if other.size is None and other.mtime is None and other.filename is None:
            return NotImplemented

        same = \
            self.size == other.size and \
            self.filename == other.filename
        if not same:
            return False

        # now deal with time.

        # TODO: provide a config option for mtime comparison precision
        #  we might want to claim times equal up to a second precision
        #  since e.g. some file systems do not even store sub-sec timing
        # TODO: config crawl.mtime_delta

        # if any of them int and another float -- we need to trim float to int
        if self.mtime == other.mtime:
            return True
        elif self.mtime is None or other.mtime is None:
            return False

        # none is None if here and not equal exactly
        if isinstance(self.mtime, int) or isinstance(other.mtime, int):
            return int(self.mtime) == int(other.mtime)
        return False

    def __ne__(self, other):
        out = self == other
        if isinstance(out, bool):
            return not out
        elif out is NotImplemented:
            return out
        else:
            raise RuntimeError("Unknown return %r" % (out,))
```
--- 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