How to Mock Twine Upload to TestPyPI in Python
Simulate a twine upload to TestPyPI with a dry-run mock function that validates distribution files and prints the intended upload action without any network call.
Python code
15 linesimport subprocess
import sys
# Mock twine upload to TestPyPI using subprocess dry-run
def mock_twine_upload(dist_file: str, repo_url: str = "https://test.pypi.org/legacy/") -> None:
"""Simulate twine upload by checking dist file and printing intended action."""
if not dist_file.endswith((".whl", ".tar.gz")):
raise ValueError(f"Invalid distribution file: {dist_file}. Must be .whl or .tar.gz")
print(f"Checking existing distribution file: {dist_file}")
print(f"Would upload to repository: {repo_url}")
print(f"Running twine upload --repository-url {repo_url} {dist_file}")
print("Mock upload successful (no actual network call performed)")
if __name__ == "__main__":
mock_twine_upload("dist/mypackage-0.1.0-py3-none-any.whl")
Output
Checking existing distribution file: dist/mypackage-0.1.0-py3-none-any.whl
Would upload to repository: https://test.pypi.org/legacy/
Running twine upload --repository-url https://test.pypi.org/legacy/ dist/mypackage-0.1.0-py3-none-any.whl
Mock upload successful (no actual network call performed)
How it works
The function mock_twine_upload validates that the distribution file ends with a wheel or source archive extension, raising a ValueError otherwise. It then prints the would-be twine command and repository URL, mimicking the upload flow without touching the network. This is useful in CI pipelines or local testing to confirm packaging output before actually publishing. The __main__ guard runs the mock against a sample wheel file, demonstrating the expected output exactly.
Common mistakes
- Forgetting to escape f-string braces when printing the twine command
- Not checking the file extension before mocking the upload
- Assuming the mock actually uploads — it only simulates the dry-run
Variations
- Use `--dry-run` with actual twine if available to avoid network calls
- Wrap the mock with a CLI parser like argparse to accept dist paths dynamically
Real-world use cases
- Verify package build output in CI before triggering an actual PyPI publish.
- Test package publishing scripts locally without hitting the real test server.
- Simulate release workflows in feature branches to catch filename or repo misconfigurations.
Sponsored
More from Modern tooling
- Build a Recipe Runner Mock in Python easy
- Build a Textual TUI App Skeleton in Python easy
- Configure ruff linter rules in pyproject.toml with Python easy
- Data Conversion Helper Functions in Python easy
- How to Bind and Mock structlog Context in Python medium
- How to Build a Chainable Filter Helper in Python easy
Keep learning
Related tutorials and quizzes for this topic.