We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
(PYL-W0102) Dangerous default argument
## Description
Mutable Default Arguments: https://docs.python-guide.org/writing/gotchas/

Do not use a mutable like `list` or `dictionary` as a default value to an argument. Python’s default arguments are evaluated once when the function is defined. Using a mutable default argument and mutating it will mutate that object for all future calls to the function as well.

## Occurrences
There are 23 occurrences of this issue in the repository.

See all occurrences on DeepSource &rarr; [deepsource.io/gh/HarshCasper/openlibrary-1/issue/PYL-W0102/occurrences/](https://deepsource.io/gh/HarshCasper/openlibrary-1/issue/PYL-W0102/occurrences/)


--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `openlibrary/plugins/upstream/adapter.py`
Content:
```
1 """Adapter to provide upstream URL structure over existing Open Library Infobase interface.
2 
3 Upstream requires:
4 
5     /user/.* -> /people/.*
6     /b/.* -> /books/.*
7     /a/.* -> /authors/.*
8 
9 This adapter module is a filter that sits above an Infobase server and fakes the new URL structure.
10 """
11 import simplejson
12 import web
13 
14 import six
15 from six.moves import urllib
16 
17 
18 urls = (
19     '/([^/]*)/get', 'get',
20     '/([^/]*)/get_many', 'get_many',
21     '/([^/]*)/things', 'things',
22     '/([^/]*)/versions', 'versions',
23     '/([^/]*)/new_key', 'new_key',
24     '/([^/]*)/save(/.*)', 'save',
25     '/([^/]*)/save_many', 'save_many',
26     '/([^/]*)/reindex', 'reindex',
27     '/([^/]*)/account/(.*)', 'account',
28     '/([^/]*)/count_edits_by_user', 'count_edits_by_user',
29     '/.*', 'proxy'
30 )
31 app = web.application(urls, globals())
32 
33 convertions = {
34 #    '/people/': '/user/',
35 #    '/books/': '/b/',
36 #    '/authors/': '/a/',
37 #    '/languages/': '/l/',
38     '/templates/': '/upstream/templates/',
39     '/macros/': '/upstream/macros/',
40     '/js/': '/upstream/js/',
41     '/css/': '/upstream/css/',
42     '/old/templates/': '/templates/',
43     '/old/macros/': '/macros/',
44     '/old/js/': '/js/',
45     '/old/css/': '/css/',
46 }
47 
48 # inverse of convertions
49 iconversions = dict((v, k) for k, v in convertions.items())
50 
51 class proxy:
52     def delegate(self, *args):
53         self.args = args
54         self.input = web.input(_method='GET', _unicode=False)
55         self.path = web.ctx.path
56 
57         if web.ctx.method in ['POST', 'PUT']:
58             self.data = web.data()
59         else:
60             self.data = None
61 
62         headers = dict((k[len('HTTP_'):].replace('-', '_').lower(), v) for k, v in web.ctx.environ.items())
63 
64         self.before_request()
65         try:
66             server = web.config.infobase_server
67             req = urllib.request.Request(server + self.path + '?' + urllib.parse.urlencode(self.input), self.data, headers=headers)
68             req.get_method = lambda: web.ctx.method
69             response = urllib.request.urlopen(req)
70         except urllib.error.HTTPError as e:
71             response = e
72         self.status_code = response.code
73         self.status_msg = response.msg
74         self.output = response.read()
75 
76         self.headers = dict(response.headers.items())
77         for k in ['transfer-encoding', 'server', 'connection', 'date']:
78             self.headers.pop(k, None)
79 
80         if self.status_code == 200:
81             self.after_request()
82         else:
83             self.process_error()
84 
85         web.ctx.status = "%s %s" % (self.status_code, self.status_msg)
86         web.ctx.headers = self.headers.items()
87         return self.output
88 
89     GET = POST = PUT = DELETE = delegate
90 
91     def before_request(self):
92         if 'key' in self.input:
93             self.input.key = convert_key(self.input.key)
94 
95     def after_request(self):
96         if self.output:
97             d = simplejson.loads(self.output)
98             d = unconvert_dict(d)
99             self.output = simplejson.dumps(d)
100 
101     def process_error(self):
102         if self.output:
103             d = simplejson.loads(self.output)
104             if 'key' in d:
105                 d['key'] = unconvert_key(d['key'])
106             self.output = simplejson.dumps(d)
107 
108 def convert_key(key, mapping=convertions):
109     """
110         >>> convert_key("/authors/OL1A", {'/authors/': '/a/'})
111         '/a/OL1A'
112     """
113     if key is None:
114         return None
115     elif key == '/':
116         return '/upstream'
117 
118     for new, old in mapping.items():
119         if key.startswith(new):
120             key2 = old + key[len(new):]
121             return key2
122     return key
123 
124 def convert_dict(d, mapping=convertions):
125     """
126         >>> convert_dict({'author': {'key': '/authors/OL1A'}}, {'/authors/': '/a/'})
127         {'author': {'key': '/a/OL1A'}}
128     """
129     if isinstance(d, dict):
130         if 'key' in d:
131             d['key'] = convert_key(d['key'], mapping)
132         for k, v in d.items():
133             d[k] = convert_dict(v, mapping)
134         return d
135     elif isinstance(d, list):
136         return [convert_dict(x, mapping) for x in d]
137     else:
138         return d
139 
140 def unconvert_key(key):
141     if key == '/upstream':
142         return '/'
143     return convert_key(key, iconversions)
144 
145 def unconvert_dict(d):
146     return convert_dict(d, iconversions)
147 
148 class get(proxy):
149     def before_request(self):
150         i = self.input
151         if 'key' in i:
152             i.key = convert_key(i.key)
153 
154 class get_many(proxy):
155     def before_request(self):
156         if 'keys' in self.input:
157             keys = self.input['keys']
158             keys = simplejson.loads(keys)
159             keys = [convert_key(k) for k in keys]
160             self.input['keys'] = simplejson.dumps(keys)
161 
162     def after_request(self):
163         d = simplejson.loads(self.output)
164         d = dict((unconvert_key(k), unconvert_dict(v)) for k, v in d.items())
165         self.output = simplejson.dumps(d)
166 
167 class things(proxy):
168     def before_request(self):
169         if 'query' in self.input:
170             q = self.input.query
171             q = simplejson.loads(q)
172 
173             def convert_keys(q):
174                 if isinstance(q, dict):
175                     return dict((k, convert_keys(v)) for k, v in q.items())
176                 elif isinstance(q, list):
177                     return [convert_keys(x) for x in q]
178                 elif isinstance(q, six.string_types):
179                     return convert_key(q)
180                 else:
181                     return q
182             self.input.query = simplejson.dumps(convert_keys(q))
183 
184     def after_request(self):
185         if self.output:
186             d = simplejson.loads(self.output)
187 
188             if self.input.get('details', '').lower() == 'true':
189                 d = unconvert_dict(d)
190             else:
191                 d = [unconvert_key(key) for key in d]
192 
193             self.output = simplejson.dumps(d)
194 
195 class versions(proxy):
196     def before_request(self):
197         if 'query' in self.input:
198             q = self.input.query
199             q = simplejson.loads(q)
200             if 'key' in q:
201                 q['key'] = convert_key(q['key'])
202             if 'author' in q:
203                 q['author'] = convert_key(q['author'])
204             self.input.query = simplejson.dumps(q)
205 
206     def after_request(self):
207         if self.output:
208             d = simplejson.loads(self.output)
209             for v in d:
210                 v['author'] = v['author'] and unconvert_key(v['author'])
211                 v['key'] = unconvert_key(v['key'])
212             self.output = simplejson.dumps(d)
213 
214 class new_key(proxy):
215     def after_request(self):
216         if self.output:
217             d = simplejson.loads(self.output)
218             d = unconvert_key(d)
219             self.output = simplejson.dumps(d)
220 
221 class save(proxy):
222     def before_request(self):
223         self.path = '/%s/save%s' % (self.args[0], convert_key(self.args[1]))
224         d = simplejson.loads(self.data)
225         d = convert_dict(d)
226         self.data = simplejson.dumps(d)
227 
228 class save_many(proxy):
229     def before_request(self):
230         i = web.input(_method="POST")
231         if 'query' in i:
232             q = simplejson.loads(i['query'])
233             q = convert_dict(q)
234             i['query'] = simplejson.dumps(q)
235             self.data = urllib.parse.urlencode(i)
236 
237 class reindex(proxy):
238     def before_request(self):
239         i = web.input(_method="POST")
240         if 'keys' in i:
241             keys = [convert_key(k) for k in simplejson.loads(i['keys'])]
242             i['keys'] = simplejson.dumps(keys)
243             self.data = urllib.parse.urlencode(i)
244 
245 class account(proxy):
246     def before_request(self):
247         i = self.input
248         if 'username' in i and i.username.startswith('/'):
249             i.username = convert_key(i.username)
250 
251 def main():
252     import sys
253     import os
254     web.config.infobase_server = sys.argv[1].rstrip('/')
255     os.environ['REAL_SCRIPT_NAME'] = ''
256 
257     sys.argv[1:] = sys.argv[2:]
258     app.run()
259 
260 if __name__ == '__main__':
261     main()
262
```
--- 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/openlibrary/plugins/upstream/adapter.py b/openlibrary/plugins/upstream/adapter.py
--- a/openlibrary/plugins/upstream/adapter.py
+++ b/openlibrary/plugins/upstream/adapter.py
@@ -105,11 +105,13 @@
                 d['key'] = unconvert_key(d['key'])
             self.output = simplejson.dumps(d)
 
-def convert_key(key, mapping=convertions):
+
+def convert_key(key, mapping=None):
     """
         >>> convert_key("/authors/OL1A", {'/authors/': '/a/'})
         '/a/OL1A'
     """
+    mapping = mapping or convertions
     if key is None:
         return None
     elif key == '/':
@@ -121,11 +123,13 @@
             return key2
     return key
 
-def convert_dict(d, mapping=convertions):
+
+def convert_dict(d, mapping=None):
     """
         >>> convert_dict({'author': {'key': '/authors/OL1A'}}, {'/authors/': '/a/'})
         {'author': {'key': '/a/OL1A'}}
     """
+    mapping = mapping or convertions
     if isinstance(d, dict):
         if 'key' in d:
             d['key'] = convert_key(d['key'], mapping)

{"golden_diff": "diff --git a/openlibrary/plugins/upstream/adapter.py b/openlibrary/plugins/upstream/adapter.py\n--- a/openlibrary/plugins/upstream/adapter.py\n+++ b/openlibrary/plugins/upstream/adapter.py\n@@ -105,11 +105,13 @@\n                 d['key'] = unconvert_key(d['key'])\n             self.output = simplejson.dumps(d)\n \n-def convert_key(key, mapping=convertions):\n+\n+def convert_key(key, mapping=None):\n     \"\"\"\n         >>> convert_key(\"/authors/OL1A\", {'/authors/': '/a/'})\n         '/a/OL1A'\n     \"\"\"\n+    mapping = mapping or convertions\n     if key is None:\n         return None\n     elif key == '/':\n@@ -121,11 +123,13 @@\n             return key2\n     return key\n \n-def convert_dict(d, mapping=convertions):\n+\n+def convert_dict(d, mapping=None):\n     \"\"\"\n         >>> convert_dict({'author': {'key': '/authors/OL1A'}}, {'/authors/': '/a/'})\n         {'author': {'key': '/a/OL1A'}}\n     \"\"\"\n+    mapping = mapping or convertions\n     if isinstance(d, dict):\n         if 'key' in d:\n             d['key'] = convert_key(d['key'], mapping)\n", "issue": "(PYL-W0102) Dangerous default argument\n## Description\r\nMutable Default Arguments: https://docs.python-guide.org/writing/gotchas/\r\n\r\nDo not use a mutable like `list` or `dictionary` as a default value to an argument. Python\u2019s default arguments are evaluated once when the function is defined. Using a mutable default argument and mutating it will mutate that object for all future calls to the function as well.\r\n\r\n## Occurrences\r\nThere are 23 occurrences of this issue in the repository.\r\n\r\nSee all occurrences on DeepSource &rarr; [deepsource.io/gh/HarshCasper/openlibrary-1/issue/PYL-W0102/occurrences/](https://deepsource.io/gh/HarshCasper/openlibrary-1/issue/PYL-W0102/occurrences/)\r\n\n", "before_files": [{"content": "\"\"\"Adapter to provide upstream URL structure over existing Open Library Infobase interface.\n\nUpstream requires:\n\n    /user/.* -> /people/.*\n    /b/.* -> /books/.*\n    /a/.* -> /authors/.*\n\nThis adapter module is a filter that sits above an Infobase server and fakes the new URL structure.\n\"\"\"\nimport simplejson\nimport web\n\nimport six\nfrom six.moves import urllib\n\n\nurls = (\n    '/([^/]*)/get', 'get',\n    '/([^/]*)/get_many', 'get_many',\n    '/([^/]*)/things', 'things',\n    '/([^/]*)/versions', 'versions',\n    '/([^/]*)/new_key', 'new_key',\n    '/([^/]*)/save(/.*)', 'save',\n    '/([^/]*)/save_many', 'save_many',\n    '/([^/]*)/reindex', 'reindex',\n    '/([^/]*)/account/(.*)', 'account',\n    '/([^/]*)/count_edits_by_user', 'count_edits_by_user',\n    '/.*', 'proxy'\n)\napp = web.application(urls, globals())\n\nconvertions = {\n#    '/people/': '/user/',\n#    '/books/': '/b/',\n#    '/authors/': '/a/',\n#    '/languages/': '/l/',\n    '/templates/': '/upstream/templates/',\n    '/macros/': '/upstream/macros/',\n    '/js/': '/upstream/js/',\n    '/css/': '/upstream/css/',\n    '/old/templates/': '/templates/',\n    '/old/macros/': '/macros/',\n    '/old/js/': '/js/',\n    '/old/css/': '/css/',\n}\n\n# inverse of convertions\niconversions = dict((v, k) for k, v in convertions.items())\n\nclass proxy:\n    def delegate(self, *args):\n        self.args = args\n        self.input = web.input(_method='GET', _unicode=False)\n        self.path = web.ctx.path\n\n        if web.ctx.method in ['POST', 'PUT']:\n            self.data = web.data()\n        else:\n            self.data = None\n\n        headers = dict((k[len('HTTP_'):].replace('-', '_').lower(), v) for k, v in web.ctx.environ.items())\n\n        self.before_request()\n        try:\n            server = web.config.infobase_server\n            req = urllib.request.Request(server + self.path + '?' + urllib.parse.urlencode(self.input), self.data, headers=headers)\n            req.get_method = lambda: web.ctx.method\n            response = urllib.request.urlopen(req)\n        except urllib.error.HTTPError as e:\n            response = e\n        self.status_code = response.code\n        self.status_msg = response.msg\n        self.output = response.read()\n\n        self.headers = dict(response.headers.items())\n        for k in ['transfer-encoding', 'server', 'connection', 'date']:\n            self.headers.pop(k, None)\n\n        if self.status_code == 200:\n            self.after_request()\n        else:\n            self.process_error()\n\n        web.ctx.status = \"%s %s\" % (self.status_code, self.status_msg)\n        web.ctx.headers = self.headers.items()\n        return self.output\n\n    GET = POST = PUT = DELETE = delegate\n\n    def before_request(self):\n        if 'key' in self.input:\n            self.input.key = convert_key(self.input.key)\n\n    def after_request(self):\n        if self.output:\n            d = simplejson.loads(self.output)\n            d = unconvert_dict(d)\n            self.output = simplejson.dumps(d)\n\n    def process_error(self):\n        if self.output:\n            d = simplejson.loads(self.output)\n            if 'key' in d:\n                d['key'] = unconvert_key(d['key'])\n            self.output = simplejson.dumps(d)\n\ndef convert_key(key, mapping=convertions):\n    \"\"\"\n        >>> convert_key(\"/authors/OL1A\", {'/authors/': '/a/'})\n        '/a/OL1A'\n    \"\"\"\n    if key is None:\n        return None\n    elif key == '/':\n        return '/upstream'\n\n    for new, old in mapping.items():\n        if key.startswith(new):\n            key2 = old + key[len(new):]\n            return key2\n    return key\n\ndef convert_dict(d, mapping=convertions):\n    \"\"\"\n        >>> convert_dict({'author': {'key': '/authors/OL1A'}}, {'/authors/': '/a/'})\n        {'author': {'key': '/a/OL1A'}}\n    \"\"\"\n    if isinstance(d, dict):\n        if 'key' in d:\n            d['key'] = convert_key(d['key'], mapping)\n        for k, v in d.items():\n            d[k] = convert_dict(v, mapping)\n        return d\n    elif isinstance(d, list):\n        return [convert_dict(x, mapping) for x in d]\n    else:\n        return d\n\ndef unconvert_key(key):\n    if key == '/upstream':\n        return '/'\n    return convert_key(key, iconversions)\n\ndef unconvert_dict(d):\n    return convert_dict(d, iconversions)\n\nclass get(proxy):\n    def before_request(self):\n        i = self.input\n        if 'key' in i:\n            i.key = convert_key(i.key)\n\nclass get_many(proxy):\n    def before_request(self):\n        if 'keys' in self.input:\n            keys = self.input['keys']\n            keys = simplejson.loads(keys)\n            keys = [convert_key(k) for k in keys]\n            self.input['keys'] = simplejson.dumps(keys)\n\n    def after_request(self):\n        d = simplejson.loads(self.output)\n        d = dict((unconvert_key(k), unconvert_dict(v)) for k, v in d.items())\n        self.output = simplejson.dumps(d)\n\nclass things(proxy):\n    def before_request(self):\n        if 'query' in self.input:\n            q = self.input.query\n            q = simplejson.loads(q)\n\n            def convert_keys(q):\n                if isinstance(q, dict):\n                    return dict((k, convert_keys(v)) for k, v in q.items())\n                elif isinstance(q, list):\n                    return [convert_keys(x) for x in q]\n                elif isinstance(q, six.string_types):\n                    return convert_key(q)\n                else:\n                    return q\n            self.input.query = simplejson.dumps(convert_keys(q))\n\n    def after_request(self):\n        if self.output:\n            d = simplejson.loads(self.output)\n\n            if self.input.get('details', '').lower() == 'true':\n                d = unconvert_dict(d)\n            else:\n                d = [unconvert_key(key) for key in d]\n\n            self.output = simplejson.dumps(d)\n\nclass versions(proxy):\n    def before_request(self):\n        if 'query' in self.input:\n            q = self.input.query\n            q = simplejson.loads(q)\n            if 'key' in q:\n                q['key'] = convert_key(q['key'])\n            if 'author' in q:\n                q['author'] = convert_key(q['author'])\n            self.input.query = simplejson.dumps(q)\n\n    def after_request(self):\n        if self.output:\n            d = simplejson.loads(self.output)\n            for v in d:\n                v['author'] = v['author'] and unconvert_key(v['author'])\n                v['key'] = unconvert_key(v['key'])\n            self.output = simplejson.dumps(d)\n\nclass new_key(proxy):\n    def after_request(self):\n        if self.output:\n            d = simplejson.loads(self.output)\n            d = unconvert_key(d)\n            self.output = simplejson.dumps(d)\n\nclass save(proxy):\n    def before_request(self):\n        self.path = '/%s/save%s' % (self.args[0], convert_key(self.args[1]))\n        d = simplejson.loads(self.data)\n        d = convert_dict(d)\n        self.data = simplejson.dumps(d)\n\nclass save_many(proxy):\n    def before_request(self):\n        i = web.input(_method=\"POST\")\n        if 'query' in i:\n            q = simplejson.loads(i['query'])\n            q = convert_dict(q)\n            i['query'] = simplejson.dumps(q)\n            self.data = urllib.parse.urlencode(i)\n\nclass reindex(proxy):\n    def before_request(self):\n        i = web.input(_method=\"POST\")\n        if 'keys' in i:\n            keys = [convert_key(k) for k in simplejson.loads(i['keys'])]\n            i['keys'] = simplejson.dumps(keys)\n            self.data = urllib.parse.urlencode(i)\n\nclass account(proxy):\n    def before_request(self):\n        i = self.input\n        if 'username' in i and i.username.startswith('/'):\n            i.username = convert_key(i.username)\n\ndef main():\n    import sys\n    import os\n    web.config.infobase_server = sys.argv[1].rstrip('/')\n    os.environ['REAL_SCRIPT_NAME'] = ''\n\n    sys.argv[1:] = sys.argv[2:]\n    app.run()\n\nif __name__ == '__main__':\n    main()\n", "path": "openlibrary/plugins/upstream/adapter.py"}], "after_files": [{"content": "\"\"\"Adapter to provide upstream URL structure over existing Open Library Infobase interface.\n\nUpstream requires:\n\n    /user/.* -> /people/.*\n    /b/.* -> /books/.*\n    /a/.* -> /authors/.*\n\nThis adapter module is a filter that sits above an Infobase server and fakes the new URL structure.\n\"\"\"\nimport simplejson\nimport web\n\nimport six\nfrom six.moves import urllib\n\n\nurls = (\n    '/([^/]*)/get', 'get',\n    '/([^/]*)/get_many', 'get_many',\n    '/([^/]*)/things', 'things',\n    '/([^/]*)/versions', 'versions',\n    '/([^/]*)/new_key', 'new_key',\n    '/([^/]*)/save(/.*)', 'save',\n    '/([^/]*)/save_many', 'save_many',\n    '/([^/]*)/reindex', 'reindex',\n    '/([^/]*)/account/(.*)', 'account',\n    '/([^/]*)/count_edits_by_user', 'count_edits_by_user',\n    '/.*', 'proxy'\n)\napp = web.application(urls, globals())\n\nconvertions = {\n#    '/people/': '/user/',\n#    '/books/': '/b/',\n#    '/authors/': '/a/',\n#    '/languages/': '/l/',\n    '/templates/': '/upstream/templates/',\n    '/macros/': '/upstream/macros/',\n    '/js/': '/upstream/js/',\n    '/css/': '/upstream/css/',\n    '/old/templates/': '/templates/',\n    '/old/macros/': '/macros/',\n    '/old/js/': '/js/',\n    '/old/css/': '/css/',\n}\n\n# inverse of convertions\niconversions = dict((v, k) for k, v in convertions.items())\n\nclass proxy:\n    def delegate(self, *args):\n        self.args = args\n        self.input = web.input(_method='GET', _unicode=False)\n        self.path = web.ctx.path\n\n        if web.ctx.method in ['POST', 'PUT']:\n            self.data = web.data()\n        else:\n            self.data = None\n\n        headers = dict((k[len('HTTP_'):].replace('-', '_').lower(), v) for k, v in web.ctx.environ.items())\n\n        self.before_request()\n        try:\n            server = web.config.infobase_server\n            req = urllib.request.Request(server + self.path + '?' + urllib.parse.urlencode(self.input), self.data, headers=headers)\n            req.get_method = lambda: web.ctx.method\n            response = urllib.request.urlopen(req)\n        except urllib.error.HTTPError as e:\n            response = e\n        self.status_code = response.code\n        self.status_msg = response.msg\n        self.output = response.read()\n\n        self.headers = dict(response.headers.items())\n        for k in ['transfer-encoding', 'server', 'connection', 'date']:\n            self.headers.pop(k, None)\n\n        if self.status_code == 200:\n            self.after_request()\n        else:\n            self.process_error()\n\n        web.ctx.status = \"%s %s\" % (self.status_code, self.status_msg)\n        web.ctx.headers = self.headers.items()\n        return self.output\n\n    GET = POST = PUT = DELETE = delegate\n\n    def before_request(self):\n        if 'key' in self.input:\n            self.input.key = convert_key(self.input.key)\n\n    def after_request(self):\n        if self.output:\n            d = simplejson.loads(self.output)\n            d = unconvert_dict(d)\n            self.output = simplejson.dumps(d)\n\n    def process_error(self):\n        if self.output:\n            d = simplejson.loads(self.output)\n            if 'key' in d:\n                d['key'] = unconvert_key(d['key'])\n            self.output = simplejson.dumps(d)\n\n\ndef convert_key(key, mapping=None):\n    \"\"\"\n        >>> convert_key(\"/authors/OL1A\", {'/authors/': '/a/'})\n        '/a/OL1A'\n    \"\"\"\n    mapping = mapping or convertions\n    if key is None:\n        return None\n    elif key == '/':\n        return '/upstream'\n\n    for new, old in mapping.items():\n        if key.startswith(new):\n            key2 = old + key[len(new):]\n            return key2\n    return key\n\n\ndef convert_dict(d, mapping=None):\n    \"\"\"\n        >>> convert_dict({'author': {'key': '/authors/OL1A'}}, {'/authors/': '/a/'})\n        {'author': {'key': '/a/OL1A'}}\n    \"\"\"\n    mapping = mapping or convertions\n    if isinstance(d, dict):\n        if 'key' in d:\n            d['key'] = convert_key(d['key'], mapping)\n        for k, v in d.items():\n            d[k] = convert_dict(v, mapping)\n        return d\n    elif isinstance(d, list):\n        return [convert_dict(x, mapping) for x in d]\n    else:\n        return d\n\ndef unconvert_key(key):\n    if key == '/upstream':\n        return '/'\n    return convert_key(key, iconversions)\n\ndef unconvert_dict(d):\n    return convert_dict(d, iconversions)\n\nclass get(proxy):\n    def before_request(self):\n        i = self.input\n        if 'key' in i:\n            i.key = convert_key(i.key)\n\nclass get_many(proxy):\n    def before_request(self):\n        if 'keys' in self.input:\n            keys = self.input['keys']\n            keys = simplejson.loads(keys)\n            keys = [convert_key(k) for k in keys]\n            self.input['keys'] = simplejson.dumps(keys)\n\n    def after_request(self):\n        d = simplejson.loads(self.output)\n        d = dict((unconvert_key(k), unconvert_dict(v)) for k, v in d.items())\n        self.output = simplejson.dumps(d)\n\nclass things(proxy):\n    def before_request(self):\n        if 'query' in self.input:\n            q = self.input.query\n            q = simplejson.loads(q)\n\n            def convert_keys(q):\n                if isinstance(q, dict):\n                    return dict((k, convert_keys(v)) for k, v in q.items())\n                elif isinstance(q, list):\n                    return [convert_keys(x) for x in q]\n                elif isinstance(q, six.string_types):\n                    return convert_key(q)\n                else:\n                    return q\n            self.input.query = simplejson.dumps(convert_keys(q))\n\n    def after_request(self):\n        if self.output:\n            d = simplejson.loads(self.output)\n\n            if self.input.get('details', '').lower() == 'true':\n                d = unconvert_dict(d)\n            else:\n                d = [unconvert_key(key) for key in d]\n\n            self.output = simplejson.dumps(d)\n\nclass versions(proxy):\n    def before_request(self):\n        if 'query' in self.input:\n            q = self.input.query\n            q = simplejson.loads(q)\n            if 'key' in q:\n                q['key'] = convert_key(q['key'])\n            if 'author' in q:\n                q['author'] = convert_key(q['author'])\n            self.input.query = simplejson.dumps(q)\n\n    def after_request(self):\n        if self.output:\n            d = simplejson.loads(self.output)\n            for v in d:\n                v['author'] = v['author'] and unconvert_key(v['author'])\n                v['key'] = unconvert_key(v['key'])\n            self.output = simplejson.dumps(d)\n\nclass new_key(proxy):\n    def after_request(self):\n        if self.output:\n            d = simplejson.loads(self.output)\n            d = unconvert_key(d)\n            self.output = simplejson.dumps(d)\n\nclass save(proxy):\n    def before_request(self):\n        self.path = '/%s/save%s' % (self.args[0], convert_key(self.args[1]))\n        d = simplejson.loads(self.data)\n        d = convert_dict(d)\n        self.data = simplejson.dumps(d)\n\nclass save_many(proxy):\n    def before_request(self):\n        i = web.input(_method=\"POST\")\n        if 'query' in i:\n            q = simplejson.loads(i['query'])\n            q = convert_dict(q)\n            i['query'] = simplejson.dumps(q)\n            self.data = urllib.parse.urlencode(i)\n\nclass reindex(proxy):\n    def before_request(self):\n        i = web.input(_method=\"POST\")\n        if 'keys' in i:\n            keys = [convert_key(k) for k in simplejson.loads(i['keys'])]\n            i['keys'] = simplejson.dumps(keys)\n            self.data = urllib.parse.urlencode(i)\n\nclass account(proxy):\n    def before_request(self):\n        i = self.input\n        if 'username' in i and i.username.startswith('/'):\n            i.username = convert_key(i.username)\n\ndef main():\n    import sys\n    import os\n    web.config.infobase_server = sys.argv[1].rstrip('/')\n    os.environ['REAL_SCRIPT_NAME'] = ''\n\n    sys.argv[1:] = sys.argv[2:]\n    app.run()\n\nif __name__ == '__main__':\n    main()\n", "path": "openlibrary/plugins/upstream/adapter.py"}]}