text: # Copyright (c) Jupyter Development Team.
  # Distributed under the terms of the Modified BSD License.
  import atexit
  import os
  import os.path as osp
  import re
  import shlex
  from glob import glob
  from pathlib import Path
  from subprocess import PIPE, CalledProcessError, Popen
  from tempfile import TemporaryDirectory
  
  from jupyter_releaser import util
  
  PYPROJECT = util.PYPROJECT
  SETUP_PY = util.SETUP_PY
  
  
  def build_dist(dist_dir, clean=True):
      """Build the python dist files into a dist folder"""
      # Clean the dist folder of existing npm tarballs
      os.makedirs(dist_dir, exist_ok=True)
      dest = Path(dist_dir)
      if clean:
          for pkg in glob(f"{dest}/*.gz") + glob(f"{dest}/*.whl"):
              os.remove(pkg)
  
      if PYPROJECT.exists():
          util.run(f"python -m build --outdir {dest} .", quiet=True, show_cwd=True)
      elif SETUP_PY.exists():
          util.run(f"python setup.py sdist --dist-dir {dest}", quiet=True)
          util.run(f"python setup.py bdist_wheel --dist-dir {dest}", quiet=True)
  
  
  def check_dist(dist_file, test_cmd="", python_imports=None, check_cmd="twine check --strict"):
      """Check a Python package locally (not as a cli)"""
      dist_file = util.normalize_path(dist_file)
      util.run(f"{check_cmd} {dist_file}")
  
      test_commands = []
  
      if test_cmd:
          test_commands.append(test_cmd)
      elif python_imports is not None:
          test_commands.extend([f'python -c "import {name}"' for name in python_imports])
      else:
          # Get the package name from the dist file name
          name = re.match(r"(\S+)-\d", osp.basename(dist_file)).groups()[0]
          name = name.replace("-", "_")
          test_commands.append(f'python -c "import {name}"')
  
      # Create venvs to install dist file
      # run the test command in the venv
      with TemporaryDirectory() as td:
          env_path = util.normalize_path(osp.abspath(td))
          if os.name == "nt":  # pragma: no cover
              bin_path = f"{env_path}/Scripts/"
          else:
              bin_path = f"{env_path}/bin"
  
          # Create the virtual env, upgrade pip,
          # install, and run test command
          util.run(f"python -m venv {env_path}")
          util.run(f"{bin_path}/python -m pip install -q -U pip")
          util.run(f"{bin_path}/pip install -q {dist_file}")
          try:
              for cmd in test_commands:
                  util.run(f"{bin_path}/{cmd}")
          except CalledProcessError as e:
              if test_cmd == "":
                  util.log(
                      'You may need to set "check_imports" to appropriate Python package names in the config file.'
                  )
              raise e
  
  
  def get_pypi_token(release_url, python_package):
      """Get the PyPI token
  
      Note: Do not print the token in CI since it will not be sanitized
      if it comes from the PYPI_TOKEN_MAP"""
      twine_pwd = os.environ.get("PYPI_TOKEN", "")
      pypi_token_map = os.environ.get("PYPI_TOKEN_MAP", "").replace(r"\n", "\n")
      if pypi_token_map and release_url:
          parts = release_url.replace("https://github.com/", "").split("/")
          repo_name = f"{parts[0]}/{parts[1]}"
          if python_package != ".":
              repo_name += f"/{python_package}"
          util.log(f"Looking for PYPI token for {repo_name} in token map")
          for line in pypi_token_map.splitlines():
              name, _, token = line.partition(",")
              if name == repo_name:
                  twine_pwd = token.strip()
                  util.log(f"Found PYPI token in map ending in {twine_pwd[-5:]}")
      elif twine_pwd:
          util.log("Using PYPI token from PYPI_TOKEN")
      else:
          util.log("PYPI token not found")
  
      return twine_pwd
  
  
  def start_local_pypi():
      """Start a local PyPI server"""
      temp_dir = TemporaryDirectory()
      cmd = f"pypi-server -p 8081  -P . -a . -o  -v {temp_dir.name}"
      proc = Popen(shlex.split(cmd), stderr=PIPE)
      # Wait for the server to start
      while True:
          line = proc.stderr.readline().decode("utf-8").strip()
          util.log(line)
          if "Listening on" in line:
              break
      atexit.register(proc.kill)
      atexit.register(temp_dir.cleanup)
  