files: # Licensed to the Apache Software Foundation (ASF) under one or more
  # contributor license agreements.  See the NOTICE file distributed with
  # this work for additional information regarding copyright ownership.
  # The ASF licenses this file to You 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.
  
  """
  Provides base classes for working with storage
  """
  
  # Backward compatibility for Python 2.5
  from __future__ import with_statement
  
  from typing import Dict
  from typing import Iterator
  from typing import List
  from typing import Optional
  from typing import Type
  
  import os.path                          # pylint: disable-msg=W0404
  import hashlib
  import warnings
  import errno
  from os.path import join as pjoin
  
  from libcloud.utils.py3 import httplib
  from libcloud.utils.py3 import b
  
  import libcloud.utils.files
  from libcloud.common.types import LibcloudError
  from libcloud.common.base import Connection
  from libcloud.common.base import ConnectionUserAndKey, BaseDriver
  from libcloud.storage.types import ObjectDoesNotExistError
  
  __all__ = [
      'Object',
      'Container',
      'StorageDriver',
  
      'CHUNK_SIZE',
      'DEFAULT_CONTENT_TYPE'
  ]
  
  CHUNK_SIZE = 8096
  
  # Default Content-Type which is sent when uploading an object if one is not
  # supplied and can't be detected when using non-strict mode.
  DEFAULT_CONTENT_TYPE = 'application/octet-stream'
  
  
  class Object(object):
      """
      Represents an object (BLOB).
      """
  
      def __init__(self,
                   name,  # type: str
                   size,  # type: int
                   hash,  # type: str
                   extra,  # type: dict
                   meta_data,  # type: dict
                   container,  # type: Container
                   driver,  # type: StorageDriver
                   ):
          """
          :param name: Object name (must be unique per container).
          :type  name: ``str``
  
          :param size: Object size in bytes.
          :type  size: ``int``
  
          :param hash: Object hash.
          :type  hash: ``str``
  
          :param container: Object container.
          :type  container: :class:`libcloud.storage.base.Container`
  
          :param extra: Extra attributes.
          :type  extra: ``dict``
  
          :param meta_data: Optional object meta data.
          :type  meta_data: ``dict``
  
          :param driver: StorageDriver instance.
          :type  driver: :class:`libcloud.storage.base.StorageDriver`
          """
  
          self.name = name
          self.size = size
          self.hash = hash
          self.container = container
          self.extra = extra or {}
          self.meta_data = meta_data or {}
          self.driver = driver
  
      def get_cdn_url(self):
          # type: () -> str
          return self.driver.get_object_cdn_url(obj=self)
  
      def enable_cdn(self):
          # type: () -> bool
          return self.driver.enable_object_cdn(obj=self)
  
      def download(self, destination_path, overwrite_existing=False,
                   delete_on_failure=True):
          # type: (str, bool, bool) -> bool
          return self.driver.download_object(self, destination_path,
                                             overwrite_existing,
                                             delete_on_failure)
  
      def as_stream(self, chunk_size=None):
          # type: (Optional[int]) -> Iterator[bytes]
          return self.driver.download_object_as_stream(self, chunk_size)
  
      def delete(self):
          # type: () -> bool
          return self.driver.delete_object(self)
  
      def __repr__(self):
          return ('<Object: name=%s, size=%s, hash=%s, provider=%s ...>' %
                  (self.name, self.size, self.hash, self.driver.name))
  
  
  class Container(object):
      """
      Represents a container (bucket) which can hold multiple objects.
      """
  
      def __init__(self,
                   name,  # type: str
                   extra,  # type: dict
                   driver,  # type: StorageDriver
                   ):
          """
          :param name: Container name (must be unique).
          :type name: ``str``
  
          :param extra: Extra attributes.
          :type extra: ``dict``
  
          :param driver: StorageDriver instance.
          :type driver: :class:`libcloud.storage.base.StorageDriver`
          """
  
          self.name = name
          self.extra = extra or {}
          self.driver = driver
  
      def iterate_objects(self, prefix=None, ex_prefix=None):
          # type: (Optional[str], Optional[str]) -> Iterator[Object]
          return self.driver.iterate_container_objects(container=self,
                                                       prefix=prefix,
                                                       ex_prefix=ex_prefix)
  
      def list_objects(self, prefix=None, ex_prefix=None):
          # type: (Optional[str], Optional[str]) -> List[Object]
          return self.driver.list_container_objects(container=self,
                                                    prefix=prefix,
                                                    ex_prefix=ex_prefix)
  
      def get_cdn_url(self):
          # type: () -> str
          return self.driver.get_container_cdn_url(container=self)
  
      def enable_cdn(self):
          # type: () -> bool
          return self.driver.enable_container_cdn(container=self)
  
      def get_object(self, object_name):
          # type: (str) -> Object
          return self.driver.get_object(container_name=self.name,
                                        object_name=object_name)
  
      def upload_object(self, file_path, object_name, extra=None,
                        verify_hash=True, headers=None):
          # type: (str, str,
  
  [... the rest is omitted ...]
files: libcloud/storage/base.py
files: # Licensed to the Apache Software Foundation (ASF) under one or more
  # contributor license agreements.  See the NOTICE file distributed with
  # this work for additional information regarding copyright ownership.
  # The ASF licenses this file to You 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.
  
  """
  Provides base classes for working with storage
  """
  
  # Backward compatibility for Python 2.5
  from __future__ import with_statement
  
  from typing import Dict
  from typing import Iterator
  from typing import List
  from typing import Optional
  from typing import Type
  
  import os.path                          # pylint: disable-msg=W0404
  import hashlib
  import warnings
  import errno
  from os.path import join as pjoin
  
  from libcloud.utils.py3 import httplib
  from libcloud.utils.py3 import b
  
  import libcloud.utils.files
  from libcloud.common.types import LibcloudError
  from libcloud.common.base import Connection
  from libcloud.common.base import ConnectionUserAndKey, BaseDriver
  from libcloud.storage.types import ObjectDoesNotExistError
  
  __all__ = [
      'Object',
      'Container',
      'StorageDriver',
  
      'CHUNK_SIZE',
      'DEFAULT_CONTENT_TYPE'
  ]
  
  CHUNK_SIZE = 8096
  
  # Default Content-Type which is sent when uploading an object if one is not
  # supplied and can't be detected when using non-strict mode.
  DEFAULT_CONTENT_TYPE = 'application/octet-stream'
  
  
  class Object(object):
      """
      Represents an object (BLOB).
      """
  
      def __init__(self,
                   name,  # type: str
                   size,  # type: int
                   hash,  # type: str
                   extra,  # type: dict
                   meta_data,  # type: dict
                   container,  # type: Container
                   driver,  # type: StorageDriver
                   ):
          """
          :param name: Object name (must be unique per container).
          :type  name: ``str``
  
          :param size: Object size in bytes.
          :type  size: ``int``
  
          :param hash: Object hash.
          :type  hash: ``str``
  
          :param container: Object container.
          :type  container: :class:`libcloud.storage.base.Container`
  
          :param extra: Extra attributes.
          :type  extra: ``dict``
  
          :param meta_data: Optional object meta data.
          :type  meta_data: ``dict``
  
          :param driver: StorageDriver instance.
          :type  driver: :class:`libcloud.storage.base.StorageDriver`
          """
  
          self.name = name
          self.size = size
          self.hash = hash
          self.container = container
          self.extra = extra or {}
          self.meta_data = meta_data or {}
          self.driver = driver
  
      def get_cdn_url(self):
          # type: () -> str
          return self.driver.get_object_cdn_url(obj=self)
  
      def enable_cdn(self):
          # type: () -> bool
          return self.driver.enable_object_cdn(obj=self)
  
      def download(self, destination_path, overwrite_existing=False,
                   delete_on_failure=True):
          # type: (str, bool, bool) -> bool
          return self.driver.download_object(self, destination_path,
                                             overwrite_existing,
                                             delete_on_failure)
  
      def as_stream(self, chunk_size=None):
          # type: (Optional[int]) -> Iterator[bytes]
          return self.driver.download_object_as_stream(self, chunk_size)
  
      def delete(self):
          # type: () -> bool
          return self.driver.delete_object(self)
  
      def __repr__(self):
          return ('<Object: name=%s, size=%s, hash=%s, provider=%s ...>' %
                  (self.name, self.size, self.hash, self.driver.name))
  
  
  class Container(object):
      """
      Represents a container (bucket) which can hold multiple objects.
      """
  
      def __init__(self,
                   name,  # type: str
                   extra,  # type: dict
                   driver,  # type: StorageDriver
                   ):
          """
          :param name: Container name (must be unique).
          :type name: ``str``
  
          :param extra: Extra attributes.
          :type extra: ``dict``
  
          :param driver: StorageDriver instance.
          :type driver: :class:`libcloud.storage.base.StorageDriver`
          """
  
          self.name = name
          self.extra = extra or {}
          self.driver = driver
  
      def iterate_objects(self, prefix=None, ex_prefix=None):
          # type: (Optional[str], Optional[str]) -> Iterator[Object]
          return self.driver.iterate_container_objects(container=self,
                                                       prefix=prefix,
                                                       ex_prefix=ex_prefix)
  
      def list_objects(self, prefix=None, ex_prefix=None):
          # type: (Optional[str], Optional[str]) -> List[Object]
          return self.driver.list_container_objects(container=self,
                                                    prefix=prefix,
                                                    ex_prefix=ex_prefix)
  
      def get_cdn_url(self):
          # type: () -> str
          return self.driver.get_container_cdn_url(container=self)
  
      def enable_cdn(self):
          # type: () -> bool
          return self.driver.enable_container_cdn(container=self)
  
      def get_object(self, object_name):
          # type: (str) -> Object
          return self.driver.get_object(container_name=self.name,
                                        object_name=object_name)
  
      def upload_object(self, file_path, object_name, extra=None,
                        verify_hash=True, headers=None):
          # type: (str, str,
  
  [... the rest is omitted ...]
files: libcloud/storage/base.py
files: # Licensed to the Apache Software Foundation (ASF) under one or more
  # contributor license agreements.  See the NOTICE file distributed with
  # this work for additional information regarding copyright ownership.
  # The ASF licenses this file to You 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.
  
  """
  Provides storage driver for working with local filesystem
  """
  
  from __future__ import with_statement
  
  import errno
  import os
  import shutil
  
  try:
      import lockfile
      from lockfile import LockTimeout, mkdirlockfile
  except ImportError:
      raise ImportError('Missing lockfile dependency, you can install it '
                        'using pip: pip install lockfile')
  
  from libcloud.utils.files import read_in_chunks
  from libcloud.utils.files import exhaust_iterator
  from libcloud.utils.py3 import relpath
  from libcloud.utils.py3 import u
  from libcloud.common.base import Connection
  from libcloud.storage.base import Object, Container, StorageDriver
  from libcloud.common.types import LibcloudError
  from libcloud.storage.types import ContainerAlreadyExistsError
  from libcloud.storage.types import ContainerDoesNotExistError
  from libcloud.storage.types import ContainerIsNotEmptyError
  from libcloud.storage.types import ObjectError
  from libcloud.storage.types import ObjectDoesNotExistError
  from libcloud.storage.types import InvalidContainerNameError
  
  IGNORE_FOLDERS = ['.lock', '.hash']
  
  
  class LockLocalStorage(object):
      """
      A class to help in locking a local path before being updated
      """
      def __init__(self, path):
          self.path = path
          self.lock = mkdirlockfile.MkdirLockFile(self.path, threaded=True)
  
      def __enter__(self):
          try:
              self.lock.acquire(timeout=0.1)
          except LockTimeout:
              raise LibcloudError('Lock timeout')
  
      def __exit__(self, type, value, traceback):
          if self.lock.is_locked():
              self.lock.release()
  
          if value is not None:
              raise value
  
  
  class LocalStorageDriver(StorageDriver):
      """
      Implementation of local file-system based storage. This is helpful
      where the user would want to use the same code (using libcloud) and
      switch between cloud storage and local storage
      """
  
      connectionCls = Connection
      name = 'Local Storage'
      website = 'http://example.com'
      hash_type = 'md5'
  
      def __init__(self, key, secret=None, secure=True, host=None, port=None,
                   **kwargs):
  
          # Use the key as the path to the storage
          self.base_path = key
  
          if not os.path.isdir(self.base_path):
              raise LibcloudError('The base path is not a directory')
  
          super(LocalStorageDriver, self).__init__(key=key, secret=secret,
                                                   secure=secure, host=host,
                                                   port=port, **kwargs)
  
      def _make_path(self, path, ignore_existing=True):
          """
          Create a path by checking if it already exists
          """
  
          try:
              os.makedirs(path)
          except OSError as exp:
              if exp.errno == errno.EEXIST and not ignore_existing:
                  raise exp
  
      def _check_container_name(self, container_name):
          """
          Check if the container name is valid
  
          :param container_name: Container name
          :type container_name: ``str``
          """
  
          if '/' in container_name or '\\' in container_name:
              raise InvalidContainerNameError(value=None, driver=self,
                                              container_name=container_name)
  
      def _make_container(self, container_name):
          """
          Create a container instance
  
          :param container_name: Container name.
          :type container_name: ``str``
  
          :return: Container instance.
          :rtype: :class:`Container`
          """
  
          self._check_container_name(container_name)
  
          full_path = os.path.join(self.base_path, container_name)
  
          try:
              stat = os.stat(full_path)
              if not os.path.isdir(full_path):
                  raise OSError('Target path is not a directory')
          except OSError:
              raise ContainerDoesNotExistError(value=None, driver=self,
                                               container_name=container_name)
  
          extra = {}
          extra['creation_time'] = stat.st_ctime
          extra['access_time'] = stat.st_atime
          extra['modify_time'] = stat.st_mtime
  
          return Container(name=container_name, extra=extra, driver=self)
  
      def _make_object(self, container, object_name):
          """
          Create an object instance
  
          :param container: Container.
          :type container: :class:`Container`
  
          :param object_name: Object name.
          :type object_name: ``str``
  
          :return: Object instance.
          :rtype: :class:`Object`
          """
  
          full_path = os.path.join(self.base_path, container.name, object_name)
  
          if os.path.isdir(full_path):
              raise ObjectError(value=None, driver=self, object_name=object_name)
  
          try:
              stat = os.stat(full_path)
          except Exception:
              raise ObjectDoesNotExistError(value=None, driver=self,
                                            object_name=object_name)
  
          # Make a hash for the file based on the metadata. We can safely
          # use only the mtime attribute here. If the file contents change,
          # the underlying file-system will change mtime
          data_hash = self._get_hash_function()
          data_hash.update(u(stat.st_mtime).encode('ascii'))
          data_hash = data_hash.hexdigest()
  
          extra = {}
          extra['creation_time'] = stat.st
  
  [... the rest is omitted ...]
files: libcloud/storage/drivers/local.py
files: # Licensed to the Apache Software Foundation (ASF) under one or more
  # contributor license agreements.  See the NOTICE file distributed with
  # this work for additional information regarding copyright ownership.
  # The ASF licenses this file to You 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.
  
  """
  Provides storage driver for working with local filesystem
  """
  
  from __future__ import with_statement
  
  import errno
  import os
  import shutil
  
  try:
      import lockfile
      from lockfile import LockTimeout, mkdirlockfile
  except ImportError:
      raise ImportError('Missing lockfile dependency, you can install it '
                        'using pip: pip install lockfile')
  
  from libcloud.utils.files import read_in_chunks
  from libcloud.utils.py3 import relpath
  from libcloud.utils.py3 import u
  from libcloud.common.base import Connection
  from libcloud.storage.base import Object, Container, StorageDriver
  from libcloud.common.types import LibcloudError
  from libcloud.storage.types import ContainerAlreadyExistsError
  from libcloud.storage.types import ContainerDoesNotExistError
  from libcloud.storage.types import ContainerIsNotEmptyError
  from libcloud.storage.types import ObjectError
  from libcloud.storage.types import ObjectDoesNotExistError
  from libcloud.storage.types import InvalidContainerNameError
  
  IGNORE_FOLDERS = ['.lock', '.hash']
  
  
  class LockLocalStorage(object):
      """
      A class to help in locking a local path before being updated
      """
      def __init__(self, path):
          self.path = path
          self.lock = mkdirlockfile.MkdirLockFile(self.path, threaded=True)
  
      def __enter__(self):
          try:
              self.lock.acquire(timeout=0.1)
          except LockTimeout:
              raise LibcloudError('Lock timeout')
  
      def __exit__(self, type, value, traceback):
          if self.lock.is_locked():
              self.lock.release()
  
          if value is not None:
              raise value
  
  
  class LocalStorageDriver(StorageDriver):
      """
      Implementation of local file-system based storage. This is helpful
      where the user would want to use the same code (using libcloud) and
      switch between cloud storage and local storage
      """
  
      connectionCls = Connection
      name = 'Local Storage'
      website = 'http://example.com'
      hash_type = 'md5'
  
      def __init__(self, key, secret=None, secure=True, host=None, port=None,
                   **kwargs):
  
          # Use the key as the path to the storage
          self.base_path = key
  
          if not os.path.isdir(self.base_path):
              raise LibcloudError('The base path is not a directory')
  
          super(LocalStorageDriver, self).__init__(key=key, secret=secret,
                                                   secure=secure, host=host,
                                                   port=port, **kwargs)
  
      def _make_path(self, path, ignore_existing=True):
          """
          Create a path by checking if it already exists
          """
  
          try:
              os.makedirs(path)
          except OSError as exp:
              if exp.errno == errno.EEXIST and not ignore_existing:
                  raise exp
  
      def _check_container_name(self, container_name):
          """
          Check if the container name is valid
  
          :param container_name: Container name
          :type container_name: ``str``
          """
  
          if '/' in container_name or '\\' in container_name:
              raise InvalidContainerNameError(value=None, driver=self,
                                              container_name=container_name)
  
      def _make_container(self, container_name):
          """
          Create a container instance
  
          :param container_name: Container name.
          :type container_name: ``str``
  
          :return: Container instance.
          :rtype: :class:`Container`
          """
  
          self._check_container_name(container_name)
  
          full_path = os.path.join(self.base_path, container_name)
  
          try:
              stat = os.stat(full_path)
              if not os.path.isdir(full_path):
                  raise OSError('Target path is not a directory')
          except OSError:
              raise ContainerDoesNotExistError(value=None, driver=self,
                                               container_name=container_name)
  
          extra = {}
          extra['creation_time'] = stat.st_ctime
          extra['access_time'] = stat.st_atime
          extra['modify_time'] = stat.st_mtime
  
          return Container(name=container_name, extra=extra, driver=self)
  
      def _make_object(self, container, object_name):
          """
          Create an object instance
  
          :param container: Container.
          :type container: :class:`Container`
  
          :param object_name: Object name.
          :type object_name: ``str``
  
          :return: Object instance.
          :rtype: :class:`Object`
          """
  
          full_path = os.path.join(self.base_path, container.name, object_name)
  
          if os.path.isdir(full_path):
              raise ObjectError(value=None, driver=self, object_name=object_name)
  
          try:
              stat = os.stat(full_path)
          except Exception:
              raise ObjectDoesNotExistError(value=None, driver=self,
                                            object_name=object_name)
  
          # Make a hash for the file based on the metadata. We can safely
          # use only the mtime attribute here. If the file contents change,
          # the underlying file-system will change mtime
          data_hash = self._get_hash_function()
          data_hash.update(u(stat.st_mtime).encode('ascii'))
          data_hash = data_hash.hexdigest()
  
          extra = {}
          extra['creation_time'] = stat.st_ctime
          extra['access_time'] =
  
  [... the rest is omitted ...]
files: libcloud/storage/drivers/local.py
files: # Licensed to the Apache Software Foundation (ASF) under one or more
  # contributor license agreements.  See the NOTICE file distributed with
  # this work for additional information regarding copyright ownership.
  # The ASF licenses this file to You 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.
  
  import base64
  import hmac
  import time
  from hashlib import sha1
  
  import libcloud.utils.py3
  
  try:
      if libcloud.utils.py3.DEFAULT_LXML:
          from lxml.etree import Element, SubElement
      else:
          from xml.etree.ElementTree import Element, SubElement
  except ImportError:
      from xml.etree.ElementTree import Element, SubElement
  
  from libcloud.utils.py3 import httplib
  from libcloud.utils.py3 import urlquote
  from libcloud.utils.py3 import b
  from libcloud.utils.py3 import tostring
  
  from libcloud.utils.xml import fixxpath, findtext
  from libcloud.utils.files import read_in_chunks
  from libcloud.common.types import InvalidCredsError, LibcloudError
  from libcloud.common.base import ConnectionUserAndKey, RawResponse
  from libcloud.common.aws import AWSBaseResponse, AWSDriver, \
      AWSTokenConnection, SignedAWSConnection
  
  from libcloud.storage.base import Object, Container, StorageDriver
  from libcloud.storage.types import ContainerError
  from libcloud.storage.types import ContainerIsNotEmptyError
  from libcloud.storage.types import InvalidContainerNameError
  from libcloud.storage.types import ContainerDoesNotExistError
  from libcloud.storage.types import ObjectDoesNotExistError
  from libcloud.storage.types import ObjectHashMismatchError
  
  # How long before the token expires
  EXPIRATION_SECONDS = 15 * 60
  
  S3_US_STANDARD_HOST = 's3.amazonaws.com'
  S3_US_EAST2_HOST = 's3-us-east-2.amazonaws.com'
  S3_US_WEST_HOST = 's3-us-west-1.amazonaws.com'
  S3_US_WEST_OREGON_HOST = 's3-us-west-2.amazonaws.com'
  S3_US_GOV_WEST_HOST = 's3-us-gov-west-1.amazonaws.com'
  S3_CN_NORTH_HOST = 's3.cn-north-1.amazonaws.com.cn'
  S3_CN_NORTHWEST_HOST = 's3.cn-northwest-1.amazonaws.com.cn'
  S3_EU_WEST_HOST = 's3-eu-west-1.amazonaws.com'
  S3_EU_WEST2_HOST = 's3-eu-west-2.amazonaws.com'
  S3_EU_CENTRAL_HOST = 's3-eu-central-1.amazonaws.com'
  S3_EU_NORTH1_HOST = 's3-eu-north-1.amazonaws.com'
  S3_AP_SOUTH_HOST = 's3-ap-south-1.amazonaws.com'
  S3_AP_SOUTHEAST_HOST = 's3-ap-southeast-1.amazonaws.com'
  S3_AP_SOUTHEAST2_HOST = 's3-ap-southeast-2.amazonaws.com'
  S3_AP_NORTHEAST1_HOST = 's3-ap-northeast-1.amazonaws.com'
  S3_AP_NORTHEAST2_HOST = 's3-ap-northeast-2.amazonaws.com'
  S3_AP_NORTHEAST_HOST = S3_AP_NORTHEAST1_HOST
  S3_SA_EAST_HOST = 's3-sa-east-1.amazonaws.com'
  S3_SA_SOUTHEAST2_HOST = 's3-sa-east-2.amazonaws.com'
  S3_CA_CENTRAL_HOST = 's3-ca-central-1.amazonaws.com'
  
  # Maps AWS region name to connection hostname
  REGION_TO_HOST_MAP = {
      'us-east-1': S3_US_STANDARD_HOST,
      'us-east-2': S3_US_EAST2_HOST,
      'us-west-1': S3_US_WEST_HOST,
      'us-west-2': S3_US_WEST_OREGON_HOST,
      'us-gov-west-1': S3_US_GOV_WEST_HOST,
      'cn-north-1': S3_CN_NORTH_HOST,
      'cn-northwest-1': S3_CN_NORTHWEST_HOST,
      'eu-west-1': S3_EU_WEST_HOST,
      'eu-west-2': S3_EU_WEST2_HOST,
      'eu-west-3': 's3.eu-west-3.amazonaws.com',
      'eu-north-1': 's3.eu-north-1.amazonaws.com',
      'eu-central-1': S3_EU_CENTRAL_HOST,
      'ap-south-1': S3_AP_SOUTH_HOST,
      'ap-southeast-1': S3_AP_SOUTHEAST_HOST,
      'ap-southeast-2': S3_AP_SOUTHEAST2_HOST,
      'ap-northeast-1': S3_AP_NORTHEAST1_HOST,
      'ap-northeast-2': S3_AP_NORTHEAST2_HOST,
      'ap-northeast-3': 's3.ap-northeast-3.amazonaws.com',
      'sa-east-1': S3_SA_EAST_HOST,
      'sa-east-2': S3_SA_SOUTHEAST2_HOST,
      'ca-central-1': S3_CA_CENTRAL_HOST,
      'me-south-1': 's3.me-south-1.amazonaws.com'
  }
  
  API_VERSION = '
  
  [... the rest is omitted ...]
files: libcloud/storage/drivers/s3.py
files: # Licensed to the Apache Software Foundation (ASF) under one or more
  # contributor license agreements.  See the NOTICE file distributed with
  # this work for additional information regarding copyright ownership.
  # The ASF licenses this file to You 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.
  
  import base64
  import hmac
  import time
  from hashlib import sha1
  
  import libcloud.utils.py3
  
  try:
      if libcloud.utils.py3.DEFAULT_LXML:
          from lxml.etree import Element, SubElement
      else:
          from xml.etree.ElementTree import Element, SubElement
  except ImportError:
      from xml.etree.ElementTree import Element, SubElement
  
  from libcloud.utils.py3 import httplib
  from libcloud.utils.py3 import urlquote
  from libcloud.utils.py3 import b
  from libcloud.utils.py3 import tostring
  
  from libcloud.utils.xml import fixxpath, findtext
  from libcloud.utils.files import read_in_chunks
  from libcloud.common.types import InvalidCredsError, LibcloudError
  from libcloud.common.base import ConnectionUserAndKey, RawResponse
  from libcloud.common.aws import AWSBaseResponse, AWSDriver, \
      AWSTokenConnection, SignedAWSConnection
  
  from libcloud.storage.base import Object, Container, StorageDriver
  from libcloud.storage.types import ContainerError
  from libcloud.storage.types import ContainerIsNotEmptyError
  from libcloud.storage.types import InvalidContainerNameError
  from libcloud.storage.types import ContainerDoesNotExistError
  from libcloud.storage.types import ObjectDoesNotExistError
  from libcloud.storage.types import ObjectHashMismatchError
  
  # How long before the token expires
  EXPIRATION_SECONDS = 15 * 60
  
  S3_US_STANDARD_HOST = 's3.amazonaws.com'
  S3_US_EAST2_HOST = 's3-us-east-2.amazonaws.com'
  S3_US_WEST_HOST = 's3-us-west-1.amazonaws.com'
  S3_US_WEST_OREGON_HOST = 's3-us-west-2.amazonaws.com'
  S3_US_GOV_WEST_HOST = 's3-us-gov-west-1.amazonaws.com'
  S3_CN_NORTH_HOST = 's3.cn-north-1.amazonaws.com.cn'
  S3_CN_NORTHWEST_HOST = 's3.cn-northwest-1.amazonaws.com.cn'
  S3_EU_WEST_HOST = 's3-eu-west-1.amazonaws.com'
  S3_EU_WEST2_HOST = 's3-eu-west-2.amazonaws.com'
  S3_EU_CENTRAL_HOST = 's3-eu-central-1.amazonaws.com'
  S3_EU_NORTH1_HOST = 's3-eu-north-1.amazonaws.com'
  S3_AP_SOUTH_HOST = 's3-ap-south-1.amazonaws.com'
  S3_AP_SOUTHEAST_HOST = 's3-ap-southeast-1.amazonaws.com'
  S3_AP_SOUTHEAST2_HOST = 's3-ap-southeast-2.amazonaws.com'
  S3_AP_NORTHEAST1_HOST = 's3-ap-northeast-1.amazonaws.com'
  S3_AP_NORTHEAST2_HOST = 's3-ap-northeast-2.amazonaws.com'
  S3_AP_NORTHEAST_HOST = S3_AP_NORTHEAST1_HOST
  S3_SA_EAST_HOST = 's3-sa-east-1.amazonaws.com'
  S3_SA_SOUTHEAST2_HOST = 's3-sa-east-2.amazonaws.com'
  S3_CA_CENTRAL_HOST = 's3-ca-central-1.amazonaws.com'
  
  # Maps AWS region name to connection hostname
  REGION_TO_HOST_MAP = {
      'us-east-1': S3_US_STANDARD_HOST,
      'us-east-2': S3_US_EAST2_HOST,
      'us-west-1': S3_US_WEST_HOST,
      'us-west-2': S3_US_WEST_OREGON_HOST,
      'us-gov-west-1': S3_US_GOV_WEST_HOST,
      'cn-north-1': S3_CN_NORTH_HOST,
      'cn-northwest-1': S3_CN_NORTHWEST_HOST,
      'eu-west-1': S3_EU_WEST_HOST,
      'eu-west-2': S3_EU_WEST2_HOST,
      'eu-west-3': 's3.eu-west-3.amazonaws.com',
      'eu-north-1': 's3.eu-north-1.amazonaws.com',
      'eu-central-1': S3_EU_CENTRAL_HOST,
      'ap-south-1': S3_AP_SOUTH_HOST,
      'ap-southeast-1': S3_AP_SOUTHEAST_HOST,
      'ap-southeast-2': S3_AP_SOUTHEAST2_HOST,
      'ap-northeast-1': S3_AP_NORTHEAST1_HOST,
      'ap-northeast-2': S3_AP_NORTHEAST2_HOST,
      'ap-northeast-3': 's3.ap-northeast-3.amazonaws.com',
      'sa-east-1': S3_SA_EAST_HOST,
      'sa-east-2': S3_SA_SOUTHEAST2_HOST,
      'ca-central-1': S3_CA_CENTRAL_HOST,
      'me-south-1': 's3.me-south-1.amazonaws.com'
  }
  
  API_VERSION = '
  
  [... the rest is omitted ...]
files: libcloud/storage/drivers/s3.py