| 2570 | } // KnobHelperPrivate::parseListenersFromExpression |
| 2571 | |
| 2572 | std::string |
| 2573 | KnobHelper::validateExpression(const std::string& expression, |
| 2574 | int dimension, |
| 2575 | bool hasRetVariable, |
| 2576 | std::string* resultAsString) |
| 2577 | { |
| 2578 | |
| 2579 | #ifdef NATRON_RUN_WITHOUT_PYTHON |
| 2580 | throw std::invalid_argument("NATRON_RUN_WITHOUT_PYTHON is defined"); |
| 2581 | #endif |
| 2582 | PythonGILLocker pgl; |
| 2583 | |
| 2584 | if ( expression.empty() ) { |
| 2585 | throw std::invalid_argument("empty expression");; |
| 2586 | } |
| 2587 | |
| 2588 | std::string error; |
| 2589 | #if 0 |
| 2590 | // the following is OK to detect that there's no "return" in the expression, |
| 2591 | // but fails if the expression contains e.g. "thisGroup" |
| 2592 | // see https://github.com/NatronGitHub/Natron/issues/294 |
| 2593 | |
| 2594 | ///Try to compile the expression and evaluate it, if it doesn't have a good syntax, throw an exception |
| 2595 | ///with the error. |
| 2596 | { |
| 2597 | // first check that the expression does not contain return |
| 2598 | EXPR_RECURSION_LEVEL(); |
| 2599 | |
| 2600 | if ( !NATRON_PYTHON_NAMESPACE::interpretPythonScript(expression, &error, 0) ) { |
| 2601 | throw std::runtime_error(error); |
| 2602 | } |
| 2603 | } |
| 2604 | #endif |
| 2605 | |
| 2606 | std::string exprCpy = expression; |
| 2607 | |
| 2608 | //if !hasRetVariable the expression is expected to be single-line |
| 2609 | if (!hasRetVariable) { |
| 2610 | std::size_t foundNewLine = expression.find("\n"); |
| 2611 | if (foundNewLine != std::string::npos) { |
| 2612 | throw std::invalid_argument("unexpected new line character \'\\n\'"); |
| 2613 | } |
| 2614 | //preprend the line with "ret = ..." |
| 2615 | std::string toInsert(" ret = "); |
| 2616 | exprCpy.insert(0, toInsert); |
| 2617 | } else { |
| 2618 | exprCpy.insert(0, " "); |
| 2619 | std::size_t foundNewLine = exprCpy.find("\n"); |
| 2620 | while (foundNewLine != std::string::npos) { |
| 2621 | exprCpy.insert(foundNewLine + 1, " "); |
| 2622 | foundNewLine = exprCpy.find("\n", foundNewLine + 1); |
| 2623 | } |
| 2624 | } |
| 2625 | |
| 2626 | KnobHolder* holder = getHolder(); |
| 2627 | if (!holder) { |
| 2628 | throw std::runtime_error("This parameter cannot have an expression"); |
| 2629 | } |
no test coverage detected