code: def put_directory(self, target_path, local_directory, **kwargs):
          
          target_path = self._normalize_path(target_path)
          if not target_path.endswith('/'):
              target_path += '/'
          gathered_files = []
  
          if not local_directory.endswith('/'):
              local_directory += '/'
  
          basedir = os.path.basename(local_directory[0: -1]) + '/'
          # gather files to upload
          for path, _, files in os.walk(local_directory):
              gathered_files.append(
                  (path, basedir + path[len(local_directory):], files)
              )
  
          for path, remote_path, files in gathered_files:
              self.mkdir(target_path + remote_path + '/')
              for name in files:
                  if not self.put_file(target_path + remote_path + '/',
                                       path + '/' + name, **kwargs):
                      return False
          return True
docs: Upload a directory with all its contents
  
          :param target_path: path of the directory to upload into
          :param local_directory: path to the local directory to upload
          :param \*\*kwargs: optional arguments that ``put_file`` accepts
          :returns: True if the operation succeeded, False otherwise
          :raises: HTTPResponseError in case an HTTP error status was returned