Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(223)

Unified Diff: tools/telemetry/third_party/gsutil/gslib/tab_complete.py

Issue 1260493004: Revert "Add gsutil 4.13 to telemetry/third_party" (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 5 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: tools/telemetry/third_party/gsutil/gslib/tab_complete.py
diff --git a/tools/telemetry/third_party/gsutil/gslib/tab_complete.py b/tools/telemetry/third_party/gsutil/gslib/tab_complete.py
deleted file mode 100644
index cd99a25d4a71e2be4a1c448ed35e6c305d1a565e..0000000000000000000000000000000000000000
--- a/tools/telemetry/third_party/gsutil/gslib/tab_complete.py
+++ /dev/null
@@ -1,337 +0,0 @@
-# -*- coding: utf-8 -*-
-# Copyright 2014 Google Inc. All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-"""Shell tab completion."""
-
-import itertools
-import json
-import threading
-import time
-
-import boto
-
-from boto.gs.acl import CannedACLStrings
-from gslib.storage_url import IsFileUrlString
-from gslib.storage_url import StorageUrlFromString
-from gslib.storage_url import StripOneSlash
-from gslib.util import GetTabCompletionCacheFilename
-from gslib.util import GetTabCompletionLogFilename
-from gslib.wildcard_iterator import CreateWildcardIterator
-
-TAB_COMPLETE_CACHE_TTL = 15
-
-_TAB_COMPLETE_MAX_RESULTS = 1000
-
-_TIMEOUT_WARNING = """
-Tab completion aborted (took >%ss), you may complete the command manually.
-The timeout can be adjusted in the gsutil configuration file.
-""".rstrip()
-
-
-class CompleterType(object):
- CLOUD_BUCKET = 'cloud_bucket'
- CLOUD_OBJECT = 'cloud_object'
- CLOUD_OR_LOCAL_OBJECT = 'cloud_or_local_object'
- LOCAL_OBJECT = 'local_object'
- LOCAL_OBJECT_OR_CANNED_ACL = 'local_object_or_canned_acl'
- NO_OP = 'no_op'
-
-
-class LocalObjectCompleter(object):
- """Completer object for local files."""
-
- def __init__(self):
- # This is only safe to import if argcomplete is present in the install
- # (which happens for Cloud SDK installs), so import on usage, not on load.
- # pylint: disable=g-import-not-at-top
- from argcomplete.completers import FilesCompleter
- self.files_completer = FilesCompleter()
-
- def __call__(self, prefix, **kwargs):
- return self.files_completer(prefix, **kwargs)
-
-
-class LocalObjectOrCannedACLCompleter(object):
- """Completer object for local files and canned ACLs.
-
- Currently, only Google Cloud Storage canned ACL names are supported.
- """
-
- def __init__(self):
- self.local_object_completer = LocalObjectCompleter()
-
- def __call__(self, prefix, **kwargs):
- local_objects = self.local_object_completer(prefix, **kwargs)
- canned_acls = [acl for acl in CannedACLStrings if acl.startswith(prefix)]
- return local_objects + canned_acls
-
-
-class TabCompletionCache(object):
- """Cache for tab completion results."""
-
- def __init__(self, prefix, results, timestamp, partial_results):
- self.prefix = prefix
- self.results = results
- self.timestamp = timestamp
- self.partial_results = partial_results
-
- @staticmethod
- def LoadFromFile(filename):
- """Instantiates the cache from a file.
-
- Args:
- filename: The file to load.
- Returns:
- TabCompletionCache instance with loaded data or an empty cache
- if the file cannot be loaded
- """
- try:
- with open(filename, 'r') as fp:
- cache_dict = json.loads(fp.read())
- prefix = cache_dict['prefix']
- results = cache_dict['results']
- timestamp = cache_dict['timestamp']
- partial_results = cache_dict['partial-results']
- except Exception: # pylint: disable=broad-except
- # Guarding against incompatible format changes in the cache file.
- # Erring on the side of not breaking tab-completion in case of cache
- # issues.
- prefix = None
- results = []
- timestamp = 0
- partial_results = False
-
- return TabCompletionCache(prefix, results, timestamp, partial_results)
-
- def GetCachedResults(self, prefix):
- """Returns the cached results for prefix or None if not in cache."""
- current_time = time.time()
- if current_time - self.timestamp >= TAB_COMPLETE_CACHE_TTL:
- return None
-
- results = None
-
- if prefix == self.prefix:
- results = self.results
- elif (not self.partial_results and prefix.startswith(self.prefix)
- and prefix.count('/') == self.prefix.count('/')):
- results = [x for x in self.results if x.startswith(prefix)]
-
- if results is not None:
- # Update cache timestamp to make sure the cache entry does not expire if
- # the user is performing multiple completions in a single
- # bucket/subdirectory since we can answer these requests from the cache.
- # e.g. gs://prefix<tab> -> gs://prefix-mid<tab> -> gs://prefix-mid-suffix
- self.timestamp = time.time()
- return results
-
- def UpdateCache(self, prefix, results, partial_results):
- """Updates the in-memory cache with the results for the given prefix."""
- self.prefix = prefix
- self.results = results
- self.partial_results = partial_results
- self.timestamp = time.time()
-
- def WriteToFile(self, filename):
- """Writes out the cache to the given file."""
- json_str = json.dumps({
- 'prefix': self.prefix,
- 'results': self.results,
- 'partial-results': self.partial_results,
- 'timestamp': self.timestamp,
- })
-
- try:
- with open(filename, 'w') as fp:
- fp.write(json_str)
- except IOError:
- pass
-
-
-class CloudListingRequestThread(threading.Thread):
- """Thread that performs a listing request for the given URL string."""
-
- def __init__(self, wildcard_url_str, gsutil_api):
- """Instantiates Cloud listing request thread.
-
- Args:
- wildcard_url_str: The URL to list.
- gsutil_api: gsutil Cloud API instance to use.
- """
- super(CloudListingRequestThread, self).__init__()
- self.daemon = True
- self._wildcard_url_str = wildcard_url_str
- self._gsutil_api = gsutil_api
- self.results = None
-
- def run(self):
- it = CreateWildcardIterator(
- self._wildcard_url_str, self._gsutil_api).IterAll(
- bucket_listing_fields=['name'])
- self.results = [
- str(c) for c in itertools.islice(it, _TAB_COMPLETE_MAX_RESULTS)]
-
-
-class TimeoutError(Exception):
- pass
-
-
-class CloudObjectCompleter(object):
- """Completer object for Cloud URLs."""
-
- def __init__(self, gsutil_api, bucket_only=False):
- """Instantiates completer for Cloud URLs.
-
- Args:
- gsutil_api: gsutil Cloud API instance to use.
- bucket_only: Whether the completer should only match buckets.
- """
- self._gsutil_api = gsutil_api
- self._bucket_only = bucket_only
-
- def _PerformCloudListing(self, wildcard_url, timeout):
- """Perform a remote listing request for the given wildcard URL.
-
- Args:
- wildcard_url: The wildcard URL to list.
- timeout: Time limit for the request.
- Returns:
- Cloud resources matching the given wildcard URL.
- Raises:
- TimeoutError: If the listing does not finish within the timeout.
- """
- request_thread = CloudListingRequestThread(wildcard_url, self._gsutil_api)
- request_thread.start()
- request_thread.join(timeout)
-
- if request_thread.is_alive():
- # This is only safe to import if argcomplete is present in the install
- # (which happens for Cloud SDK installs), so import on usage, not on load.
- # pylint: disable=g-import-not-at-top
- import argcomplete
- argcomplete.warn(_TIMEOUT_WARNING % timeout)
- raise TimeoutError()
-
- results = request_thread.results
-
- return results
-
- def __call__(self, prefix, **kwargs):
- if not prefix:
- prefix = 'gs://'
- elif IsFileUrlString(prefix):
- return []
-
- wildcard_url = prefix + '*'
- url = StorageUrlFromString(wildcard_url)
- if self._bucket_only and not url.IsBucket():
- return []
-
- timeout = boto.config.getint('GSUtil', 'tab_completion_timeout', 5)
- if timeout == 0:
- return []
-
- start_time = time.time()
-
- cache = TabCompletionCache.LoadFromFile(GetTabCompletionCacheFilename())
- cached_results = cache.GetCachedResults(prefix)
-
- timing_log_entry_type = ''
- if cached_results is not None:
- results = cached_results
- timing_log_entry_type = ' (from cache)'
- else:
- try:
- results = self._PerformCloudListing(wildcard_url, timeout)
- if self._bucket_only and len(results) == 1:
- results = [StripOneSlash(results[0])]
- partial_results = (len(results) == _TAB_COMPLETE_MAX_RESULTS)
- cache.UpdateCache(prefix, results, partial_results)
- except TimeoutError:
- timing_log_entry_type = ' (request timeout)'
- results = []
-
- cache.WriteToFile(GetTabCompletionCacheFilename())
-
- end_time = time.time()
- num_results = len(results)
- elapsed_seconds = end_time - start_time
- _WriteTimingLog(
- '%s results%s in %.2fs, %.2f results/second for prefix: %s\n' %
- (num_results, timing_log_entry_type, elapsed_seconds,
- num_results / elapsed_seconds, prefix))
-
- return results
-
-
-class CloudOrLocalObjectCompleter(object):
- """Completer object for Cloud URLs or local files.
-
- Invokes the Cloud object completer if the input looks like a Cloud URL and
- falls back to local file completer otherwise.
- """
-
- def __init__(self, gsutil_api):
- self.cloud_object_completer = CloudObjectCompleter(gsutil_api)
- self.local_object_completer = LocalObjectCompleter()
-
- def __call__(self, prefix, **kwargs):
- if IsFileUrlString(prefix):
- completer = self.local_object_completer
- else:
- completer = self.cloud_object_completer
- return completer(prefix, **kwargs)
-
-
-class NoOpCompleter(object):
- """Completer that always returns 0 results."""
-
- def __call__(self, unused_prefix, **unused_kwargs):
- return []
-
-
-def MakeCompleter(completer_type, gsutil_api):
- """Create a completer instance of the given type.
-
- Args:
- completer_type: The type of completer to create.
- gsutil_api: gsutil Cloud API instance to use.
- Returns:
- A completer instance.
- Raises:
- RuntimeError: if completer type is not supported.
- """
- if completer_type == CompleterType.CLOUD_OR_LOCAL_OBJECT:
- return CloudOrLocalObjectCompleter(gsutil_api)
- elif completer_type == CompleterType.LOCAL_OBJECT:
- return LocalObjectCompleter()
- elif completer_type == CompleterType.LOCAL_OBJECT_OR_CANNED_ACL:
- return LocalObjectOrCannedACLCompleter()
- elif completer_type == CompleterType.CLOUD_BUCKET:
- return CloudObjectCompleter(gsutil_api, bucket_only=True)
- elif completer_type == CompleterType.CLOUD_OBJECT:
- return CloudObjectCompleter(gsutil_api)
- elif completer_type == CompleterType.NO_OP:
- return NoOpCompleter()
- else:
- raise RuntimeError(
- 'Unknown completer "%s"' % completer_type)
-
-
-def _WriteTimingLog(message):
- """Write an entry to the tab completion timing log, if it's enabled."""
- if boto.config.getbool('GSUtil', 'tab_completion_time_logs', False):
- with open(GetTabCompletionLogFilename(), 'ab') as fp:
- fp.write(message)
-
« no previous file with comments | « tools/telemetry/third_party/gsutil/gslib/storage_url.py ('k') | tools/telemetry/third_party/gsutil/gslib/tests/__init__.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698