Skip to content

fix(parsers): stop coercing free-text fields (single-letter cue names); rc11 - #8

Merged
ibiltari merged 1 commit into
mainfrom
fix/name-coercion-869cqbpxa
Jul 28, 2026
Merged

fix(parsers): stop coercing free-text fields (single-letter cue names); rc11#8
ibiltari merged 1 commit into
mainfrom
fix/name-coercion-869cqbpxa

Conversation

@ibiltari

Copy link
Copy Markdown
Member

Closes ClickUp 869cqbpxa"Error al querer poner el nombre de una cue de una sola letra".

The bug

There was never a length rule. NameStringType has always been minLength=1, and the frontend cue-name input has no validator at all.

CuemsParser.str_to_value() ran every scalar through intfloatstrtoboolUuid regardless of its key, so free text was silently rewritten on save. Because strtobool accepts the truth abbreviations, the failing characters were exactly its vocabulary:

Typed name Persisted as
n, N, f, F False
y, Y, t, T True
09 the integer
a, b, x, Q, … (correct)

18 of 62 alphanumeric single characters were corrupted, plus yes/no/true/false/on/off. Reproduced on test2 through the editor's real save path: a cue named n was written to XML as <name>False</name>.

Second failure class, same root cause

A cue named lowercase none/null hit the ['none','null','']None branch, serialised to <name/>, and failed minLength=1 — a hard XMLSchemaValidationError at save time, not silent corruption. The new short-circuit precedes that branch, so both are fixed together.

The fix

STRING_TYPED_KEYS + an optional key argument on str_to_value, threaded through all four call sites. Keeping key optional leaves existing single-argument callers unaffected.

id is deliberately excluded: the Uuid() branch inside str_to_value is the only thing producing Uuid objects on parse (parsers assign via raw dict.__setitem__ and never reach the property setters), so adding it would downgrade every cue/script/media id to a plain str. Consequence: DmxSceneType.id (script.xsd:403, declared xs:string) can't be covered by this mechanism — accepted, since DMX scene ids are system-assigned.

Scope — narrower than first assumed

Only name, description and file_name are reachable today. An earlier analysis claimed output_name was also affected; that is empirically false. output_name, parameter_name, icon and color never reach str_to_value, for three distinct reasons:

  • outputsParser.parse() constructs output objects directly via self._class(item)
  • fade_profileParser diverts parameters to _normalize_fade_parameters() before the scalar branch
  • get_class('ui_properties') misses (the class is UI_properties) and falls back to GenericDict raw passthrough

They're kept in the allowlist as defensive entries so that fixing any of those bypasses can't silently reintroduce this bug. The comment in the source says so explicitly.

Testing

  • New tests/test_name_coercion.py: exhaustive sweep over all 62 alphanumeric single characters per reachable key, the boolean/nullish word set, full XML round-trip, and negative tests pinning that enabled/autoload/timecode/loop still coerce and id still yields a Uuid.
  • Full suite: 551 passed. One pre-existing unrelated failure (test_realtime_25fps_jitter, a ±1ms wall-clock tolerance test) — confirmed it fails identically on a clean tree without this change.
  • Verified on test2 against the live stack: all 62 single characters clean through a full XML round-trip, none/null no longer error, and enabled 'true'→True / loop '1'→1 still correct.

Follow-ups (not in this PR)

  • Projects already saved carry the corrupted name in their cue_script.xml; the original text is unrecoverable (n, no, N, off all collapse to False) and needs manual renaming.
  • cuems-nodeconf has the identical bug at NodeXmlBuilders.py:80 (calls the inherited str_to_value without a key) — tracked as ClickUp 869eag7hv.
  • Deriving string-typed keys from the XSD instead of a hand-maintained allowlist, and the get_parser_class/get_class case-sensitivity defects — each needs its own plan.

str_to_value() ran every scalar through int -> float -> strtobool -> Uuid
regardless of its key, so free text was silently rewritten on save. Since
strtobool accepts the truth abbreviations, a cue named n/N/f/F was persisted
as False, y/Y/t/T as True, and any bare digit as an int -- 18 of the 62
alphanumeric single characters, plus yes/no/true/false/on/off.

Reported as "can't name a cue with a single letter" (ClickUp 869cqbpxa).
There was never a length rule: NameStringType has always been minLength=1,
and the frontend has no validator. The failing characters were exactly
strtobool's vocabulary, which is why searching for a min-length check found
nothing.

Separately, a cue named lowercase none/null hit the ['none','null','']
-> None branch, serialised to <name/>, and failed NameStringType's
minLength=1 -- a hard XMLSchemaValidationError at save rather than silent
corruption. The new short-circuit precedes that branch, fixing both.

Adds STRING_TYPED_KEYS and an optional key argument to str_to_value,
threaded through all four call sites. Keeping key optional leaves existing
single-argument callers unaffected.

Only name, description and file_name are reachable today; output_name,
parameter_name, icon and color are currently shielded by unrelated bypasses
in outputsParser, _normalize_fade_parameters and the GenericDict fallback.
They are listed anyway so fixing those bypasses cannot silently reintroduce
this bug. 'id' is deliberately excluded -- the Uuid() branch is the only
thing producing Uuid objects on parse.

Closes ClickUp 869cqbpxa.
@cursor

cursor Bot commented Jul 28, 2026

Copy link
Copy Markdown

Bugbot is not enabled for your account, so this pull request was not reviewed.

Enable Bugbot in the Cursor dashboard to get automatic reviews on future PRs.

@codecov

codecov Bot commented Jul 28, 2026

Copy link
Copy Markdown

Welcome to Codecov 🎉

Once you merge this PR into your default branch, you're all set! Codecov will compare coverage reports and display results in all future pull requests.

ℹ️ You can also turn on project coverage checks and project coverage reporting on Pull Request comment

Thanks for integrating Codecov - We've got you covered ☂️

@ibiltari
ibiltari merged commit cbab5b2 into main Jul 28, 2026
3 checks passed
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.

1 participant