Skip to content

Commit

Permalink
Replace twine with uv for publishing scenarios (#223)
Browse files Browse the repository at this point in the history
  • Loading branch information
zanieb authored Oct 1, 2024
1 parent a59c274 commit 4b2ee8d
Show file tree
Hide file tree
Showing 6 changed files with 94 additions and 442 deletions.
4 changes: 2 additions & 2 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,11 @@ classifiers = [
requires-python = ">=3.12"
dependencies = [
"msgspec>=0.18.4",
"twine>=4.0.2",
"hatchling>=1.20.0",
"chevron-blue>=0.2.1",
"setuptools>=69.1.1",
"pyyaml>=6.0.1"
"pyyaml>=6.0.1",
"uv>=0.4.17",
]

[build-system]
Expand Down
2 changes: 1 addition & 1 deletion src/packse/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -305,7 +305,7 @@ def _add_publish_parser(subparsers):
parser.add_argument(
"--dry-run",
action="store_true",
help="Do not actually publish, just show twine commands that would be used.",
help="Do not actually publish, just show uv commands that would be used.",
)
parser.add_argument(
"--skip-existing",
Expand Down
20 changes: 9 additions & 11 deletions src/packse/publish.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ def publish(
start_time = time.time()

if not anonymous and not (
"TWINE_PASSWORD" in os.environ or "PACKSE_PUBLISH_PASSWORD" in os.environ
"UV_PUBLISH_PASSWORD" in os.environ or "PACKSE_PUBLISH_PASSWORD" in os.environ
):
raise PublishNoCredentials()

Expand Down Expand Up @@ -188,32 +188,30 @@ def publish_package_distribution(
"""
Publish a package distribution file.
"""
command = ["twine", "upload", "--repository-url", index_url, str(target.resolve())]
command = ["uv", "publish", "--publish-url", index_url, str(target.resolve())]
if dry_run:
print("Would execute: " + " ".join(command))
return

start_time = time.time()
try:
env = os.environ.copy()
# Ensure twine does not prompt for credentials
env["TWINE_NON_INTERACTIVE"] = "1"

# Pass the publish username through to twine
if publish_username := os.environ.get("PACKSE_PUBLISH_USERNAME"):
env["TWINE_USERNAME"] = publish_username
env["UV_PUBLISH_USERNAME"] = publish_username

# Configure the username for tokens by default
env.setdefault("TWINE_USERNAME", "__token__")
env.setdefault("UV_PUBLISH_USERNAME", "__token__")

# Pass the publish token through to twine
if publish_token := os.environ.get("PACKSE_PUBLISH_PASSWORD"):
env["TWINE_PASSWORD"] = publish_token
env["UV_PUBLISH_PASSWORD"] = publish_token

# Twine requires a username and password even if we don't want to use them
# Provide a username and password even if we don't want to use them
if anonymous:
env["TWINE_USERNAME"] = "ANON"
env["TWINE_PASSWORD"] = "ANON"
env["UV_PUBLISH_USERNAME"] = "ANON"
env["UV_PUBLISH_PASSWORD"] = "ANON"

output = subprocess.check_output(
command, stderr=subprocess.STDOUT, env=env, timeout=60
Expand All @@ -229,7 +227,7 @@ def publish_package_distribution(
if "ConnectionError" in output:
raise PublishConnectionError(target.name)
raise PublishToolError(
f"Publishing {target.name} with twine failed",
f"Publishing {target.name} with uv failed",
output,
)
else:
Expand Down
68 changes: 34 additions & 34 deletions tests/__snapshots__/test_publish.ambr
Original file line number Diff line number Diff line change
Expand Up @@ -18,15 +18,15 @@

''',
'stdout': '''
Would execute: twine upload --repository-url https://test.pypi.org/legacy/ [DISTDIR]/example_961b4c22-0.0.0.tar.gz
Would execute: twine upload --repository-url https://test.pypi.org/legacy/ [DISTDIR]/example_a_961b4c22-1.0.0-py3-none-any.whl
Would execute: twine upload --repository-url https://test.pypi.org/legacy/ [DISTDIR]/example_a_961b4c22-1.0.0.tar.gz
Would execute: twine upload --repository-url https://test.pypi.org/legacy/ [DISTDIR]/example_b_961b4c22-1.0.0-py3-none-any.whl
Would execute: twine upload --repository-url https://test.pypi.org/legacy/ [DISTDIR]/example_b_961b4c22-1.0.0.tar.gz
Would execute: twine upload --repository-url https://test.pypi.org/legacy/ [DISTDIR]/example_b_961b4c22-2.0.0-py3-none-any.whl
Would execute: twine upload --repository-url https://test.pypi.org/legacy/ [DISTDIR]/example_b_961b4c22-2.0.0.tar.gz
Would execute: twine upload --repository-url https://test.pypi.org/legacy/ [DISTDIR]/example_b_961b4c22-3.0.0-py3-none-any.whl
Would execute: twine upload --repository-url https://test.pypi.org/legacy/ [DISTDIR]/example_b_961b4c22-3.0.0.tar.gz
Would execute: uv publish --publish-url https://test.pypi.org/legacy/ [DISTDIR]/example_961b4c22-0.0.0.tar.gz
Would execute: uv publish --publish-url https://test.pypi.org/legacy/ [DISTDIR]/example_a_961b4c22-1.0.0-py3-none-any.whl
Would execute: uv publish --publish-url https://test.pypi.org/legacy/ [DISTDIR]/example_a_961b4c22-1.0.0.tar.gz
Would execute: uv publish --publish-url https://test.pypi.org/legacy/ [DISTDIR]/example_b_961b4c22-1.0.0-py3-none-any.whl
Would execute: uv publish --publish-url https://test.pypi.org/legacy/ [DISTDIR]/example_b_961b4c22-1.0.0.tar.gz
Would execute: uv publish --publish-url https://test.pypi.org/legacy/ [DISTDIR]/example_b_961b4c22-2.0.0-py3-none-any.whl
Would execute: uv publish --publish-url https://test.pypi.org/legacy/ [DISTDIR]/example_b_961b4c22-2.0.0.tar.gz
Would execute: uv publish --publish-url https://test.pypi.org/legacy/ [DISTDIR]/example_b_961b4c22-3.0.0-py3-none-any.whl
Would execute: uv publish --publish-url https://test.pypi.org/legacy/ [DISTDIR]/example_b_961b4c22-3.0.0.tar.gz
example-961b4c22

''',
Expand All @@ -51,47 +51,47 @@
Publishing 'example-961b4c22'...
Published example_961b4c22-0.0.0.tar.gz in [TIME]:

<mock twine logs>
<mock uv logs>

Published 'example_961b4c22-0.0.0.tar.gz'
Published example_a_961b4c22-1.0.0-py3-none-any.whl in [TIME]:

<mock twine logs>
<mock uv logs>

Published 'example_a_961b4c22-1.0.0-py3-none-any.whl'
Published example_a_961b4c22-1.0.0.tar.gz in [TIME]:

<mock twine logs>
<mock uv logs>

Published 'example_a_961b4c22-1.0.0.tar.gz'
Published example_b_961b4c22-1.0.0-py3-none-any.whl in [TIME]:

<mock twine logs>
<mock uv logs>

Published 'example_b_961b4c22-1.0.0-py3-none-any.whl'
Published example_b_961b4c22-1.0.0.tar.gz in [TIME]:

<mock twine logs>
<mock uv logs>

Published 'example_b_961b4c22-1.0.0.tar.gz'
Published example_b_961b4c22-2.0.0-py3-none-any.whl in [TIME]:

<mock twine logs>
<mock uv logs>

Published 'example_b_961b4c22-2.0.0-py3-none-any.whl'
Published example_b_961b4c22-2.0.0.tar.gz in [TIME]:

<mock twine logs>
<mock uv logs>

Published 'example_b_961b4c22-2.0.0.tar.gz'
Published example_b_961b4c22-3.0.0-py3-none-any.whl in [TIME]:

<mock twine logs>
<mock uv logs>

Published 'example_b_961b4c22-3.0.0-py3-none-any.whl'
Published example_b_961b4c22-3.0.0.tar.gz in [TIME]:

<mock twine logs>
<mock uv logs>

Published 'example_b_961b4c22-3.0.0.tar.gz'
Published 1 targets (9 new files) in [TIME]
Expand All @@ -103,7 +103,7 @@
''',
})
# ---
# name: test_publish_example_twine_fails_with_already_exists
# name: test_publish_example_uv_fails_with_already_exists
dict({
'exit_code': 1,
'stderr': '''
Expand All @@ -116,7 +116,7 @@
'stdout': '',
})
# ---
# name: test_publish_example_twine_fails_with_rate_limit
# name: test_publish_example_uv_fails_with_rate_limit
dict({
'exit_code': 1,
'stderr': '''
Expand All @@ -129,70 +129,70 @@
'stdout': '',
})
# ---
# name: test_publish_example_twine_fails_with_unknown_error
# name: test_publish_example_uv_fails_with_unknown_error
dict({
'exit_code': 1,
'stderr': '''
Publishing 1 target to https://test.pypi.org/legacy/...
Publishing 'example-961b4c22'...
Publishing example_961b4c22-0.0.0.tar.gz with twine failed:
<twine error message>
Publishing example_961b4c22-0.0.0.tar.gz with uv failed:
<uv error message>
.
Failed to publish 1/1 targets.

''',
'stdout': '',
})
# ---
# name: test_publish_example_twine_succeeds
# name: test_publish_example_uv_succeeds
dict({
'exit_code': 0,
'stderr': '''
Publishing 1 target to https://test.pypi.org/legacy/...
Publishing 'example-961b4c22'...
Published example_961b4c22-0.0.0.tar.gz in [TIME]:

<twine happy message>
<uv happy message>

Published 'example_961b4c22-0.0.0.tar.gz'
Published example_a_961b4c22-1.0.0-py3-none-any.whl in [TIME]:

<twine happy message>
<uv happy message>

Published 'example_a_961b4c22-1.0.0-py3-none-any.whl'
Published example_a_961b4c22-1.0.0.tar.gz in [TIME]:

<twine happy message>
<uv happy message>

Published 'example_a_961b4c22-1.0.0.tar.gz'
Published example_b_961b4c22-1.0.0-py3-none-any.whl in [TIME]:

<twine happy message>
<uv happy message>

Published 'example_b_961b4c22-1.0.0-py3-none-any.whl'
Published example_b_961b4c22-1.0.0.tar.gz in [TIME]:

<twine happy message>
<uv happy message>

Published 'example_b_961b4c22-1.0.0.tar.gz'
Published example_b_961b4c22-2.0.0-py3-none-any.whl in [TIME]:

<twine happy message>
<uv happy message>

Published 'example_b_961b4c22-2.0.0-py3-none-any.whl'
Published example_b_961b4c22-2.0.0.tar.gz in [TIME]:

<twine happy message>
<uv happy message>

Published 'example_b_961b4c22-2.0.0.tar.gz'
Published example_b_961b4c22-3.0.0-py3-none-any.whl in [TIME]:

<twine happy message>
<uv happy message>

Published 'example_b_961b4c22-3.0.0-py3-none-any.whl'
Published example_b_961b4c22-3.0.0.tar.gz in [TIME]:

<twine happy message>
<uv happy message>

Published 'example_b_961b4c22-3.0.0.tar.gz'
Published 1 targets (9 new files) in [TIME]
Expand All @@ -204,7 +204,7 @@
''',
})
# ---
# name: test_publish_example_twine_succeeds_parallel
# name: test_publish_example_uv_succeeds_parallel
dict({
'exit_code': 0,
'stderr': '<not included>',
Expand Down
Loading

0 comments on commit 4b2ee8d

Please sign in to comment.