1   
  2   
  3   
  4   
  5   
  6   
  7   
  8   
  9   
 10   
 11   
 12   
 13   
 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       
 36      try: 
 37          from oauth2client.locked_file import LockedFile 
 38      except ImportError: 
 39           
 40          raise ImportError( 
 41              "file_cache is unavailable when using oauth2client >= 4.0.0 or google-auth" 
 42          ) 
 43   
 44  from . import base 
 45  from ..discovery_cache import DISCOVERY_DOC_MAX_AGE 
 46   
 47  LOGGER = logging.getLogger(__name__) 
 48   
 49  FILENAME = "google-api-python-client-discovery-doc.cache" 
 50  EPOCH = datetime.datetime.utcfromtimestamp(0) 
 51   
 52   
 54      try: 
 55          return (date - EPOCH).total_seconds() 
 56      except AttributeError: 
 57           
 58           
 59          delta = date - EPOCH 
 60          return ( 
 61              delta.microseconds + (delta.seconds + delta.days * 24 * 3600) * 10 ** 6 
 62          ) / 10 ** 6 
  63   
 64   
 66      f.file_handle().seek(0) 
 67      try: 
 68          cache = json.load(f.file_handle()) 
 69      except Exception: 
 70           
 71           
 72          cache = {} 
 73          f.file_handle().truncate(0) 
 74          f.file_handle().seek(0) 
 75          json.dump(cache, f.file_handle()) 
 76      return cache 
  77   
 78   
 80      """A file based cache for the discovery documents.""" 
 81   
 83          """Constructor. 
 84   
 85        Args: 
 86          max_age: Cache expiration in seconds. 
 87        """ 
 88          self._max_age = max_age 
 89          self._file = os.path.join(tempfile.gettempdir(), FILENAME) 
 90          f = LockedFile(self._file, "a+", "r") 
 91          try: 
 92              f.open_and_lock() 
 93              if f.is_locked(): 
 94                  _read_or_initialize_cache(f) 
 95               
 96               
 97          except Exception as e: 
 98              LOGGER.warning(e, exc_info=True) 
 99          finally: 
100              f.unlock_and_close() 
 101   
102 -    def get(self, url): 
 103          f = LockedFile(self._file, "r+", "r") 
104          try: 
105              f.open_and_lock() 
106              if f.is_locked(): 
107                  cache = _read_or_initialize_cache(f) 
108                  if url in cache: 
109                      content, t = cache.get(url, (None, 0)) 
110                      if _to_timestamp(datetime.datetime.now()) < t + self._max_age: 
111                          return content 
112                  return None 
113              else: 
114                  LOGGER.debug("Could not obtain a lock for the cache file.") 
115                  return None 
116          except Exception as e: 
117              LOGGER.warning(e, exc_info=True) 
118          finally: 
119              f.unlock_and_close() 
 120   
121 -    def set(self, url, content): 
 122          f = LockedFile(self._file, "r+", "r") 
123          try: 
124              f.open_and_lock() 
125              if f.is_locked(): 
126                  cache = _read_or_initialize_cache(f) 
127                  cache[url] = (content, _to_timestamp(datetime.datetime.now())) 
128                   
129                  for k, (_, timestamp) in list(cache.items()): 
130                      if ( 
131                          _to_timestamp(datetime.datetime.now()) 
132                          >= timestamp + self._max_age 
133                      ): 
134                          del cache[k] 
135                  f.file_handle().truncate(0) 
136                  f.file_handle().seek(0) 
137                  json.dump(cache, f.file_handle()) 
138              else: 
139                  LOGGER.debug("Could not obtain a lock for the cache file.") 
140          except Exception as e: 
141              LOGGER.warning(e, exc_info=True) 
142          finally: 
143              f.unlock_and_close() 
  144   
145   
146  cache = Cache(max_age=DISCOVERY_DOC_MAX_AGE) 
147