You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
ORPA-pyOpenRPA/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/twine/commands/upload.py

135 lines
5.0 KiB

# Copyright 2013 Donald Stufft
#
# Licensed 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
#
# https://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 argparse
import os.path
from twine.commands import _find_dists
from twine.package import PackageFile
from twine import exceptions
from twine import settings
from twine import utils
def skip_upload(response, skip_existing, package):
filename = package.basefilename
msg_400 = (
# Old PyPI message:
f'A file named "{filename}" already exists for',
# Warehouse message:
'File already exists',
# Nexus Repository OSS message:
'Repository does not allow updating assets',
)
msg_403 = 'Not enough permissions to overwrite artifact'
# NOTE(sigmavirus24): PyPI presently returns a 400 status code with the
# error message in the reason attribute. Other implementations return a
# 409 or 403 status code. We only want to skip an upload if:
# 1. The user has told us to skip existing packages (skip_existing is
# True) AND
# 2. a) The response status code is 409 OR
# 2. b) The response status code is 400 AND it has a reason that matches
# what we expect PyPI or Nexus OSS to return to us. OR
# 2. c) The response status code is 403 AND the text matches what we
# expect Artifactory to return to us.
return (skip_existing and (response.status_code == 409 or
(response.status_code == 400 and
response.reason.startswith(msg_400)) or
(response.status_code == 403 and msg_403 in response.text)))
def upload(upload_settings, dists):
dists = _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 = upload_settings.repository_config['repository']
print(f"Uploading distributions to {repository_url}")
repository = upload_settings.create_repository()
uploaded_packages = []
for filename in uploads:
package = PackageFile.from_filename(filename, upload_settings.comment)
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
signed_name = package.signed_basefilename
if signed_name in signatures:
package.add_gpg_signature(signatures[signed_name], signed_name)
elif upload_settings.sign:
package.sign(upload_settings.sign_with, upload_settings.identity)
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()
def main(args):
parser = argparse.ArgumentParser(prog="twine upload")
settings.Settings.register_argparse_arguments(parser)
parser.add_argument(
"dists",
nargs="+",
metavar="dist",
help="The distribution files to upload to the repository "
"(package index). Usually dist/* . May additionally contain "
"a .asc file to include an existing signature with the "
"file upload.",
)
args = parser.parse_args(args)
upload_settings = settings.Settings.from_argparse(args)
# Call the upload function with the arguments from the command line
return upload(upload_settings, args.dists)