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

Raise exception if attempting upload to deprecated legacy PyPI URLs #322

Merged
merged 2 commits into from
Mar 18, 2018
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
2 changes: 2 additions & 0 deletions docs/changelog.rst
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
Changelog
=========

* :bug:`322 major` Raise exception if attempting upload to deprecated legacy
PyPI URLs.
* :feature:`320` Remove PyPI as default ``register`` package index.
* :feature:`319` Support Metadata 2.1 (:pep:`566`), including Markdown
for ``description`` fields.
Expand Down
36 changes: 35 additions & 1 deletion tests/test_upload.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
import pytest

from twine.commands import upload
from twine import package, cli
from twine import package, cli, exceptions
import twine

import helpers
Expand Down Expand Up @@ -95,6 +95,40 @@ def test_get_config_old_format(tmpdir):
).format(pypirc)


def test_deprecated_repo(tmpdir):
with pytest.raises(exceptions.UploadToDeprecatedPyPIDetected) as err:
pypirc = os.path.join(str(tmpdir), ".pypirc")
dists = ["tests/fixtures/twine-1.5.0-py2.py3-none-any.whl"]

with open(pypirc, "w") as fp:
fp.write(textwrap.dedent("""
[pypi]
repository: https://pypi.python.org/pypi/
username:foo
password:bar
"""))

upload.upload(dists=dists, repository="pypi", sign=None, identity=None,
username=None, password=None, comment=None,
cert=None, client_cert=None,
sign_with=None, config_file=pypirc, skip_existing=False,
repository_url=None,
)

assert err.args[0] == (
"You're trying to upload to the legacy PyPI site "
"'https://pypi.python.org/pypi/'. "
"Uploading to those sites is deprecated. \n "
"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. \n "
"More at "
"https://packaging.python.org/guides/migrating-to-pypi-org/ ."
)


def test_skip_existing_skips_files_already_on_PyPI(monkeypatch):
response = pretend.stub(
status_code=400,
Expand Down
21 changes: 15 additions & 6 deletions twine/commands/upload.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@

import twine.exceptions as exc
from twine.package import PackageFile
from twine.repository import Repository, LEGACY_PYPI
from twine.repository import Repository, LEGACY_PYPI, LEGACY_TEST_PYPI
from twine import utils


Expand Down Expand Up @@ -98,11 +98,20 @@ def upload(dists, repository, sign, identity, username, password, comment,

print("Uploading distributions to {0}".format(config["repository"]))

if config["repository"].startswith(LEGACY_PYPI):
print(
"Note: you are uploading to the old upload URL. It's recommended "
"to use the new URL \"{0}\" or to leave the URL unspecified and "
"allow twine to choose.".format(utils.DEFAULT_REPOSITORY))
if config["repository"].startswith((LEGACY_PYPI, LEGACY_TEST_PYPI)):
raise exc.UploadToDeprecatedPyPIDetected(
"You're trying to upload to the legacy PyPI site '{0}'. "
"Uploading to those sites is deprecated. \n "
"The new sites are pypi.org and test.pypi.org. Try using "
"{1} (or {2}) to upload your packages instead. "
"These are the default URLs for Twine now. \n More at "
"https://packaging.python.org/guides/migrating-to-pypi-org/ "
".".format(
config["repository"],
utils.DEFAULT_REPOSITORY,
utils.TEST_REPOSITORY
)
)

username = utils.get_username(username, config)
password = utils.get_password(
Expand Down
6 changes: 6 additions & 0 deletions twine/exceptions.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,3 +30,9 @@ class PackageNotFound(Exception):
This is only used when attempting to register a package.
"""
pass


class UploadToDeprecatedPyPIDetected(Exception):
"""An upload attempt was detected to deprecated legacy PyPI
sites pypi.python.org or testpypi.python.org."""
pass
1 change: 1 addition & 0 deletions twine/repository.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
KEYWORDS_TO_NOT_FLATTEN = set(["gpg_signature", "content"])

LEGACY_PYPI = 'https://pypi.python.org/'
LEGACY_TEST_PYPI = 'https://testpypi.python.org/'
WAREHOUSE = 'https://upload.pypi.org/'
OLD_WAREHOUSE = 'https://upload.pypi.io/'

Expand Down
8 changes: 6 additions & 2 deletions twine/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -140,11 +140,15 @@ def normalize_repository_url(url):


def check_status_code(response):
if (response.status_code == 500 and
"""
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 500 error response. "
"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/ "
Expand Down