We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Deprecation of oauth2client dependency
According to the readme google/oauth2client is deprecated. They suggest switching to [google-auth](https://google-auth.readthedocs.io/) or [oauthlib](http://oauthlib.readthedocs.io/). 

This probably means that this package and all of the docs should also be refactored into using these new packages?

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `setup.py`
Content:
```
1 # Copyright 2014 Google Inc. All Rights Reserved.
2 #
3 # Licensed under the Apache License, Version 2.0 (the "License");
4 # you may not use this file except in compliance with the License.
5 # You may obtain a copy of the License at
6 #
7 #      http://www.apache.org/licenses/LICENSE-2.0
8 #
9 # Unless required by applicable law or agreed to in writing, software
10 # distributed under the License is distributed on an "AS IS" BASIS,
11 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 # See the License for the specific language governing permissions and
13 # limitations under the License.
14 
15 """Setup script for Google API Python client.
16 
17 Also installs included versions of third party libraries, if those libraries
18 are not already installed.
19 """
20 from __future__ import print_function
21 
22 import sys
23 
24 if sys.version_info < (2, 7):
25   print('google-api-python-client requires python version >= 2.7.',
26         file=sys.stderr)
27   sys.exit(1)
28 if (3, 1) <= sys.version_info < (3, 3):
29   print('google-api-python-client requires python3 version >= 3.3.',
30         file=sys.stderr)
31   sys.exit(1)
32 
33 from setuptools import setup
34 import pkg_resources
35 
36 def _DetectBadness():
37   import os
38   if 'SKIP_GOOGLEAPICLIENT_COMPAT_CHECK' in os.environ:
39     return
40   o2c_pkg = None
41   try:
42     o2c_pkg = pkg_resources.get_distribution('oauth2client')
43   except pkg_resources.DistributionNotFound:
44     pass
45   oauth2client = None
46   try:
47     import oauth2client
48   except ImportError:
49     pass
50   if o2c_pkg is None and oauth2client is not None:
51     raise RuntimeError(
52         'Previous version of google-api-python-client detected; due to a '
53         'packaging issue, we cannot perform an in-place upgrade. Please remove '
54         'the old version and re-install this package.'
55     )
56 
57 _DetectBadness()
58 
59 packages = [
60     'apiclient',
61     'googleapiclient',
62     'googleapiclient/discovery_cache',
63 ]
64 
65 install_requires = [
66     'httplib2>=0.9.2,<1dev',
67     'oauth2client>=1.5.0,<5.0.0dev',
68     'six>=1.6.1,<2dev',
69     'uritemplate>=3.0.0,<4dev',
70 ]
71 
72 long_desc = """The Google API Client for Python is a client library for
73 accessing the Plus, Moderator, and many other Google APIs."""
74 
75 import googleapiclient
76 version = googleapiclient.__version__
77 
78 setup(
79     name="google-api-python-client",
80     version=version,
81     description="Google API Client Library for Python",
82     long_description=long_desc,
83     author="Google Inc.",
84     url="http://github.com/google/google-api-python-client/",
85     install_requires=install_requires,
86     packages=packages,
87     package_data={},
88     license="Apache 2.0",
89     keywords="google api client",
90     classifiers=[
91         'Programming Language :: Python :: 2',
92         'Programming Language :: Python :: 2.7',
93         'Programming Language :: Python :: 3',
94         'Programming Language :: Python :: 3.3',
95         'Programming Language :: Python :: 3.4',
96         'Programming Language :: Python :: 3.5',
97         'Programming Language :: Python :: 3.6',
98         'Development Status :: 5 - Production/Stable',
99         'Intended Audience :: Developers',
100         'License :: OSI Approved :: Apache Software License',
101         'Operating System :: OS Independent',
102         'Topic :: Internet :: WWW/HTTP',
103     ],
104 )
105
```

Path: `googleapiclient/discovery_cache/file_cache.py`
Content:
```
1 # Copyright 2014 Google Inc. All Rights Reserved.
2 #
3 # Licensed under the Apache License, Version 2.0 (the "License");
4 # you may not use this file except in compliance with the License.
5 # You may obtain a copy of the License at
6 #
7 #      http://www.apache.org/licenses/LICENSE-2.0
8 #
9 # Unless required by applicable law or agreed to in writing, software
10 # distributed under the License is distributed on an "AS IS" BASIS,
11 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 # See the License for the specific language governing permissions and
13 # limitations under the License.
14 
15 """File based cache for the discovery document.
16 
17 The cache is stored in a single file so that multiple processes can
18 share the same cache. It locks the file whenever accesing to the
19 file. When the cache content is corrupted, it will be initialized with
20 an empty cache.
21 """
22 
23 from __future__ import division
24 
25 import datetime
26 import json
27 import logging
28 import os
29 import tempfile
30 import threading
31 
32 try:
33   from oauth2client.contrib.locked_file import LockedFile
34 except ImportError:
35   # oauth2client < 2.0.0
36   try:
37     from oauth2client.locked_file import LockedFile
38   except ImportError:
39     # oauth2client > 4.0.0
40     raise ImportError(
41       'file_cache is unavailable when using oauth2client >= 4.0.0')
42 
43 from . import base
44 from ..discovery_cache import DISCOVERY_DOC_MAX_AGE
45 
46 LOGGER = logging.getLogger(__name__)
47 
48 FILENAME = 'google-api-python-client-discovery-doc.cache'
49 EPOCH = datetime.datetime.utcfromtimestamp(0)
50 
51 
52 def _to_timestamp(date):
53   try:
54     return (date - EPOCH).total_seconds()
55   except AttributeError:
56     # The following is the equivalent of total_seconds() in Python2.6.
57     # See also: https://docs.python.org/2/library/datetime.html
58     delta = date - EPOCH
59     return ((delta.microseconds + (delta.seconds + delta.days * 24 * 3600)
60              * 10**6) / 10**6)
61 
62 
63 def _read_or_initialize_cache(f):
64   f.file_handle().seek(0)
65   try:
66     cache = json.load(f.file_handle())
67   except Exception:
68     # This means it opens the file for the first time, or the cache is
69     # corrupted, so initializing the file with an empty dict.
70     cache = {}
71     f.file_handle().truncate(0)
72     f.file_handle().seek(0)
73     json.dump(cache, f.file_handle())
74   return cache
75 
76 
77 class Cache(base.Cache):
78   """A file based cache for the discovery documents."""
79 
80   def __init__(self, max_age):
81       """Constructor.
82 
83       Args:
84         max_age: Cache expiration in seconds.
85       """
86       self._max_age = max_age
87       self._file = os.path.join(tempfile.gettempdir(), FILENAME)
88       f = LockedFile(self._file, 'a+', 'r')
89       try:
90         f.open_and_lock()
91         if f.is_locked():
92           _read_or_initialize_cache(f)
93         # If we can not obtain the lock, other process or thread must
94         # have initialized the file.
95       except Exception as e:
96         LOGGER.warning(e, exc_info=True)
97       finally:
98         f.unlock_and_close()
99 
100   def get(self, url):
101     f = LockedFile(self._file, 'r+', 'r')
102     try:
103       f.open_and_lock()
104       if f.is_locked():
105         cache = _read_or_initialize_cache(f)
106         if url in cache:
107           content, t = cache.get(url, (None, 0))
108           if _to_timestamp(datetime.datetime.now()) < t + self._max_age:
109             return content
110         return None
111       else:
112         LOGGER.debug('Could not obtain a lock for the cache file.')
113         return None
114     except Exception as e:
115       LOGGER.warning(e, exc_info=True)
116     finally:
117       f.unlock_and_close()
118 
119   def set(self, url, content):
120     f = LockedFile(self._file, 'r+', 'r')
121     try:
122       f.open_and_lock()
123       if f.is_locked():
124         cache = _read_or_initialize_cache(f)
125         cache[url] = (content, _to_timestamp(datetime.datetime.now()))
126         # Remove stale cache.
127         for k, (_, timestamp) in list(cache.items()):
128           if _to_timestamp(datetime.datetime.now()) >= timestamp + self._max_age:
129             del cache[k]
130         f.file_handle().truncate(0)
131         f.file_handle().seek(0)
132         json.dump(cache, f.file_handle())
133       else:
134         LOGGER.debug('Could not obtain a lock for the cache file.')
135     except Exception as e:
136       LOGGER.warning(e, exc_info=True)
137     finally:
138       f.unlock_and_close()
139 
140 
141 cache = Cache(max_age=DISCOVERY_DOC_MAX_AGE)
142
```
--- 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/googleapiclient/discovery_cache/file_cache.py b/googleapiclient/discovery_cache/file_cache.py
--- a/googleapiclient/discovery_cache/file_cache.py
+++ b/googleapiclient/discovery_cache/file_cache.py
@@ -36,9 +36,9 @@
   try:
     from oauth2client.locked_file import LockedFile
   except ImportError:
-    # oauth2client > 4.0.0
+    # oauth2client > 4.0.0 or google-auth
     raise ImportError(
-      'file_cache is unavailable when using oauth2client >= 4.0.0')
+      'file_cache is unavailable when using oauth2client >= 4.0.0 or google-auth')
 
 from . import base
 from ..discovery_cache import DISCOVERY_DOC_MAX_AGE
diff --git a/setup.py b/setup.py
--- a/setup.py
+++ b/setup.py
@@ -64,7 +64,8 @@
 
 install_requires = [
     'httplib2>=0.9.2,<1dev',
-    'oauth2client>=1.5.0,<5.0.0dev',
+    'google-auth>=1.4.1',
+    'google-auth-httplib2>=0.0.3',
     'six>=1.6.1,<2dev',
     'uritemplate>=3.0.0,<4dev',
 ]

{"golden_diff": "diff --git a/googleapiclient/discovery_cache/file_cache.py b/googleapiclient/discovery_cache/file_cache.py\n--- a/googleapiclient/discovery_cache/file_cache.py\n+++ b/googleapiclient/discovery_cache/file_cache.py\n@@ -36,9 +36,9 @@\n   try:\n     from oauth2client.locked_file import LockedFile\n   except ImportError:\n-    # oauth2client > 4.0.0\n+    # oauth2client > 4.0.0 or google-auth\n     raise ImportError(\n-      'file_cache is unavailable when using oauth2client >= 4.0.0')\n+      'file_cache is unavailable when using oauth2client >= 4.0.0 or google-auth')\n \n from . import base\n from ..discovery_cache import DISCOVERY_DOC_MAX_AGE\ndiff --git a/setup.py b/setup.py\n--- a/setup.py\n+++ b/setup.py\n@@ -64,7 +64,8 @@\n \n install_requires = [\n     'httplib2>=0.9.2,<1dev',\n-    'oauth2client>=1.5.0,<5.0.0dev',\n+    'google-auth>=1.4.1',\n+    'google-auth-httplib2>=0.0.3',\n     'six>=1.6.1,<2dev',\n     'uritemplate>=3.0.0,<4dev',\n ]\n", "issue": "Deprecation of oauth2client dependency\nAccording to the readme google/oauth2client is deprecated. They suggest switching to [google-auth](https://google-auth.readthedocs.io/) or [oauthlib](http://oauthlib.readthedocs.io/). \r\n\r\nThis probably means that this package and all of the docs should also be refactored into using these new packages?\n", "before_files": [{"content": "# Copyright 2014 Google Inc. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#      http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\n\"\"\"Setup script for Google API Python client.\n\nAlso installs included versions of third party libraries, if those libraries\nare not already installed.\n\"\"\"\nfrom __future__ import print_function\n\nimport sys\n\nif sys.version_info < (2, 7):\n  print('google-api-python-client requires python version >= 2.7.',\n        file=sys.stderr)\n  sys.exit(1)\nif (3, 1) <= sys.version_info < (3, 3):\n  print('google-api-python-client requires python3 version >= 3.3.',\n        file=sys.stderr)\n  sys.exit(1)\n\nfrom setuptools import setup\nimport pkg_resources\n\ndef _DetectBadness():\n  import os\n  if 'SKIP_GOOGLEAPICLIENT_COMPAT_CHECK' in os.environ:\n    return\n  o2c_pkg = None\n  try:\n    o2c_pkg = pkg_resources.get_distribution('oauth2client')\n  except pkg_resources.DistributionNotFound:\n    pass\n  oauth2client = None\n  try:\n    import oauth2client\n  except ImportError:\n    pass\n  if o2c_pkg is None and oauth2client is not None:\n    raise RuntimeError(\n        'Previous version of google-api-python-client detected; due to a '\n        'packaging issue, we cannot perform an in-place upgrade. Please remove '\n        'the old version and re-install this package.'\n    )\n\n_DetectBadness()\n\npackages = [\n    'apiclient',\n    'googleapiclient',\n    'googleapiclient/discovery_cache',\n]\n\ninstall_requires = [\n    'httplib2>=0.9.2,<1dev',\n    'oauth2client>=1.5.0,<5.0.0dev',\n    'six>=1.6.1,<2dev',\n    'uritemplate>=3.0.0,<4dev',\n]\n\nlong_desc = \"\"\"The Google API Client for Python is a client library for\naccessing the Plus, Moderator, and many other Google APIs.\"\"\"\n\nimport googleapiclient\nversion = googleapiclient.__version__\n\nsetup(\n    name=\"google-api-python-client\",\n    version=version,\n    description=\"Google API Client Library for Python\",\n    long_description=long_desc,\n    author=\"Google Inc.\",\n    url=\"http://github.com/google/google-api-python-client/\",\n    install_requires=install_requires,\n    packages=packages,\n    package_data={},\n    license=\"Apache 2.0\",\n    keywords=\"google api client\",\n    classifiers=[\n        'Programming Language :: Python :: 2',\n        'Programming Language :: Python :: 2.7',\n        'Programming Language :: Python :: 3',\n        'Programming Language :: Python :: 3.3',\n        'Programming Language :: Python :: 3.4',\n        'Programming Language :: Python :: 3.5',\n        'Programming Language :: Python :: 3.6',\n        'Development Status :: 5 - Production/Stable',\n        'Intended Audience :: Developers',\n        'License :: OSI Approved :: Apache Software License',\n        'Operating System :: OS Independent',\n        'Topic :: Internet :: WWW/HTTP',\n    ],\n)\n", "path": "setup.py"}, {"content": "# Copyright 2014 Google Inc. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#      http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\n\"\"\"File based cache for the discovery document.\n\nThe cache is stored in a single file so that multiple processes can\nshare the same cache. It locks the file whenever accesing to the\nfile. When the cache content is corrupted, it will be initialized with\nan empty cache.\n\"\"\"\n\nfrom __future__ import division\n\nimport datetime\nimport json\nimport logging\nimport os\nimport tempfile\nimport threading\n\ntry:\n  from oauth2client.contrib.locked_file import LockedFile\nexcept ImportError:\n  # oauth2client < 2.0.0\n  try:\n    from oauth2client.locked_file import LockedFile\n  except ImportError:\n    # oauth2client > 4.0.0\n    raise ImportError(\n      'file_cache is unavailable when using oauth2client >= 4.0.0')\n\nfrom . import base\nfrom ..discovery_cache import DISCOVERY_DOC_MAX_AGE\n\nLOGGER = logging.getLogger(__name__)\n\nFILENAME = 'google-api-python-client-discovery-doc.cache'\nEPOCH = datetime.datetime.utcfromtimestamp(0)\n\n\ndef _to_timestamp(date):\n  try:\n    return (date - EPOCH).total_seconds()\n  except AttributeError:\n    # The following is the equivalent of total_seconds() in Python2.6.\n    # See also: https://docs.python.org/2/library/datetime.html\n    delta = date - EPOCH\n    return ((delta.microseconds + (delta.seconds + delta.days * 24 * 3600)\n             * 10**6) / 10**6)\n\n\ndef _read_or_initialize_cache(f):\n  f.file_handle().seek(0)\n  try:\n    cache = json.load(f.file_handle())\n  except Exception:\n    # This means it opens the file for the first time, or the cache is\n    # corrupted, so initializing the file with an empty dict.\n    cache = {}\n    f.file_handle().truncate(0)\n    f.file_handle().seek(0)\n    json.dump(cache, f.file_handle())\n  return cache\n\n\nclass Cache(base.Cache):\n  \"\"\"A file based cache for the discovery documents.\"\"\"\n\n  def __init__(self, max_age):\n      \"\"\"Constructor.\n\n      Args:\n        max_age: Cache expiration in seconds.\n      \"\"\"\n      self._max_age = max_age\n      self._file = os.path.join(tempfile.gettempdir(), FILENAME)\n      f = LockedFile(self._file, 'a+', 'r')\n      try:\n        f.open_and_lock()\n        if f.is_locked():\n          _read_or_initialize_cache(f)\n        # If we can not obtain the lock, other process or thread must\n        # have initialized the file.\n      except Exception as e:\n        LOGGER.warning(e, exc_info=True)\n      finally:\n        f.unlock_and_close()\n\n  def get(self, url):\n    f = LockedFile(self._file, 'r+', 'r')\n    try:\n      f.open_and_lock()\n      if f.is_locked():\n        cache = _read_or_initialize_cache(f)\n        if url in cache:\n          content, t = cache.get(url, (None, 0))\n          if _to_timestamp(datetime.datetime.now()) < t + self._max_age:\n            return content\n        return None\n      else:\n        LOGGER.debug('Could not obtain a lock for the cache file.')\n        return None\n    except Exception as e:\n      LOGGER.warning(e, exc_info=True)\n    finally:\n      f.unlock_and_close()\n\n  def set(self, url, content):\n    f = LockedFile(self._file, 'r+', 'r')\n    try:\n      f.open_and_lock()\n      if f.is_locked():\n        cache = _read_or_initialize_cache(f)\n        cache[url] = (content, _to_timestamp(datetime.datetime.now()))\n        # Remove stale cache.\n        for k, (_, timestamp) in list(cache.items()):\n          if _to_timestamp(datetime.datetime.now()) >= timestamp + self._max_age:\n            del cache[k]\n        f.file_handle().truncate(0)\n        f.file_handle().seek(0)\n        json.dump(cache, f.file_handle())\n      else:\n        LOGGER.debug('Could not obtain a lock for the cache file.')\n    except Exception as e:\n      LOGGER.warning(e, exc_info=True)\n    finally:\n      f.unlock_and_close()\n\n\ncache = Cache(max_age=DISCOVERY_DOC_MAX_AGE)\n", "path": "googleapiclient/discovery_cache/file_cache.py"}], "after_files": [{"content": "# Copyright 2014 Google Inc. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#      http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\n\"\"\"Setup script for Google API Python client.\n\nAlso installs included versions of third party libraries, if those libraries\nare not already installed.\n\"\"\"\nfrom __future__ import print_function\n\nimport sys\n\nif sys.version_info < (2, 7):\n  print('google-api-python-client requires python version >= 2.7.',\n        file=sys.stderr)\n  sys.exit(1)\nif (3, 1) <= sys.version_info < (3, 3):\n  print('google-api-python-client requires python3 version >= 3.3.',\n        file=sys.stderr)\n  sys.exit(1)\n\nfrom setuptools import setup\nimport pkg_resources\n\ndef _DetectBadness():\n  import os\n  if 'SKIP_GOOGLEAPICLIENT_COMPAT_CHECK' in os.environ:\n    return\n  o2c_pkg = None\n  try:\n    o2c_pkg = pkg_resources.get_distribution('oauth2client')\n  except pkg_resources.DistributionNotFound:\n    pass\n  oauth2client = None\n  try:\n    import oauth2client\n  except ImportError:\n    pass\n  if o2c_pkg is None and oauth2client is not None:\n    raise RuntimeError(\n        'Previous version of google-api-python-client detected; due to a '\n        'packaging issue, we cannot perform an in-place upgrade. Please remove '\n        'the old version and re-install this package.'\n    )\n\n_DetectBadness()\n\npackages = [\n    'apiclient',\n    'googleapiclient',\n    'googleapiclient/discovery_cache',\n]\n\ninstall_requires = [\n    'httplib2>=0.9.2,<1dev',\n    'google-auth>=1.4.1',\n    'google-auth-httplib2>=0.0.3',\n    'six>=1.6.1,<2dev',\n    'uritemplate>=3.0.0,<4dev',\n]\n\nlong_desc = \"\"\"The Google API Client for Python is a client library for\naccessing the Plus, Moderator, and many other Google APIs.\"\"\"\n\nimport googleapiclient\nversion = googleapiclient.__version__\n\nsetup(\n    name=\"google-api-python-client\",\n    version=version,\n    description=\"Google API Client Library for Python\",\n    long_description=long_desc,\n    author=\"Google Inc.\",\n    url=\"http://github.com/google/google-api-python-client/\",\n    install_requires=install_requires,\n    packages=packages,\n    package_data={},\n    license=\"Apache 2.0\",\n    keywords=\"google api client\",\n    classifiers=[\n        'Programming Language :: Python :: 2',\n        'Programming Language :: Python :: 2.7',\n        'Programming Language :: Python :: 3',\n        'Programming Language :: Python :: 3.3',\n        'Programming Language :: Python :: 3.4',\n        'Programming Language :: Python :: 3.5',\n        'Programming Language :: Python :: 3.6',\n        'Development Status :: 5 - Production/Stable',\n        'Intended Audience :: Developers',\n        'License :: OSI Approved :: Apache Software License',\n        'Operating System :: OS Independent',\n        'Topic :: Internet :: WWW/HTTP',\n    ],\n)\n", "path": "setup.py"}, {"content": "# Copyright 2014 Google Inc. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#      http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\n\"\"\"File based cache for the discovery document.\n\nThe cache is stored in a single file so that multiple processes can\nshare the same cache. It locks the file whenever accesing to the\nfile. When the cache content is corrupted, it will be initialized with\nan empty cache.\n\"\"\"\n\nfrom __future__ import division\n\nimport datetime\nimport json\nimport logging\nimport os\nimport tempfile\nimport threading\n\ntry:\n  from oauth2client.contrib.locked_file import LockedFile\nexcept ImportError:\n  # oauth2client < 2.0.0\n  try:\n    from oauth2client.locked_file import LockedFile\n  except ImportError:\n    # oauth2client > 4.0.0 or google-auth\n    raise ImportError(\n      'file_cache is unavailable when using oauth2client >= 4.0.0 or google-auth')\n\nfrom . import base\nfrom ..discovery_cache import DISCOVERY_DOC_MAX_AGE\n\nLOGGER = logging.getLogger(__name__)\n\nFILENAME = 'google-api-python-client-discovery-doc.cache'\nEPOCH = datetime.datetime.utcfromtimestamp(0)\n\n\ndef _to_timestamp(date):\n  try:\n    return (date - EPOCH).total_seconds()\n  except AttributeError:\n    # The following is the equivalent of total_seconds() in Python2.6.\n    # See also: https://docs.python.org/2/library/datetime.html\n    delta = date - EPOCH\n    return ((delta.microseconds + (delta.seconds + delta.days * 24 * 3600)\n             * 10**6) / 10**6)\n\n\ndef _read_or_initialize_cache(f):\n  f.file_handle().seek(0)\n  try:\n    cache = json.load(f.file_handle())\n  except Exception:\n    # This means it opens the file for the first time, or the cache is\n    # corrupted, so initializing the file with an empty dict.\n    cache = {}\n    f.file_handle().truncate(0)\n    f.file_handle().seek(0)\n    json.dump(cache, f.file_handle())\n  return cache\n\n\nclass Cache(base.Cache):\n  \"\"\"A file based cache for the discovery documents.\"\"\"\n\n  def __init__(self, max_age):\n      \"\"\"Constructor.\n\n      Args:\n        max_age: Cache expiration in seconds.\n      \"\"\"\n      self._max_age = max_age\n      self._file = os.path.join(tempfile.gettempdir(), FILENAME)\n      f = LockedFile(self._file, 'a+', 'r')\n      try:\n        f.open_and_lock()\n        if f.is_locked():\n          _read_or_initialize_cache(f)\n        # If we can not obtain the lock, other process or thread must\n        # have initialized the file.\n      except Exception as e:\n        LOGGER.warning(e, exc_info=True)\n      finally:\n        f.unlock_and_close()\n\n  def get(self, url):\n    f = LockedFile(self._file, 'r+', 'r')\n    try:\n      f.open_and_lock()\n      if f.is_locked():\n        cache = _read_or_initialize_cache(f)\n        if url in cache:\n          content, t = cache.get(url, (None, 0))\n          if _to_timestamp(datetime.datetime.now()) < t + self._max_age:\n            return content\n        return None\n      else:\n        LOGGER.debug('Could not obtain a lock for the cache file.')\n        return None\n    except Exception as e:\n      LOGGER.warning(e, exc_info=True)\n    finally:\n      f.unlock_and_close()\n\n  def set(self, url, content):\n    f = LockedFile(self._file, 'r+', 'r')\n    try:\n      f.open_and_lock()\n      if f.is_locked():\n        cache = _read_or_initialize_cache(f)\n        cache[url] = (content, _to_timestamp(datetime.datetime.now()))\n        # Remove stale cache.\n        for k, (_, timestamp) in list(cache.items()):\n          if _to_timestamp(datetime.datetime.now()) >= timestamp + self._max_age:\n            del cache[k]\n        f.file_handle().truncate(0)\n        f.file_handle().seek(0)\n        json.dump(cache, f.file_handle())\n      else:\n        LOGGER.debug('Could not obtain a lock for the cache file.')\n    except Exception as e:\n      LOGGER.warning(e, exc_info=True)\n    finally:\n      f.unlock_and_close()\n\n\ncache = Cache(max_age=DISCOVERY_DOC_MAX_AGE)\n", "path": "googleapiclient/discovery_cache/file_cache.py"}]}