Skip to content

read metadata and cards from tar without extracting multi-dim arrays - #563

Open
lol782 wants to merge 2 commits into
NNPDF:masterfrom
lol782:fix/533-read-card-from-tar
Open

read metadata and cards from tar without extracting multi-dim arrays#563
lol782 wants to merge 2 commits into
NNPDF:masterfrom
lol782:fix/533-read-card-from-tar

Conversation

@lol782

@lol782 lol782 commented Aug 31, 2026

Copy link
Copy Markdown
Contributor

closes #533

Implements the cheap card-reading we discussed in #533.

Approach (following your instructions )

  • Added from_raw to TheoryCard, OperatorCard, and Metadata (in runcards.py / metadata.py). Each takes raw yaml, applies the v1/v2 upgrades, then calls from_dict. This is the upgrade logic lifted out of the EKO.theory_card / EKO.operator_card properties.
  • Added load_meta_and_cards_from_tar(path) in runcards.py: opens the archive and pulls only metadata.yaml / theory.yaml / operator.yaml via tarfile.extractfile — the operators are never extracted. Order is metadata → theory → operator (operator upgrade needs the theory dict).
  • Refactored the two EKO properties to reuse from_raw, so folder-reading and tar-reading share one code path.

Points I'd like your view on

  1. Metadata legacy upgrade. v1/v2.update_metadata needs the folder (paths), which the tar path doesn't have. So I kept that legacy 0.13/0.14 upgrade inside Metadata.load and made from_raw do the plain build. Consequence: reading a very old EKO straight from tar won't auto-upgrade its metadata. Fine for modern files — is that an acceptable boundary, or do you want it handled differently?
  2. Function placement. Put load_meta_and_cards_from_tar in runcards.py as you suggested.
  3. Test depth. Added a test that reads the cards from a real archive and checks types + a few values. Let me know if you want stronger assertions.

Existing io tests pass locally and below is the new one.
Screenshot 2026-08-31 180517

@felixhekhorn felixhekhorn added enhancement New feature or request output Output format and management labels Sep 3, 2026

@felixhekhorn felixhekhorn left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Remember to run pre-commit

Comment thread src/eko/io/metadata.py
return content

@classmethod
def from_raw(cls, raw: dict) -> "Metadata":

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Metadata legacy upgrade

yeah, seems that the update_metadata s take paths - but if you look to the function body they don't do anything with it so I'd say we can just remove them from there, because we definitely need patches here

Comment thread src/eko/io/runcards.py Outdated
raise KeyError(f"'{filename}' not found in {tar.name}")


def load_meta_and_cards_from_tar(path):

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Function placement

fine for me - any clever suggestion for a shorter function name? 🙃 being explicit is also fine

Comment thread tests/eko/io/test_struct.py Outdated

def test_load_meta_and_cards_from_tar(self, eko_factory: EKOFactory):
"""Load metadata and both YAML cards from a real EKO archive."""
eko = eko_factory.get()

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Test depth

this is only the current data version - can we please add also all the older as in

for name in ["v1-0.13.tar", "v1-0.14.tar", "v3.tar"]:
? Consider putting this list into a fixture so we can reuse it here and there

Comment thread src/eko/io/runcards.py Outdated
def from_raw(cls, raw: dict, data_version: int, theory_raw)-> "OperatorCard":
"""Build an operator card from a raw dictionary."""
if data_version == 1:
raw =v1.update_operator(raw)

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

since you are not testing on the full set of versions you did not realize that this is wrong - look:

def update_operator(raw_op: dict, raw_th) -> dict:

there is a reason I put the argument there 🙃

Comment thread src/eko/io/runcards.py

Only this member's bytes are read; nothing else is extracted.
"""
for member in tar.getmembers():

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.

Is this "costless". If it is, then this is fine.

Otherwise, this function could take a list of filenames so that one can extract all of the files we need in one go.

Comment thread src/eko/io/runcards.py Outdated
raise KeyError(f"'{filename}' not found in {tar.name}")


def load_meta_and_cards_from_tar(path):

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.

Suggested change
def load_meta_and_cards_from_tar(path):
def load_meta_and_cards_from_tar(eko_path):

if we are being explicit, better to be explicit here (so that it is clear to the user that this is the "eko path"

@lol782

lol782 commented Sep 5, 2026

Copy link
Copy Markdown
Contributor Author

fix the required changes, Apologies for not remembering pre-commit.

  • Operator card bug — from_raw wasn't forwarding the theory dict to v1/v2.update_operator. Fixed (this was the empty-operator failure on legacy versions).
  • Metadata legacy upgrade — removed the unused paths argument from update_metadata in v1.py/v2.py, and moved the version patching into Metadata.from_raw (which was where the legacy case was failing). load now just reads the file and calls from_raw.
  • Tests — added a fixture with the legacy + current archives (v1-0.13.tar, v1-0.14.tar, v3.tar) so both test_legacy.py and the new test reuse it. The new function is now tested across all versions, not just current. Both pass.
  • Runcards — Changed the function logic to improve performance. Previously, it scanned the member list up to three times; now, the number of scans is hardcoded to three.

and also changed the name from load_meta_and_cards_from_tar → read_eko_cards and for test function name too.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request output Output format and management

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Interface to extract only the *.yaml metadata

3 participants