Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add helpful error message for incorrect PyPI URL #509

Merged
merged 14 commits into from
Oct 30, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 17 additions & 0 deletions tests/test_upload.py
Original file line number Diff line number Diff line change
Expand Up @@ -285,3 +285,20 @@ def none_upload(*args, **settings_kwargs):
assert "pypipassword" == upload_settings.password
assert "pypiuser" == upload_settings.username
assert "/foo/bar.crt" == upload_settings.cacert


@pytest.mark.parametrize('repo_url', [
"https://upload.pypi.org/",
"https://test.pypi.org/",
"https://pypi.org/"
])
def test_check_status_code_for_wrong_repo_url(repo_url, make_settings):
upload_settings = make_settings()

# override defaults to use incorrect URL
upload_settings.repository_config['repository'] = repo_url

with pytest.raises(twine.exceptions.InvalidPyPIUploadURL):
upload.upload(upload_settings, [
WHEEL_FIXTURE, SDIST_FIXTURE, NEW_SDIST_FIXTURE, NEW_WHEEL_FIXTURE
])
18 changes: 17 additions & 1 deletion tests/test_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,9 @@
import textwrap

import pytest
import pretend

from twine import utils
from twine import utils, exceptions

import helpers

Expand Down Expand Up @@ -389,3 +390,18 @@ def t(foo=False):
t(1)

assert t(foo=True)


@pytest.mark.parametrize('repo_url', [
"https://pypi.python.org",
"https://testpypi.python.org"
])
def test_check_status_code_for_deprecated_pypi_url(repo_url):
response = pretend.stub(
status_code=410,
url=repo_url
)

# value of Verbose doesn't matter for this check
with pytest.raises(exceptions.UploadToDeprecatedPyPIDetected):
utils.check_status_code(response, False)
9 changes: 9 additions & 0 deletions twine/exceptions.py
Original file line number Diff line number Diff line change
Expand Up @@ -101,3 +101,12 @@ class InvalidDistribution(TwineException):
"""Raised when a distribution is invalid."""

pass


class InvalidPyPIUploadURL(TwineException):
"""Repository configuration tries to use PyPI with an incorrect URL.

For example, https://pypi.org instead of https://upload.pypi.org/legacy.
"""

pass
39 changes: 23 additions & 16 deletions twine/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
import configparser
from urllib.parse import urlparse, urlunparse

from requests.exceptions import HTTPError
import requests

try:
import keyring # noqa
Expand Down Expand Up @@ -130,24 +130,31 @@ def normalize_repository_url(url):


def check_status_code(response, verbose):
"""Generate a helpful message based on the response from the repository.

Raise a custom exception for recognized errors. Otherwise, print the
response content (based on the verbose option) before re-raising the
HTTPError.
"""
Shouldn't happen, thanks to the UploadToDeprecatedPyPIDetected
exception, but this is in case that breaks and it does.
"""
if (response.status_code == 410 and
response.url.startswith(("https://pypi.python.org",
"https://testpypi.python.org"))):
print("It appears you're uploading to pypi.python.org (or "
"testpypi.python.org). You've received a 410 error response. "
"Uploading to those sites is deprecated. The new sites are "
"pypi.org and test.pypi.org. Try using "
"https://upload.pypi.org/legacy/ "
"(or https://test.pypi.org/legacy/) to upload your packages "
"instead. These are the default URLs for Twine now. More at "
"https://packaging.python.org/guides/migrating-to-pypi-org/ ")
if response.status_code == 410 and "pypi.python.org" in response.url:
raise exceptions.UploadToDeprecatedPyPIDetected(
f"It appears you're uploading to pypi.python.org (or "
f"testpypi.python.org). You've received a 410 error response. "
f"Uploading to those sites is deprecated. The new sites are "
f"pypi.org and test.pypi.org. Try using {DEFAULT_REPOSITORY} (or "
f"{TEST_REPOSITORY}) to upload your packages instead. These are "
f"the default URLs for Twine now. More at "
f"https://packaging.python.org/guides/migrating-to-pypi-org/.")
elif response.status_code == 405 and "pypi.org" in response.url:
raise exceptions.InvalidPyPIUploadURL(
f"It appears you're trying to upload to pypi.org but have an "
f"invalid URL. You probably want one of these two URLs: "
f"{DEFAULT_REPOSITORY} or {TEST_REPOSITORY}. Check your "
f"--repository-url value.")

try:
response.raise_for_status()
except HTTPError as err:
except requests.HTTPError as err:
if response.text:
if verbose:
print('Content received from server:\n{}'.format(
Expand Down