Repository navigation
Add the web elements only when the caller has not, and read every valid Set Header name - #140
Merged
Merged
Conversation
…names These tests fail on the code as it is and pass once the fixes that follow are in. PipelineBuilder.build() adds the Sequence Element, the JSON Builder, the JavaScript Builder and the Set Headers Element whatever the caller added. web-integration.md lines 30 to 45 at 706de1f0 says each MUST be present and is added only when it is not, with the JSON Builder immediately before the JavaScript Builder. The new tests in tests/test_web_integration_elements.py add each element themselves and expect it to be the only one of its kind, where the caller put it. A caller's own Sequence Element must give a sequence of 1 for a request with no session id, where today the request is counted twice and gives 2. A JSON Builder the caller lacks must go immediately before the caller's JavaScript Builder, and an element whose data key differs only in letter case counts as present. set-headers-element.md lines 10 to 20 at 706de1f0 says the identifier in SetHeader[Identifier][HeaderName] "MUST NOT have upper-case characters after the first character", so the first character may be either case. tests/test_setheader.py asserted that SetHeaderbrowserAccept-CH is refused, which pinned the wrong behaviour, so that name now expects Accept-CH. SetHeaderAcceptAccept-CH must give Accept-CH, where today every copy of the identifier is removed and it gives -CH. SetHeader with nothing after it must raise the wrong format message rather than an IndexError. The error test is renamed test_get_response_header_name_error, because it shared its name with the test of valid names, and it now fails when nothing is raised.
The lookup in BasicListEvidenceKeyFilter is about to change from a search of its list to a set, and these tests pass on the code as it is, so they show the change keeps what the filter does. A listed key is accepted in any letters and anything else is refused. The list attribute still holds the keys in lower case in the order given, because the web integration and the metadata examples read it. A list set after the filter is made, or by a subclass that never calls the base constructor, is the one matched.
web-integration.md lines 30 to 45 at 706de1f0 says the Sequence Element, the JSON Builder, the JavaScript Builder and the Set Headers Element MUST be present, and that each is added only when it is not. An added Sequence Element goes first, an added JSON Builder immediately before the JavaScript Builder, and an added JavaScript Builder or Set Headers Element after all other elements. PipelineBuilder.build() added all four whatever the caller had added. A caller's own Sequence Element then ran twice, so each request moved the sequence on by two, and a caller's own JavaScript Builder ran before the JSON Builder added after it, so it had no JSON to read. build() now adds each element only when none of the caller's elements has the same data key, compared in any letters. The data key decides rather than the class because flow data keeps each element's results under its data key in lower case, and the JavaScript Builder and the web integration functions read these results by that key. A second element with the same key would replace the caller's results whatever its class, and a caller's own element in place of one of these, of any class, is the one those readers find. The Node.js pipeline builder decides the same way. When the caller added a JavaScript Builder but no JSON Builder, the JSON Builder goes immediately before the caller's JavaScript Builder. Otherwise the added elements go where they went before. The add_javascript_builder, add_sequence_element, add_json_builder_element, add_javascript_builder_element, use_setheader_properties and add_set_header_element settings work as before. build_from_configuration is unchanged. This makes CallerAddedWebElementTests in tests/test_web_integration_elements.py pass.
… whole set-headers-element.md lines 10 to 20 at 706de1f0 names these properties SetHeader[Identifier][HeaderName], and says the identifier "MUST NOT have upper-case characters after the first character", so its first character may be either case. get_response_header_name refused an identifier that starts in lower case, so SetHeaderbrowserAccept-CH raised an error instead of giving Accept-CH. It also took the identifier out with replace, which removes every copy of it, so SetHeaderAcceptAccept-CH gave -CH. A name of SetHeader alone raised an IndexError rather than the wrong format message. The header name is now everything from the first upper-case letter after the identifier's first character. A name with no identifier, or no header name after it, raises the wrong format message, and a name that does not start with SetHeader raises the same message as before. The upper-case letters are A to Z, as in the split this replaces. A name whose identifier starts with one of them, and does not appear again in the header name, gives the same header as before, which covers SetHeaderBrowserAccept-CH, SetHeaderHardwareAccept-CH and SetHeaderPlatformAccept-CH. This makes test_get_response_header_name and test_get_response_header_name_error in tests/test_setheader.py pass.
…d the JSON served These tests pass on the code as it is. Each pins a rule the code already meets. web-integration.md lines 242 to 253 at 706de1f0 says the endpoint MUST compare the If-None-Match header with the ETag before the Pipeline processes the request, and MUST NOT process a request whose If-None-Match matches. The existing tests checked only the status code. test_a_matching_request_is_not_processed in tests/test_web_client_side.py counts the requests an element processes, and a matching GET, HEAD or POST leaves the count unchanged. sequence-element.md lines 39 to 44 at 706de1f0 says a query.sequence that is not a whole number, or a string of the digits 0 to 9, from 0 up to 2,147,483,646 is not present, and that no error is recorded. The existing test gave -5 and 5.0 only as text. testSequenceNumberThatIsNegativeOrHasAFractionIsAbsent in tests/test_web_integration_elements.py gives -5 and 1.5 as numbers and expects a sequence of 1 with no error. javascript-builder.md line 348 at 706de1f0 says the endpoint the script calls back "MUST return JSON data in the same form as the JSON embedded within the JavaScript". test_the_json_served_is_the_json_builders_json in tests/test_web_client_side.py keeps the flow data the JSON endpoint processes and checks that the body is that flow data's JSON Builder JSON.
…dentifier in the format message
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.
The Pipeline builder added the web integration elements again when the caller had already added them, and the Set Header Element misread two valid property names. This draft fixes both, with tests for three web integration rules the code already meets.
Problem
PipelineBuilder.build()joined the Sequence Element, the caller's elements, the JSON Builder and JavaScript Builder, and the Set Headers Element without looking at what the caller had added (pipelinebuilder.pylines 191 to 195 at cf904f8e). A caller's own Sequence Element ran twice, so the sequence moved on by two on every request, and a caller's own JavaScript Builder ran before the JSON Builder the builder added after it.get_response_header_namerefused an identifier whose first letter is lower case, and removed every copy of the identifier, soSetHeaderAcceptAccept-CHgave-CH(setheaderelement.pylines 192 to 233 at cf904f8e).SetHeaderwith nothing after it raisedIndexError.get_setheader_properties_pipelinetook any property withsetheaderanywhere in its name (line 105), so a name holding it later on would raise while processing. The names in use (SetHeaderBrowserAccept-CH,SetHeaderHardwareAccept-CH,SetHeaderPlatformAccept-CH) were read correctly.What the specification says
web-integration.md lines 33 to 45 at 706de1f0:
set-headers-element.md lines 10 to 18 at 706de1f0 give the format
SetHeader[Identifier][HeaderName], where "TheSetHeaderprefix indicates that this Property is intended for setting HTTP response headers" and the identifier "MUST NOT have upper-case characters after the first character".The three rules tested here and already met are web-integration.md lines 242 to 245 ("It MUST do so, and MUST NOT process a request whose 'If-None-Match' header matches"), sequence-element.md lines 39 to 44 ("A
query.sequencevalue that is not a whole number, or a string made only of the digits 0 to 9 ... is not present") and javascript-builder.md line 348 (the endpoint "MUST return JSON data in the same form as the JSON embedded within the JavaScript").What changed
All in
pipeline/fiftyone_pipeline_core.PipelineBuilder.build()adds each web integration element its settings ask for only when the caller's elements hold none with the same data key, in any letters, because Flow Data keeps each element's results under its data key in lower case and the JavaScript Builder andweb.pyread these elements by that key. The Sequence Element still goes first and the others last, and a JSON Builder goes immediately before a JavaScript Builder the caller added. The switches (add_javascript_builder,add_sequence_element,add_json_builder_element,add_javascript_builder_element,use_setheader_properties,add_set_header_element) work as before, andbuild_from_configurationis unchanged.get_response_header_nametakes the header name from the first upper-case letter after the identifier's first character, so the first character may be either case and the header name is kept whole. A name with no identifier or no header name raises the format message, which now names[Identifier]as the specification does.get_setheader_properties_pipelinetakes only properties whose names start withSetHeader.If-None-Matchmatches gets 304 without the Pipeline processing it (an element counts its process calls).query.sequencegiven as the numbers -5 and 1.5 is not present, so the sequence is 1. The JSON endpoint's body is the JSON Builder's JSON for the same request. And a new test ofBasicListEvidenceKeyFilter, which no core test covered, checks it keeps keys in any letters.How it was verified
rccf904f8) plus only a throwaway workflow. The sevenCallerAddedWebElementTestsfailed (a caller's Sequence Element ran twice and the sequence was 2, a caller's JSON Builder, JavaScript Builder and Set Headers Element were each added again, and the JSON Builder went after a caller's JavaScript Builder), and so didSetHeaderbrowserAccept-CH,SetHeaderAcceptAccept-CHandSetHeader, on Ubuntu and Windows.test_get_setheader_properties_pipeline_needs_the_prefixfailed ("1 failed, 504 passed" in the core tests).rc6ad5ae2, is green on its second attempt. Its ten Build and Test jobs, Python 3.10 to 3.14 on Ubuntu and Windows, each passed, the 11Setting 'PullRequestSha'lines all name 94914bc, and Configure printed "Left out 5 macOS entries". On the first attempt onlyUbuntu_Python_3.14failed, in the shared Selenium contract tests against both Device Detection examples, at "Driver service process exited unexpectedly before initialization completed" and then a WebDriver session that timed out. That is the browser driver failing to start in the shared tests, which this change does not touch, and selenium-api-tests#28 starts Chrome and Firefox once before the first test that uses them so that it stops. That job was run again and passed. macOS was left out of this draft's full build under the 9 November decision. The rc head is built with macOS before it merges into main.What it releases
fiftyone_pipeline_coreand its dependants, which Monday's release plan releases already.What remains
build_from_configurationadds none of these elements, as before.