Beispiel #1
0
def upload(upload_settings: settings.Settings, dists: List[str]) -> None:
    dists = commands._find_dists(dists)
    # Determine if the user has passed in pre-signed distributions
    signatures = {os.path.basename(d): d for d in dists if d.endswith(".asc")}
    uploads = [i for i in dists if not i.endswith(".asc")]

    upload_settings.check_repository_url()
    repository_url = cast(str, upload_settings.repository_config["repository"])
    print(f"Uploading distributions to {repository_url}")

    packages_to_upload = [
        _make_package(filename, signatures, upload_settings)
        for filename in uploads
    ]

    repository = upload_settings.create_repository()
    uploaded_packages = []

    for package in packages_to_upload:
        skip_message = "  Skipping {} because it appears to already exist".format(
            package.basefilename)

        # Note: The skip_existing check *needs* to be first, because otherwise
        #       we're going to generate extra HTTP requests against a hardcoded
        #       URL for no reason.
        if upload_settings.skip_existing and repository.package_is_uploaded(
                package):
            print(skip_message)
            continue

        resp = repository.upload(package)

        # Bug 92. If we get a redirect we should abort because something seems
        # funky. The behaviour is not well defined and redirects being issued
        # by PyPI should never happen in reality. This should catch malicious
        # redirects as well.
        if resp.is_redirect:
            raise exceptions.RedirectDetected.from_args(
                repository_url,
                resp.headers["location"],
            )

        if skip_upload(resp, upload_settings.skip_existing, package):
            print(skip_message)
            continue

        utils.check_status_code(resp, upload_settings.verbose)

        uploaded_packages.append(package)

    release_urls = repository.release_urls(uploaded_packages)
    if release_urls:
        print("\nView at:")
        for url in release_urls:
            print(url)

    # Bug 28. Try to silence a ResourceWarning by clearing the connection
    # pool.
    repository.close()
Beispiel #2
0
def publish_pypi(target, args):
    """
    Build and publish the target on a pypi repository
    """
    config = Configuration(args)
    assert config.has_pypi_auth(), "Missing PyPi authentication"

    # Build the project
    setup = target.check_path("setup.py")
    logger.info(f"Building Python project using {setup}")
    sandbox.run_setup(setup, ["clean", "sdist", "bdist_wheel"])

    # Check some files were produced
    dist = target.check_path("dist")
    build = glob.glob(f"{dist}/*")
    assert len(build) > 0, "No built files found"
    logger.info("Will upload {}".format(", ".join(map(os.path.basename,
                                                      build))))

    # Use default repository
    repository = args.repository or DEFAULT_REPOSITORY
    logger.info(f"Will upload on {repository}")

    # Upload it through twine
    upload_settings = Settings(
        username=config.pypi["username"],
        password=config.pypi["password"],
        repository_url=repository,
        verbose=True,
        disable_progress_bar=False,
    )
    twine_upload(upload_settings, build)

    logger.info("PyPi publication finished.")
Beispiel #3
0
    def handle(self) -> int:
        from twine.settings import Settings
        from twine.commands.upload import upload

        distributions: list[Path] = []

        with tempfile.TemporaryDirectory() as tmpdir:
            for project in self.app.repository.projects():
                if not project.is_python_project: continue

                self.line(f'Build <info>{project.dist_name()}</info>')
                backend = Pep517BuildBackend(
                    project.pyproject_toml.value()['build-system']
                    ['build-backend'], project.directory, Path(tmpdir))

                sdist = backend.build_sdist()
                self.line(f'  <comment>{sdist.name}</comment>')
                wheel = backend.build_wheel()
                self.line(f'  <comment>{wheel.name}</comment>')

                distributions += [sdist, wheel]

            if not self.option("dry"):
                kwargs = {
                    option.name.replace('-', '_'): self.option(option.name)
                    for option in self.options
                }
                kwargs['repository_name'] = kwargs.pop('repository')
                settings = Settings(**kwargs)
                upload(settings, [str(d) for d in distributions])

        return 0
Beispiel #4
0
 def prepare(self):
     super().prepare()
     self.shell = True
     self.pypi_repository = self.get_config("pypi_repository")
     self.pypirc_path = os.path.expanduser(self.config.get("config_file"))
     self.twine_settings = Settings(
         config_file=self.pypirc_path,
         repository_name=self.pypi_repository,
         sign=self.get_config("sign"),
         identity=self.get_config("identity"),
         sign_with=self.get_config("sign_with"),
     )
Beispiel #5
0
def upload_component(component_path,
                     repo="pypi",
                     username=None,
                     password=None):
    """Upload a given component to pypi

    The pypi username and password must either be specified in a ~/.pypirc
    file or in environment variables PYPI_USER and PYPI_PASS
    """

    if username is None:
        username = input("Enter your username [%s]: " % repo)

    if password is None:
        password = getpass(
            ("Enter your password [%s]: " % repo).encode('utf-8'))

    distpath = os.path.join(component_path, 'dist', '*')
    distpath = os.path.realpath(os.path.abspath(distpath))
    dists = glob.glob(distpath)

    repo_name = repo
    repo_url = None
    if "://" in repo_name:
        repo_url = repo
        repo_name = None

    try:
        #Invoke upload this way since subprocess call of twine cli has cross platform issues
        settings = Settings(username=username,
                            password=password,
                            repository_name=repo_name,
                            repository_url=repo_url)
        upload(settings, dists)
    except requests.exceptions.HTTPError as exc:
        code = exc.response.status_code

        if repo_name is None:
            repo_name = repo_url

        msg = "Unknown response from server"
        if code == 409 or code == 400:
            msg = "Package already exists"

        raise ExternalError("PyPI repository '%s'" % repo_name,
                            "HTTP status %d: %s" % (code, msg))
Beispiel #6
0
def pypi(package, dry_run):
    """Deploys build artifacts (python packages to PyPI)

    Deployment is only allowed for packages in which the visibility is
    "public".  This check prevents publishing of private resources to
    the (public) PyPI webserver.
    """

    if dry_run:
        logger.warn("!!!! DRY RUN MODE !!!!")
        logger.warn("Nothing is being deployed to server")

    # determine project visibility
    public = os.environ["CI_PROJECT_VISIBILITY"] == "public"

    if not public:
        raise RuntimeError(
            "The repository %s is not public - a package "
            "deriving from it therefore, CANNOT be published to PyPI. "
            "You must follow the relevant software disclosure procedures "
            'and set this repository to "public" before trying again.' %
            os.environ["CI_PROJECT_PATH"])

    from twine.settings import Settings

    from ..constants import CACERT

    settings = Settings(
        username=os.environ["PYPIUSER"],
        password=os.environ["PYPIPASS"],
        skip_existing=True,
        cacert=CACERT,
    )

    if not dry_run:
        from twine.commands.upload import upload

        for k in package:

            logger.info("Deploying python package %s to PyPI", k)
            upload(settings, [k])
            logger.info("%s: Deployed to PyPI - OK", k)
Beispiel #7
0
def register(register_settings: settings.Settings, package: str) -> None:
    repository_url = cast(str,
                          register_settings.repository_config["repository"])
    print(f"Registering package to {repository_url}")
    repository = register_settings.create_repository()

    if not os.path.exists(package):
        raise exceptions.PackageNotFound(
            f'"{package}" does not exist on the file system.')

    resp = repository.register(
        package_file.PackageFile.from_filename(package,
                                               register_settings.comment))
    repository.close()

    if resp.is_redirect:
        raise exceptions.RedirectDetected.from_args(
            repository_url,
            resp.headers["location"],
        )

    resp.raise_for_status()
Beispiel #8
0
 def store_settings(self, config: dict) -> Settings:
     credential_kwargs = super()._transform_key_to_credential_kwargs(
         config["azure"]["keyvault_keys"][current_filename(__file__)])
     return Settings(**credential_kwargs)