8000 fix: modifying start and end variable strings by sacha-c · Pull Request #1997 · cookiecutter/cookiecutter · GitHub
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content

fix: modifying start and end variable strings #1997

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

Merged
merged 6 commits into from
Feb 19, 2024

Conversation

sacha-c
Copy link
Contributor
@sacha-c sacha-c commented Dec 16, 2023

Note: I recreated this closed PR #1963 as requested)

Description

Cookiecutter supports using _jinja2_env_vars to modify the jinja environment. However when modifying variable_start_string or variable_end_string it will not work because we are hard-coding the start and end strings for the main directory creation (see here). In addition, the jinja context is not always populated with the _jinja2_env_vars, for example when getting the placeholder prompts here

Technical details

This change does 3 things (which are in separate commits for readability):

  1. Creates a common utility function create_env_with_context so the jinja environment is created similarly and with context each time.
    • Note that I also considered creating a single jinja env object & passing it around, however it requires much more refactoring (especially of tests), and we need to create it at least twice anyway (once to create the cookiecutter prompt, and once after the prompts are passed to the context), so I decided to go for the easier solution for now.
  2. Leverages the _jinja2_env_vars to search for the initial cookiecutter directory, to allow this customization of variable_start_string and variable_end_string.
  3. Small refactor to move prompt_and_delete from utils to prompt. It was causing circular import issues when having prompt import utils, because utils was importing prompt. And in any case I would say it makes more sense for it to live in prompt because it is a prompt as well after all.

I also removed the ensure_dir_is_templated check because the same logic is used to find the dir, and is therefore redundant.

Use-case
In react-native projects, it's extremely common to use {{ and }} to pass objects to components. For example:

<MyComponent
    some-prop={{ key: 'value' }}
</MyComponent>

Since {{ is the default jinja variable string prefix, jinja goes crazy with react-native templates 🤪 .
A solution to this is to set _jinja2_env_vars.variable_start_string == '{%{' (or something else). But cookiecutter currently has issues when overriding this setting.

Testing

Tested locally on a react-native project with _jinja2_env_vars.variable_start_string == '{%{' and _jinja2_env_vars.variable_end_string == '}%}'

Copy link
Member
@kurtmckee kurtmckee left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for your work on this, @sacha-c!

This looks really good to me. I had a couple questions, and I've left a request for one additional test.

),
],
)
def test_find_template(repo_name, env, expected):
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would you add a negative find() test? I'd like to see demonstrated behavior when the environment variables and the directory name don't align, like "Jinja vars are {%{ and }%} but the directory is {{ repo }}".

I'm not advocating that {{ / }} is a fallback, just wanting a negative test to demonstrate the expected failure case.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've added a parametrized test here: template with custom jinja strings but folder with default jinja strings
where the jinja configuration is overriden with {%{, but the template folder is uses {{

In this case cookiecutter should not be able to find the template folder because it is not accurately named, so it should fail with NonTemplatedInputDirException

Comment on lines -14 to -18
@pytest.mark.parametrize('invalid_dirname', ['', '{foo}', '{{foo', 'bar}}'])
def test_ensure_dir_is_templated_raises(invalid_dirname):
"""Verify `ensure_dir_is_templated` raises on wrong directories names input."""
with pytest.raises(exceptions.NonTemplatedInputDirException):
generate.ensure_dir_is_templated(invalid_dirname)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is the expected behavior if the directory is not templated?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

True, I removed this function because I felt it was redundant with the way the folder was found in the first place; both were using the same logic & failing the same way

I had deleted this test but did not add a new test case to exemplify this scenario, this is now fixed 🙂
I've added an additional test case in test_find_template::template missing folder

The error thrown will be NonTemplatedInputDirException

Cookiecutter supports using _jinja2_env_vars to modify the jinja environment.
However when modifying variable_start_string or variable_end_string it will not work
because we are hard-coding the start and end strings for the main directory creation.

This change leverages the _jinja2_env_vars to search for the main directory, to allow
this customization of variable_start_string and variable_end_string.

I also remove the  check because the same logic
is used to find the dir, which is therefore redundant.
prompt_and_delete was a function in utils which also made use of read_user_yes_no
which was in prompt.
This means that prompt could not import utils because it would create a circular import.
This change moves prompt_and_delete to prompt, so that prompt may make use of util functions
@sacha-c sacha-c force-pushed the fix/jinja-variable-directory-name branch from 774e4f1 to e12ac18 Compare December 16, 2023 15:59
@eric-musliner
Copy link

What's the latest update on this? Would be extremely useful to have this ability

@eric-musliner
Copy link

What's the latest update on this? Would be extremely useful to have this ability

@ericof

@sacha-c
Copy link
Contributor Author
sacha-c commented Feb 19, 2024

@kurtmckee @ericof @jensens
This PR looks ready & has been reviewed, is there anything I can help with to get merged?
Thanks!

@kurtmckee
Copy link
Member

@sacha-c I don't have rights to merge in this repo. A maintainer will need to merge.

@jensens jensens added the enhancement This issue/PR relates to a feature request. label Feb 19, 2024
@jensens jensens merged commit 04b42e1 into cookiecutter:main Feb 19, 2024
@eric-musliner
Copy link

When can we expect a release to include this enhancement?

@jensens
Copy link
Contributor
jensens commented Feb 20, 2024

I plan to look first at some other PR's, but expect it within next 2-3 weeks.

@sacha-c sacha-c deleted the fix/jinja-variable-directory-name branch February 20, 2024 18:50
LaurenceWarne added a commit to LaurenceWarne/prefab.el that referenced this pull request Jul 20, 2024
On older versions of cookiecutter (pre
cookiecutter/cookiecutter#1997) the
find.find_template function took one parameter but after that PR it
now takes two (in an apparent breaking change).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement This issue/PR relates to a feature request.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants
0