Commit f1137cf1 by Arun Babu Neelicattu Committed by GitHub

Add --dry-run option for publish command (#2199)

This change introduces `--dry-run` option for the publish
command. When used, will perform all actions required for
publishing except for uploading build artifacts.

Resolves: #2181
parent ab8ef199
......@@ -325,6 +325,7 @@ It can also build the package if you pass it the `--build` option.
Should match a repository name set by the [`config`](#config) command.
* `--username (-u)`: The username to access the repository.
* `--password (-p)`: The password to access the repository.
* `--dry-run`: Perform all actions except upload the package.
## config
......
......@@ -26,6 +26,7 @@ class PublishCommand(Command):
flag=False,
),
option("build", None, "Build the package before publishing."),
option("dry-run", None, "Perform all actions except upload the package."),
]
help = """The publish command builds and uploads the package to a remote repository.
......@@ -79,4 +80,5 @@ the config command.
self.option("password"),
cert,
client_cert,
self.option("dry-run"),
)
......@@ -26,7 +26,15 @@ class Publisher:
def files(self):
return self._uploader.files
def publish(self, repository_name, username, password, cert=None, client_cert=None):
def publish(
self,
repository_name,
username,
password,
cert=None,
client_cert=None,
dry_run=False,
):
if repository_name:
self._io.write_line(
"Publishing <c1>{}</c1> (<c2>{}</c2>) "
......@@ -90,4 +98,5 @@ class Publisher:
url,
cert=cert or get_cert(self._poetry.config, repository_name),
client_cert=resolved_client_cert,
dry_run=dry_run,
)
......@@ -95,8 +95,8 @@ class Uploader:
return self._username is not None and self._password is not None
def upload(
self, url, cert=None, client_cert=None
): # type: (str, Optional[Path], Optional[Path]) -> None
self, url, cert=None, client_cert=None, dry_run=False
): # type: (str, Optional[Path], Optional[Path], bool) -> None
session = self.make_session()
if cert:
......@@ -106,7 +106,7 @@ class Uploader:
session.cert = str(client_cert)
try:
self._upload(session, url)
self._upload(session, url, dry_run)
finally:
session.close()
......@@ -188,9 +188,9 @@ class Uploader:
return data
def _upload(self, session, url):
def _upload(self, session, url, dry_run=False):
try:
self._do_upload(session, url)
self._do_upload(session, url, dry_run)
except HTTPError as e:
if (
e.response.status_code == 400
......@@ -203,15 +203,16 @@ class Uploader:
raise UploadError(e)
def _do_upload(self, session, url):
def _do_upload(self, session, url, dry_run=False):
for file in self.files:
# TODO: Check existence
resp = self._upload_file(session, url, file)
resp = self._upload_file(session, url, file, dry_run)
resp.raise_for_status()
if not dry_run:
resp.raise_for_status()
def _upload_file(self, session, url, file):
def _upload_file(self, session, url, file, dry_run=False):
data = self.post_data(file)
data.update(
{
......@@ -238,14 +239,17 @@ class Uploader:
bar.start()
resp = session.post(
url,
data=monitor,
allow_redirects=False,
headers={"Content-Type": monitor.content_type},
)
resp = None
if not dry_run:
resp = session.post(
url,
data=monitor,
allow_redirects=False,
headers={"Content-Type": monitor.content_type},
)
if resp.ok:
if dry_run or resp.ok:
bar.set_format(
" - Uploading <c1>{0}</c1> <fg=green>%percent%%</>".format(
file.name
......
......@@ -60,7 +60,7 @@ def test_publish_with_cert(app_tester, mocker):
app_tester.execute("publish --cert path/to/ca.pem")
assert [
(None, None, None, Path("path/to/ca.pem"), None)
(None, None, None, Path("path/to/ca.pem"), None, False)
] == publisher_publish.call_args
......@@ -69,5 +69,22 @@ def test_publish_with_client_cert(app_tester, mocker):
app_tester.execute("publish --client-cert path/to/client.pem")
assert [
(None, None, None, None, Path("path/to/client.pem"))
(None, None, None, None, Path("path/to/client.pem"), False)
] == publisher_publish.call_args
def test_publish_dry_run(app_tester, http):
http.register_uri(
http.POST, "https://upload.pypi.org/legacy/", status=403, body="Forbidden"
)
exit_code = app_tester.execute("publish --dry-run --username foo --password bar")
assert 0 == exit_code
output = app_tester.io.fetch_output()
error = app_tester.io.fetch_error()
assert "Publishing simple-project (1.2.3) to PyPI" in output
assert "- Uploading simple-project-1.2.3.tar.gz" in error
assert "- Uploading simple_project-1.2.3-py2.py3-none-any.whl" in error
......@@ -23,7 +23,7 @@ def test_publish_publishes_to_pypi_by_default(fixture_dir, mocker, config):
assert [("foo", "bar")] == uploader_auth.call_args
assert [
("https://upload.pypi.org/legacy/",),
{"cert": None, "client_cert": None},
{"cert": None, "client_cert": None, "dry_run": False},
] == uploader_upload.call_args
......@@ -45,7 +45,7 @@ def test_publish_can_publish_to_given_repository(fixture_dir, mocker, config):
assert [("foo", "bar")] == uploader_auth.call_args
assert [
("http://foo.bar",),
{"cert": None, "client_cert": None},
{"cert": None, "client_cert": None, "dry_run": False},
] == uploader_upload.call_args
......@@ -74,7 +74,7 @@ def test_publish_uses_token_if_it_exists(fixture_dir, mocker, config):
assert [("__token__", "my-token")] == uploader_auth.call_args
assert [
("https://upload.pypi.org/legacy/",),
{"cert": None, "client_cert": None},
{"cert": None, "client_cert": None, "dry_run": False},
] == uploader_upload.call_args
......@@ -98,7 +98,7 @@ def test_publish_uses_cert(fixture_dir, mocker, config):
assert [("foo", "bar")] == uploader_auth.call_args
assert [
("https://foo.bar",),
{"cert": Path(cert), "client_cert": None},
{"cert": Path(cert), "client_cert": None, "dry_run": False},
] == uploader_upload.call_args
......@@ -119,7 +119,7 @@ def test_publish_uses_client_cert(fixture_dir, mocker, config):
assert [
("https://foo.bar",),
{"cert": None, "client_cert": Path(client_cert)},
{"cert": None, "client_cert": Path(client_cert), "dry_run": False},
] == uploader_upload.call_args
......@@ -137,5 +137,5 @@ def test_publish_read_from_environment_variable(fixture_dir, environ, mocker, co
assert [("bar", "baz")] == uploader_auth.call_args
assert [
("https://foo.bar",),
{"cert": None, "client_cert": None},
{"cert": None, "client_cert": None, "dry_run": False},
] == uploader_upload.call_args
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment