docs: def push(package, is_public=False, is_team=False, reupload=False, hash=None):
      """
      Push a Quilt data package to the server
      """
      team, owner, pkg, subpath = parse_package(package, allow_subpath=True)
      _check_team_id(team)
      session = _get_session(team)
  
      store, pkgroot = PackageStore.find_package(team, owner, pkg, pkghash=hash)
      if pkgroot is None:
          raise CommandException("Package {package} not found.".format(package=package))
  
      pkghash = hash_contents(pkgroot)
      if hash is not None:
          assert pkghash == hash
      contents = pkgroot
  
      for component in subpath:
          try:
              contents = contents.children[component]
          except (AttributeError, KeyError):
              raise CommandException("Invalid subpath: %r" % component)
  
      def _push_package(dry_run=False, sizes=dict()):
          data = json.dumps(dict(
              dry_run=dry_run,
              is_public=is_public,
              is_team=is_team,
              contents=contents,
              description="",  # TODO
              sizes=sizes
          ), default=encode_node)
  
          compressed_data = gzip_compress(data.encode('utf-8'))
  
          if subpath:
              return session.post(
                  "{url}/api/package_update/{owner}/{pkg}/{subpath}".format(
                      url=get_registry_url(team),
                      owner=owner,
                      pkg=pkg,
                      subpath='/'.join(subpath)
                  ),
                  data=compressed_data,
                  headers={
                      'Content-Encoding': 'gzip'
                  }
              )
          else:
              return session.put(
                  "{url}/api/package/{owner}/{pkg}/{hash}".format(
                      url=get_registry_url(team),
                      owner=owner,
                      pkg=pkg,
                      hash=pkghash
                  ),
                  data=compressed_data,
                  headers={
                      'Content-Encoding': 'gzip'
                  }
              )
  
      print("Fetching upload URLs from the registry...")
      resp = _push_package(dry_run=True)
      obj_urls = resp.json()['upload_urls']
  
      assert set(obj_urls) == set(find_object_hashes(contents))
  
      obj_sizes = {
          obj_hash: os.path.getsize(store.object_path(obj_hash)) for obj_hash in obj_urls
      }
  
      success = upload_fragments(store, obj_urls, obj_sizes, reupload=reupload)
      if not success:
          raise CommandException("Failed to upload fragments")
  
      print("Uploading package metadata...")
      resp = _push_package(sizes=obj_sizes)
      package_url = resp.json()['package_url']
  
      if not subpath:
          # Update the latest tag.
          print("Updating the 'latest' tag...")
          session.put(
              "{url}/api/tag/{owner}/{pkg}/{tag}".format(
                  url=get_registry_url(team),
                  owner=owner,
                  pkg=pkg,
                  tag=LATEST_TAG
              ),
              data=json.dumps(dict(
                  hash=pkghash
              ))
          )
  
      print("Push complete. %s is live:\n%s" % (package, package_url))