Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Jinjava clear file #866

Open
Academic-123 opened this issue May 26, 2022 · 16 comments
Open

Jinjava clear file #866

Academic-123 opened this issue May 26, 2022 · 16 comments

Comments

@Academic-123
Copy link

Please help on this issue
https://ru.stackoverflow.com/questions/1413804/jinjava-%d0%be%d1%87%d0%b8%d1%89%d0%b0%d0%b5%d1%82-%d1%84%d0%b0%d0%b9%d0%bb

@jasmith-hs
Copy link
Contributor

jasmith-hs commented May 26, 2022

This will happen if you have an interpreter with a different config on the stack (in this case, one that has isFailOnUnknownTokens() == false)

    JinjavaInterpreter parentInterpreter = JinjavaInterpreter.getCurrent();
    if (parentInterpreter != null) {
      renderConfig = parentInterpreter.getConfig();
      ...
    }

    JinjavaInterpreter interpreter = globalConfig
      .getInterpreterFactory()
      .newInstance(this, context, renderConfig);
    JinjavaInterpreter.pushCurrent(interpreter);
    try {
      String result = interpreter.render(template);

renderConfig will get overridden with the parent interpreter's config if there is an interpreter on the stack, rather than just the jinjava.getGlobalConfig()

Try calling JinjavaInterpreter.popCurrent() before the code block in the StackOverflow question and see if it works properly

@Academic-123
Copy link
Author

Academic-123 commented May 26, 2022

This will happen if you have an interpreter with a different config on the stack (in this case, one that has isFailOnUnknownTokens() == false)

    JinjavaInterpreter parentInterpreter = JinjavaInterpreter.getCurrent();
    if (parentInterpreter != null) {
      renderConfig = parentInterpreter.getConfig();
      ...
    }

    JinjavaInterpreter interpreter = globalConfig
      .getInterpreterFactory()
      .newInstance(this, context, renderConfig);
    JinjavaInterpreter.pushCurrent(interpreter);
    try {
      String result = interpreter.render(template);

renderConfig will get overridden with the parent interpreter's config if there is an interpreter on the stack, rather than just the jinjava.getGlobalConfig()

Try calling JinjavaInterpreter.popCurrent() before the code block in the StackOverflow question and see if it works properly

Now I get hostname={{host}} if the context does not have the necessary variable, how to make it throw an error if the required variable is not found in context?

@jasmith-hs
Copy link
Contributor

Are there more details to your setup. The render result should have a blank output and it should have an error in renderResult.getErrors(). Are there no FATAL errors in your RenderResult?

@Academic-123
Copy link
Author

Academic-123 commented May 27, 2022

Are there more details to your setup. The render result should have a blank output and it should have an error in renderResult.getErrors(). Are there no FATAL errors in your RenderResult?

Yesterday I used JinjavaInterpeter.popCurrent(); and everything worked, but today it again clears the file, tell me what might be the problem? I understand that sounds unreasonable but I did even mvn clean, and did Invalidate Cache

@jasmith-hs
Copy link
Contributor

while(JinjavaInterpreter.getCurrent() != null) {
    JinjavaInterpreter.popCurrent();
}

Maybe doing this will help.

@Academic-123
Copy link
Author

while(JinjavaInterpreter.getCurrent() != null) {
    JinjavaInterpreter.popCurrent();
}

Maybe doing this will help.

Does not help.

@jasmith-hs
Copy link
Contributor

Can you reproduce this with a minimal Junit test that you can paste or link here?

@Academic-123
Copy link
Author

Academic-123 commented May 27, 2022

while(JinjavaInterpreter.getCurrent() != null) {
    JinjavaInterpreter.popCurrent();
}

Maybe doing this will help.

If there are no other options, then how to make sure that after rendering hostname={{hostname}} is not replaced with hostname= . You must, if the variable in the context is not found, leave the value as was hostname={{hostaname}} ?

@Academic-123
Copy link
Author

Academic-123 commented May 27, 2022

Can you reproduce this with a minimal Junit test that you can paste or link here?

JUnit4: 4.12
Jinjava: 2.6.0
commons-io: 1.3.2
jackson-annotations: 2.13.2

file with extension .properties

@Test
    public void test() throws IOException {
        while(JinjavaInterpreter.getCurrent() != null) {
            JinjavaInterpreter.popCurrent();
        }
        JinjavaConfig.Builder config = JinjavaConfig.newBuilder();
        config.withFailOnUnknownTokens(true);
        Jinjava jinjava = new Jinjava(config.build());

        RenderResult renderResult = jinjava.renderForResult(Resources.toString(new File(Resources.getResource(
                "test.properties").getPath()).toURI().toURL(), StandardCharsets.UTF_8), new HashMap<>());

        String path = Resources.getResource("test.properties").getPath();
        List<String> linesList = Files.readLines(new File(path), StandardCharsets.UTF_8);

        StringBuilder result = new StringBuilder();
        linesList.forEach((str) -> result.append(str + "\n"));

        System.out.println("expected: " + result);
        System.out.println("actual: " + renderResult.getOutput());
        System.out.println("End");
        Assert.assertEquals(result.toString(), renderResult.getOutput());
    }

@jasmith-hs
Copy link
Contributor

If you want the exception to be thrown, then you'd run:

JinjavaInterpreter interpreter = jinjava.newInterpreter();
interpreter.render(input);

This will throw an UnknownTokenException.

If you're using jinjava.renderForResult(), then the output should be empty and there should be a TemplateError in renderResult.getErrors().

Are you telling me that after running the above code, renderResult.getOutput() contains hostname=?

@Academic-123
Copy link
Author

Academic-123 commented May 28, 2022

If you want the exception to be thrown, then you'd run:

JinjavaInterpreter interpreter = jinjava.newInterpreter();
interpreter.render(input);

This will throw an UnknownTokenException.

If you're using jinjava.renderForResult(), then the output should be empty and there should be a TemplateError in renderResult.getErrors().

Are you telling me that after running the above code, renderResult.getOutput() contains hostname=?

No, after running the code above renderResult.getOutput() contains an empty value

  1. I want the config.withFailOnUnknownTokens(false) flag renderResult.getOutput() to return
    hostname={{hostname}} if the variable is not found instead of hostname= .
  2. If the flag is set in config.withFailOnUnknownTokens(true) it threw an error instead of clearing the file, the test above will show

@Academic-123
Copy link
Author

Academic-123 commented May 28, 2022

If you want the exception to be thrown, then you'd run:

JinjavaInterpreter interpreter = jinjava.newInterpreter();
interpreter.render(input);

This will throw an UnknownTokenException.

If you're using jinjava.renderForResult(), then the output should be empty and there should be a TemplateError in renderResult.getErrors().

Are you telling me that after running the above code, renderResult.getOutput() contains hostname=?

  1. Looks like my mistake was because the blank result was written into a file
    renderResult.getOutput()

How do you respond to my first block in the comments above?

@jasmith-hs
Copy link
Contributor

I thought you were wanting it to throw an exception?
If you don't want to throw an exception, and instead leave the expression as-is, you could combine the dynamic variable resolver #572 with using Eager Execution. Use a dynamic variable resolver that maps all string values to a DeferredValue.instance().
You can turn on Eager execution mode by doing config.withExecutionMode(EagerExecutionMode.instance()).
Combining these things will make it so that any value that does not exist on the context will be treated as a deferred value, and it will not be evaluated, which sounds like what you are looking for.
For example if you had:

{% if hostname %}
hostname={{hostname}}
{% else %}
hostname={{ 'none' }}
{% endif %}

the output would be:

{% if hostname %}
hostname={{hostname}}
{% else %}
hostname=none
{% endif %}

@Academic-123
Copy link
Author

Я думал, вы хотите, чтобы он выдал исключение? Если вы не хотите генерировать исключение и вместо этого оставляете выражение как есть, вы можете комбинировать преобразователь динамических переменных #572 с использованием Eager Execution. Используйте преобразователь динамических переменных, который сопоставляет все строковые значения с файлом DeferredValue.instance(). Вы можете включить режим выполнения Eager, выполнив config.withExecutionMode(EagerExecutionMode.instance()). Комбинация этих вещей сделает так, что любое значение, которое не существует в контексте, будет рассматриваться как отложенное значение и не будет оцениваться, что звучит как то, что вы ищете. Например, если у вас было:

{% if hostname %}
hostname={{hostname}}
{% else %}
hostname={{ 'none' }}
{% endif %}

вывод будет:

{% if hostname %}
hostname={{hostname}}
{% else %}
hostname=none
{% endif %}

Thank you, that solved my problem

@Academic-123
Copy link
Author

Academic-123 commented May 31, 2022

I thought you were wanting it to throw an exception? If you don't want to throw an exception, and instead leave the expression as-is, you could combine the dynamic variable resolver #572 with using Eager Execution. Use a dynamic variable resolver that maps all string values to a DeferredValue.instance(). You can turn on Eager execution mode by doing config.withExecutionMode(EagerExecutionMode.instance()). Combining these things will make it so that any value that does not exist on the context will be treated as a deferred value, and it will not be evaluated, which sounds like what you are looking for. For example if you had:

{% if hostname %}
hostname={{hostname}}
{% else %}
hostname={{ 'none' }}
{% endif %}

the output would be:

{% if hostname %}
hostname={{hostname}}
{% else %}
hostname=none
{% endif %}

Hello, and how to make jinjava not fall with the error com.hubspot.jinjava.interpret.UnknownTokenException: Unknown token found: Unclosed comment on variables such as: hostname={#hostname}?

file contains only line hostname={#hostname}

@jasmith-hs
Copy link
Contributor

Hello, and how to make jinjava not fall with the error com.hubspot.jinjava.interpret.UnknownTokenException: Unknown token found: Unclosed comment on variables such as: hostname={#hostname}?

file contains only line hostname={#hostname}

No way to avoid that one. {#hostname} is invalid jinja syntax because {# and #} are used for comments. If you open a comment, you need to close it as well. Jinjava allows you to specify custom token symbols though, so you can remove the comment symbols if you want to, rather than using DefaultTokenScannerSymbols

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

No branches or pull requests

2 participants