[treeplayer] Don't mistake formulas for script files in TTree::Draw - #22774
[treeplayer] Don't mistake formulas for script files in TTree::Draw#22774guitargeek wants to merge 1 commit into
Conversation
Test Results 23 files 23 suites 3d 17h 14m 59s ⏱️ For more details on these failures, see this check. Results for commit f7edbf1. ♻️ This comment has been updated with latest results. |
| /// in the TTree::Draw documentation. Determine whether 'expression' names | ||
| /// such a script file. | ||
| /// | ||
| /// Besides checking that the file exists, require that it has an extension: |
There was a problem hiding this comment.
I reworded it to "we require", with "we" being ROOT.
| return 0; | ||
| } | ||
| Error("DrawSelect", | ||
| "Drawing using a C++ file currently requires that both the expression and the selection are " |
There was a problem hiding this comment.
Good idea! That fits much better
| return false; | ||
|
|
||
| const TString candidate = expression; | ||
| if (candidate.Index("Alt$") >= 0 || candidate.Index("Entries$") >= 0 || candidate.Index("LocalEntries$") >= 0 || |
There was a problem hiding this comment.
I think it would be nicer to read to put all the special functions in a vector and then to loop over the vector.
There was a problem hiding this comment.
The updated PR is doing that
| // the leading part of a formula (e.g. a file named "abs") must not make | ||
| // TTree::Draw interpret the formula as the name of a C++ script called with | ||
| // arguments: only files with an extension qualify as scripts. | ||
| TEST(TTreeDrawRegressions, ExpressionNotShadowedByFile) |
There was a problem hiding this comment.
Perhaps also test that the intended behavior still works, i.e. when you leave, say, abs.C as a macro and try to run it.
There was a problem hiding this comment.
Added a test for that, tracing the minimal required code path that is required to test with because full ACLiC would take about 10 seconds.
`TTree::Draw` can take the name of a C++ script file instead of a
TTreeFormula expression for both the variable expression and the
selection. To decide between the two, `TTreePlayer::DrawSelect` checked
whether a matching file exists via `TSystem::IsFileInIncludePath()`,
which strips a trailing parenthesized part as ACLiC-style macro
arguments. A formula like `"abs(Bs_TRUEID)"` was thus reduced to
`"abs"`, and if an unrelated file with that name happened to exist in
the current directory, the Draw call failed:
```
root [0] tree->Draw("Bs_MCORR", "abs(Bs_TRUEID)")
Error in <TTreePlayer::DrawSelect>: Drawing using a C++ macro
currently requires that both the expression and the selection are
files: "Bs_MCORR" is not a file
```
Two inconsistencies made the trap wider: the selection branch did not
require a dot in the candidate string at all, and the varexp branch
checked for a dot before stripping the arguments, so a decimal
constant inside the parentheses (e.g. `"abs(x+0.5)"`) satisfied it.
Factor the decision into a single helper used for both arguments, which
requires the candidate - after stripping the ACLiC mode and arguments -
to have an extension. This is not a new restriction:
`TTreeProxyGenerator::WriteProxy()` already refuses a script without an
extension (the function name is derived from the basename minus the
extension, for the cut script too), so such a file could never be
processed anyway. It now evaluates as a formula instead of failing with
a misleading error.
Add regression tests that exercise the previously failing Draw calls in
the presence of a shadowing file named "abs", and that check a real
"abs.C" macro is still recognized as a script because of its extension.
Fixes https://its.cern.ch/jira/browse/ROOT-8000
🤖 Done with the help of AI
TTree::Drawcan take the name of a C++ script file instead of a TTreeFormula expression for both the variable expression and the selection. To decide between the two,TTreePlayer::DrawSelectchecked whether a matching file exists viaTSystem::IsFileInIncludePath(), which strips a trailing parenthesized part as ACLiC-style macro arguments. A formula like"abs(Bs_TRUEID)"was thus reduced to"abs", and if an unrelated file with that name happened to exist in the current directory, the Draw call failed:Two inconsistencies made the trap wider: the selection branch did not require a dot in the candidate string at all, and the varexp branch checked for a dot before stripping the arguments, so a decimal constant inside the parentheses (e.g.
"abs(x+0.5)") satisfied it.Factor the decision into a single helper used for both arguments, which requires the candidate - after stripping the ACLiC mode and arguments - to have an extension. This is not a new restriction:
TTreeProxyGenerator::WriteProxy()already refuses a script without an extension (the function name is derived from the basename minus the extension, for the cut script too), so such a file could never be processed anyway. It now evaluates as a formula instead of failing with a misleading error.Add regression tests that exercise the previously failing Draw calls in the presence of a shadowing file named "abs", and that check a real "abs.C" macro is still recognized as a script because of its extension.
Fixes https://its.cern.ch/jira/browse/ROOT-8000
🤖 Done with the help of AI