Skip to content
This repository has been archived by the owner on Jun 27, 2018. It is now read-only.

Commit

Permalink
Merge remote-tracking branch 'upstream/develop' into develop
Browse files Browse the repository at this point in the history
  • Loading branch information
shahms committed Feb 15, 2013
2 parents 6022679 + 7648c38 commit 8369a78
Show file tree
Hide file tree
Showing 36 changed files with 2,189 additions and 690 deletions.
57 changes: 44 additions & 13 deletions boto/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
# Copyright (c) 2010-2011, Eucalyptus Systems, Inc.
# Copyright (c) 2011, Nexenta Systems Inc.
# Copyright (c) 2012 Amazon.com, Inc. or its affiliates.
# Copyright (c) 2010, Google, Inc.
# All rights reserved.
#
# Permission is hereby granted, free of charge, to any person obtaining a
Expand Down Expand Up @@ -41,6 +42,14 @@
UserAgent = 'Boto/%s (%s)' % (__version__, sys.platform)
config = Config()

# Regex to disallow buckets violating charset or not [3..255] chars total.
BUCKET_NAME_RE = re.compile(r'^[a-z0-9][a-z0-9\._-]{1,253}[a-z0-9]$')
# Regex to disallow buckets with individual DNS labels longer than 63.
TOO_LONG_DNS_NAME_COMP = re.compile(r'[-_a-z0-9]{64}')
GENERATION_RE = re.compile(r'(?P<versionless_uri_str>.+)'
r'#(?P<generation>[0-9]{16,})$')
VERSION_RE = re.compile('(?P<versionless_uri_str>.+)#(?P<version_id>.+)$')


def init_logging():
for file in BotoConfigLocations:
Expand Down Expand Up @@ -657,7 +666,7 @@ def connect_elastictranscoder(aws_access_key_id=None,

def storage_uri(uri_str, default_scheme='file', debug=0, validate=True,
bucket_storage_uri_class=BucketStorageUri,
suppress_consec_slashes=True):
suppress_consec_slashes=True, is_latest=False):
"""
Instantiate a StorageUri from a URI string.
Expand All @@ -673,6 +682,9 @@ def storage_uri(uri_str, default_scheme='file', debug=0, validate=True,
:param bucket_storage_uri_class: Allows mocking for unit tests.
:param suppress_consec_slashes: If provided, controls whether
consecutive slashes will be suppressed in key paths.
:type is_latest: bool
:param is_latest: whether this versioned object represents the
current version.
We allow validate to be disabled to allow caller
to implement bucket-level wildcarding (outside the boto library;
Expand All @@ -684,14 +696,17 @@ def storage_uri(uri_str, default_scheme='file', debug=0, validate=True,
``uri_str`` must be one of the following formats:
* gs://bucket/name
* gs://bucket/name#ver
* s3://bucket/name
* gs://bucket
* s3://bucket
* filename (which could be a Unix path like /a/b/c or a Windows path like
C:\a\b\c)
The last example uses the default scheme ('file', unless overridden)
The last example uses the default scheme ('file', unless overridden).
"""
version_id = None
generation = None

# Manually parse URI components instead of using urlparse.urlparse because
# what we're calling URIs don't really fit the standard syntax for URIs
Expand All @@ -708,7 +723,8 @@ def storage_uri(uri_str, default_scheme='file', debug=0, validate=True,
if not (platform.system().lower().startswith('windows')
and colon_pos == 1
and drive_char >= 'a' and drive_char <= 'z'):
raise InvalidUriError('"%s" contains ":" instead of "://"' % uri_str)
raise InvalidUriError('"%s" contains ":" instead of "://"' %
uri_str)
scheme = default_scheme.lower()
path = uri_str
else:
Expand All @@ -727,23 +743,38 @@ def storage_uri(uri_str, default_scheme='file', debug=0, validate=True,
else:
path_parts = path.split('/', 1)
bucket_name = path_parts[0]
if (validate and bucket_name and
# Disallow buckets violating charset or not [3..255] chars total.
(not re.match('^[a-z0-9][a-z0-9\._-]{1,253}[a-z0-9]$', bucket_name)
# Disallow buckets with individual DNS labels longer than 63.
or re.search('[-_a-z0-9]{64}', bucket_name))):
raise InvalidUriError('Invalid bucket name in URI "%s"' % uri_str)
# If enabled, ensure the bucket name is valid, to avoid possibly
# confusing other parts of the code. (For example if we didn't
object_name = ''
# If validate enabled, ensure the bucket name is valid, to avoid
# possibly confusing other parts of the code. (For example if we didn't
# catch bucket names containing ':', when a user tried to connect to
# the server with that name they might get a confusing error about
# non-integer port numbers.)
object_name = ''
if (validate and bucket_name and
(not BUCKET_NAME_RE.match(bucket_name)
or TOO_LONG_DNS_NAME_COMP.search(bucket_name))):
raise InvalidUriError('Invalid bucket name in URI "%s"' % uri_str)
if scheme == 'gs':
match = GENERATION_RE.search(path)
if match:
md = match.groupdict()
versionless_uri_str = md['versionless_uri_str']
path_parts = versionless_uri_str.split('/', 1)
generation = int(md['generation'])
elif scheme == 's3':
match = VERSION_RE.search(path)
if match:
md = match.groupdict()
versionless_uri_str = md['versionless_uri_str']
path_parts = versionless_uri_str.split('/', 1)
version_id = md['version_id']
else:
raise InvalidUriError('Unrecognized scheme "%s"' % scheme)
if len(path_parts) > 1:
object_name = path_parts[1]
return bucket_storage_uri_class(
scheme, bucket_name, object_name, debug,
suppress_consec_slashes=suppress_consec_slashes)
suppress_consec_slashes=suppress_consec_slashes,
version_id=version_id, generation=generation, is_latest=is_latest)


def storage_uri_for_key(key):
Expand Down
Loading

0 comments on commit 8369a78

Please sign in to comment.