Skip to content

Support repodata v3 draft for monolithic, sharded repodata including .whl - #265

Merged
dholth merged 36 commits into
mainfrom
262-wheel
Apr 8, 2026
Merged

Support repodata v3 draft for monolithic, sharded repodata including .whl#265
dholth merged 36 commits into
mainfrom
262-wheel

Conversation

@dholth

@dholth dholth commented Mar 11, 2026

Copy link
Copy Markdown
Contributor

Description

Ability to output wheel metadata to monolithic and sharded repodata.

Does not create the wheel metadata; a different program must have already inserted it into our database before repodata generation runs.

Per the pattern in https://github.com/conda-incubator/conda-pypi-test or the draft repodata v3 at conda/ceps#146

See also #262

Fix #268

AI-assisted

Checklist - did you ...

  • Add a file to the news directory (using the template) for the next release's release notes?
  • Add / update necessary tests?
  • Add / update outdated documentation?

@dholth
dholth requested a review from danyeaw March 11, 2026 22:12
@dholth dholth self-assigned this Mar 11, 2026
@github-project-automation github-project-automation Bot moved this to 🆕 New in 🔎 Review Mar 11, 2026
@conda-bot conda-bot added the cla-signed [bot] added once the contributor has signed the CLA label Mar 11, 2026
@dholth

dholth commented Mar 12, 2026

Copy link
Copy Markdown
Contributor Author

Will update to jump to the v3 key containing per-format subsections.

@dholth dholth changed the title Support "packages.whl" section in API Support outputing .whl metadata for monolithic and sharded repodata Mar 12, 2026
@dholth dholth changed the title Support outputing .whl metadata for monolithic and sharded repodata Support repodata v3 draft for monolithic, sharded repodata including .whl Mar 12, 2026
@dholth dholth moved this from 🆕 New to 🏗️ In Progress in 🔎 Review Mar 12, 2026
Comment thread conda_index/index/__init__.py
Comment thread conda_index/index/sqlitecache.py Outdated
continue

return new_repodata_packages, new_repodata_conda_packages
if v3:

@ForgottenProgramme ForgottenProgramme Mar 17, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this means if v3 is true, older sections are ignored, and new_packages will be empty:

        new_packages = {
            "packages": {},
            "packages.conda": {},
            "packages.whl": {},
        }

Is that intended?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If v3 is True, then we put all packages into the new_v3_packages dict and "packages", "packages.conda" will be empty. This is simpler than the "migrated-since" in the draft CEP.
I think the "new_" prefix is confusing here since it's just "all of them"; this name might be left over from old-conda-index which didn't pull all packages from cache every time.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That doesn't follow the spirit of the CEP, though. The point is to be backwards compatible, so this will effective leave incompatible clients behind.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This was written to follow experimental wheel work and to defer the spirit of the CEP.

Comment thread conda_index/index/sqlitecache.py Outdated
if section_and_key is None:
log.warning("%s has unsupported package extension", path)
continue
key, v3_path = section_and_key

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the name key is used to refer to the second element of the returned tuple here. It's a bit confusing.
We should change it to: section, key = section_and_key.

Comment thread conda_index/postgres/cache.py Outdated
if section_and_key is None:
log.warning("%s has unsupported package extension", path)
continue
key, v3_path = section_and_key

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same here

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Created #272 to resolve these

@ForgottenProgramme

Copy link
Copy Markdown
Contributor

The main objective of this PR is to add a top level key called "v3" to repodata.json.
Under this key, there could be three sections (named after three supported package extensions).
Under each of these package extensions names are inturn package names.
Under each package name will be package metadata
So we get something like:

"v3": {
    "tar.bz2": {
      "package_a": { "version": "1.2.3", ... }
    },
    "conda": {
      "package_b": { "version": "2.3.4", ... }
    },
    "whl": {
      "package_c": { "version": "3.4.5", ... }
    }

I have added a few comments but the PR looks good to me.

Comment thread conda_index/index/sqlitecache.py
Comment thread conda_index/index/sqlitecache.py Outdated
}
}
if v3
else {"packages": {}, "packages.conda": {}}

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

shard should always include the packages, packages.conda keys

Comment thread conda_index/postgres/cache.py Outdated
}
}
if v3
else {"packages": {}, "packages.conda": {}}

@dholth dholth Mar 24, 2026

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It would be nice if the boring "constructing the big dict" could be moved to the abstract base class instead of duplicated per database.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes, agreed. There is a lot of duplicate code. We can either write a function to create these dictionaries in this PR or do that in a subsequent PR.
I am okay with addressing this in the next PR.

Comment thread conda_index/cli/__init__.py
Comment thread conda_index/cli/__init__.py Outdated
show_default=True,
)
@click.option(
"--repodata-v3/--no-repodata-v3",

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Eventually, there'll be a v4, v5... should we instead have a non-boolean flag like --max-repodata-version or something?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are repodata versions something that are sequential, or are they more like CPU flags where we may use any set of them?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey @dholth, they are sequential and we would probably keep all previous versions as well for backwards compatibility (although maybe there is a deprecation time eventually?)

Comment thread conda_index/index/cache.py Outdated
@jaimergp

Copy link
Copy Markdown
Member

There's no repodata v3 yet, so I'm not sure what this is trying to do (I guess adding support for the wheels preview). In that case, maybe it should leave conda packages alone for now and simply populate whl. Also there are a lot of type hint changes here that are unrelated and pollute the PR, so ideally those are proposed separately.

Co-authored-by: jaimergp <jaimergp@users.noreply.github.com>
@dholth

dholth commented Mar 30, 2026

Copy link
Copy Markdown
Contributor Author

There's no repodata v3 yet, so I'm not sure what this is trying to do (I guess adding support for the wheels preview). In that case, maybe it should leave conda packages alone for now and simply populate whl. Also there are a lot of type hint changes here that are unrelated and pollute the PR, so ideally those are proposed separately.

Yes this is only intended to support the wheels preview.

@ryanskeith ryanskeith left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Overall, I am not seeing any huge red flags about going forward this way. I don't think anyone is a fan of having version 2's of code but it is a necessary evil at times to get things working well.

for name, shard in cache.indexed_shards():
shard_data = compressor.compress(sqlitecache.packb_typed(shard))
shard_hash = hashlib.sha256(shard_data).digest()
v3_data = {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is the concern processing time? If so, could this be an elective post processing function?

for name, shard in cache.indexed_shards():
shard_data = compressor.compress(sqlitecache.packb_typed(shard))
shard_hash = hashlib.sha256(shard_data).digest()
v3_data = {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, I see. It is part of the spec. I am not sure what the intent of this spec provides.

if fn in repodata[key]:
repodata[key][fn]["revoked"] = True
repodata[key][fn]["depends"].append("package_has_been_revoked")
records = repodata.get(key, {})

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

repodata patch doesn't work with wheel or v3

Comment thread conda_index/index/cache.py Outdated
Comment thread conda_index/index/__init__.py
package_sections = {
".tar.bz2": "packages",
".conda": "packages.conda",
".whl": "packages.whl",

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A little obsolete since there isn't a "packages.whl" in current specs but we also use it to populate IndexedPackages / IndexedShard dataclasses.

Comment thread conda_index/postgres/cache.py Outdated
Comment thread conda_index/postgres/cache.py Outdated

@danyeaw danyeaw left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey @dholth, this looks great - thanks for this! I made a couple of additional suggestions.

@github-project-automation github-project-automation Bot moved this from 🏗️ In Progress to ✅ Approved in 🔎 Review Apr 7, 2026
dholth and others added 5 commits April 7, 2026 15:18
@dholth
dholth merged commit 228fd6a into main Apr 8, 2026
23 checks passed
@dholth
dholth deleted the 262-wheel branch April 8, 2026 15:47
@github-project-automation github-project-automation Bot moved this from ✅ Approved to 🏁 Done in 🔎 Review Apr 8, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

cla-signed [bot] added once the contributor has signed the CLA

Projects

Archived in project

Development

Successfully merging this pull request may close these issues.

Output .whl to repodata if already present in index database

7 participants