-
Notifications
You must be signed in to change notification settings - Fork 871
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
Private Projects #8214
Comments
This exists already as a |
This is mentioned over in python-poetry/poetry#1537 (comment) — we might want to include a private mode that avoids attempting to upload to the registry at all. cc @konstin |
@zanieb Yeah, I personally feel like the |
I'd love to support something like For now, we should start hinting users towards the |
I understand that in some contexts we may not know where the wheels come from, but I feel like we should still be able to read project metadata and configuration when publishing artifacts for builds in a project. This seems like a fairly important base capability for
How "not allowed" is this? Couldn't we append this when building the wheel and source dists? |
I agree with @zanieb on this. It's fairly important to protect users against shooting themselves in the foot when they accidentally attempt to publish something that is marked as private.
This respects the apparent rule of not setting the classifier automatically while still protecting the user as much as possible. I strongly encourage not adding any |
There's two options to implementing private project: METADATA and pyproject.toml. MetadataOne option is going through the METADATA file and making sure The non-uv solution is adding [project]
name = "foo-internal"
version = "0.1.0"
classifiers = ["Private :: Do Not Upload"] This prevents publishing to PyPI. (There is a separate question that alternative registries such as GitLab have options to host packages both as public and private, but I'm skipping over that here.)
PEP 621 is unambiguous that we must not append to static parts of [project]
name = "foo-internal"
version = "0.1.0"
dynamic = ["classifier"]
[tool.uv]
private = true Through
I prefer pyproject.tomlThe other option is requiring pyproject.toml to be present. To check for The other, bigger downside is that this will be ignored when using a standard workflow such as There are other advantages too for requiring pyproject.toml for publish, e.g., reading configuration from it. In the current trade-off, that doesn't tip the scales for me towards switching to a poetry-like [project]
name = "foo-internal"
version = "0.1.0"
classifiers = ["Private :: Do Not Upload"] I agree that cargo and npm have a clearly better state, and would favor the addition of |
Is there a third option where if pyproject.toml is present, then |
Yeah I agree, I don't think we need to require it. We could always add a flag that requires we can find it; for people that are concerned about accidentally ignoring their configuration. |
Users are concerned that they might accidentally publish their private package to PyPI, thereby exposing company internals and their private source code. However, for this to happen, the user needs to call `uv publish` without an index option, while having credentials for PyPI set either in environment variables (and the private index credentials not set to those env vars) or in the keyring (without scoping to a package), and that token having the project in scope. As easiest protection, we recommend **never generating a PyPI token scoped to all projects**, only generating one that is matched to the specific, public project: Without a matching token, no accidental publishing can happen. --- The `Private :: Do Not Upload` prevent packages from being uploaded to PyPI (https://pypi.org/classifiers/). This is unergonomic: The classifiers are a system for metadata, not for configuration, they are not part of uv's docs and it doesn't have the discoverability of regular settings. The most evident idea for solving this is `tool.uv.publish`: ``` [tool.uv] private = true ``` Unfortunately, this doesn't actually offer reliable protection: It only works when the pyproject.toml is present (we currently don't require checkouts for `uv publish`) and it doesn't work with twine or any other publishing tool. The second idea is translating this to `classifiers = ["Private :: Do Not Upload"]`. Unfortunately, PEP 621 forbids this, it requires that we must not append to static parts of `[project]` when building the wheel and source dists. This is needed for the ability to read `pyproject.toml` without a build. There is an escape hatch that requires explicitly declaring specifiers as dynamic, we set the actual classifier on build depending on the value of `tool.uv.private`, i.e., if we see `tool.uv.private = true` we transform the metadata on build as if we had `classifiers = ["Private :: Do Not Upload"]`: ```toml [project] name = "foo-internal" version = "0.1.0" dynamic = ["classifier"] [tool.uv] private = true ``` Through `dynamic`, we are allowed to emit the following as METADATA: ```text Metadata-Version: 2.3 Name: foo-internal Version: 0.1.0 Version: Private :: Do Not Upload ``` Just setting `classifiers = ["Private :: Do Not Upload"]` is, unlike the above, self-documenting and more concise. --- Given all that we document that you shouldn't create unscoped tokens and that you can use `classifiers = ["Private :: Do Not Upload"]`. Note that we cannot handle e.g. a GitLab repository that is set to public accidentally. It falls into the domain of registry vendors to have guardrails (e.g. private-by-default registries when the status of the source is unknown) Fixed #8214
I know packaging tool authors are generally against putting UX details into PEPs, but maybe this is a case where it would make sense to propose an optional That way as long as the project developers are running their CI builds with a version that respects the flag, publication tools will still see the classifier in the metadata. |
That is an interesting idea. The downsides I see to this are:
But I do like the overall idea of proposing that |
Yeah, that's one of the two main advantages I see in defining
If the invalid classifier is explicitly present in the metadata, even old versions of Twine (or other tools) won't successfully upload the package. So even though people (or their dev tools) would need to express "this is private" twice, they'd be doing it for a specific backwards compatibility reason. (and if |
Is it possible to mark a uv project as
private
such thatuv publish
is completely disabled? For private code this is a desirable feature.Something like:
NPM has a similar
"private": true
:In Cargo, this is controlled by the
publish
flag.For some additional motivation, see a similar feature request for Poetry
The text was updated successfully, but these errors were encountered: