We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
lazyjson - OSError: Bad file descriptor
this issue is bothering me for too long, a bug that appears 1 out of 5 times i startup xonsh:

```
$ XONSH_DEBUG=1 python3 -m xonsh
Exception ignored in: <bound method LazyJSON.__del__ of <xonsh.lazyjson.LazyJSON object at 0xb4a89fec>>
Traceback (most recent call last):
  File "/home/laerus/.local/lib/python3.4/site-packages/xonsh/lazyjson.py", line 212, in __del__
    self.close()
  File "/home/laerus/.local/lib/python3.4/site-packages/xonsh/lazyjson.py", line 217, in close
    self._f.close()
OSError: [Errno 9] Bad file descriptor
```

anyone else getting this? any ideas on debugging it? 


--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `xonsh/lazyjson.py`
Content:
```
1 # -*- coding: utf-8 -*-
2 """Implements a lazy JSON file class that wraps around json data."""
3 import io
4 import json
5 import weakref
6 import contextlib
7 import collections.abc as abc
8 
9 
10 def _to_json_with_size(obj, offset=0, sort_keys=False):
11     if isinstance(obj, str):
12         s = json.dumps(obj)
13         o = offset
14         n = size = len(s.encode())  # size in bytes
15     elif isinstance(obj, abc.Mapping):
16         s = '{'
17         j = offset + 1
18         o = {}
19         size = {}
20         items = sorted(obj.items()) if sort_keys else obj.items()
21         for key, val in items:
22             s_k, o_k, n_k, size_k = _to_json_with_size(key, offset=j,
23                                                        sort_keys=sort_keys)
24             s += s_k + ': '
25             j += n_k + 2
26             s_v, o_v, n_v, size_v = _to_json_with_size(val, offset=j,
27                                                        sort_keys=sort_keys)
28             o[key] = o_v
29             size[key] = size_v
30             s += s_v + ', '
31             j += n_v + 2
32         if s.endswith(', '):
33             s = s[:-2]
34         s += '}\n'
35         n = len(s)
36         o['__total__'] = offset
37         size['__total__'] = n
38     elif isinstance(obj, abc.Sequence):
39         s = '['
40         j = offset + 1
41         o = []
42         size = []
43         for x in obj:
44             s_x, o_x, n_x, size_x = _to_json_with_size(x, offset=j,
45                                                        sort_keys=sort_keys)
46             o.append(o_x)
47             size.append(size_x)
48             s += s_x + ', '
49             j += n_x + 2
50         if s.endswith(', '):
51             s = s[:-2]
52         s += ']\n'
53         n = len(s)
54         o.append(offset)
55         size.append(n)
56     else:
57         s = json.dumps(obj, sort_keys=sort_keys)
58         o = offset
59         n = size = len(s)
60     return s, o, n, size
61 
62 
63 def index(obj, sort_keys=False):
64     """Creates an index for a JSON file."""
65     idx = {}
66     json_obj = _to_json_with_size(obj, sort_keys=sort_keys)
67     s, idx['offsets'], _, idx['sizes'] = json_obj
68     return s, idx
69 
70 
71 JSON_FORMAT = \
72 """{{"locs": [{iloc:>10}, {ilen:>10}, {dloc:>10}, {dlen:>10}],
73  "index": {index},
74  "data": {data}
75 }}
76 """
77 
78 
79 def dumps(obj, sort_keys=False):
80     """Dumps an object to JSON with an index."""
81     data, idx = index(obj, sort_keys=sort_keys)
82     jdx = json.dumps(idx, sort_keys=sort_keys)
83     iloc = 69
84     ilen = len(jdx)
85     dloc = iloc + ilen + 11
86     dlen = len(data)
87     s = JSON_FORMAT.format(index=jdx, data=data, iloc=iloc, ilen=ilen,
88                            dloc=dloc, dlen=dlen)
89     return s
90 
91 
92 def ljdump(obj, fp, sort_keys=False):
93     """Dumps an object to JSON file."""
94     s = dumps(obj, sort_keys=sort_keys)
95     fp.write(s)
96 
97 
98 class LJNode(abc.Mapping, abc.Sequence):
99     """A proxy node for JSON nodes. Acts as both sequence and mapping."""
100 
101     def __init__(self, offsets, sizes, root):
102         """Parameters
103         ----------
104         offsets : dict, list, or int
105             offsets of corresponding data structure, in bytes
106         sizes : dict, list, or int
107             sizes of corresponding data structure, in bytes
108         root : weakref.proxy of LazyJSON
109             weakref back to root node, which should be a LazyJSON object.
110         """
111         self.offsets = offsets
112         self.sizes = sizes
113         self.root = root
114         self.is_mapping = isinstance(self.offsets, abc.Mapping)
115         self.is_sequence = isinstance(self.offsets, abc.Sequence)
116 
117     def __len__(self):
118         # recall that for maps, the '__total__' key is added and for
119         # sequences the last element represents the total size/offset.
120         return len(self.sizes) - 1
121 
122     def load(self):
123         """Returns the Python data structure represented by the node."""
124         if self.is_mapping:
125             offset = self.offsets['__total__']
126             size = self.sizes['__total__']
127         elif self.is_sequence:
128             offset = self.offsets[-1]
129             size = self.sizes[-1]
130         elif isinstance(self.offsets, int):
131             offset = self.offsets
132             size = self.sizes
133         return self._load_or_node(offset, size)
134 
135     def _load_or_node(self, offset, size):
136         if isinstance(offset, int):
137             with self.root._open(newline='\n') as f:
138                 f.seek(self.root.dloc + offset)
139                 s = f.read(size)
140             val = json.loads(s)
141         elif isinstance(offset, (abc.Mapping, abc.Sequence)):
142             val = LJNode(offset, size, self.root)
143         else:
144             raise TypeError('incorrect types for offset node')
145         return val
146 
147     def _getitem_mapping(self, key):
148         if key == '__total__':
149             raise KeyError('"__total__" is a special LazyJSON key!')
150         offset = self.offsets[key]
151         size = self.sizes[key]
152         return self._load_or_node(offset, size)
153 
154     def _getitem_sequence(self, key):
155         if isinstance(key, int):
156             rtn = self._load_or_node(self.offsets[key], self.sizes[key])
157         elif isinstance(key, slice):
158             key = slice(*key.indices(len(self)))
159             rtn = list(map(self._load_or_node, self.offsets[key],
160                            self.sizes[key]))
161         else:
162             raise TypeError('only integer indexing available')
163         return rtn
164 
165     def __getitem__(self, key):
166         if self.is_mapping:
167             rtn = self._getitem_mapping(key)
168         elif self.is_sequence:
169             rtn = self._getitem_sequence(key)
170         else:
171             raise NotImplementedError
172         return rtn
173 
174     def __iter__(self):
175         if self.is_mapping:
176             keys = set(self.offsets.keys())
177             keys.discard('__total__')
178             yield from iter(keys)
179         elif self.is_sequence:
180             i = 0
181             n = len(self)
182             while i < n:
183                 yield self._load_or_node(self.offsets[i], self.sizes[i])
184                 i += 1
185         else:
186             raise NotImplementedError
187 
188 
189 class LazyJSON(LJNode):
190     """Represents a lazy json file. Can be used like a normal Python
191     dict or list.
192     """
193 
194     def __init__(self, f, reopen=True):
195         """Parameters
196         ----------
197         f : file handle or str
198             JSON file to open.
199         reopen : bool, optional
200             Whether new file handle should be opened for each load.
201         """
202         self._f = f
203         self.reopen = reopen
204         if not reopen and isinstance(f, str):
205             self._f = open(f, 'r', newline='\n')
206         self._load_index()
207         self.root = weakref.proxy(self)
208         self.is_mapping = isinstance(self.offsets, abc.Mapping)
209         self.is_sequence = isinstance(self.offsets, abc.Sequence)
210 
211     def __del__(self):
212         self.close()
213 
214     def close(self):
215         """Close the file handle, if appropriate."""
216         if not self.reopen and isinstance(self._f, io.IOBase):
217             self._f.close()
218 
219     @contextlib.contextmanager
220     def _open(self, *args, **kwargs):
221         if self.reopen and isinstance(self._f, str):
222             f = open(self._f, *args, **kwargs)
223             yield f
224             f.close()
225         else:
226             yield self._f
227 
228     def _load_index(self):
229         """Loads the index from the start of the file."""
230         with self._open(newline='\n') as f:
231             # read in the location data
232             f.seek(9)
233             locs = f.read(48)
234             locs = json.loads(locs)
235             self.iloc, self.ilen, self.dloc, self.dlen = locs
236             # read in the index
237             f.seek(self.iloc)
238             idx = f.read(self.ilen)
239             idx = json.loads(idx)
240         self.offsets = idx['offsets']
241         self.sizes = idx['sizes']
242 
243     def __enter__(self):
244         return self
245 
246     def __exit__(self, exc_type, exc_value, traceback):
247         self.close()
248 
249
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/xonsh/lazyjson.py b/xonsh/lazyjson.py
--- a/xonsh/lazyjson.py
+++ b/xonsh/lazyjson.py
@@ -214,7 +214,10 @@
     def close(self):
         """Close the file handle, if appropriate."""
         if not self.reopen and isinstance(self._f, io.IOBase):
-            self._f.close()
+            try:
+                self._f.close()
+            except OSError:
+                pass
 
     @contextlib.contextmanager
     def _open(self, *args, **kwargs):

{"golden_diff": "diff --git a/xonsh/lazyjson.py b/xonsh/lazyjson.py\n--- a/xonsh/lazyjson.py\n+++ b/xonsh/lazyjson.py\n@@ -214,7 +214,10 @@\n     def close(self):\n         \"\"\"Close the file handle, if appropriate.\"\"\"\n         if not self.reopen and isinstance(self._f, io.IOBase):\n-            self._f.close()\n+            try:\n+                self._f.close()\n+            except OSError:\n+                pass\n \n     @contextlib.contextmanager\n     def _open(self, *args, **kwargs):\n", "issue": "lazyjson - OSError: Bad file descriptor\nthis issue is bothering me for too long, a bug that appears 1 out of 5 times i startup xonsh:\n\n```\n$ XONSH_DEBUG=1 python3 -m xonsh\nException ignored in: <bound method LazyJSON.__del__ of <xonsh.lazyjson.LazyJSON object at 0xb4a89fec>>\nTraceback (most recent call last):\n  File \"/home/laerus/.local/lib/python3.4/site-packages/xonsh/lazyjson.py\", line 212, in __del__\n    self.close()\n  File \"/home/laerus/.local/lib/python3.4/site-packages/xonsh/lazyjson.py\", line 217, in close\n    self._f.close()\nOSError: [Errno 9] Bad file descriptor\n```\n\nanyone else getting this? any ideas on debugging it? \n\n", "before_files": [{"content": "# -*- coding: utf-8 -*-\n\"\"\"Implements a lazy JSON file class that wraps around json data.\"\"\"\nimport io\nimport json\nimport weakref\nimport contextlib\nimport collections.abc as abc\n\n\ndef _to_json_with_size(obj, offset=0, sort_keys=False):\n    if isinstance(obj, str):\n        s = json.dumps(obj)\n        o = offset\n        n = size = len(s.encode())  # size in bytes\n    elif isinstance(obj, abc.Mapping):\n        s = '{'\n        j = offset + 1\n        o = {}\n        size = {}\n        items = sorted(obj.items()) if sort_keys else obj.items()\n        for key, val in items:\n            s_k, o_k, n_k, size_k = _to_json_with_size(key, offset=j,\n                                                       sort_keys=sort_keys)\n            s += s_k + ': '\n            j += n_k + 2\n            s_v, o_v, n_v, size_v = _to_json_with_size(val, offset=j,\n                                                       sort_keys=sort_keys)\n            o[key] = o_v\n            size[key] = size_v\n            s += s_v + ', '\n            j += n_v + 2\n        if s.endswith(', '):\n            s = s[:-2]\n        s += '}\\n'\n        n = len(s)\n        o['__total__'] = offset\n        size['__total__'] = n\n    elif isinstance(obj, abc.Sequence):\n        s = '['\n        j = offset + 1\n        o = []\n        size = []\n        for x in obj:\n            s_x, o_x, n_x, size_x = _to_json_with_size(x, offset=j,\n                                                       sort_keys=sort_keys)\n            o.append(o_x)\n            size.append(size_x)\n            s += s_x + ', '\n            j += n_x + 2\n        if s.endswith(', '):\n            s = s[:-2]\n        s += ']\\n'\n        n = len(s)\n        o.append(offset)\n        size.append(n)\n    else:\n        s = json.dumps(obj, sort_keys=sort_keys)\n        o = offset\n        n = size = len(s)\n    return s, o, n, size\n\n\ndef index(obj, sort_keys=False):\n    \"\"\"Creates an index for a JSON file.\"\"\"\n    idx = {}\n    json_obj = _to_json_with_size(obj, sort_keys=sort_keys)\n    s, idx['offsets'], _, idx['sizes'] = json_obj\n    return s, idx\n\n\nJSON_FORMAT = \\\n\"\"\"{{\"locs\": [{iloc:>10}, {ilen:>10}, {dloc:>10}, {dlen:>10}],\n \"index\": {index},\n \"data\": {data}\n}}\n\"\"\"\n\n\ndef dumps(obj, sort_keys=False):\n    \"\"\"Dumps an object to JSON with an index.\"\"\"\n    data, idx = index(obj, sort_keys=sort_keys)\n    jdx = json.dumps(idx, sort_keys=sort_keys)\n    iloc = 69\n    ilen = len(jdx)\n    dloc = iloc + ilen + 11\n    dlen = len(data)\n    s = JSON_FORMAT.format(index=jdx, data=data, iloc=iloc, ilen=ilen,\n                           dloc=dloc, dlen=dlen)\n    return s\n\n\ndef ljdump(obj, fp, sort_keys=False):\n    \"\"\"Dumps an object to JSON file.\"\"\"\n    s = dumps(obj, sort_keys=sort_keys)\n    fp.write(s)\n\n\nclass LJNode(abc.Mapping, abc.Sequence):\n    \"\"\"A proxy node for JSON nodes. Acts as both sequence and mapping.\"\"\"\n\n    def __init__(self, offsets, sizes, root):\n        \"\"\"Parameters\n        ----------\n        offsets : dict, list, or int\n            offsets of corresponding data structure, in bytes\n        sizes : dict, list, or int\n            sizes of corresponding data structure, in bytes\n        root : weakref.proxy of LazyJSON\n            weakref back to root node, which should be a LazyJSON object.\n        \"\"\"\n        self.offsets = offsets\n        self.sizes = sizes\n        self.root = root\n        self.is_mapping = isinstance(self.offsets, abc.Mapping)\n        self.is_sequence = isinstance(self.offsets, abc.Sequence)\n\n    def __len__(self):\n        # recall that for maps, the '__total__' key is added and for\n        # sequences the last element represents the total size/offset.\n        return len(self.sizes) - 1\n\n    def load(self):\n        \"\"\"Returns the Python data structure represented by the node.\"\"\"\n        if self.is_mapping:\n            offset = self.offsets['__total__']\n            size = self.sizes['__total__']\n        elif self.is_sequence:\n            offset = self.offsets[-1]\n            size = self.sizes[-1]\n        elif isinstance(self.offsets, int):\n            offset = self.offsets\n            size = self.sizes\n        return self._load_or_node(offset, size)\n\n    def _load_or_node(self, offset, size):\n        if isinstance(offset, int):\n            with self.root._open(newline='\\n') as f:\n                f.seek(self.root.dloc + offset)\n                s = f.read(size)\n            val = json.loads(s)\n        elif isinstance(offset, (abc.Mapping, abc.Sequence)):\n            val = LJNode(offset, size, self.root)\n        else:\n            raise TypeError('incorrect types for offset node')\n        return val\n\n    def _getitem_mapping(self, key):\n        if key == '__total__':\n            raise KeyError('\"__total__\" is a special LazyJSON key!')\n        offset = self.offsets[key]\n        size = self.sizes[key]\n        return self._load_or_node(offset, size)\n\n    def _getitem_sequence(self, key):\n        if isinstance(key, int):\n            rtn = self._load_or_node(self.offsets[key], self.sizes[key])\n        elif isinstance(key, slice):\n            key = slice(*key.indices(len(self)))\n            rtn = list(map(self._load_or_node, self.offsets[key],\n                           self.sizes[key]))\n        else:\n            raise TypeError('only integer indexing available')\n        return rtn\n\n    def __getitem__(self, key):\n        if self.is_mapping:\n            rtn = self._getitem_mapping(key)\n        elif self.is_sequence:\n            rtn = self._getitem_sequence(key)\n        else:\n            raise NotImplementedError\n        return rtn\n\n    def __iter__(self):\n        if self.is_mapping:\n            keys = set(self.offsets.keys())\n            keys.discard('__total__')\n            yield from iter(keys)\n        elif self.is_sequence:\n            i = 0\n            n = len(self)\n            while i < n:\n                yield self._load_or_node(self.offsets[i], self.sizes[i])\n                i += 1\n        else:\n            raise NotImplementedError\n\n\nclass LazyJSON(LJNode):\n    \"\"\"Represents a lazy json file. Can be used like a normal Python\n    dict or list.\n    \"\"\"\n\n    def __init__(self, f, reopen=True):\n        \"\"\"Parameters\n        ----------\n        f : file handle or str\n            JSON file to open.\n        reopen : bool, optional\n            Whether new file handle should be opened for each load.\n        \"\"\"\n        self._f = f\n        self.reopen = reopen\n        if not reopen and isinstance(f, str):\n            self._f = open(f, 'r', newline='\\n')\n        self._load_index()\n        self.root = weakref.proxy(self)\n        self.is_mapping = isinstance(self.offsets, abc.Mapping)\n        self.is_sequence = isinstance(self.offsets, abc.Sequence)\n\n    def __del__(self):\n        self.close()\n\n    def close(self):\n        \"\"\"Close the file handle, if appropriate.\"\"\"\n        if not self.reopen and isinstance(self._f, io.IOBase):\n            self._f.close()\n\n    @contextlib.contextmanager\n    def _open(self, *args, **kwargs):\n        if self.reopen and isinstance(self._f, str):\n            f = open(self._f, *args, **kwargs)\n            yield f\n            f.close()\n        else:\n            yield self._f\n\n    def _load_index(self):\n        \"\"\"Loads the index from the start of the file.\"\"\"\n        with self._open(newline='\\n') as f:\n            # read in the location data\n            f.seek(9)\n            locs = f.read(48)\n            locs = json.loads(locs)\n            self.iloc, self.ilen, self.dloc, self.dlen = locs\n            # read in the index\n            f.seek(self.iloc)\n            idx = f.read(self.ilen)\n            idx = json.loads(idx)\n        self.offsets = idx['offsets']\n        self.sizes = idx['sizes']\n\n    def __enter__(self):\n        return self\n\n    def __exit__(self, exc_type, exc_value, traceback):\n        self.close()\n\n", "path": "xonsh/lazyjson.py"}], "after_files": [{"content": "# -*- coding: utf-8 -*-\n\"\"\"Implements a lazy JSON file class that wraps around json data.\"\"\"\nimport io\nimport json\nimport weakref\nimport contextlib\nimport collections.abc as abc\n\n\ndef _to_json_with_size(obj, offset=0, sort_keys=False):\n    if isinstance(obj, str):\n        s = json.dumps(obj)\n        o = offset\n        n = size = len(s.encode())  # size in bytes\n    elif isinstance(obj, abc.Mapping):\n        s = '{'\n        j = offset + 1\n        o = {}\n        size = {}\n        items = sorted(obj.items()) if sort_keys else obj.items()\n        for key, val in items:\n            s_k, o_k, n_k, size_k = _to_json_with_size(key, offset=j,\n                                                       sort_keys=sort_keys)\n            s += s_k + ': '\n            j += n_k + 2\n            s_v, o_v, n_v, size_v = _to_json_with_size(val, offset=j,\n                                                       sort_keys=sort_keys)\n            o[key] = o_v\n            size[key] = size_v\n            s += s_v + ', '\n            j += n_v + 2\n        if s.endswith(', '):\n            s = s[:-2]\n        s += '}\\n'\n        n = len(s)\n        o['__total__'] = offset\n        size['__total__'] = n\n    elif isinstance(obj, abc.Sequence):\n        s = '['\n        j = offset + 1\n        o = []\n        size = []\n        for x in obj:\n            s_x, o_x, n_x, size_x = _to_json_with_size(x, offset=j,\n                                                       sort_keys=sort_keys)\n            o.append(o_x)\n            size.append(size_x)\n            s += s_x + ', '\n            j += n_x + 2\n        if s.endswith(', '):\n            s = s[:-2]\n        s += ']\\n'\n        n = len(s)\n        o.append(offset)\n        size.append(n)\n    else:\n        s = json.dumps(obj, sort_keys=sort_keys)\n        o = offset\n        n = size = len(s)\n    return s, o, n, size\n\n\ndef index(obj, sort_keys=False):\n    \"\"\"Creates an index for a JSON file.\"\"\"\n    idx = {}\n    json_obj = _to_json_with_size(obj, sort_keys=sort_keys)\n    s, idx['offsets'], _, idx['sizes'] = json_obj\n    return s, idx\n\n\nJSON_FORMAT = \\\n\"\"\"{{\"locs\": [{iloc:>10}, {ilen:>10}, {dloc:>10}, {dlen:>10}],\n \"index\": {index},\n \"data\": {data}\n}}\n\"\"\"\n\n\ndef dumps(obj, sort_keys=False):\n    \"\"\"Dumps an object to JSON with an index.\"\"\"\n    data, idx = index(obj, sort_keys=sort_keys)\n    jdx = json.dumps(idx, sort_keys=sort_keys)\n    iloc = 69\n    ilen = len(jdx)\n    dloc = iloc + ilen + 11\n    dlen = len(data)\n    s = JSON_FORMAT.format(index=jdx, data=data, iloc=iloc, ilen=ilen,\n                           dloc=dloc, dlen=dlen)\n    return s\n\n\ndef ljdump(obj, fp, sort_keys=False):\n    \"\"\"Dumps an object to JSON file.\"\"\"\n    s = dumps(obj, sort_keys=sort_keys)\n    fp.write(s)\n\n\nclass LJNode(abc.Mapping, abc.Sequence):\n    \"\"\"A proxy node for JSON nodes. Acts as both sequence and mapping.\"\"\"\n\n    def __init__(self, offsets, sizes, root):\n        \"\"\"Parameters\n        ----------\n        offsets : dict, list, or int\n            offsets of corresponding data structure, in bytes\n        sizes : dict, list, or int\n            sizes of corresponding data structure, in bytes\n        root : weakref.proxy of LazyJSON\n            weakref back to root node, which should be a LazyJSON object.\n        \"\"\"\n        self.offsets = offsets\n        self.sizes = sizes\n        self.root = root\n        self.is_mapping = isinstance(self.offsets, abc.Mapping)\n        self.is_sequence = isinstance(self.offsets, abc.Sequence)\n\n    def __len__(self):\n        # recall that for maps, the '__total__' key is added and for\n        # sequences the last element represents the total size/offset.\n        return len(self.sizes) - 1\n\n    def load(self):\n        \"\"\"Returns the Python data structure represented by the node.\"\"\"\n        if self.is_mapping:\n            offset = self.offsets['__total__']\n            size = self.sizes['__total__']\n        elif self.is_sequence:\n            offset = self.offsets[-1]\n            size = self.sizes[-1]\n        elif isinstance(self.offsets, int):\n            offset = self.offsets\n            size = self.sizes\n        return self._load_or_node(offset, size)\n\n    def _load_or_node(self, offset, size):\n        if isinstance(offset, int):\n            with self.root._open(newline='\\n') as f:\n                f.seek(self.root.dloc + offset)\n                s = f.read(size)\n            val = json.loads(s)\n        elif isinstance(offset, (abc.Mapping, abc.Sequence)):\n            val = LJNode(offset, size, self.root)\n        else:\n            raise TypeError('incorrect types for offset node')\n        return val\n\n    def _getitem_mapping(self, key):\n        if key == '__total__':\n            raise KeyError('\"__total__\" is a special LazyJSON key!')\n        offset = self.offsets[key]\n        size = self.sizes[key]\n        return self._load_or_node(offset, size)\n\n    def _getitem_sequence(self, key):\n        if isinstance(key, int):\n            rtn = self._load_or_node(self.offsets[key], self.sizes[key])\n        elif isinstance(key, slice):\n            key = slice(*key.indices(len(self)))\n            rtn = list(map(self._load_or_node, self.offsets[key],\n                           self.sizes[key]))\n        else:\n            raise TypeError('only integer indexing available')\n        return rtn\n\n    def __getitem__(self, key):\n        if self.is_mapping:\n            rtn = self._getitem_mapping(key)\n        elif self.is_sequence:\n            rtn = self._getitem_sequence(key)\n        else:\n            raise NotImplementedError\n        return rtn\n\n    def __iter__(self):\n        if self.is_mapping:\n            keys = set(self.offsets.keys())\n            keys.discard('__total__')\n            yield from iter(keys)\n        elif self.is_sequence:\n            i = 0\n            n = len(self)\n            while i < n:\n                yield self._load_or_node(self.offsets[i], self.sizes[i])\n                i += 1\n        else:\n            raise NotImplementedError\n\n\nclass LazyJSON(LJNode):\n    \"\"\"Represents a lazy json file. Can be used like a normal Python\n    dict or list.\n    \"\"\"\n\n    def __init__(self, f, reopen=True):\n        \"\"\"Parameters\n        ----------\n        f : file handle or str\n            JSON file to open.\n        reopen : bool, optional\n            Whether new file handle should be opened for each load.\n        \"\"\"\n        self._f = f\n        self.reopen = reopen\n        if not reopen and isinstance(f, str):\n            self._f = open(f, 'r', newline='\\n')\n        self._load_index()\n        self.root = weakref.proxy(self)\n        self.is_mapping = isinstance(self.offsets, abc.Mapping)\n        self.is_sequence = isinstance(self.offsets, abc.Sequence)\n\n    def __del__(self):\n        self.close()\n\n    def close(self):\n        \"\"\"Close the file handle, if appropriate.\"\"\"\n        if not self.reopen and isinstance(self._f, io.IOBase):\n            try:\n                self._f.close()\n            except OSError:\n                pass\n\n    @contextlib.contextmanager\n    def _open(self, *args, **kwargs):\n        if self.reopen and isinstance(self._f, str):\n            f = open(self._f, *args, **kwargs)\n            yield f\n            f.close()\n        else:\n            yield self._f\n\n    def _load_index(self):\n        \"\"\"Loads the index from the start of the file.\"\"\"\n        with self._open(newline='\\n') as f:\n            # read in the location data\n            f.seek(9)\n            locs = f.read(48)\n            locs = json.loads(locs)\n            self.iloc, self.ilen, self.dloc, self.dlen = locs\n            # read in the index\n            f.seek(self.iloc)\n            idx = f.read(self.ilen)\n            idx = json.loads(idx)\n        self.offsets = idx['offsets']\n        self.sizes = idx['sizes']\n\n    def __enter__(self):\n        return self\n\n    def __exit__(self, exc_type, exc_value, traceback):\n        self.close()\n\n", "path": "xonsh/lazyjson.py"}]}