diff --git a/gcloud/datastore/connection.py b/gcloud/datastore/connection.py index 2840c787616f..36ce9bbd297d 100644 --- a/gcloud/datastore/connection.py +++ b/gcloud/datastore/connection.py @@ -406,7 +406,7 @@ def save_entity(self, dataset_id, key_pb, properties, insert.key.CopyFrom(key_pb) - for name, value in properties.iteritems(): + for name, value in properties.items(): prop = insert.property.add() # Set the name of the property. prop.name = name diff --git a/gcloud/datastore/demo/demo.py b/gcloud/datastore/demo/demo.py index 4d511fa6cb44..41c22922dfb0 100644 --- a/gcloud/datastore/demo/demo.py +++ b/gcloud/datastore/demo/demo.py @@ -16,47 +16,47 @@ toy.save() # If we look it up by its key, we should find it... -print dataset.get_entities([toy.key()]) +print(dataset.get_entities([toy.key()])) # And we should be able to delete it... toy.delete() # Since we deleted it, if we do another lookup it shouldn't be there again: -print dataset.get_entities([toy.key()]) +print(dataset.get_entities([toy.key()])) # Now let's try a more advanced query. # We'll start by look at all Thing entities: query = dataset.query().kind('Thing') # Let's look at the first two. -print query.limit(2).fetch() +print(query.limit(2).fetch()) # Now let's check for Thing entities named 'Computer' -print query.filter('name =', 'Computer').fetch() +print(query.filter('name =', 'Computer').fetch()) # If you want to filter by multiple attributes, # you can string .filter() calls together. -print query.filter('name =', 'Computer').filter('age =', 10).fetch() +print(query.filter('name =', 'Computer').filter('age =', 10).fetch()) # You can also work inside a transaction. # (Check the official docs for explanations of what's happening here.) with dataset.transaction(): - print 'Creating and savng an entity...' + print('Creating and savng an entity...') thing = dataset.entity('Thing') thing.key(thing.key().name('foo')) thing['age'] = 10 thing.save() - print 'Creating and saving another entity...' + print('Creating and saving another entity...') thing2 = dataset.entity('Thing') thing2.key(thing2.key().name('bar')) thing2['age'] = 15 thing2.save() - print 'Committing the transaction...' + print('Committing the transaction...') # Now that the transaction is commited, let's delete the entities. -print thing.delete(), thing2.delete() +print(thing.delete(), thing2.delete()) # To rollback a transaction, just call .rollback() with dataset.transaction() as t: @@ -67,16 +67,16 @@ # Let's check if the entity was actually created: created = dataset.get_entities([thing.key()]) -print 'yes' if created else 'no' +print('yes' if created else 'no') # Remember, a key won't be complete until the transaction is commited. # That is, while inside the transaction block, thing.key() will be incomplete. with dataset.transaction(): thing = dataset.entity('Thing') thing.save() - print thing.key() # This will be partial + print(thing.key()) # This will be partial -print thing.key() # This will be complete +print(thing.key()) # This will be complete # Now let's delete the entity. thing.delete() diff --git a/gcloud/datastore/helpers.py b/gcloud/datastore/helpers.py index 66ef4567ad37..23b617a45116 100644 --- a/gcloud/datastore/helpers.py +++ b/gcloud/datastore/helpers.py @@ -9,6 +9,7 @@ from google.protobuf.internal.type_checkers import Int64ValueChecker import pytz +import six from gcloud.datastore.entity import Entity from gcloud.datastore.key import Key @@ -117,17 +118,17 @@ def _pb_attr_value(val): # Regardless of what timezone is on the value, convert it to UTC. val = val.astimezone(pytz.utc) # Convert the datetime to a microsecond timestamp. - value = long(calendar.timegm(val.timetuple()) * 1e6) + val.microsecond + value = int(calendar.timegm(val.timetuple()) * 1e6) + val.microsecond elif isinstance(val, Key): name, value = 'key', val.to_protobuf() elif isinstance(val, bool): name, value = 'boolean', val elif isinstance(val, float): name, value = 'double', val - elif isinstance(val, (int, long)): + elif isinstance(val, six.integer_types): INT_VALUE_CHECKER.CheckValue(val) # Raise an exception if invalid. - name, value = 'integer', long(val) # Always cast to a long. - elif isinstance(val, unicode): + name, value = 'integer', int(val) # Always cast to an integer. + elif isinstance(val, six.text_type): name, value = 'string', val elif isinstance(val, (bytes, str)): name, value = 'blob', val @@ -239,7 +240,7 @@ def _set_protobuf_value(value_pb, val): key = val.key() if key is not None: e_pb.key.CopyFrom(key.to_protobuf()) - for item_key, value in val.iteritems(): + for item_key, value in val.items(): p_pb = e_pb.property.add() p_pb.name = item_key _set_protobuf_value(p_pb.value, value) diff --git a/gcloud/datastore/key.py b/gcloud/datastore/key.py index e73d5a811433..c1ba77740468 100644 --- a/gcloud/datastore/key.py +++ b/gcloud/datastore/key.py @@ -3,6 +3,8 @@ import copy from itertools import izip +import six + from gcloud.datastore import datastore_v1_pb2 as datastore_pb @@ -100,7 +102,7 @@ def from_path(cls, *args, **kwargs): for kind, id_or_name in izip(items, items): entry = {'kind': kind} - if isinstance(id_or_name, basestring): + if isinstance(id_or_name, six.string_types): entry['name'] = id_or_name else: entry['id'] = id_or_name diff --git a/gcloud/demo.py b/gcloud/demo.py index 5dbd8476ae12..3ef2192ca15c 100644 --- a/gcloud/demo.py +++ b/gcloud/demo.py @@ -4,6 +4,7 @@ import os.path import sys import time +from six.moves import input class DemoRunner(object): @@ -36,7 +37,7 @@ def run(self): interact('(Hit CTRL-D to exit...)', local=self.LOCALS) def wait(self): - raw_input() + input() @classmethod def get_line_type(cls, line): @@ -50,9 +51,14 @@ def get_indent_level(self, line): return None return len(line) - len(line.lstrip()) + def _print(self, text='', newline=True): + sys.stdout.write(text) + if newline: + sys.stdout.write('\n') + def write(self, lines): - print - print '\n'.join(lines), + self._print() + self._print('\n'.join(lines), False) self.wait() def code(self, lines): @@ -69,9 +75,9 @@ def code(self, lines): # Print the prefix for the line depending on the indentation level. if indent == 0: - print '>>> ', + self._print('>>> ', False) elif indent > 0: - print '\n... ', + self._print('\n... ', False) elif indent is None: continue diff --git a/gcloud/storage/acl.py b/gcloud/storage/acl.py index 54174bed5ca1..f80f7affc0a5 100644 --- a/gcloud/storage/acl.py +++ b/gcloud/storage/acl.py @@ -185,7 +185,7 @@ def reset(self): def __iter__(self): self._ensure_loaded() - for entity in self.entities.itervalues(): + for entity in self.entities.values(): for role in entity.get_roles(): if role: yield {'entity': str(entity), 'role': role} @@ -342,7 +342,7 @@ def get_entities(self): :returns: A list of all Entity objects. """ self._ensure_loaded() - return self.entities.values() + return list(self.entities.values()) def reload(self): """Reload the ACL data from Cloud Storage. diff --git a/gcloud/storage/bucket.py b/gcloud/storage/bucket.py index 38f135e4504a..f782e7fe3b7b 100644 --- a/gcloud/storage/bucket.py +++ b/gcloud/storage/bucket.py @@ -9,6 +9,7 @@ from gcloud.storage.acl import DefaultObjectACL from gcloud.storage.iterator import Iterator from gcloud.storage.key import Key +import six class _KeyIterator(Iterator): @@ -224,13 +225,7 @@ def new_key(self, key): if isinstance(key, Key): return key - # Support Python 2 and 3. - try: - string_type = basestring - except NameError: # pragma: NO COVER PY3k - string_type = str - - if isinstance(key, string_type): + if isinstance(key, six.string_types): return Key(bucket=self, name=key) raise TypeError('Invalid key: %s' % key) diff --git a/gcloud/storage/connection.py b/gcloud/storage/connection.py index 08f492312568..e1beead37b67 100644 --- a/gcloud/storage/connection.py +++ b/gcloud/storage/connection.py @@ -16,6 +16,7 @@ from gcloud.storage import exceptions from gcloud.storage.bucket import Bucket from gcloud.storage.iterator import Iterator +import six def _utcnow(): # pragma: NO COVER testing replaces @@ -413,13 +414,7 @@ def new_bucket(self, bucket): if isinstance(bucket, Bucket): return bucket - # Support Python 2 and 3. - try: - string_type = basestring - except NameError: # pragma: NO COVER PY3k - string_type = str - - if isinstance(bucket, string_type): + if isinstance(bucket, six.string_types): return Bucket(connection=self, name=bucket) raise TypeError('Invalid bucket: %s' % bucket) @@ -537,7 +532,7 @@ def _get_expiration_seconds(expiration): # Turn the datetime into a timestamp (seconds, not microseconds). expiration = int(calendar.timegm(expiration.timetuple())) - if not isinstance(expiration, (int, long)): + if not isinstance(expiration, six.integer_types): raise TypeError('Expected an integer timestamp, datetime, or ' 'timedelta. Got %s' % type(expiration)) return expiration diff --git a/gcloud/storage/demo/demo.py b/gcloud/storage/demo/demo.py index 1b20131f9442..d1f2631e7cb8 100644 --- a/gcloud/storage/demo/demo.py +++ b/gcloud/storage/demo/demo.py @@ -9,17 +9,17 @@ connection = demo.get_connection() # OK, now let's look at all of the buckets... -print connection.get_all_buckets() # This might take a second... +print(connection.get_all_buckets()) # This might take a second... # Now let's create a new bucket... import time bucket_name = ("bucket-%s" % time.time()).replace(".", "") # Get rid of dots. -print bucket_name +print(bucket_name) bucket = connection.create_bucket(bucket_name) -print bucket +print(bucket) # Let's look at all of the buckets again... -print connection.get_all_buckets() +print(connection.get_all_buckets()) # How about we create a new key inside this bucket. key = bucket.new_key("my-new-file.txt") @@ -28,13 +28,13 @@ key.set_contents_from_string("this is some data!") # ... and we can read that data back again. -print key.get_contents_as_string() +print(key.get_contents_as_string()) # Now let's delete that key. -print key.delete() +print(key.delete()) # And now that we're done, let's delete that bucket... -print bucket.delete() +print(bucket.delete()) # Alright! That's all! # Here's an interactive prompt for you now... diff --git a/gcloud/storage/iterator.py b/gcloud/storage/iterator.py index 8986560175be..1ee0dbb08867 100644 --- a/gcloud/storage/iterator.py +++ b/gcloud/storage/iterator.py @@ -49,7 +49,7 @@ def __init__(self, connection, path, extra_params=None): self.next_page_token = None self.extra_params = extra_params or {} reserved_in_use = self.RESERVED_PARAMS.intersection( - self.extra_params.keys()) + self.extra_params) if reserved_in_use: raise ValueError(('Using a reserved parameter', reserved_in_use)) diff --git a/regression/clear_datastore.py b/regression/clear_datastore.py index 7d6080c070c3..5059840cc845 100644 --- a/regression/clear_datastore.py +++ b/regression/clear_datastore.py @@ -4,6 +4,7 @@ # This assumes the command is being run via tox hence the # repository root is the current directory. from regression import regression_utils +from six.moves import input FETCH_MAX = 20 @@ -62,8 +63,8 @@ def remove_kind(dataset, kind): return # Now that we have all results, we seek to delete. - print 'Deleting keys:' - print results + print('Deleting keys:') + print(results) ancestors = get_ancestors(results) if len(ancestors) > TRANSACTION_MAX_GROUPS: @@ -76,11 +77,11 @@ def remove_kind(dataset, kind): def remove_all_entities(): - print 'This command will remove all entities for the following kinds:' - print '\n'.join(['- ' + val for val in ALL_KINDS]) - response = raw_input('Is this OK [y/n]? ') + print('This command will remove all entities for the following kinds:') + print('\n'.join(['- ' + val for val in ALL_KINDS])) + response = input('Is this OK [y/n]? ') if response.lower() != 'y': - print 'Doing nothing.' + print('Doing nothing.') return dataset = regression_utils.get_dataset() diff --git a/regression/populate_datastore.py b/regression/populate_datastore.py index d4ffb37a5f69..34f65cf4d132 100644 --- a/regression/populate_datastore.py +++ b/regression/populate_datastore.py @@ -1,5 +1,6 @@ """Script to populate datastore with regression test data.""" +from six.moves import zip from gcloud import datastore # This assumes the command is being run via tox hence the @@ -82,8 +83,8 @@ def add_characters(): entity = datastore.entity.Entity(dataset=dataset).key(key) entity.update(character) entity.save() - print 'Adding Character %s %s' % (character['name'], - character['family']) + print('Adding Character %s %s' % (character['name'], + character['family'])) if __name__ == '__main__': diff --git a/regression/regression_utils.py b/regression/regression_utils.py index 6255231dc785..423c8f98d056 100644 --- a/regression/regression_utils.py +++ b/regression/regression_utils.py @@ -1,3 +1,4 @@ +from __future__ import print_function import os import sys @@ -21,12 +22,12 @@ def get_environ(require_datastore=False, require_storage=False): if require_datastore: if DATASET_ID is None or CLIENT_EMAIL is None or KEY_FILENAME is None: - print >> sys.stderr, ENVIRON_ERROR_MSG + print(ENVIRON_ERROR_MSG, file=sys.stderr) sys.exit(1) if require_storage: if PROJECT_ID is None or CLIENT_EMAIL is None or KEY_FILENAME is None: - print >> sys.stderr, ENVIRON_ERROR_MSG + print(ENVIRON_ERROR_MSG, file=sys.stderr) sys.exit(1) return { diff --git a/run_pylint.py b/run_pylint.py index 333b16d88a17..fa3c7f7cd1a8 100644 --- a/run_pylint.py +++ b/run_pylint.py @@ -22,16 +22,18 @@ PRODUCTION_RC = 'pylintrc_default' TEST_RC = 'pylintrc_reduced' TEST_DISABLED_MESSAGES = [ - 'invalid-name', - 'missing-docstring', - 'too-many-public-methods', - 'too-few-public-methods', 'attribute-defined-outside-init', - 'unbalanced-tuple-unpacking', - 'too-many-locals', 'exec-used', + 'import-error', + 'invalid-name', + 'missing-docstring', 'no-init', 'no-self-use', + 'superfluous-parens', + 'too-few-public-methods', + 'too-many-locals', + 'too-many-public-methods', + 'unbalanced-tuple-unpacking', ] TEST_RC_ADDITIONS = { 'MESSAGES CONTROL': { diff --git a/setup.py b/setup.py index b0d6002fcca7..e7328f4c0991 100644 --- a/setup.py +++ b/setup.py @@ -8,9 +8,7 @@ if sys.version_info <= (2, 4): - ERROR = 'Requires Python Version 2.5 or above... exiting.' - print >> sys.stderr, ERROR - sys.exit(1) + raise Exception('Requires Python Version 2.5 or above... exiting.') REQUIREMENTS = [ @@ -20,6 +18,7 @@ 'pycrypto', 'pyopenssl', 'pytz', + 'six', ] setup(