Skip to content

feat: version-aware .tla loading with migrations#550

Open
FelipeDefensor wants to merge 1 commit into
devfrom
claude/brave-vaughan-5b4f3a
Open

feat: version-aware .tla loading with migrations#550
FelipeDefensor wants to merge 1 commit into
devfrom
claude/brave-vaughan-5b4f3a

Conversation

@FelipeDefensor

@FelipeDefensor FelipeDefensor commented Jun 22, 2026

Copy link
Copy Markdown
Collaborator

Summary

Adds version handling when opening .tla files. Until now open_tla stored the
file version but never read it: opening a file written by a newer TiLiA silently
partial-loaded and could drop unknown data on save, and older-format upgrades were
done with ad-hoc shims scattered inside deserialize_timelines.

This PR:

  • Warns + asks confirmation before opening a file from a newer TiLiA version
    (open_tlaGet.FROM_USER_YES_OR_NO). Declining aborts the load.
  • Adds tilia/file/migration.py: an ordered list of small, composable
    dict -> dict migrations applied to the raw file data on load.
  • Moves the inline display_position -> ordinal shim out of
    deserialize_timelines into the registry (target 0.1.1), giving version
    upgrades a single source of truth.
  • Registers the upcoming v0.7 timeline-kind rename
    (MARKER_TIMELINE -> Marker) as a dormant migration (target 0.7.0)

Follow-up

When syncing onto the v0.7.0 branch, delete the inline _get_timeline_class_string
shim there — the dormant 0.7.0 migration replaces it.

- open_tla now warns and asks for confirmation before opening a file
  written by a newer TiLiA version, since data that version understands
  may be silently dropped on save.
- Add tilia/file/migration.py: an ordered list of dict->dict migrations
  applied to the raw file data on load. A migration runs only when
  file_version < target <= app_version, so a migration written for an
  unreleased version stays dormant until that version ships.
- Move the inline display_position->ordinal shim out of
  deserialize_timelines into the registry (target 0.1.1) and relocate
  its test, giving version upgrades a single source of truth.
- Register the upcoming 0.7 timeline-kind rename (MARKER_TIMELINE ->
  Marker) as a dormant migration (target 0.7.0).
@FelipeDefensor FelipeDefensor added this to the 0.6.4 milestone Jun 22, 2026
@FelipeDefensor FelipeDefensor requested a review from azfoo June 22, 2026 15:14
@azfoo

azfoo commented Jun 23, 2026

Copy link
Copy Markdown
Collaborator

is this meant to merge into dev instead of main?

@FelipeDefensor

Copy link
Copy Markdown
Collaborator Author

is this meant to merge into dev instead of main?

Yes. I wonder if we are doing the main vs. dev thing in a unconventional way, Claude always seems to get it wrong.

@FelipeDefensor FelipeDefensor changed the base branch from main to dev June 24, 2026 09:06
@azfoo

azfoo commented Jun 30, 2026

Copy link
Copy Markdown
Collaborator

is this meant to merge into dev instead of main?

Yes. I wonder if we are doing the main vs. dev thing in a unconventional way, Claude always seems to get it wrong.

I suppose there is also main vs stable...

Comment thread tilia/file/migration.py
Comment on lines +20 to +36
def _parse_version(version: str) -> tuple[int, ...]:
"""Parse a version string into a comparable tuple of ints.

Reads the leading integer of each dot-separated segment, so suffixes
are ignored (``"0.7.0rc1"`` -> ``(0, 7, 0)``).
"""
parts: list[int] = []
for segment in version.split("."):
digits = ""
for char in segment:
if not char.isdigit():
break
digits += char
if not digits:
break
parts.append(int(digits))
return tuple(parts) or (0,)

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.

stdlib's platform._comparable_version?

Comment on lines +23 to +26
"This file was created with TiLiA {} but you are running {}.\n"
"It may not load correctly, and saving could discard data that this "
"version doesn't understand.\n\n"
"Open it anyway?"

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.

this message seems a bit tame. something about "Errors may occur and information may be lost" would probably be more accurate. do we need to add info on where a newer version can be downloaded from?

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.

related to this: what happens when loading a newer version with a tl type that is not known to the older one? pretty sure nothing loads at all because of it, but do verify!

Comment thread tilia/file/migration.py


def is_from_newer_version(data: dict, app_version: str = VERSION) -> bool:
return _parse_version(data.get("version", "0.0.0")) > _parse_version(app_version)

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.

should there be a default? or should it error when not found?

(rather this actually depends on whether or not we validate or migrate first...)

)
return False, None, None

valid, reason = validate_tla_data(data)

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.

are we sure we want to validate before migrating?

"0.1.0",
{"0": make_timeline("HIERARCHY_TIMELINE", display_position=0)},
)
del data["timelines"]["0"]["ordinal"]

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.

add a comment on the del or make a function that adds for >0.1?

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants