text: """
  This module exports some simple names used throughout the CodaLab bundle system:
    - The various CodaLab error classes, with documentation for each.
    - The State class, an enumeration of all legal bundle states.
    - precondition, a utility method that check's a function's input preconditions.
  """
  import os
  import http.client
  import urllib.request
  import urllib.error
  
  from dataclasses import dataclass
  from retry import retry
  from enum import Enum
  
  # Increment this on master when ready to cut a release.
  # http://semver.org/
  CODALAB_VERSION = '0.5.50'
  BINARY_PLACEHOLDER = '<binary>'
  URLOPEN_TIMEOUT_SECONDS = int(os.environ.get('CODALAB_URLOPEN_TIMEOUT_SECONDS', 5 * 60))
  
  
  class IntegrityError(ValueError):
      """
      Raised by the model when there is a database integrity issue.
  
      Indicates a serious error that either means that there was a bug in the model
      code that left the database in a bad state, or that there was an out-of-band
      database edit with the same result.
      """
  
  
  class PreconditionViolation(ValueError):
      """
      Raised when a value generated by one module fails to satisfy a precondition
      required by another module.
  
      This class of error is serious and should indicate a problem in code, but it
      it is not an AssertionError because it is not local to a single module.
      """
  
  
  class UsageError(ValueError):
      """
      Raised when user input causes an exception. This error is the only one for
      which the command-line client suppresses output.
      """
  
  
  class NotFoundError(UsageError):
      """
      Raised when a requested resource has not been found. Similar to HTTP status
      404.
      """
  
  
  class AuthorizationError(UsageError):
      """
      Raised when access to a resource is refused because authentication is required
      and has not been provided. Similar to HTTP status 401.
      """
  
  
  class PermissionError(UsageError):
      """
      Raised when access to a resource is refused because the user does not have
      necessary permissions. Similar to HTTP status 403.
      """
  
  
  class LoginPermissionError(ValueError):
      """
      Raised when the login credentials are incorrect.
      """
  
  
  class DiskQuotaExceededError(ValueError):
      """
      Raised when the disk quota left on the server is less than the bundle size.
      """
  
  
  # Listed in order of most specific to least specific.
  http_codes_and_exceptions = [
      (http.client.FORBIDDEN, PermissionError),
      (http.client.UNAUTHORIZED, AuthorizationError),
      (http.client.NOT_FOUND, NotFoundError),
      (http.client.BAD_REQUEST, UsageError),
  ]
  
  
  def exception_to_http_error(e):
      """
      Returns the appropriate HTTP error code and message for the given exception.
      """
      for known_code, exception_type in http_codes_and_exceptions:
          if isinstance(e, exception_type):
              return known_code, str(e)
      return http.client.INTERNAL_SERVER_ERROR, str(e)
  
  
  def http_error_to_exception(code, message):
      """
      Returns the appropriate exception for the given HTTP error code and message.
      """
      for known_code, exception_type in http_codes_and_exceptions:
          if code == known_code:
              return exception_type(message)
      if code >= 400 and code < 500:
          return UsageError(message)
      return Exception(message)
  
  
  def precondition(condition, message):
      if not condition:
          raise PreconditionViolation(message)
  
  
  def ensure_str(response):
      """
      Ensure the data type of input response to be string
      :param response: a response in bytes or string
      :return: the input response in string
      """
      if isinstance(response, str):
          return response
      try:
          return response.decode()
      except UnicodeDecodeError:
          return BINARY_PLACEHOLDER
  
  
  @retry(urllib.error.URLError, tries=2, delay=1, backoff=2)
  def urlopen_with_retry(request: urllib.request.Request, timeout: int = URLOPEN_TIMEOUT_SECONDS):
      """
      Makes a request using urlopen with a timeout of URLOPEN_TIMEOUT_SECONDS seconds and retries on failures.
      Retries a maximum of 2 times, with an initial delay of 1 second and
      exponential backoff factor of 2 for subsequent failures (1s and 2s).
      :param request: Can be a url string or a Request object
      :param timeout: Timeout for urlopen in seconds
      :return: the response object
      """
      return urllib.request.urlopen(request, timeout=timeout)
  
  
  class StorageType(Enum):
      """Possible storage types for bundles.
      When updating this enum, sync it with with the enum in the storage_type column
      in codalab.model.tables and add the appropriate migrations to reflect the column change.
      """
  
      DISK_STORAGE = "disk"
      AZURE_BLOB_STORAGE = "azure_blob"
  
  
  class StorageURLScheme(Enum):
      """Possible storage URL schemes. URLs for the
      corresponding storage type will begin with the
      scheme specified.
      """
  
      DISK_STORAGE = ""
      AZURE_BLOB_STORAGE = "azfs://"
  
  
  @dataclass(frozen=True)
  class LinkedBundlePath:
      """A LinkedBundlePath refers to a path that points to the location of a linked bundle within a specific storage location.
      It can either point directly to the bundle, or to a file that is located within that bundle.
      It is constructed by parsing a given bundle link URL by calling parse_bundle_url().
  
      Attributes:
          storage_type (StorageType): Which storage type is used to store this bundle.
  
          bundle_path (str): Path to the bundle contents in that particular storage.
  
          is_archive (bool): Whether this bundle is stored as an indexed archive file (contents.gz / contents.tar.gz + an index.sqlite file. Only done currently by Azure Blob Storage.
  
          is_archive_dir (bool): Whether this bundle is stored as a contents.tar.gz file (which represents a directory) or
          a contents.gz file (which represents a single file). Only applicable if is_archive is True.
  
          uses_beam (bool): Whether this bundle's storage type requires using Apache Beam to interact with it.
  
          archive_subpath (str): If is_archive is True, returns the subpath within the archive file for the file that this BundlePath points to.
  
          bundle_uuid (str): UUID of the bundle that this path refers to.
      """
  
      storage_type: StorageType
      bundle_path: str
      is_archive: bool
      is_archive_dir: bool
      uses_beam: bool
      archive_subpath: str
      bundle_uuid: str
  
  
  def parse_linked_bundle_url(url):
      """Parses a linked bundle URL. This bundle URL usually refers to:
          - an archive file on Blob Storage: "azfs://storageclwsdev0/bundles/uuid/contents.tar.gz" (contents.gz for files, contents.tar.gz for directories)
          - a single file that is stored within a subpath of an archive file on Blob Storage: "azfs://storageclwsdev0/bundles/uuid/contents.tar.gz/file1"
  
          Returns a LinkedBundlePath instance to encode this information.
      """
      if url.startswith(StorageURLScheme.AZURE_BLOB_STORAGE.value):
          uses_beam = True
          storage_type = StorageType.AZURE_BLOB_STORAGE.value
          url = url[len(StorageURLScheme.AZURE_BLOB_STORAGE.value) :]
          storage_account, container, bundle_uuid, contents_file, *remainder = url.split("/", 4)
          bundle_path = f"{StorageURLScheme.AZURE_BLOB_STORAGE.value}{storage_account}/{container}/{bundle_uuid}/{contents_file}"
          is_archive = contents_file.endswith(".gz") or contents_file.endswith(".tar.gz")
          is_archive_dir = contents_file.endswith(".tar.gz")
          archive_subpath = remainder[0] if is_archive and len(remainder) else None
      else:
          storage_type = StorageType.DISK_STORAGE.value
          bundle_path = url
          is_archive = False
          is_archive_dir = False
          uses_beam = False
          archive_subpath = None
          bundle_uuid = None
      return LinkedBundlePath(
          storage_type=storage_type,
          bundle_path=bundle_path,
          is_archive=is_archive,
          is_archive_dir=is_archive_dir,
          uses_beam=uses_beam,
          archive_subpath=archive_subpath,
          bundle_uuid=bundle_uuid,
      )
  