Repository navigation
Add the update operation and five shared cases for IdfObject.update - #43
Merged
Merged
Conversation
An all-or-nothing multi-field update cannot be expressed as a sequence of set-field operations, each of which applies on its own, so the corpus gains a fifth operation kind. An update carries its group in fields, which may be empty, and an optional outcome, applied (the default) or refused. A field value may also be a list of groups, each mapping inner field names to text, for an extensible wrapper key such as vertices. Each runner maps the operation to obj.update(group) with values coerced as for add, catches the library's error only when the case declares the group refused, and reports a mismatch in either direction as a failure that names the operation. A library with no update method on objects is a failure too, never a refusal: the method is looked up on the class, because attribute access on an unknown name can itself raise. Neither runner reads the return value, which differs between the libraries. The new assertion compares the canonical epJSON after the operations with expected.after.epJSON. The epjson assertion compares the document as read, and preserved-text excludes touched objects, so neither can show what an operation produced, or that a refused group was partly written. tools/regenerate.sh produces the expectation with ConvertInputFormat from a committed after.idf for every case that declares the assertion, whatever its truth; a convention case still has no expected.epJSON. Four convention cases, each generated from the oracle: update-all-valid, update-refused-unknown-name, update-refused-name and update-wrapper-key. Both libraries' current update implementations pass all four. idfkit's main branch has no IDFObject.update yet, so known-divergence.toml lists its eight failures against idfkit/idfkit#235, to be removed by the pull request that adds the method. Also corrects the Python runner's coercion of fields that accept a sizing keyword, which the library describes as number|string and which were handed over as text. idfkit-unification feature 015, FR-015.
The review of the update operation found that a refused case accepted any exception as the refusal, so a library whose update raised on every call would pass all of them, and that both libraries applied plain entries before rejecting the contents of the extensible list. 1. A fifth case, update-refused-wrapper-contents, gives vertices a list whose second group carries the unknown member bogus beside a valid Surface Type entry. The group is refused and after.idf is the input. expected.after.epJSON is generated by ConvertInputFormat 26.1.0. 2. An update declared refused now names, in a required refused list, the entries the library must report. Both runners fail the case unless the error carries a line " - <entry>:" for each one. The schema, both models and the manifest carry the list, and each refused case declares it. 3. known-divergence.toml records the six typescript failures measured against idfkit-js b44819b and the two python failures of the new case, all against idfkit#235, under a section of their own. The header counts are recounted: 28 entries over 7 issues and 14 cases. 4. post-operation-epjson reads an epJSON input as epJSON in both runners rather than always as IDF. 5. regenerate.sh detects an assertion declared in a multi-line array, and its help prints the whole header rather than a fixed line range. 6. Loading the corpus now ties after.idf to the operations: a case declaring post-operation-epjson must declare operations and carry after.idf; a case whose operations are all refused updates must have an after.idf identical to its input, and any other case one that differs; an update without post-operation-epjson is rejected. 7. The Python runner reads a type's description once per operation and treats a field described without a type as text instead of failing on None.split. The JavaScript runner looks the type up once too. 8. Operation fields are typed and frozen all the way down in Python: a group is a GroupValue, a list of groups a tuple, and both mappings a picklable read-only FrozenMapping, matching the deep freeze of the JavaScript model. 9. Stale prose: the runner's "ninth assertion" comment, the operation kind count, the workflow's test count (117 of 230), the README case count and layout, regenerate.sh usage, and the case notes that implied preserved-text could detect a partly applied group. It cannot, since it excludes every touched object; post-operation-epjson is the assertion that shows nothing was applied. Against idfkit 66d90b2b and idfkit-js b44819b both runners exit 0 with 17 and 11 outstanding exceptions. Against the feature heads, idfkit c90639fb and idfkit-js ebf97c6, all five update cases pass in both languages, so each library's pull request removes its own entries. idfkit-unification feature 015, FR-015.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Adds the corpus support for the multi-field
updateshared by both libraries (idfkit/idfkit#235, feature 015): one operation kind, one assertion, and five cases withtruth = "convention". The naming-register entries for the concept are already released ingovernance-2026.30(#42). This pull request is intended to be released asconformance-2026.17, the level each library raises its pin to when it lands its side.Changes
Operation kind
update. An operation names an object and a group of fields (a list of groups is accepted), declaresoutcome = "applied"or"refused", and, when refused, declaresrefused: the group keys expected to be refused. Both runners call the library'supdate. A refused outcome passes only if the library raises and its message holds a line beginning- <entry>:for each declared key; any other error, or no error, fails the case. A library withoutupdatefails rather than refuses.Assertion
post-operation-epjson. Reads the case's input (IDF or epJSON, asinput_filedeclares), applies the operations, and compares the canonical epJSON withexpected.after.epJSON, whichtools/regenerate.shproduces with ConvertInputFormat from the committedafter.idf.Corpus loading checks. A case declaring
post-operation-epjsonmust have operations and anafter.idf. When every operation is a refused update,after.idfmust equal the input byte for byte; otherwise it must differ from it.Five cases, all
energyplus_version = "26.1.0"and taggedtier1:update-all-validupdate-refused-unknown-namerefused = [the unknown name])update-refused-namename(tagnaming)update-wrapper-keyextensible)update-refused-wrapper-contentsextensible)known-divergence.toml. 16 entries for the update cases, all tracked by Add IDFObject.update() for bulk field updates idfkit#235: 10 for idfkitmain, which has noIDFObject.update, and 6 for idfkit-jsmain, whoseupdatewrites entries before the refused one. Each library's pull request removes its own. The file now holds 28 entries over 7 issues and 14 cases, on a corpus of 74 cases and 226 assertions.Runners and tooling.
GroupValue, tuples, a picklable read-only mapping), matching the JavaScript model's deep freeze.tools/regenerate.shdetects assertions declared in multi-line arrays, and--helpprints its whole header.Results against the libraries
main66d90b2bmainb44819bc90639fbVerification
python -m pytest tests -q: 322 passed.python -m pytest runners/tests -q: 229 passed.node --teston the four runner test files: 230 passed.tools/validate_governance.py,tools/check_consumers.pyandtools.energyplus.check_roster: pass.manifest.jsonvalidates againstmanifest.schema.json, and fails as expected if a refused case'srefusedlist is removed.Known limitation, not changed here
Both runner models drop
writer_optionswhen writing the manifest back out, so a round trip does not reproducemanifest.jsonexactly. This predates this pull request.